Using Newton Joints

This example shows a Newton slider joint. For success with the steps below, you need to have installed GLScene and GLSceneLCL_NGD.

  1. Start a new form-based application in Lazarus. Save all, saving the project as JointDemo and the unit as uJointDemo.
  2. Copy newton.dll and dJointLibrary.dll from GLSceneLCL\external to the project folder.
  3. Select menu item Project > Project Inspector... and add GLSceneLCL_NGD as a new requirement.
  4. Add to the form from the GLScene tab a GLScene, GLSceneViewer, GLCadencer and GLNGDManager.
  5. Drag the bottom right corner of the form and GLSceneViewer to give the scene a reasonable size.
  6. Double click on the GLScene1 icon to obtain the GLScene Editor. Click on Scene objects then on the top right icon to add a camera. Add also to Scene objects two cubes and a light source.
  7. Use the Object Inspector to change the names of the cubes to Ground and SliderCube.
  8. Use the Object Inspector to change the properties of Ground. Change its CubeDepth and CubeWidth to 20 and its Position.Y to -1. Click on the Behaviours ellipsis, then on the + icon of the pop-up and add a NGD Static behaviour. Select the created behaviour and select GLNGDManager1 as its manager.
  9. Use the Object Inspector to change the properties of SliderCube. Change its CubeDepth, CubeWidth and CubeHeight to 2 and its Position.Y to 1. Click on the Behaviours ellipsis, click on the + icon of the pop-up and add a NGD Dynamic behaviour. Select the created behaviour and change Force.X to -110 and select GLNGDManager1 as its manager.
  10. Use the Object Inspector to add a joint by right clicking on NewtonJoint: TOwnedCollection and selecting Add Item. Set its JointType to JointType nj_CustomSlider, its ChildObject to SliderCube and its ParentObject to Ground. Set SliderOptions PinDirection X, Y, and Z to -1, 1 and -1, respectively. (Leave the PivotPoint X, Y and X at 0).
  11. Use the Object Inspector to change Y and Z coordinates of the camera's position to 3 and 15, respectively. Change the X, Y, and Z coordinates of the light source position to -10, 5 and 2, respectively.
  12. Set the Camera property of the GLSceneViewer1 to GLCamera1 and the Scene property of GLCadencer1 to GLScene1.
    Our text view of the form is now as follows
    object Form1: TForm1
      Left = 512
      Height = 442
      Top = 125
      Width = 683
      Caption = 'Form1'
      ClientHeight = 442
      ClientWidth = 683
      LCLVersion = '1.6.0.4'
      object GLSceneViewer1: TGLSceneViewer
        Left = 8
        Height = 426
        Top = 16
        Width = 664
        Camera = GLCamera1
        FieldOfView = 153.57893371582
        TabOrder = 0
      end
      object GLScene1: TGLScene
        left = 16
        top = 8
        object GLCamera1: TGLCamera
          TagFloat = 0
          DepthOfView = 100
          FocalLength = 50
          TargetObject = Ground
          Position.Coordinates = {
            0000000000004040000070410000803F
          }
        end
        object Ground: TGLCube
          TagFloat = 0
          PitchAngle = 0
          Position.Coordinates = {
            00000000000080BF000000000000803F
          }
          RollAngle = 0
          TurnAngle = 0
          BehavioursData = {
            0458434F4C02010201060C54474C4E47445374617469630200060A4E47442053
            746174696302000201060D474C4E47444D616E61676572310800090500000000
            000AD7A3F83F0600
          }
          CubeSize = {
            0000A0410000803F0000A041
          }
        end
        object SliderCube: TGLCube
          TagFloat = 0
          PitchAngle = 0
          Position.Coordinates = {
            000000000000803F000000000000803F
          }
          RollAngle = 0
          TurnAngle = 0
          BehavioursData = {
            0458434F4C02010201060D54474C4E474444796E616D69630200060B4E474420
            44796E616D696302000201060D474C4E47444D616E6167657231080009050000
            0000000AD7A3F83F0600020109050000000000CDCCCCFB3F0500000000000000
            80FF3F0905000000000000000000000200090000DCC200000000000000000000
            00000200080200090000000000000000000000000000803F020008
          }
          CubeSize = {
            000000400000004000000040
          }
        end
        object GLLightSource1: TGLLightSource
          TagFloat = 0
          ConstAttenuation = 1
          LinearAttenuation = 0
          QuadraticAttenuation = 0
          Position.Coordinates = {
            0000A0C000002041000000400000803F
          }
          SpotCutOff = 180
          SpotExponent = 0
        end
      end
      object GLNGDManager1: TGLNGDManager
        VisibleAtRunTime = True
        NewtonSurfaceItem = <>
        NewtonSurfacePair = <>
        NewtonJoint = <    
          item
            CustomSliderOptions.PinDirection.Coordinates = {
              000080BF0000803F000080BF00000000
            }
            JointType = nj_CustomSlider
            ParentObject = Ground
            ChildObject = SliderCube
            CollisionState = True
          end>
        left = 96
        top = 8
      end
      object GLCadencer1: TGLCadencer
        Scene = GLScene1
        MaxDeltaTime = 0
        MinDeltaTime = 0
        FixedDeltaTime = 0
        OnProgress = GLCadencer1Progress
        left = 56
        top = 8
      end
    end   
    
  13. Replace GLBaseClasses in the uses clause with GLBehaviours.
  14. Double click in the OnProgress event of GLCadencer1 and paste into the created procedure these two lines.
      GLNGDManager1.Step(deltaTime);
      if TGLNGDDynamic(SliderCube.Behaviours[0]).Force.X < 0.01 then
        TGLNGDDynamic(SliderCube.Behaviours[0]).Force.X := TGLNGDDynamic(SliderCube.Behaviours[0]).Force.X + 0.01;    
    
    
    The essential code of the unit should be as follows.
    unit uJointDemo;
    
    {$mode objfpc}{$H+}
    
    interface
    
    uses
      Classes, SysUtils, FileUtil, GLScene, GLLCLViewer, GLNGDManager, GLObjects,
      GLCadencer, Forms, Controls, Graphics, Dialogs, GLBehaviours;
    
    type
      TForm1 = class(TForm)
        GLCadencer1: TGLCadencer;
        GLCamera1: TGLCamera;
        Ground: TGLCube;
        SliderCube: TGLCube;
        GLLightSource1: TGLLightSource;
        GLNGDManager1: TGLNGDManager;
        GLScene1: TGLScene;
        GLSceneViewer1: TGLSceneViewer;
        procedure GLCadencer1Progress(Sender: TObject; const deltaTime, newTime: Double);
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.lfm}
    
    procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime, newTime: Double);
    begin
      GLNGDManager1.Step(deltaTime);
      if TGLNGDDynamic(SliderCube.Behaviours[0]).Force.X < 0.01 then
        TGLNGDDynamic(SliderCube.Behaviours[0]).Force.X := TGLNGDDynamic(SliderCube.Behaviours[0]).Force.X + 0.01;
    end;
    
    end.
        
    
  15. Execute the application.
    When executing the application, you may receive an error message that WGL_ARB_pbuffer support is required. Check the box with caption Ignore this exception type and press the button to continue.
    The custom slider joint ensures that the sliding cube takes a diagonal path. Initially the force in the -X direction overcomes gravity acting downwards and the cube ascends. With each frame the horizontal force is reduced until it reaches 0. When gravity overcomes the force, the cube descends until it collides with the ground.

It is very easy to omit a crucial step, but you quickly learn from your mistakes! You should be able to adapt the steps to the use of the other types of joint, but the use of custom hinge joints for a wheeled vehicle can be tricky and we provide instructions for a moving chassis on the next page. The supplied NewtonJoints sample is very useful.

Programming - a skill for life!

How to set-up and use GLScene in Lazarus