LZScene

Форк
0
/
GLNGDManager.pas 
3143 строки · 100.3 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
  A Newton Game Dynamics Manager for GLScene.
6
  Where can I find ... ?
7
   Newton Game Dynamics Engine               (http://newtondynamics.com)
8
   NewtonImport, a Delphi header translation (http://newtondynamics.com/forum/viewtopic.php?f=9&t=5273#p35865)
9

10
  Notes:
11
  This code is still being developed so any part of it may change at anytime.
12
}
13

14
unit GLNGDManager;
15

16
interface
17

18
{.$I GLScene.inc}
19

20
uses
21
  Classes, // TComponent Tlist TWriter TReader TPersistent
22
  SysUtils, //System utilities
23
  Math, // Samevalue isZero to compare single
24
  Types,
25
  NewtonImport,
26
  //NewtonImport_JointLibrary, // Newton
27

28
  GLVectorGeometry, // PVector TVector TMatrix PMatrix NullHmgVector...
29
  GLVectorLists, // TaffineVectorList for Tree
30
  GLXCollection, // TXCollection file function
31
  GLBaseClasses,
32
  GLScene,
33
  GLManager,
34
  GLCrossPlatform,
35
  GLCoordinates, //
36
  GLObjects,
37
  GLGeomObjects,
38
  GLVectorFileObjects, // cube cone freeform...
39
  GLColor,
40
  GLGeometryBB, // For show debug
41
  GLVectorTypes;
42

43
type
44
  NGDFloat = NewtonImport.dFloat;
45
  PNGDFloat = ^NGDFloat;
46

47
  TGLNGDHeightField = record
48
    heightArray: array of Word;
49
    width: Integer;
50
    depth: Integer;
51
    gridDiagonals: Boolean;
52
    widthDepthScale: Single;
53
    heightScale: Single;
54
  end;
55

56
  TGLNGDBehaviour = class;
57
  TGLNGDManager = class;
58
  TGLNGDSurfaceItem = class;
59
  TGLNGDJoint = class;
60

61
  TGLNGDSolverModels = (smExact = 0, smLinear1, smLinear2, smLinear3, smLinear4,
62
    smLinear5, smLinear6, smLinear7, smLinear8, smLinear9);
63

64
  TGLNGDFrictionModels = (fmExact = 0, fmAdaptive);
65
  TGLNGDPickedActions = (paAttach = 0, paMove, paDetach);
66

67
  TGLNGDManagerDebug = (mdShowGeometry, mdShowAABB, mdShowCenterOfMass,
68
    mdShowContact, mdShowJoint, mdShowForce, mdShowAppliedForce,
69
    mdShowAppliedVelocity);
70
  TGLNGDManagerDebugs = set of TGLNGDManagerDebug;
71

72
  TGLNGDCollisions = (nc_Primitive = 0, nc_Convex, nc_BBox, nc_BSphere,
73
    nc_Tree, nc_Mesh, nc_Null, nc_HeightField, nc_NGDFile);
74

75
  TGLNGDJoints = (nj_BallAndSocket, nj_Hinge, nj_Slider, nj_Corkscrew,
76
    nj_Universal, nj_CustomBallAndSocket, nj_CustomHinge, nj_CustomSlider,
77
    nj_UpVector, nj_KinematicController);
78

79
  TGLNGDBehaviourList = class(TList)
80
  protected
81
    function GetBehav(index: Integer): TGLNGDBehaviour;
82
    procedure PutBehav(index: Integer; Item: TGLNGDBehaviour);
83
  public
84
    property ItemsBehav[index: Integer]
85
      : TGLNGDBehaviour read GetBehav write PutBehav; default;
86
  end;
87

88
  { Events for Newton Callback }
89
  TCollisionIteratorEvent = procedure(const userData: Pointer;
90
    vertexCount: Integer; const cfaceArray: PNGDFloat;
91
    faceId: Integer) of object;
92

93
  TApplyForceAndTorqueEvent = procedure(const cbody: NewtonBody;
94
    timestep: NGDFloat; threadIndex: Integer) of object;
95

96
  TSetTransformEvent = procedure(const cbody: NewtonBody;
97
    const cmatrix: PNGDFloat; threadIndex: Integer) of object;
98

99
  TSerializeEvent = procedure(serializeHandle: Pointer; const cbuffer: Pointer;
100
    size: Cardinal) of object;
101

102
  TDeSerializeEvent = procedure(serializeHandle: Pointer; buffer: Pointer;
103
    size: Cardinal) of object;
104

105
  TAABBOverlapEvent = function(const cmaterial: NewtonMaterial;
106
    const cbody0: NewtonBody; const cbody1: NewtonBody;
107
    threadIndex: Integer): Boolean of object;
108

109
  TContactProcessEvent = procedure(const ccontact: NewtonJoint;
110
    timestep: NGDFloat; threadIndex: Integer) of object;
111

112
  TGLNGDDebugOption = class(TPersistent)
113
  strict private
114
    FManager: TGLNGDManager;
115
    FGeomColorDyn: TGLColor; // Green
116
    FGeomColorStat: TGLColor; // Red
117
    FAABBColor: TGLColor; // Yellow
118
    FAABBColorSleep: TGLColor; // Orange
119
    FCenterOfMassColor: TGLColor; // Purple dot
120
    FContactColor: TGLColor; // White
121
    FJointAxisColor: TGLColor; // Blue
122
    FJointPivotColor: TGLColor; // Aquamarine
123
    FForceColor: TGLColor; // Black
124
    FAppliedForceColor: TGLColor; // Silver
125
    FAppliedVelocityColor: TGLColor; // Lime
126
    FCustomColor: TGLColor; // Aqua
127
    FDotAxisSize: Single; // 1
128
    FNGDManagerDebugs: TGLNGDManagerDebugs; // Default All false
129
    procedure SetNGDManagerDebugs(const Value: TGLNGDManagerDebugs);
130
    procedure SetDotAxisSize(const Value: Single);
131
    function StoredDotAxis: Boolean;
132
  public
133
    constructor Create(AOwner: TComponent);
134
    destructor Destroy; override;
135
  published
136
    property GeomColorDyn: TGLColor read FGeomColorDyn write FGeomColorDyn;
137
    property GeomColorStat: TGLColor read FGeomColorStat write FGeomColorStat;
138
    property AABBColor: TGLColor read FAABBColor write FAABBColor;
139
    property AABBColorSleep: TGLColor read FAABBColorSleep write FAABBColorSleep;
140
    property CenterOfMassColor: TGLColor read FCenterOfMassColor write FCenterOfMassColor;
141
    property ContactColor: TGLColor read FContactColor write FContactColor;
142
    property JointAxisColor: TGLColor read FJointAxisColor write FJointAxisColor;
143
    property JointPivotColor: TGLColor read FJointPivotColor write FJointPivotColor;
144
    property ForceColor: TGLColor read FForceColor write FForceColor;
145
    property AppliedForceColor: TGLColor read FAppliedForceColor write FAppliedForceColor;
146
    property AppliedVelocityColor: TGLColor read FAppliedVelocityColor write FAppliedVelocityColor;
147
    property CustomColor: TGLColor read FCustomColor write FCustomColor;
148
    property NGDManagerDebugs: TGLNGDManagerDebugs read FNGDManagerDebugs write
149
      SetNGDManagerDebugs default[];
150
    property DotAxisSize: Single read FDotAxisSize write SetDotAxisSize stored
151
      StoredDotAxis;
152
  end;
153

154
  TGLNGDManager = class(TComponent)
155
  strict private
156
    FVisible: Boolean; // Show Debug at design time
157
    FVisibleAtRunTime: Boolean; // Show Debug at run time
158
    FDllVersion: Integer;
159
    FSolverModel: TGLNGDSolverModels; // Default=Exact
160
    FFrictionModel: TGLNGDFrictionModels; // Default=Exact
161
    FMinimumFrameRate: Integer; // Default=60
162
    FWorldSizeMin: TGLCoordinates; // Default=-100, -100, -100
163
    FWorldSizeMax: TGLCoordinates; // Default=100, 100, 100
164
    FThreadCount: Integer; // Default=1
165
    FGravity: TGLCoordinates; // Default=(0,-9.81,0)
166
    FNewtonSurfaceItem: TCollection;
167
    FNewtonSurfacePair: TOwnedCollection;
168
    FNewtonJointGroup: TOwnedCollection;
169
    FNGDDebugOption: TGLNGDDebugOption;
170
    FGLLines: TGLLines;
171
  private
172
    FNewtonWorld: NewtonWorld;
173
    FNGDBehaviours: TGLNGDBehaviourList;
174
    FCurrentColor: TGLColor;
175
  protected
176
    procedure Loaded; override;
177
    procedure SetVisible(const Value: Boolean);
178
    procedure SetVisibleAtRunTime(const Value: Boolean);
179
    procedure SetSolverModel(const Value: TGLNGDSolverModels);
180
    procedure SetFrictionModel(const Value: TGLNGDFrictionModels);
181
    procedure SetMinimumFrameRate(const Value: Integer);
182
    procedure SetThreadCount(const Value: Integer);
183
    procedure SetGLLines(const Value: TGLLines);
184
    function GetBodyCount: Integer;
185
    function GetConstraintCount: Integer;
186
    procedure AddNode(const coords: TGLCustomCoordinates); overload;
187
    procedure AddNode(const X, Y, Z: Single); overload;
188
    procedure AddNode(const Value: TVector); overload;
189
    procedure AddNode(const Value: TAffineVector); overload;
190
    procedure RebuildAllMaterial;
191
    procedure RebuildAllJoint(Sender: TObject);
192
    // Events
193
    procedure NotifyWorldSizeChange(Sender: TObject);
194
    procedure NotifyChange(Sender: TObject); // Debug view
195
  public
196
    constructor Create(AOwner: TComponent); override;
197
    destructor Destroy; override;
198
    procedure Step(deltatime: Single);
199
  published
200
    property Visible: Boolean read FVisible write SetVisible default True;
201
    property VisibleAtRunTime: Boolean read FVisibleAtRunTime write
202
      SetVisibleAtRunTime default False;
203
    property SolverModel: TGLNGDSolverModels read FSolverModel write
204
      SetSolverModel default smExact;
205
    property FrictionModel: TGLNGDFrictionModels read FFrictionModel write
206
      SetFrictionModel default fmExact;
207
    property MinimumFrameRate: Integer read FMinimumFrameRate write
208
      SetMinimumFrameRate default 60;
209
    property ThreadCount: Integer read FThreadCount write SetThreadCount default 1;
210
    property DllVersion: Integer read FDllVersion;
211
    property NewtonBodyCount: Integer read GetBodyCount;
212
    property NewtonConstraintCount: Integer read GetConstraintCount;
213
    property Gravity: TGLCoordinates read FGravity write FGravity;
214
    property WorldSizeMin: TGLCoordinates read FWorldSizeMin write FWorldSizeMin;
215
    property WorldSizeMax: TGLCoordinates read FWorldSizeMax write FWorldSizeMax;
216
    property NewtonSurfaceItem: TCollection read FNewtonSurfaceItem write FNewtonSurfaceItem;
217
    property NewtonSurfacePair: TOwnedCollection read FNewtonSurfacePair write
218
      FNewtonSurfacePair;
219
    property DebugOption: TGLNGDDebugOption read FNGDDebugOption write
220
      FNGDDebugOption;
221
    property Line: TGLLines read FGLLines write SetGLLines;
222
    property NewtonJoint: TOwnedCollection read FNewtonJointGroup write
223
      FNewtonJointGroup;
224
  end;
225

226
  {  Basis structures for GLScene behaviour style implementations. }
227
  TGLNGDBehaviour = class(TGLBehaviour)
228
  private
229
    FManager: TGLNGDManager;
230
    FManagerName: string;
231
    FInitialized: Boolean;
232
    FNewtonBody: NewtonBody;
233
    FCollision: NewtonCollision;
234
    FNewtonBodyMatrix: TMatrix; // Position and Orientation
235
    FContinuousCollisionMode: Boolean; // Default=False
236
    FNGDCollisions: TGLNGDCollisions;
237
    FCollisionIteratorEvent: TCollisionIteratorEvent;
238
    FOwnerBaseSceneObject: TGLBaseSceneObject;
239
    // FNullCollisionMass: Single; // Default=0
240
    FTreeCollisionOptimize: Boolean; // Default=True
241
    FConvexCollisionTolerance: Single; // Default=0.01 1%
242
    FFileCollision: string;
243
    FNGDSurfaceItem: TGLNGDSurfaceItem;
244
    FHeightFieldOptions: TGLNGDHeightField;
245
  protected
246
    procedure Initialize; virtual;
247
    procedure Finalize; virtual;
248
    procedure WriteToFiler(writer: TWriter); override;
249
    procedure ReadFromFiler(reader: TReader); override;
250
    procedure Loaded; override;
251
    procedure SetManager(Value: TGLNGDManager);
252
    procedure SetNewtonBodyMatrix(const Value: TMatrix);
253
    procedure SetContinuousCollisionMode(const Value: Boolean);
254
    function GetNewtonBodyMatrix: TMatrix;
255
    function GetNewtonBodyAABB: TAABB;
256
    procedure UpdCollision; virtual;
257
    procedure Render; virtual;
258
    procedure SetNGDNewtonCollisions(const Value: TGLNGDCollisions);
259
    procedure SetNGDSurfaceItem(const Value: TGLNGDSurfaceItem);
260
    procedure SetHeightFieldOptions(const Value: TGLNGDHeightField);
261
    function GetPrimitiveCollision(): NewtonCollision;
262
    function GetConvexCollision(): NewtonCollision;
263
    function GetBBoxCollision(): NewtonCollision;
264
    function GetBSphereCollision(): NewtonCollision;
265
    function GetTreeCollision(): NewtonCollision;
266
    function GetMeshCollision(): NewtonCollision;
267
    function GetNullCollision(): NewtonCollision;
268
    function GetHeightFieldCollision(): NewtonCollision;
269
    function GetNGDFileCollision(): NewtonCollision;
270
    function StoredTolerance: Boolean;
271
    // Event
272
    procedure OnCollisionIteratorEvent(const userData: Pointer;
273
      vertexCount: Integer; const cfaceArray: PNGDFloat; faceId: Integer);
274
    // CallBack
275
    class procedure NewtonCollisionIterator(const userData: Pointer;
276
      vertexCount: Integer; const faceArray: PNGDFloat;
277
      faceId: Integer); static; cdecl;
278
    class procedure NewtonSerialize(serializeHandle: Pointer;
279
      const buffer: Pointer; size: Cardinal); static; cdecl;
280
    class procedure NewtonDeserialize(serializeHandle: Pointer;
281
      buffer: Pointer; size: Cardinal); static; cdecl;
282
  public
283
    constructor Create(AOwner: TGLXCollection); override;
284
    destructor Destroy; override;
285
    procedure Reinitialize;
286
    property Initialized: Boolean read FInitialized;
287
    class function UniqueItem: Boolean; override;
288
    property NewtonBodyMatrix: TMatrix read GetNewtonBodyMatrix write
289
      SetNewtonBodyMatrix;
290
    property NewtonBodyAABB: TAABB read GetNewtonBodyAABB;
291
    procedure Serialize(filename: string);
292
    procedure DeSerialize(filename: string);
293
    property HeightFieldOptions: TGLNGDHeightField read FHeightFieldOptions write
294
      SetHeightFieldOptions;
295
  published
296
    property Manager: TGLNGDManager read FManager write SetManager;
297
    property ContinuousCollisionMode: Boolean read FContinuousCollisionMode write
298
      SetContinuousCollisionMode default False;
299
    property NGDNewtonCollisions: TGLNGDCollisions read FNGDCollisions
300
      write SetNGDNewtonCollisions default nc_Primitive;
301
    property TreeCollisionOptimize: Boolean read FTreeCollisionOptimize write
302
      FTreeCollisionOptimize default True;
303
    property ConvexCollisionTolerance: Single read FConvexCollisionTolerance write
304
      FConvexCollisionTolerance stored StoredTolerance;
305
    property FileCollision: string read FFileCollision write FFileCollision;
306
    property NGDSurfaceItem: TGLNGDSurfaceItem read FNGDSurfaceItem write
307
      SetNGDSurfaceItem;
308
  end;
309

310
  TGLNGDDynamic = class(TGLNGDBehaviour)
311
  strict private
312
    FAABBmin: TGLCoordinates;
313
    FAABBmax: TGLCoordinates;
314
    FForce: TGLCoordinates;
315
    FTorque: TGLCoordinates;
316
    FCenterOfMass: TGLCoordinates;
317
    FAutoSleep: Boolean; // Default=True
318
    FLinearDamping: Single; // default=0.1
319
    FAngularDamping: TGLCoordinates; // Default=0.1
320
    FDensity: Single; // Default=1
321
    FUseGravity: Boolean; // Default=True
322
    FNullCollisionVolume: Single; // Default=0
323
    FApplyForceAndTorqueEvent: TApplyForceAndTorqueEvent;
324
    FSetTransformEvent: TSetTransformEvent;
325
    FCustomForceAndTorqueEvent: TApplyForceAndTorqueEvent;
326
    // Read Only
327
    FVolume: Single;
328
    FMass: Single;
329
    FAppliedForce: TGLCoordinates;
330
    FAppliedTorque: TGLCoordinates;
331
    FAppliedOmega: TGLCoordinates;
332
    FAppliedVelocity: TGLCoordinates;
333
    function StoredDensity: Boolean;
334
    function StoredLinearDamping: Boolean;
335
    function StoredNullCollisionVolume: Boolean;
336
  protected
337
    procedure SetAutoSleep(const Value: Boolean);
338
    procedure SetLinearDamping(const Value: Single);
339
    procedure SetDensity(const Value: Single); virtual;
340
    procedure Initialize; override;
341
    procedure Finalize; override;
342
    procedure WriteToFiler(writer: TWriter); override;
343
    procedure ReadFromFiler(reader: TReader); override;
344
    procedure Loaded; override;
345
    procedure Render; override;
346
    // Events
347
    procedure NotifyCenterOfMassChange(Sender: TObject);
348
    procedure NotifyAngularDampingChange(Sender: TObject);
349
    procedure OnApplyForceAndTorqueEvent(const cbody: NewtonBody;
350
      timestep: NGDFloat; threadIndex: Integer);
351
    procedure OnSetTransformEvent(const cbody: NewtonBody;
352
      const cmatrix: PNGDFloat; threadIndex: Integer);
353
    // Callback
354
    class procedure NewtonApplyForceAndTorque(const body: NewtonBody;
355
      timestep: NGDFloat; threadIndex: Integer); static; cdecl;
356
    class procedure NewtonSetTransform(const body: NewtonBody;
357
      const matrix: PNGDFloat; threadIndex: Integer); static; cdecl;
358
  public
359
    constructor Create(AOwner: TGLXCollection); override;
360
    destructor Destroy; override;
361
    procedure AddImpulse(const veloc, pointposit: TVector);
362
    function GetOmega: TVector;
363
    procedure SetOmega(const Omega: TVector);
364
    function GetVelocity: TVector;
365
    procedure SetVelocity(const Velocity: TVector);
366
    class function FriendlyName: string; override;
367
    property CustomForceAndTorqueEvent
368
      : TApplyForceAndTorqueEvent read FCustomForceAndTorqueEvent write
369
      FCustomForceAndTorqueEvent;
370
    property Velocity: TVector read GetVelocity write SetVelocity;
371
    property Omega: TVector read GetOmega write SetOmega;
372
  published
373
    property Force: TGLCoordinates read FForce write FForce;
374
    property Torque: TGLCoordinates read FTorque write FTorque;
375
    property CenterOfMass
376
      : TGLCoordinates read FCenterOfMass write FCenterOfMass;
377
    property AutoSleep: Boolean read FAutoSleep write SetAutoSleep default True;
378
    property LinearDamping
379
      : Single read FLinearDamping write SetLinearDamping
380
      stored StoredLinearDamping;
381
    property AngularDamping
382
      : TGLCoordinates read FAngularDamping write FAngularDamping;
383
    property Density
384
      : Single read FDensity write SetDensity stored StoredDensity;
385
    property UseGravity
386
      : Boolean read FUseGravity write FUseGravity default True;
387
    property NullCollisionVolume
388
      : Single read FNullCollisionVolume write FNullCollisionVolume stored
389
      StoredNullCollisionVolume;
390
    // Read Only
391
    property AppliedOmega: TGLCoordinates read FAppliedOmega;
392
    property AppliedVelocity: TGLCoordinates read FAppliedVelocity;
393
    property AppliedForce: TGLCoordinates read FAppliedForce;
394
    property AppliedTorque: TGLCoordinates read FAppliedTorque;
395
    property Volume: Single read FVolume;
396
    property Mass: Single read FMass;
397
  end;
398

399
  TGLNGDStatic = class(TGLNGDBehaviour)
400
  protected
401
    procedure Render; override;
402
  public
403
    class function FriendlyName: string; override;
404
  published
405
  end;
406

407
  TGLNGDSurfaceItem = class(TCollectionItem)
408
  private
409
    FDisplayName: string;
410
  protected
411
    function GetDisplayName: string; override;
412
    procedure SetDisplayName(const Value: string); override;
413
  published
414
    property DisplayName;
415
    property ID;
416
  end;
417

418
  TGLNGDSurfacePair = class(TCollectionItem)
419
  strict private
420
    FManager: TGLNGDManager;
421
    FNGDSurfaceItem1: TGLNGDSurfaceItem;
422
    FNGDSurfaceItem2: TGLNGDSurfaceItem;
423
    FAABBOverlapEvent: TAABBOverlapEvent;
424
    FContactProcessEvent: TContactProcessEvent;
425
    FSoftness: Single; // 0.1
426
    FElasticity: Single; // 0.4
427
    FCollidable: Boolean; // true
428
    FStaticFriction: Single; // 0.9
429
    FKineticFriction: Single; // 0.5
430
    FContinuousCollisionMode: Boolean; // False
431
    FThickness: Boolean; // False
432
    procedure SetCollidable(const Value: Boolean);
433
    procedure SetElasticity(const Value: Single);
434
    procedure SetKineticFriction(const Value: Single);
435
    procedure SetSoftness(const Value: Single);
436
    procedure SetStaticFriction(const Value: Single);
437
    procedure SetContinuousCollisionMode(const Value: Boolean);
438
    procedure SetThickness(const Value: Boolean);
439
    function StoredElasticity: Boolean;
440
    function StoredKineticFriction: Boolean;
441
    function StoredSoftness: Boolean;
442
    function StoredStaticFriction: Boolean;
443
  private
444
    // Callback
445
    class function NewtonAABBOverlap(const material: NewtonMaterial;
446
      const body0: NewtonBody; const body1: NewtonBody;
447
      threadIndex: Integer): Integer; static; cdecl;
448
    class procedure NewtonContactsProcess(const contact: NewtonJoint;
449
      timestep: NGDFloat; threadIndex: Integer); static; cdecl;
450
    // Event
451
    function OnNewtonAABBOverlapEvent(const cmaterial: NewtonMaterial;
452
      const cbody0: NewtonBody; const cbody1: NewtonBody;
453
      threadIndex: Integer): Boolean;
454
    procedure OnNewtonContactsProcessEvent(const ccontact: NewtonJoint;
455
      timestep: NGDFloat; threadIndex: Integer);
456
  public
457
    constructor Create(Collection: TCollection); override;
458
    procedure SetMaterialItems(const item1, item2: TGLNGDSurfaceItem);
459
    property NGDSurfaceItem1: TGLNGDSurfaceItem read FNGDSurfaceItem1;
460
    property NGDSurfaceItem2: TGLNGDSurfaceItem read FNGDSurfaceItem2;
461
  published
462
    property Softness: Single read FSoftness write SetSoftness stored
463
      StoredSoftness;
464
    property Elasticity: Single read FElasticity write SetElasticity stored
465
      StoredElasticity;
466
    property Collidable
467
      : Boolean read FCollidable write SetCollidable default True;
468
    property StaticFriction
469
      : Single read FStaticFriction write SetStaticFriction
470
      stored StoredStaticFriction;
471
    property KineticFriction
472
      : Single read FKineticFriction write SetKineticFriction stored
473
      StoredKineticFriction;
474
    property ContinuousCollisionMode
475
      : Boolean read FContinuousCollisionMode write
476
      SetContinuousCollisionMode default False;
477
    property Thickness
478
      : Boolean read FThickness write SetThickness default False;
479
    property ContactProcessEvent
480
      : TContactProcessEvent read FContactProcessEvent
481
      write FContactProcessEvent;
482
    property AABBOverlapEvent: TAABBOverlapEvent read FAABBOverlapEvent write
483
      FAABBOverlapEvent;
484
  end;
485

486
  TGLNGDJointPivot = class(TPersistent)
487
  private
488
    FManager: TGLNGDManager;
489
    FPivotPoint: TGLCoordinates;
490
    FOuter: TGLNGDJoint;
491
  public
492
    constructor Create(AOwner: TComponent; aOuter: TGLNGDJoint); virtual;
493
    destructor Destroy; override;
494
  published
495
    property PivotPoint: TGLCoordinates read FPivotPoint write FPivotPoint;
496
  end;
497

498
  TGLNGDJointPin = class(TGLNGDJointPivot)
499
  private
500
    FPinDirection: TGLCoordinates;
501
  public
502
    constructor Create(AOwner: TComponent; aOuter: TGLNGDJoint); override;
503
    destructor Destroy; override;
504
  published
505
    property PinDirection: TGLCoordinates read FPinDirection write FPinDirection;
506
  end;
507

508
  TGLNGDJointPin2 = class(TGLNGDJointPin)
509
  private
510
    FPinDirection2: TGLCoordinates;
511
  public
512
    constructor Create(AOwner: TComponent; aOuter: TGLNGDJoint); override;
513
    destructor Destroy; override;
514
  published
515
    property PinDirection2: TGLCoordinates read FPinDirection2 write FPinDirection2;
516
  end;
517

518
  TGLNGDJointBallAndSocket = class(TGLNGDJointPivot)
519
  private
520
    FConeAngle: Single; // 90
521
    FMinTwistAngle: Single; // -90
522
    FMaxTwistAngle: Single; // 90
523
    procedure SetConeAngle(const Value: Single);
524
    procedure SetMaxTwistAngle(const Value: Single);
525
    procedure SetMinTwistAngle(const Value: Single);
526
    function StoredMaxTwistAngle: Boolean;
527
    function StoredMinTwistAngle: Boolean;
528
    function StoredConeAngle: Boolean;
529
  public
530
    constructor Create(AOwner: TComponent; aOuter: TGLNGDJoint); override;
531
  published
532
    property ConeAngle: Single read FConeAngle write SetConeAngle stored
533
      StoredConeAngle;
534
    property MinTwistAngle: Single read FMinTwistAngle write SetMinTwistAngle
535
      stored StoredMinTwistAngle;
536
    property MaxTwistAngle: Single read FMaxTwistAngle write SetMaxTwistAngle
537
      stored StoredMaxTwistAngle;
538
  end;
539

540
  TGLNGDJointHinge = class(TGLNGDJointPin)
541
  private
542
    FMinAngle: Single; // -90
543
    FMaxAngle: Single; // 90
544
    procedure SetMaxAngle(const Value: Single);
545
    procedure SetMinAngle(const Value: Single);
546
    function StoredMaxAngle: Boolean;
547
    function StoredMinAngle: Boolean;
548
  public
549
    constructor Create(AOwner: TComponent; aOuter: TGLNGDJoint); override;
550
  published
551
    property MinAngle: Single read FMinAngle write SetMinAngle stored
552
      StoredMinAngle;
553
    property MaxAngle: Single read FMaxAngle write SetMaxAngle stored
554
      StoredMaxAngle;
555
  end;
556

557
  TGLNGDJointSlider = class(TGLNGDJointPin)
558
  private
559
    FMinDistance: Single; // -10
560
    FMaxDistance: Single; // 10
561
    procedure SetMaxDistance(const Value: Single);
562
    procedure SetMinDistance(const Value: Single);
563
    function StoredMaxDistance: Boolean;
564
    function StoredMinDistance: Boolean;
565
  public
566
    constructor Create(AOwner: TComponent; aOuter: TGLNGDJoint); override;
567
  published
568
    property MinDistance: Single read FMinDistance write SetMinDistance stored
569
	   StoredMinDistance;
570
    property MaxDistance: Single read FMaxDistance write SetMaxDistance stored
571
	   StoredMaxDistance;
572
  end;
573

574
  TGLNGDJointKinematicController = class(TPersistent)
575
  private
576
    FPickModeLinear: Boolean; // False
577
    FLinearFriction: Single; // 750
578
    FAngularFriction: Single; // 250
579
    function StoredAngularFriction: Boolean;
580
    function StoredLinearFriction: Boolean;
581
  public
582
    constructor Create();
583
  published
584
    property PickModeLinear: Boolean read FPickModeLinear write FPickModeLinear
585
      default False;
586
    property LinearFriction: Single read FLinearFriction write FLinearFriction stored
587
      StoredLinearFriction;
588
    property AngularFriction: Single read FAngularFriction write FAngularFriction stored
589
      StoredAngularFriction;
590
  end;
591

592
  TGLNGDJoint = class(TCollectionItem)
593
  private
594
    // Global
595
    FManager: TGLNGDManager;
596
    FParentObject: TGLBaseSceneObject;
597
    FJointType: TGLNGDJoints;
598
    FStiffness: Single; // 0.9
599
    // With Two object
600
    // Every joint except nj_UpVector and nj_KinematicController
601
    FChildObject: TGLBaseSceneObject;
602
    FCollisionState: Boolean; // False
603
    // With classic joint
604
    // nj_BallAndSocket, nj_Hinge, nj_Slider, nj_Corkscrew
605
    // nj_Universal, nj_UpVector
606
    FNewtonJoint: NewtonJoint;
607
    // With CustomJoint
608
    // nj_CustomBallAndSocket, nj_CustomHinge, nj_CustomSlider
609
    // nj_KinematicController
610
    FNewtonUserJoint: NewtonJoint;
611
    // nj_UpVector
612
    FUPVectorDirection: TGLCoordinates;
613
    FBallAndSocketOptions: TGLNGDJointPivot;
614
    FHingeOptions: TGLNGDJointPin;
615
    FSliderOptions: TGLNGDJointPin;
616
    FCorkscrewOptions: TGLNGDJointPin;
617
    FUniversalOptions: TGLNGDJointPin2;
618
    FCustomBallAndSocketOptions: TGLNGDJointBallAndSocket;
619
    FCustomHingeOptions: TGLNGDJointHinge;
620
    FCustomSliderOptions: TGLNGDJointSlider;
621
    FKinematicOptions: TGLNGDJointKinematicController;
622
    procedure SetJointType(const Value: TGLNGDJoints);
623
    procedure SetChildObject(const Value: TGLBaseSceneObject);
624
    procedure SetCollisionState(const Value: Boolean);
625
    procedure SetParentObject(const Value: TGLBaseSceneObject);
626
    procedure SetStiffness(const Value: Single);
627
    procedure Render;
628
    function StoredStiffness: Boolean;
629
    procedure DestroyNewtonData;
630
  public
631
    constructor Create(Collection: TCollection); override;
632
    destructor Destroy; override;
633
    procedure KinematicControllerPick(pickpoint: TVector;
634
      PickedActions: TGLNGDPickedActions);
635
  published
636
    property BallAndSocketOptions: TGLNGDJointPivot read FBallAndSocketOptions write
637
      FBallAndSocketOptions;
638
    property HingeOptions: TGLNGDJointPin read FHingeOptions write FHingeOptions;
639
    property SliderOptions: TGLNGDJointPin read FSliderOptions write FSliderOptions;
640
    property CorkscrewOptions: TGLNGDJointPin read FCorkscrewOptions write FCorkscrewOptions;
641
    property UniversalOptions: TGLNGDJointPin2 read FUniversalOptions write FUniversalOptions;
642
    property CustomBallAndSocketOptions: TGLNGDJointBallAndSocket read FCustomBallAndSocketOptions write
643
      FCustomBallAndSocketOptions;
644
    property CustomHingeOptions: TGLNGDJointHinge read FCustomHingeOptions write
645
      FCustomHingeOptions;
646
    property CustomSliderOptions: TGLNGDJointSlider read FCustomSliderOptions write
647
      FCustomSliderOptions;
648
    property KinematicControllerOptions: TGLNGDJointKinematicController read FKinematicOptions write
649
      FKinematicOptions;
650
    property JointType: TGLNGDJoints read FJointType write SetJointType;
651
    property ParentObject: TGLBaseSceneObject read FParentObject write
652
      SetParentObject;
653
    property ChildObject: TGLBaseSceneObject read FChildObject write
654
      SetChildObject;
655
    property CollisionState: Boolean read FCollisionState write SetCollisionState default False;
656
    property Stiffness: Single read FStiffness write SetStiffness stored
657
      StoredStiffness;
658
    property UPVectorDirection: TGLCoordinates read FUPVectorDirection write FUPVectorDirection;
659
  end;
660

661

662
function GetNGDStatic(Obj: TGLBaseSceneObject): TGLNGDStatic;
663
function GetOrCreateNGDStatic(Obj: TGLBaseSceneObject): TGLNGDStatic;
664
function GetNGDDynamic(Obj: TGLBaseSceneObject): TGLNGDDynamic;
665
function GetOrCreateNGDDynamic(Obj: TGLBaseSceneObject): TGLNGDDynamic;
666
function GetBodyFromGLSceneObject(Obj: TGLBaseSceneObject): NewtonBody;
667

668
//----------------------------------------------------------------------
669
implementation
670
//----------------------------------------------------------------------
671

672
const
673
  epsilon = 0.0000001; // 1E-07
674

675
function GetNGDStatic(Obj: TGLBaseSceneObject): TGLNGDStatic;
676
begin
677
  Result := TGLNGDStatic(Obj.Behaviours.GetByClass(TGLNGDStatic));
678
end;
679

680
function GetOrCreateNGDStatic(Obj: TGLBaseSceneObject): TGLNGDStatic;
681
begin
682
  Result := TGLNGDStatic(Obj.GetOrCreateBehaviour(TGLNGDStatic));
683
end;
684

685
function GetNGDDynamic(Obj: TGLBaseSceneObject): TGLNGDDynamic;
686
begin
687
  Result := TGLNGDDynamic(Obj.Behaviours.GetByClass(TGLNGDDynamic));
688
end;
689

690
function GetOrCreateNGDDynamic(Obj: TGLBaseSceneObject): TGLNGDDynamic;
691
begin
692
  Result := TGLNGDDynamic(Obj.GetOrCreateBehaviour(TGLNGDDynamic));
693
end;
694

695
function GetBodyFromGLSceneObject(Obj: TGLBaseSceneObject): NewtonBody;
696
var
697
  Behaviour: TGLNGDBehaviour;
698
begin
699
  Behaviour := TGLNGDBehaviour(Obj.Behaviours.GetByClass(TGLNGDBehaviour));
700
  Assert(Behaviour <> nil, 'NGD Behaviour (static or dynamic) is missing for this object');
701
  Result := Behaviour.FNewtonBody;
702
end;
703

704
// ------------------------------------------------------------------
705
// ------------------------------------------------------------------
706
// ------------------------------------------------------------------
707

708
//-----------------------
709
// TGLNGDDebugOption
710
//-----------------------
711
constructor TGLNGDDebugOption.Create(AOwner: TComponent);
712
begin
713
  FManager := AOwner as TGLNGDManager;
714
  with FManager do
715
  begin
716
    FGeomColorDyn := TGLColor.CreateInitialized(self, clrGreen, NotifyChange);
717
    FGeomColorStat := TGLColor.CreateInitialized(self, clrRed, NotifyChange);
718
    FAABBColor := TGLColor.CreateInitialized(self, clrYellow, NotifyChange);
719
    FAABBColorSleep := TGLColor.CreateInitialized(self, clrOrange,
720
      NotifyChange);
721
    FCenterOfMassColor := TGLColor.CreateInitialized(self, clrPurple,
722
      NotifyChange);
723
    FContactColor := TGLColor.CreateInitialized(self, clrWhite, NotifyChange);
724
    FJointAxisColor := TGLColor.CreateInitialized(self, clrBlue, NotifyChange);
725
    FJointPivotColor := TGLColor.CreateInitialized(self, clrAquamarine,
726
      NotifyChange);
727

728
    FForceColor := TGLColor.CreateInitialized(self, clrBlack, NotifyChange);
729
    FAppliedForceColor := TGLColor.CreateInitialized(self, clrSilver,
730
      NotifyChange);
731
    FAppliedVelocityColor := TGLColor.CreateInitialized(self, clrLime,
732
      NotifyChange);
733

734
    FCustomColor := TGLColor.CreateInitialized(self, clrAqua, NotifyChange);
735
  end;
736
  FDotAxisSize := 1;
737
  FNGDManagerDebugs := [];
738

739
  FManager := AOwner as TGLNGDManager;
740
end;
741

742
destructor TGLNGDDebugOption.Destroy;
743
begin
744
  FGeomColorDyn.Free;
745
  FGeomColorStat.Free;
746
  FAABBColor.Free;
747
  FAABBColorSleep.Free;
748
  FCenterOfMassColor.Free;
749
  FContactColor.Free;
750
  FJointAxisColor.Free;
751
  FJointPivotColor.Free;
752
  FForceColor.Free;
753
  FAppliedForceColor.Free;
754
  FAppliedVelocityColor.Free;
755
  FCustomColor.Free;
756
  inherited;
757
end;
758

759
procedure TGLNGDDebugOption.SetDotAxisSize(const Value: Single);
760
begin
761
  FDotAxisSize := Value;
762
  FManager.NotifyChange(self);
763
end;
764

765
procedure TGLNGDDebugOption.SetNGDManagerDebugs(const Value: TGLNGDManagerDebugs);
766
begin
767
  FNGDManagerDebugs := Value;
768
  FManager.NotifyChange(self);
769
end;
770

771
function TGLNGDDebugOption.StoredDotAxis: Boolean;
772
begin
773
  Result := not SameValue(FDotAxisSize, 1, epsilon);
774
end;
775

776
//------------------------
777
// TGLNGDManager
778
//------------------------
779
procedure TGLNGDManager.AddNode(const Value: TVector);
780
begin
781
  if Assigned(FGLLines) then
782
  begin
783
    FGLLines.Nodes.AddNode(Value);
784

785
    with (FGLLines.Nodes.Last as TGLLinesNode) do
786
      Color := FCurrentColor;
787
  end;
788
end;
789

790
procedure TGLNGDManager.AddNode(const coords: TGLCustomCoordinates);
791
begin
792
  if Assigned(FGLLines) then
793
  begin
794
    FGLLines.Nodes.AddNode(coords); (FGLLines.Nodes.Last as TGLLinesNode)
795
    .Color := FCurrentColor;
796
  end;
797
end;
798

799
procedure TGLNGDManager.AddNode(const X, Y, Z: Single);
800
begin
801
  if Assigned(FGLLines) then
802
  begin
803
    FGLLines.Nodes.AddNode(X, Y, Z); (FGLLines.Nodes.Last as TGLLinesNode)
804
    .Color := FCurrentColor;
805
  end;
806
end;
807

808
procedure TGLNGDManager.AddNode(const Value: TAffineVector);
809
begin
810
  if Assigned(FGLLines) then
811
  begin
812
    FGLLines.Nodes.AddNode(Value); (FGLLines.Nodes.Last as TGLLinesNode)
813
    .Color := FCurrentColor;
814
  end;
815
end;
816

817
constructor TGLNGDManager.Create(AOwner: TComponent);
818
var
819
  minworld, maxworld: TVector;
820
begin
821
  inherited;
822
  FNGDBehaviours := TGLNGDBehaviourList.Create;
823
  FVisible := True;
824
  FVisibleAtRunTime := False;
825
  FSolverModel := smExact;
826
  FFrictionModel := fmExact;
827
  FMinimumFrameRate := 60;
828
  FWorldSizeMin := TGLCoordinates.CreateInitialized(self,
829
    VectorMake(-100, -100, -100, 0), csPoint);
830
  FWorldSizeMax := TGLCoordinates.CreateInitialized(self,
831
    VectorMake(100, 100, 100, 0), csPoint);
832

833
  // Using Events because we need to call API Function when
834
  // theses TGLCoordinates change.
835
  FWorldSizeMin.OnNotifyChange := NotifyWorldSizeChange;
836
  FWorldSizeMax.OnNotifyChange := NotifyWorldSizeChange;
837

838
  FThreadCount := 1;
839
  FGravity := TGLCoordinates3.CreateInitialized(self,
840
    VectorMake(0, -9.81, 0, 0), csVector);
841

842
  FNewtonWorld := NewtonCreate;//(nil, nil);
843
  FDllVersion := NewtonWorldGetVersion;//(FNewtonWorld);
844

845
  // This is to prevent body out the world at startTime
846
  minworld := VectorMake(-1E50, -1E50, -1E50);
847
  maxworld := VectorMake(1E50, 1E50, 1E50);
848
  //NewtonSetWorldSize(FNewtonWorld, @minworld, @maxworld);
849
//  NewtonSetStackSize
850

851
  NewtonWorldSetUserData(FNewtonWorld, self);
852

853
  FNewtonSurfaceItem := TCollection.Create(TGLNGDSurfaceItem);
854
  FNewtonSurfacePair := TOwnedCollection.Create(self, TGLNGDSurfacePair);
855
  FNewtonJointGroup := TOwnedCollection.Create(self, TGLNGDJoint);
856
  FNGDDebugOption := TGLNGDDebugOption.Create(self);
857
  RegisterManager(self);
858
end;
859

860
destructor TGLNGDManager.Destroy;
861
begin
862
  // for joint before body.
863
  FreeAndNil(FNewtonJointGroup);
864

865
  // Unregister everything
866
  while FNGDBehaviours.Count > 0 do
867
    FNGDBehaviours[0].Manager := nil;
868

869
  // Clean up everything
870
  FreeAndNil(FNGDBehaviours);
871
  FreeAndNil(FWorldSizeMin);
872
  FreeAndNil(FWorldSizeMax);
873
  FreeAndNil(FGravity);
874
  FreeAndNil(FNewtonSurfaceItem);
875
  FreeAndNil(FNewtonSurfacePair);
876
  FreeAndNil(FNGDDebugOption);
877

878
  NewtonDestroyAllBodies(FNewtonWorld);
879
  NewtonMaterialDestroyAllGroupID(FNewtonWorld);
880
  NewtonDestroy(FNewtonWorld);
881
  FNewtonWorld := nil;
882
  DeregisterManager(self);
883
  inherited;
884
end;
885

886
procedure TGLNGDManager.Loaded;
887
begin
888
  inherited;
889
  NotifyWorldSizeChange(self);
890
  RebuildAllJoint(self);
891
end;
892

893
function TGLNGDManager.GetBodyCount: Integer;
894
begin
895
  if (csDesigning in ComponentState) then
896
    Result := FNGDBehaviours.Count
897
  else
898
    Result := NewtonWorldGetBodyCount(FNewtonWorld);
899
end;
900

901
function TGLNGDManager.GetConstraintCount: Integer;
902
begin
903
  if (csDesigning in ComponentState) then
904
    Result := FNewtonJointGroup.Count
905
  else
906
    // Constraint is the number of joint
907
    Result := NewtonWorldGetConstraintCount(FNewtonWorld);
908
end;
909

910
procedure TGLNGDManager.NotifyChange(Sender: TObject);
911
var
912
  I: Integer;
913
begin
914
  // This event is raise
915
  // when debugOptions properties are edited,
916
  // when a behavior is initialized/finalize,
917
  // when joints are rebuilded, (runtime only)
918
  // when visible and visibleAtRuntime are edited (designTime only),
919
  // in manager.step, and in SetGLLines.
920

921
  // Here the manager call render method for bodies and joints in its lists
922

923
  if not Assigned(FGLLines) then
924
    exit;
925
  FGLLines.Nodes.Clear;
926

927
  if not Visible then
928
    exit;
929
  if not(csDesigning in ComponentState) then
930
    if not VisibleAtRunTime then
931
      exit;
932

933
  for I := 0 to FNGDBehaviours.Count - 1 do
934
    FNGDBehaviours[I].Render;
935

936
  if mdShowJoint in FNGDDebugOption.NGDManagerDebugs then
937
    for I := 0 to NewtonJoint.Count - 1 do //
938
  (NewtonJoint.Items[I] as TGLNGDJoint)
939
      .Render;
940

941
end;
942

943
procedure TGLNGDManager.SetFrictionModel(const Value: TGLNGDFrictionModels);
944
begin
945
  FFrictionModel := Value;
946
  //if not(csDesigning in ComponentState) then
947
  //  NewtonSetFrictionModel(FNewtonWorld, Ord(FFrictionModel));
948
end;
949

950
procedure TGLNGDManager.SetGLLines(const Value: TGLLines);
951
begin
952
  if Assigned(FGLLines) then
953
    FGLLines.Nodes.Clear;
954

955
  FGLLines := Value;
956

957
  if Assigned(FGLLines) then
958
  begin
959
    FGLLines.SplineMode := lsmSegments;
960
    FGLLines.NodesAspect := lnaInvisible;
961
    FGLLines.Options := [loUseNodeColorForLines];
962
    FGLLines.Pickable := False;
963
    NotifyChange(self);
964
  end;
965
end;
966

967
procedure TGLNGDManager.SetMinimumFrameRate(const Value: Integer);
968
begin
969
  if (Value >= 60) and (Value <= 1000) then
970
    FMinimumFrameRate := Value;
971
 // if not(csDesigning in ComponentState) then
972
 //   NewtonSetMinimumFrameRate(FNewtonWorld, FMinimumFrameRate);
973
end;
974

975
procedure TGLNGDManager.SetSolverModel(const Value: TGLNGDSolverModels);
976
begin
977
  FSolverModel := Value;
978
  if not(csDesigning in ComponentState) then
979
    NewtonSetSolverModel(FNewtonWorld, Ord(FSolverModel));
980
end;
981

982
procedure TGLNGDManager.SetThreadCount(const Value: Integer);
983
begin
984
  if Value > 0 then
985
    FThreadCount := Value;
986
  NewtonSetThreadsCount(FNewtonWorld, FThreadCount);
987
  FThreadCount := NewtonGetThreadsCount(FNewtonWorld);
988
end;
989

990
procedure TGLNGDManager.SetVisible(const Value: Boolean);
991
begin
992
  FVisible := Value;
993
  if (csDesigning in ComponentState) then
994
    NotifyChange(self);
995
end;
996

997
procedure TGLNGDManager.SetVisibleAtRunTime(const Value: Boolean);
998
begin
999
  FVisibleAtRunTime := Value;
1000
  if (csDesigning in ComponentState) then
1001
    NotifyChange(self);
1002
end;
1003

1004
procedure TGLNGDManager.NotifyWorldSizeChange(Sender: TObject);
1005
begin
1006
  //if not(csDesigning in ComponentState) then
1007
  //  NewtonSetWorldSize(FNewtonWorld, @FWorldSizeMin.AsVector,
1008
  //    @FWorldSizeMax.AsVector);
1009
end;
1010

1011
procedure TGLNGDManager.RebuildAllJoint(Sender: TObject);
1012

1013
  procedure BuildBallAndSocket(Joint: TGLNGDJoint);
1014
  begin
1015
    with Joint do
1016
      if Assigned(FParentObject) and Assigned(FChildObject) then
1017
      begin
1018
        FNewtonJoint := NewtonConstraintCreateBall(FNewtonWorld,
1019
          @(FBallAndSocketOptions.FPivotPoint.AsVector),
1020
          GetBodyFromGLSceneObject(FChildObject),
1021
          GetBodyFromGLSceneObject(FParentObject));
1022
        NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
1023
        NewtonJointSetStiffness(FNewtonJoint, FStiffness);
1024
      end;
1025
  end;
1026

1027
  procedure BuildHinge(Joint: TGLNGDJoint);
1028
  begin
1029
    with Joint do
1030
      if Assigned(FParentObject) and Assigned(FChildObject) then
1031
      begin
1032
        FNewtonJoint := NewtonConstraintCreateHinge(FNewtonWorld,
1033
          @(FHingeOptions.FPivotPoint.AsVector),
1034
          @(FHingeOptions.FPinDirection.AsVector),
1035
          GetBodyFromGLSceneObject(FChildObject),
1036
          GetBodyFromGLSceneObject(FParentObject));
1037
        NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
1038
        NewtonJointSetStiffness(FNewtonJoint, FStiffness);
1039
      end;
1040
  end;
1041

1042
  procedure BuildSlider(Joint: TGLNGDJoint);
1043
  begin
1044
    with Joint do
1045
      if Assigned(FParentObject) and Assigned(FChildObject) then
1046
      begin
1047
        FNewtonJoint := NewtonConstraintCreateSlider(FNewtonWorld,
1048
          @(FSliderOptions.FPivotPoint.AsVector),
1049
          @(FSliderOptions.FPinDirection.AsVector),
1050
          GetBodyFromGLSceneObject(FChildObject),
1051
          GetBodyFromGLSceneObject(FParentObject));
1052
        NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
1053
        NewtonJointSetStiffness(FNewtonJoint, FStiffness);
1054
      end;
1055
  end;
1056

1057
  procedure BuildCorkscrew(Joint: TGLNGDJoint);
1058
  begin
1059
    with Joint do
1060
      if Assigned(FParentObject) and Assigned(FChildObject) then
1061
      begin
1062
        FNewtonJoint := NewtonConstraintCreateCorkscrew(FNewtonWorld,
1063
          @(FCorkscrewOptions.FPivotPoint.AsVector),
1064
          @(FCorkscrewOptions.FPinDirection.AsVector),
1065
          GetBodyFromGLSceneObject(FChildObject),
1066
          GetBodyFromGLSceneObject(FParentObject));
1067
        NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
1068
        NewtonJointSetStiffness(FNewtonJoint, FStiffness);
1069
      end;
1070
  end;
1071

1072
  procedure BuildUniversal(Joint: TGLNGDJoint);
1073
  begin
1074
    with Joint do
1075
      if Assigned(FParentObject) and Assigned(FChildObject) then
1076
      begin
1077
        FNewtonJoint := NewtonConstraintCreateUniversal(FNewtonWorld,
1078
          @(FUniversalOptions.FPivotPoint.AsVector),
1079
          @(FUniversalOptions.FPinDirection.AsVector),
1080
          @(FUniversalOptions.FPinDirection2.AsVector),
1081
          GetBodyFromGLSceneObject(FChildObject),
1082
          GetBodyFromGLSceneObject(FParentObject));
1083
        NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
1084
        NewtonJointSetStiffness(FNewtonJoint, FStiffness);
1085
      end;
1086
  end;
1087

1088
  procedure BuildCustomBallAndSocket(Joint: TGLNGDJoint);
1089
  var
1090
    pinAndPivot: TMatrix;
1091
  begin
1092
    with Joint do
1093
      //if Assigned(FParentObject) and Assigned(FChildObject) then
1094
      //begin
1095
      //  pinAndPivot := IdentityHmgMatrix;
1096
      //  pinAndPivot.W := FCustomBallAndSocketOptions.FPivotPoint.AsVector;
1097
      //  FNewtonUserJoint := CreateCustomBallAndSocket(@pinAndPivot,
1098
      //    GetBodyFromGLSceneObject(FChildObject),
1099
      //    GetBodyFromGLSceneObject(FParentObject));
1100
      //  BallAndSocketSetConeAngle(FNewtonUserJoint,
1101
      //    DegToRad(FCustomBallAndSocketOptions.FConeAngle));
1102
      //  BallAndSocketSetTwistAngle(FNewtonUserJoint,
1103
      //    DegToRad(FCustomBallAndSocketOptions.FMinTwistAngle),
1104
      //    DegToRad(FCustomBallAndSocketOptions.FMaxTwistAngle));
1105
      //  CustomSetBodiesCollisionState(FNewtonUserJoint, Ord(FCollisionState));
1106
      //  NewtonJointSetStiffness(CustomGetNewtonJoint(FNewtonUserJoint),
1107
      //    FStiffness);
1108
      //end;
1109
  end;
1110

1111
  procedure BuildCustomHinge(Joint: TGLNGDJoint);
1112
  var
1113
    pinAndPivot: TMatrix;
1114
    bso: TGLBaseSceneObject;
1115
  begin
1116
    { Newton wait from FPinAndPivotMatrix a structure like that:
1117
      First row: the pin direction
1118
      Second and third rows are set to create an orthogonal matrix
1119
      Fourth: The pivot position
1120

1121
      In glscene, the GLBaseSceneObjects direction is the third row,
1122
      because the first row is the right vector (second row is up vector). }
1123
    with Joint do
1124
      if Assigned(FParentObject) and Assigned(FChildObject) then
1125
      begin
1126
        bso := TGLBaseSceneObject.Create(FManager);
1127
        bso.AbsolutePosition := FCustomHingeOptions.FPivotPoint.AsVector;
1128
        bso.AbsoluteDirection := FCustomHingeOptions.FPinDirection.AsVector;
1129
        pinAndPivot := bso.AbsoluteMatrix;
1130
        pinAndPivot.X := bso.AbsoluteMatrix.Z;
1131
        pinAndPivot.Z := bso.AbsoluteMatrix.X;
1132
        bso.Free;
1133

1134
        //FNewtonUserJoint := CreateCustomHinge(@pinAndPivot,
1135
        //  GetBodyFromGLSceneObject(FChildObject),
1136
        //  GetBodyFromGLSceneObject(FParentObject));
1137
        //HingeEnableLimits(FNewtonUserJoint, 1);
1138
        //HingeSetLimits(FNewtonUserJoint,
1139
        //  DegToRad(FCustomHingeOptions.FMinAngle),
1140
        //  DegToRad(FCustomHingeOptions.FMaxAngle));
1141
        //CustomSetBodiesCollisionState(FNewtonUserJoint, Ord(FCollisionState));
1142
        //NewtonJointSetStiffness(CustomGetNewtonJoint(FNewtonUserJoint),
1143
        //  FStiffness);
1144
        //CustomSetUserData(FNewtonUserJoint, CustomHingeOptions);
1145
      end;
1146
  end;
1147

1148
  procedure BuildCustomSlider(Joint: TGLNGDJoint);
1149
  var
1150
    pinAndPivot: TMatrix;
1151
    bso: TGLBaseSceneObject;
1152

1153
  begin
1154
    { Newton wait from FPinAndPivotMatrix a structure like that:
1155
      First row: the pin direction
1156
      Second and third rows are set to create an orthogonal matrix
1157
      Fourth: The pivot position
1158

1159
      In glscene, the GLBaseSceneObjects direction is the third row,
1160
      because the first row is the right vector (second row is up vector). }
1161
    with Joint do
1162
      if Assigned(FParentObject) and Assigned(FChildObject) then
1163
      begin
1164

1165
        bso := TGLBaseSceneObject.Create(FManager);
1166
        bso.AbsolutePosition := FCustomSliderOptions.FPivotPoint.AsVector;
1167
        bso.AbsoluteDirection := FCustomSliderOptions.FPinDirection.AsVector;
1168
        pinAndPivot := bso.AbsoluteMatrix;
1169
        pinAndPivot.X := bso.AbsoluteMatrix.Z;
1170
        pinAndPivot.Z := bso.AbsoluteMatrix.X;
1171
        bso.Free;
1172

1173
        //FNewtonUserJoint := CreateCustomSlider(@pinAndPivot, GetBodyFromGLSceneObject(FChildObject), GetBodyFromGLSceneObject(FParentObject));
1174
        //SliderEnableLimits(FNewtonUserJoint, 1);
1175
        //SliderSetLimits(FNewtonUserJoint, FCustomSliderOptions.FMinDistance, FCustomSliderOptions.FMaxDistance);
1176
        //NewtonJointSetStiffness(CustomGetNewtonJoint(FNewtonUserJoint),0);
1177
        //
1178
        //CustomSetBodiesCollisionState(FNewtonUserJoint, Ord(FCollisionState));
1179
        //CustomSetUserData(FNewtonUserJoint, CustomSliderOptions);
1180
      end;
1181
  end;
1182

1183
  procedure BuildUpVector(Joint: TGLNGDJoint);
1184
  begin
1185
    with Joint do
1186
      if Assigned(FParentObject) then
1187
      begin
1188
        FNewtonJoint := NewtonConstraintCreateUpVector(FNewtonWorld,
1189
          @FUPVectorDirection.AsVector,
1190
          GetBodyFromGLSceneObject(FParentObject));
1191
      end;
1192
  end;
1193

1194
  procedure BuildKinematicController(Joint: TGLNGDJoint);
1195
  begin
1196
    // do nothing
1197
  end;
1198

1199
  procedure BuildOneJoint(Joint: TGLNGDJoint);
1200
  begin
1201
    case Joint.FJointType of
1202
      nj_BallAndSocket:
1203
        begin
1204
          Joint.DestroyNewtonData;
1205
          BuildBallAndSocket(Joint);
1206
        end;
1207

1208
      nj_Hinge:
1209
        begin
1210
          Joint.DestroyNewtonData;
1211
          BuildHinge(Joint);
1212
        end;
1213

1214
      nj_Slider:
1215
        begin
1216
          Joint.DestroyNewtonData;
1217
          BuildSlider(Joint);
1218
        end;
1219

1220
      nj_Corkscrew:
1221
        begin
1222
          Joint.DestroyNewtonData;
1223
          BuildCorkscrew(Joint);
1224
        end;
1225

1226
      nj_Universal:
1227
        begin
1228
          Joint.DestroyNewtonData;
1229
          BuildUniversal(Joint);
1230
        end;
1231

1232
      nj_CustomBallAndSocket:
1233
        begin
1234
          Joint.DestroyNewtonData;
1235
          BuildCustomBallAndSocket(Joint);
1236
        end;
1237

1238
      nj_CustomHinge:
1239
        begin
1240
          Joint.DestroyNewtonData;
1241
          BuildCustomHinge(Joint);
1242
        end;
1243

1244
      nj_CustomSlider:
1245
        begin
1246
          Joint.DestroyNewtonData;
1247
          BuildCustomSlider(Joint);
1248
        end;
1249

1250
      nj_UpVector:
1251
        begin
1252
          Joint.DestroyNewtonData;
1253
          BuildUpVector(Joint);
1254
        end;
1255

1256
      nj_KinematicController:
1257
        begin
1258
          // DestroyJoint(Joint);
1259
          // BuildKinematicController(Joint);
1260
        end;
1261
    end;
1262
  end;
1263

1264
var
1265
  i: Integer;
1266
begin
1267

1268
  if not(csDesigning in ComponentState) and not(csLoading in ComponentState)
1269
    then
1270
  begin
1271
    if Sender is TGLNGDManager then
1272
      for i := 0 to NewtonJoint.Count - 1 do
1273
        BuildOneJoint(NewtonJoint.Items[i] as TGLNGDJoint);
1274

1275
    if (Sender is TGLNGDJoint) then
1276
      BuildOneJoint((Sender as TGLNGDJoint));
1277

1278
    if Sender is TGLCoordinates then
1279
      BuildOneJoint(((Sender as TGLCoordinates).Owner as TGLNGDJoint));
1280

1281
    NotifyChange(self);
1282
  end;
1283

1284
end;
1285

1286
procedure TGLNGDManager.RebuildAllMaterial;
1287

1288
  procedure BuildMaterialPair;
1289
  var
1290
    I, ID0, ID1: Integer;
1291
  begin
1292
    for I := 0 to FNewtonSurfacePair.Count - 1 do
1293
      with (FNewtonSurfacePair.Items[I] as TGLNGDSurfacePair) do
1294
      begin
1295
        if Assigned(NGDSurfaceItem1) and Assigned(NGDSurfaceItem2) then
1296
        begin
1297
          ID0 := NGDSurfaceItem1.ID;
1298
          ID1 := NGDSurfaceItem2.ID;
1299

1300
          //NewtonMaterialSetContinuousCollisionMode(FNewtonWorld, ID0, ID1,
1301
          //  Ord(ContinuousCollisionMode));
1302
          if Thickness then
1303
            NewtonMaterialSetSurfaceThickness(FNewtonWorld, ID0, ID1, 1);
1304
          NewtonMaterialSetDefaultSoftness(FNewtonWorld, ID0, ID1, Softness);
1305
          NewtonMaterialSetDefaultElasticity(FNewtonWorld, ID0, ID1,
1306
            Elasticity);
1307
          NewtonMaterialSetDefaultCollidable(FNewtonWorld, ID0, ID1,
1308
            Ord(Collidable));
1309
          NewtonMaterialSetDefaultFriction(FNewtonWorld, ID0, ID1,
1310
            StaticFriction, KineticFriction);
1311

1312
          //NewtonMaterialSetCollisionCallback(FNewtonWorld, ID0, ID1,
1313
          //  FNewtonSurfacePair.Items[I], @TGLNGDSurfacePair.NewtonAABBOverlap,
1314
          //  @TGLNGDSurfacePair.NewtonContactsProcess);
1315
        end;
1316
      end;
1317
  end;
1318

1319
var
1320
  I: Integer;
1321
  maxID: Integer;
1322
begin
1323
  maxID := 0;
1324
  if not(csDesigning in ComponentState) then
1325
  begin
1326
    // for newton materials
1327
    NewtonMaterialDestroyAllGroupID(FNewtonWorld);
1328

1329
    // Creates materialID
1330
    for I := 0 to FNewtonSurfaceItem.Count - 1 do
1331
      maxID := MaxInteger((FNewtonSurfaceItem.Items[I] as TGLNGDSurfaceItem).ID,
1332
        maxID);
1333
    for I := 0 to maxID - 1 do
1334
      NewtonMaterialCreateGroupID(FNewtonWorld);
1335

1336
    // assign matID to bodies
1337
    for I := 0 to FNGDBehaviours.Count - 1 do
1338
      with FNGDBehaviours[I] do
1339
        if Assigned(FNGDSurfaceItem) then
1340
          NewtonBodySetMaterialGroupID(FNewtonBody, FNGDSurfaceItem.ID)
1341
        else
1342
          NewtonBodySetMaterialGroupID(FNewtonBody, 0);
1343

1344
    // Set values to newton material pair :callback userdata friction...
1345
    BuildMaterialPair;
1346
  end;
1347
end;
1348

1349
procedure TGLNGDManager.Step(deltatime: Single);
1350
begin
1351
  if not(csDesigning in ComponentState) then
1352
    NewtonUpdate(FNewtonWorld, deltatime);
1353

1354
  NotifyChange(self);
1355
end;
1356

1357
//---------------------------
1358
//  TGLNGDBehaviour
1359
//---------------------------
1360

1361
constructor TGLNGDBehaviour.Create(AOwner: TGLXCollection);
1362
begin
1363
  inherited;
1364
  FInitialized := False;
1365
  FOwnerBaseSceneObject := OwnerBaseSceneObject;
1366

1367
  FContinuousCollisionMode := False;
1368
  FNewtonBody := nil;
1369
  FCollision := nil;
1370

1371
  FNGDCollisions := nc_Primitive;
1372

1373
  FCollisionIteratorEvent := OnCollisionIteratorEvent;
1374

1375
  FTreeCollisionOptimize := True;
1376
  FConvexCollisionTolerance := 0.01;
1377
  FFileCollision := '';
1378
  name := 'NGD Static';
1379
end;
1380

1381
destructor TGLNGDBehaviour.Destroy;
1382
begin
1383
  if Assigned(FManager) then
1384
    Manager := nil;  // This will call finalize
1385
  inherited;
1386
end;
1387

1388
procedure TGLNGDBehaviour.Finalize;
1389
var
1390
  i: integer;
1391
begin
1392
  FInitialized := False;
1393

1394
  if Assigned(FManager) then
1395
  begin
1396

1397
    if Assigned(FManager.NewtonJoint) then
1398
    for i := FManager.NewtonJoint.Count-1 downto 0 do
1399
    begin
1400
      if ((FManager.NewtonJoint.Items[i] as TGLNGDJoint).ParentObject = FOwnerBaseSceneObject)
1401
      or ((FManager.NewtonJoint.Items[i] as TGLNGDJoint).ChildObject = FOwnerBaseSceneObject) then
1402
      begin
1403
        FManager.NewtonJoint.Items[i].Free;
1404
      end;
1405
    end;
1406

1407
    NewtonDestroyBody(FNewtonBody);
1408
    FNewtonBody := nil;
1409
    FCollision := nil;
1410
  end;
1411
end;
1412

1413
function TGLNGDBehaviour.GetBBoxCollision: NewtonCollision;
1414
var
1415
  vc: array [0 .. 7] of TVector;
1416
  I: Integer;
1417
begin
1418
  for I := 0 to 8 - 1 do
1419
    vc[I] := AABBToBB(FOwnerBaseSceneObject.AxisAlignedBoundingBoxEx).BBox[I];
1420
  Result := NewtonCreateConvexHull(FManager.FNewtonWorld, 8, @vc[0],
1421
    SizeOf(TVector), 0.01, 0, nil);
1422
end;
1423

1424
function TGLNGDBehaviour.GetBSphereCollision: NewtonCollision;
1425
var
1426
  boundingSphere: TBSphere;
1427
  collisionOffsetMatrix: TMatrix;
1428
begin
1429
  AABBToBSphere(FOwnerBaseSceneObject.AxisAlignedBoundingBoxEx, boundingSphere);
1430

1431
  collisionOffsetMatrix := IdentityHmgMatrix;
1432
  collisionOffsetMatrix.W := VectorMake(boundingSphere.Center, 1);
1433
  Result := NewtonCreateSphere(FManager.FNewtonWorld, boundingSphere.Radius,0, @collisionOffsetMatrix);
1434
end;
1435

1436
function TGLNGDBehaviour.GetConvexCollision: NewtonCollision;
1437
var
1438
  I, J: Integer;
1439
  vertexArray: array of TVertex;
1440
begin
1441
  if FOwnerBaseSceneObject is TGLBaseMesh then
1442
  begin
1443
    with (FOwnerBaseSceneObject as TGLBaseMesh) do
1444
    begin
1445

1446
      for I := 0 to MeshObjects.Count - 1 do
1447
        for J := 0 to MeshObjects[I].Vertices.Count - 1 do
1448
        begin
1449
          SetLength(vertexArray, Length(vertexArray) + 1);
1450
          vertexArray[Length(vertexArray) - 1] := MeshObjects[I].Vertices[J];
1451
        end;
1452

1453
      if Length(vertexArray) > 0 then
1454
        Result := NewtonCreateConvexHull(FManager.FNewtonWorld,
1455
          Length(vertexArray), @vertexArray[0], SizeOf(TVertex),
1456
          FConvexCollisionTolerance, 0, nil)
1457
      else
1458
        Result := GetNullCollision;
1459
    end;
1460
  end
1461
  else
1462
    Result := GetNullCollision;
1463
end;
1464

1465
function TGLNGDBehaviour.GetHeightFieldCollision: NewtonCollision;
1466
var
1467
  I: Integer;
1468
  attributeMap: array of ShortInt;
1469
begin
1470
  SetLength(attributeMap, Length(FHeightFieldOptions.heightArray));
1471
  for I := 0 to Length(FHeightFieldOptions.heightArray) - 1 do
1472
    attributeMap[I] := 0;
1473
 result:=nil;
1474
  //Result := NewtonCreateHeightFieldCollision(FManager.FNewtonWorld,
1475
  //  FHeightFieldOptions.width, FHeightFieldOptions.depth,
1476
  //  Ord(FHeightFieldOptions.gridDiagonals),
1477
  //  PUnsigned_short(FHeightFieldOptions.heightArray), P2Char(attributeMap),
1478
  //  FHeightFieldOptions.widthDepthScale, FHeightFieldOptions.heightScale, 0);
1479
end;
1480

1481
function TGLNGDBehaviour.GetMeshCollision: NewtonCollision;
1482
var
1483
  collisionArray: array of NewtonCollision;
1484
  I, J: Integer;
1485
  vertexArray: array of TVertex;
1486
begin
1487
  if FOwnerBaseSceneObject is TGLBaseMesh then
1488
  begin
1489
    with (FOwnerBaseSceneObject as TGLBaseMesh) do
1490
    begin
1491

1492
      // Iterate trough mesh of GLobject
1493
      for I := 0 to MeshObjects.Count - 1 do
1494
      begin
1495
        // Iterate trough vertices of mesh
1496
        for J := 0 to MeshObjects[I].Vertices.Count - 1 do
1497
        begin
1498
          SetLength(vertexArray, Length(vertexArray) + 1);
1499
          vertexArray[Length(vertexArray) - 1] := MeshObjects[I].Vertices[J];
1500
        end;
1501

1502
        if Length(vertexArray) > 3 then
1503
        begin
1504
          SetLength(collisionArray, Length(collisionArray) + 1);
1505

1506
          collisionArray[Length(collisionArray) - 1] := NewtonCreateConvexHull
1507
            (FManager.FNewtonWorld, Length(vertexArray), @vertexArray[0],
1508
            SizeOf(TVertex), FConvexCollisionTolerance, 0, nil);
1509

1510
          // Remove last collision if the newton function was not successful
1511
          if collisionArray[Length(collisionArray) - 1] = nil then
1512
            SetLength(collisionArray, Length(collisionArray) - 1);
1513

1514
        end;
1515
        SetLength(vertexArray, 0);
1516
      end;
1517

1518
      //if Length(collisionArray) > 0 then
1519
      //  Result := NewtonCreateCompoundCollision(FManager.FNewtonWorld,
1520
      //    Length(collisionArray), TCollisionPrimitiveArray(@collisionArray[0]), 0)
1521
      //else
1522
      //  Result := GetNullCollision;
1523
      //
1524
    end;
1525
  end
1526
  else
1527
    Result := GetNullCollision;
1528
end;
1529

1530

1531
function TGLNGDBehaviour.GetNewtonBodyMatrix: TMatrix;
1532
begin
1533
  if Assigned(FManager) then
1534
    NewtonBodyGetmatrix(FNewtonBody, @FNewtonBodyMatrix);
1535
  Result := FNewtonBodyMatrix;
1536
end;
1537

1538
function TGLNGDBehaviour.GetNewtonBodyAABB: TAABB;
1539
begin
1540
  if Assigned(FManager) then
1541
    NewtonBodyGetAABB(FNewtonBody, @(Result.min), @(Result.max));
1542
end;
1543

1544
function TGLNGDBehaviour.GetNGDFileCollision: NewtonCollision;
1545
var
1546
  MyFile: TFileStream;
1547
begin
1548

1549
  if FileExists(FFileCollision) then
1550
  begin
1551
    MyFile := TFileStream.Create(FFileCollision, fmOpenRead);
1552
    Result := NewtonCreateCollisionFromSerialization(FManager.FNewtonWorld,
1553
      @TGLNGDBehaviour.NewtonDeserialize, Pointer(MyFile));
1554
    MyFile.Free;
1555
  end
1556
  else
1557
    Result := NewtonCreateNull(FManager.FNewtonWorld);
1558
end;
1559

1560
function TGLNGDBehaviour.GetNullCollision: NewtonCollision;
1561
begin
1562
  Result := NewtonCreateNull(FManager.FNewtonWorld);
1563
end;
1564

1565
function TGLNGDBehaviour.GetPrimitiveCollision: NewtonCollision;
1566
var
1567
  collisionOffsetMatrix: TMatrix; // For cone capsule and cylinder
1568
begin
1569
  collisionOffsetMatrix := IdentityHmgMatrix;
1570

1571
  if (FOwnerBaseSceneObject is TGLCube) then
1572
  begin
1573
    with (FOwnerBaseSceneObject as TGLCube) do
1574
      Result := NewtonCreateBox(FManager.FNewtonWorld, CubeWidth, CubeHeight,
1575
        CubeDepth, 0, @collisionOffsetMatrix);
1576
  end
1577

1578
  else if (FOwnerBaseSceneObject is TGLSphere) then
1579
  begin
1580
    with (FOwnerBaseSceneObject as TGLSphere) do
1581
      Result := NewtonCreateSphere(FManager.FNewtonWorld, Radius, 0, @collisionOffsetMatrix);
1582
  end
1583

1584
  else if (FOwnerBaseSceneObject is TGLCone) then
1585
  begin
1586
    collisionOffsetMatrix := MatrixMultiply(collisionOffsetMatrix,
1587
      CreateRotationMatrixZ(Pi / 2.0));
1588
    with (FOwnerBaseSceneObject as TGLCone) do
1589
      Result := NewtonCreateCone(FManager.FNewtonWorld, BottomRadius, Height,
1590
        0, @collisionOffsetMatrix);
1591
  end
1592

1593
  else if (FOwnerBaseSceneObject is TGLCapsule) then
1594
  begin
1595
    collisionOffsetMatrix := MatrixMultiply(collisionOffsetMatrix,
1596
      CreateRotationMatrixY(Pi / 2.0));
1597
    with (FOwnerBaseSceneObject as TGLCapsule) do
1598
      // Use Cylinder shape for buoyancy
1599
      Result := NewtonCreateCapsule(FManager.FNewtonWorld, Radius,
1600
        Height + 2 * Radius,height, 0, @collisionOffsetMatrix);
1601
  end
1602

1603
  else if (FOwnerBaseSceneObject is TGLCylinder) then
1604
  begin
1605
    collisionOffsetMatrix := MatrixMultiply(collisionOffsetMatrix,
1606
      CreateRotationMatrixZ(Pi / 2.0));
1607
    with (FOwnerBaseSceneObject as TGLCylinder) do
1608
      Result := NewtonCreateCylinder(FManager.FNewtonWorld, TopRadius, BottomRadius,
1609
        Height, 0, @collisionOffsetMatrix);
1610
  end
1611
  else
1612
    Result := GetNullCollision;
1613
end;
1614

1615
function TGLNGDBehaviour.GetTreeCollision: NewtonCollision;
1616
var
1617
  meshIndex, triangleIndex: Integer;
1618
  triangleList: TAffineVectorList;
1619
  v: array [0 .. 2] of TAffineVector;
1620
begin
1621

1622
  if FOwnerBaseSceneObject is TGLBaseMesh then
1623
  begin
1624
    with (FOwnerBaseSceneObject as TGLBaseMesh) do
1625
    begin
1626
      Result := NewtonCreateTreeCollision(FManager.FNewtonWorld, 0);
1627
      NewtonTreeCollisionBeginBuild(Result);
1628

1629
      for meshIndex := 0 to MeshObjects.Count - 1 do
1630
      begin
1631
        triangleList := MeshObjects[meshIndex].ExtractTriangles;
1632
        for triangleIndex := 0 to triangleList.Count - 1 do
1633
        begin
1634
          if triangleIndex mod 3 = 0 then
1635
          begin
1636
            v[0] := triangleList.Items[triangleIndex];
1637
            // ScaleVector(v[0], FOwnerBaseSceneObject.Scale.X);
1638
            v[1] := triangleList.Items[triangleIndex + 1];
1639
            // ScaleVector(v[1], FOwnerBaseSceneObject.Scale.Y);
1640
            v[2] := triangleList.Items[triangleIndex + 2];
1641
            // ScaleVector(v[2], FOwnerBaseSceneObject.Scale.Z);
1642
            NewtonTreeCollisionAddFace(Result, 3, @(v), SizeOf(TAffineVector),
1643
              1);
1644
          end;
1645
        end;
1646
        triangleList.Free;
1647
      end;
1648
      NewtonTreeCollisionEndBuild(Result, Ord(FTreeCollisionOptimize));
1649
    end;
1650
  end
1651
  else
1652
    Result := GetNullCollision;
1653
end;
1654

1655
procedure TGLNGDBehaviour.Initialize;
1656
begin
1657
  FInitialized := True;
1658

1659
  if Assigned(FManager) then
1660
  begin
1661
    // Creates NewtonBody with null collision
1662
    FCollision := NewtonCreateNull(FManager.FNewtonWorld);
1663
    FNewtonBodyMatrix := FOwnerBaseSceneObject.AbsoluteMatrix;
1664
    //FNewtonBody := NewtonCreateBody(FManager.FNewtonWorld, FCollision,
1665
    //  @FNewtonBodyMatrix);
1666
    //
1667
    //// Release NewtonCollision
1668
    //NewtonReleaseCollision(FManager.FNewtonWorld, FCollision);
1669

1670
    // Set Link between glscene and newton
1671
    NewtonBodySetUserdata(FNewtonBody, self);
1672

1673
    // Set position and orientation
1674
    SetNewtonBodyMatrix(FOwnerBaseSceneObject.AbsoluteMatrix);
1675

1676
    // Set Collision
1677
    UpdCollision;
1678
  end;
1679
end;
1680

1681
procedure TGLNGDBehaviour.Loaded;
1682
var
1683
  mng: TComponent;
1684
begin
1685
  inherited;
1686
  if FManagerName <> '' then
1687
  begin
1688
    mng := FindManager(TGLNGDManager, FManagerName);
1689
    if Assigned(mng) then
1690
      Manager := TGLNGDManager(mng);
1691
    FManagerName := '';
1692
  end;
1693

1694
  if Assigned(FManager) then
1695
  begin
1696
    SetContinuousCollisionMode(FContinuousCollisionMode);
1697
  end;
1698
end;
1699

1700
class procedure TGLNGDBehaviour.NewtonCollisionIterator
1701
  (const userData: Pointer; vertexCount: Integer; const faceArray: PNGDFloat;
1702
  faceId: Integer)cdecl;
1703
begin
1704
  TGLNGDBehaviour(userData).FCollisionIteratorEvent(userData, vertexCount,
1705
    faceArray, faceId);
1706
end;
1707

1708
// Serializes are called by NGDBehaviour to save and load collision in file
1709
// It's better to save/load big collisions [over 50000 polygones] to reduce
1710
// loading time
1711
class procedure TGLNGDBehaviour.NewtonDeserialize(serializeHandle,
1712
  buffer: Pointer; size: Cardinal)cdecl;
1713
begin
1714
  TFileStream(serializeHandle).read(buffer^, size);
1715
end;
1716

1717
class procedure TGLNGDBehaviour.NewtonSerialize(serializeHandle: Pointer;
1718
  const buffer: Pointer; size: Cardinal)cdecl;
1719
begin
1720
  TFileStream(serializeHandle).write(buffer^, size);
1721
end;
1722

1723
procedure TGLNGDBehaviour.OnCollisionIteratorEvent(const userData: Pointer;
1724
  vertexCount: Integer; const cfaceArray: PNGDFloat; faceId: Integer);
1725
var
1726
  I: Integer;
1727
  v0, v1: array [0 .. 2] of Single;
1728
  vA: array of Single;
1729
begin
1730
  // This algorithme draw Collision Shape for Debuggin.
1731
  // Taken to Sascha Willems in SDLNewton-Demo at
1732
  // http://www.saschawillems.de/?page_id=82
1733

1734
  // Leave if there is no or to much vertex
1735
  if (vertexCount = 0) then
1736
    exit;
1737

1738
  SetLength(vA, vertexCount * 3);
1739
  Move(cfaceArray^, vA[0], vertexCount * 3 * SizeOf(Single));
1740
  v0[0] := vA[(vertexCount - 1) * 3];
1741
  v0[1] := vA[(vertexCount - 1) * 3 + 1];
1742
  v0[2] := vA[(vertexCount - 1) * 3 + 2];
1743
  for I := 0 to vertexCount - 1 do
1744
  begin
1745
    v1[0] := vA[I * 3];
1746
    v1[1] := vA[I * 3 + 1];
1747
    v1[2] := vA[I * 3 + 2];
1748
    FManager.AddNode(v0[0], v0[1], v0[2]);
1749
    FManager.AddNode(v1[0], v1[1], v1[2]);
1750
    v0 := v1;
1751
  end;
1752
end;
1753

1754
procedure TGLNGDBehaviour.Reinitialize;
1755
begin
1756
  if Initialized then
1757
  begin
1758
    // Set Appropriate NewtonCollision
1759
    UpdCollision();
1760
    // Set position and orientation
1761
    SetNewtonBodyMatrix(FOwnerBaseSceneObject.AbsoluteMatrix);
1762
  end;
1763
  Loaded;
1764
end;
1765

1766
procedure TGLNGDBehaviour.Render;
1767
var
1768
  M: TMatrix;
1769
begin
1770
  // Rebuild collision in design time
1771
  if (csDesigning in FOwnerBaseSceneObject.ComponentState) then
1772
    Reinitialize;
1773

1774
  if self is TGLNGDDynamic then
1775
    FManager.FCurrentColor := FManager.DebugOption.GeomColorDyn
1776
  else
1777
    FManager.FCurrentColor := FManager.DebugOption.GeomColorStat;
1778
  M := FOwnerBaseSceneObject.AbsoluteMatrix;
1779
  if mdShowGeometry in FManager.DebugOption.NGDManagerDebugs then
1780
    NewtonCollisionForEachPolygonDo(FCollision, @M,
1781
      @TGLNGDBehaviour.NewtonCollisionIterator, self);
1782
end;
1783

1784
// In this procedure, we assign collision to body
1785
// [Because when initialised, the collision for body is type NULL]
1786
procedure TGLNGDBehaviour.UpdCollision;
1787
var
1788
  collisionInfoRecord: TNewtonCollisionInfoRecord;
1789
begin
1790

1791
  case FNGDCollisions of
1792
    nc_Primitive:
1793
      FCollision := GetPrimitiveCollision;
1794
    nc_Convex:
1795
      FCollision := GetConvexCollision;
1796
    nc_BBox:
1797
      FCollision := GetBBoxCollision;
1798
    nc_BSphere:
1799
      FCollision := GetBSphereCollision;
1800
    nc_Tree:
1801
      FCollision := GetTreeCollision;
1802
    nc_Mesh:
1803
      FCollision := GetMeshCollision;
1804
    nc_Null:
1805
      FCollision := GetNullCollision;
1806
    nc_HeightField:
1807
      FCollision := GetHeightFieldCollision;
1808
    nc_NGDFile:
1809
      FCollision := GetNGDFileCollision;
1810
  end;
1811

1812
  if Assigned(FCollision) then
1813
  begin
1814
    NewtonBodySetCollision(FNewtonBody, FCollision);
1815

1816
    // The API Ask for releasing Collision to avoid memory leak
1817
    NewtonCollisionGetInfo(FCollision, @collisionInfoRecord);
1818
    //if collisionInfoRecord.m_referenceCount > 2 then
1819
    //  NewtonReleaseCollision(FManager.FNewtonWorld, FCollision);
1820
  end;
1821

1822
end;
1823

1824
procedure TGLNGDBehaviour.SetContinuousCollisionMode(const Value: Boolean);
1825
begin
1826
  // for continue collision to be active the continue collision mode must on
1827
  // the material pair of the colliding bodies as well as on at
1828
  // least one of the two colliding bodies.
1829
  // see NewtonBodySetContinuousCollisionMode
1830
  // see NewtonMaterialSetContinuousCollisionMode
1831
  FContinuousCollisionMode := Value;
1832
  if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
1833
    if Assigned(FManager) then
1834
      NewtonBodySetContinuousCollisionMode(FNewtonBody, Ord(Value));
1835
end;
1836

1837
procedure TGLNGDBehaviour.SetHeightFieldOptions(const Value: TGLNGDHeightField);
1838
begin
1839
  FHeightFieldOptions := Value;
1840
  Reinitialize;
1841
end;
1842

1843
procedure TGLNGDBehaviour.SetManager(Value: TGLNGDManager);
1844
begin
1845
  if FManager <> Value then
1846
  begin
1847
    if Assigned(FManager) then
1848
    begin
1849
      if Initialized then
1850
        Finalize;
1851
      FManager.FNGDBehaviours.Remove(self);
1852
      // FManager.NotifyChange(self);
1853
    end;
1854
    FManager := Value;
1855
    if Assigned(FManager) then
1856
    begin
1857
      Initialize;
1858
      FManager.FNGDBehaviours.Add(self);
1859
      FManager.NotifyChange(self);
1860
    end;
1861
  end;
1862
end;
1863

1864
procedure TGLNGDBehaviour.SetNewtonBodyMatrix(const Value: TMatrix);
1865
begin
1866
  FNewtonBodyMatrix := Value;
1867
  if Assigned(FManager) then
1868
    NewtonBodySetmatrix(FNewtonBody, @FNewtonBodyMatrix);
1869
end;
1870

1871
procedure TGLNGDBehaviour.SetNGDNewtonCollisions
1872
  (const Value: TGLNGDCollisions);
1873
begin
1874
  FNGDCollisions := Value;
1875
  if Assigned(FManager) then
1876
    UpdCollision;
1877
end;
1878

1879
procedure TGLNGDBehaviour.SetNGDSurfaceItem(const Value: TGLNGDSurfaceItem);
1880
begin
1881
  FNGDSurfaceItem := Value;
1882
  FManager.RebuildAllMaterial;
1883
end;
1884

1885
function TGLNGDBehaviour.StoredTolerance: Boolean;
1886
begin
1887
  Result := not SameValue(FConvexCollisionTolerance, 0.01, epsilon);
1888
end;
1889

1890
class function TGLNGDBehaviour.UniqueItem: Boolean;
1891
begin
1892
  Result := True;
1893
end;
1894

1895
procedure TGLNGDBehaviour.ReadFromFiler(reader: TReader);
1896
var
1897
  version: Integer;
1898
begin
1899
  inherited;
1900
  with reader do
1901
  begin
1902
    version := ReadInteger; // read data version
1903
    Assert(version <= 1); // Archive version
1904

1905
    FManagerName := ReadString;
1906
    FContinuousCollisionMode := ReadBoolean;
1907
    read(FNGDCollisions, SizeOf(TGLNGDCollisions));
1908
    FTreeCollisionOptimize := ReadBoolean;
1909
    if version <= 0 then
1910
      FConvexCollisionTolerance := ReadSingle
1911
    else
1912
      FConvexCollisionTolerance := ReadFloat;
1913
    FFileCollision := ReadString;
1914
  end;
1915
end;
1916

1917
procedure TGLNGDBehaviour.WriteToFiler(writer: TWriter);
1918
begin
1919
  inherited;
1920
  with writer do
1921
  begin
1922
    WriteInteger(1); // Archive version
1923
    if Assigned(FManager) then
1924
      WriteString(FManager.GetNamePath)
1925
    else
1926
      WriteString('');
1927
    WriteBoolean(FContinuousCollisionMode);
1928
    write(FNGDCollisions, SizeOf(TGLNGDCollisions));
1929
    WriteBoolean(FTreeCollisionOptimize);
1930
    WriteFloat(FConvexCollisionTolerance);
1931
    WriteString(FFileCollision);
1932
  end;
1933
end;
1934

1935
procedure TGLNGDBehaviour.Serialize(filename: string);
1936
var
1937
  MyFile: TFileStream;
1938
begin
1939
  MyFile := TFileStream.Create(filename, fmCreate or fmOpenReadWrite);
1940

1941
  NewtonCollisionSerialize(FManager.FNewtonWorld, FCollision,
1942
    @TGLNGDBehaviour.NewtonSerialize, Pointer(MyFile));
1943

1944
  MyFile.Free;
1945
end;
1946

1947
procedure TGLNGDBehaviour.DeSerialize(filename: string);
1948
var
1949
  MyFile: TFileStream;
1950
  collisionInfoRecord: TNewtonCollisionInfoRecord;
1951
begin
1952
  MyFile := TFileStream.Create(filename, fmOpenRead);
1953

1954
  FCollision := NewtonCreateCollisionFromSerialization(FManager.FNewtonWorld,
1955
    @TGLNGDBehaviour.NewtonDeserialize, Pointer(MyFile));
1956

1957
  // SetCollision;
1958
  NewtonBodySetCollision(FNewtonBody, FCollision);
1959

1960
  // Release collision
1961
  NewtonCollisionGetInfo(FCollision, @collisionInfoRecord);
1962
  //if collisionInfoRecord.m_referenceCount > 2 then
1963
  //  NewtonReleaseCollision(FManager.FNewtonWorld, FCollision);
1964

1965
  MyFile.Free;
1966
end;
1967

1968
{ TGLNGDDynamic }
1969

1970
procedure TGLNGDDynamic.AddImpulse(const veloc, pointposit: TVector);
1971
begin
1972
  //if Assigned(FNewtonBody) then
1973
  //  NewtonBodyAddImpulse(FNewtonBody, @veloc, @pointposit);
1974
end;
1975

1976
constructor TGLNGDDynamic.Create(AOwner: TGLXCollection);
1977
begin
1978
  inherited;
1979
  FAutoSleep := True;
1980
  FLinearDamping := 0.1;
1981
  FAngularDamping := TGLCoordinates.CreateInitialized(self,
1982
    VectorMake(0.1, 0.1, 0.1, 0), csPoint);
1983
  FAngularDamping.OnNotifyChange := NotifyAngularDampingChange;
1984
  FDensity := 1;
1985
  FVolume := 1;
1986
  FForce := TGLCoordinates.CreateInitialized(self, NullHmgVector, csVector);
1987
  FTorque := TGLCoordinates.CreateInitialized(self, NullHmgVector, csVector);
1988
  FCenterOfMass := TGLCoordinates.CreateInitialized(self, NullHmgVector,
1989
    csPoint);
1990
  FCenterOfMass.OnNotifyChange := NotifyCenterOfMassChange;
1991
  FAABBmin := TGLCoordinates.CreateInitialized(self, NullHmgVector, csPoint);
1992
  FAABBmax := TGLCoordinates.CreateInitialized(self, NullHmgVector, csPoint);
1993
  FAppliedOmega := TGLCoordinates.CreateInitialized(self, NullHmgVector,
1994
    csVector);
1995
  FAppliedVelocity := TGLCoordinates.CreateInitialized(self, NullHmgVector,
1996
    csVector);
1997
  FAppliedForce := TGLCoordinates.CreateInitialized(self, NullHmgVector,
1998
    csVector);
1999
  FAppliedTorque := TGLCoordinates.CreateInitialized(self, NullHmgVector,
2000
    csVector);
2001
  FUseGravity := True;
2002
  FNullCollisionVolume := 0;
2003

2004
  FApplyForceAndTorqueEvent := OnApplyForceAndTorqueEvent;
2005
  FSetTransformEvent := OnSetTransformEvent;
2006
  name := 'NGD Dynamic'
2007
end;
2008

2009
destructor TGLNGDDynamic.Destroy;
2010
begin
2011
  // Clean up everything
2012
  FAngularDamping.Free;
2013
  FForce.Free;
2014
  FTorque.Free;
2015
  FCenterOfMass.Free;
2016
  FAABBmin.Free;
2017
  FAABBmax.Free;
2018
  FAppliedForce.Free;
2019
  FAppliedTorque.Free;
2020
  FAppliedVelocity.Free;
2021
  FAppliedOmega.Free;
2022
  inherited;
2023
end;
2024

2025
procedure TGLNGDDynamic.Finalize;
2026
begin
2027
  if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
2028
    if Assigned(FManager) then
2029
    begin
2030
      // Removing Callback
2031
      NewtonBodySetForceAndTorqueCallback(FNewtonBody, nil);
2032
      NewtonBodySetTransformCallback(FNewtonBody, nil);
2033
    end;
2034
  inherited;
2035
end;
2036

2037
class function TGLNGDDynamic.FriendlyName: string;
2038
begin
2039
  Result := 'NGD Dynamic';
2040
end;
2041

2042

2043
procedure TGLNGDDynamic.Initialize;
2044
begin
2045
  inherited;
2046
  if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
2047
    if Assigned(FManager) then
2048
    begin
2049
      // Set Density, Mass and inertie matrix
2050
      SetDensity(FDensity);
2051

2052
      // Set Callback
2053
      NewtonBodySetForceAndTorqueCallback(FNewtonBody,
2054
        @TGLNGDDynamic.NewtonApplyForceAndTorque);
2055
      NewtonBodySetTransformCallback(FNewtonBody,
2056
        @TGLNGDDynamic.NewtonSetTransform);
2057
    end;
2058
end;
2059

2060
procedure TGLNGDDynamic.Render;
2061

2062
  procedure DrawAABB(min, max: TGLCoordinates3);
2063
  begin
2064

2065
    {
2066
      //    H________G
2067
      //   /.       /|
2068
      //  / .      / |
2069
      // D__._____C  |
2070
      // |  .     |  |
2071
      // | E.-----|--F
2072
      // | .      | /
2073
      // |.       |/
2074
      // A________B
2075
      }
2076
    // Back
2077
    FManager.AddNode(min.X, min.Y, min.Z); // E
2078
    FManager.AddNode(max.X, min.Y, min.Z); // F
2079

2080
    FManager.AddNode(max.X, min.Y, min.Z); // F
2081
    FManager.AddNode(max.X, max.Y, min.Z); // G
2082

2083
    FManager.AddNode(max.X, max.Y, min.Z); // G
2084
    FManager.AddNode(min.X, max.Y, min.Z); // H
2085

2086
    FManager.AddNode(min.X, max.Y, min.Z); // H
2087
    FManager.AddNode(min.X, min.Y, min.Z); // E
2088

2089
    // Front
2090
    FManager.AddNode(min.X, min.Y, max.Z); // A
2091
    FManager.AddNode(max.X, min.Y, max.Z); // B
2092

2093
    FManager.AddNode(max.X, min.Y, max.Z); // B
2094
    FManager.AddNode(max.X, max.Y, max.Z); // C
2095

2096
    FManager.AddNode(max.X, max.Y, max.Z); // C
2097
    FManager.AddNode(min.X, max.Y, max.Z); // D
2098

2099
    FManager.AddNode(min.X, max.Y, max.Z); // D
2100
    FManager.AddNode(min.X, min.Y, max.Z); // A
2101

2102
    // Edges
2103
    FManager.AddNode(min.X, min.Y, max.Z); // A
2104
    FManager.AddNode(min.X, min.Y, min.Z); // E
2105

2106
    FManager.AddNode(max.X, min.Y, max.Z); // B
2107
    FManager.AddNode(max.X, min.Y, min.Z); // F
2108

2109
    FManager.AddNode(max.X, max.Y, max.Z); // C
2110
    FManager.AddNode(max.X, max.Y, min.Z); // G
2111

2112
    FManager.AddNode(min.X, max.Y, max.Z); // D
2113
    FManager.AddNode(min.X, max.Y, min.Z); // H
2114
  end;
2115

2116
  procedure DrawContact;
2117
  var
2118
    cnt: NewtonJoint;
2119
    thisContact: NewtonJoint;
2120
    material: NewtonMaterial;
2121
    pos, nor: TVector;
2122
  begin
2123
    FManager.FCurrentColor := FManager.DebugOption.ContactColor;
2124
    cnt := NewtonBodyGetFirstContactJoint(FNewtonBody);
2125
    while cnt <> nil do
2126
    begin
2127
      thisContact := NewtonContactJointGetFirstContact(cnt);
2128
      while thisContact <> nil do
2129
      begin
2130
        material := NewtonContactGetMaterial(thisContact);
2131
        NewtonMaterialGetContactPositionAndNormal(material, FNewtonBody, @pos, @nor);
2132

2133
        FManager.AddNode(pos);
2134
        nor := VectorAdd(pos, nor);
2135
        FManager.AddNode(nor);
2136

2137
        thisContact := NewtonContactJointGetNextContact(cnt, thisContact);
2138
      end;
2139
      cnt := NewtonBodyGetNextContactJoint(FNewtonBody, cnt);
2140
    end;
2141
  end;
2142

2143
  function GetAbsCom(): TVector;
2144
  var
2145
    M: TMatrix;
2146
  begin
2147
    NewtonBodyGetCentreOfMass(FNewtonBody, @Result);
2148
    M := IdentityHmgMatrix;
2149
    M.W := Result;
2150
    M.W.W := 1;
2151
    M := MatrixMultiply(M, FOwnerBaseSceneObject.AbsoluteMatrix);
2152
    Result := M.W;
2153
  end;
2154

2155
  procedure DrawForce;
2156
  var
2157
    pos: TVector;
2158
    nor: TVector;
2159
  begin
2160
    pos := GetAbsCom;
2161

2162
    if mdShowForce in FManager.DebugOption.NGDManagerDebugs then
2163
    begin
2164
      FManager.FCurrentColor := FManager.DebugOption.ForceColor;
2165
      nor := VectorAdd(pos, FForce.AsVector);
2166
      FManager.AddNode(pos);
2167
      FManager.AddNode(nor);
2168
    end;
2169

2170
    if mdShowAppliedForce in FManager.DebugOption.NGDManagerDebugs then
2171
    begin
2172
      FManager.FCurrentColor := FManager.DebugOption.AppliedForceColor;
2173
      nor := VectorAdd(pos, FAppliedForce.AsVector);
2174
      FManager.AddNode(pos);
2175
      FManager.AddNode(nor);
2176

2177
    end;
2178

2179
    if mdShowAppliedVelocity in FManager.DebugOption.NGDManagerDebugs then
2180
    begin
2181
      FManager.FCurrentColor := FManager.DebugOption.AppliedVelocityColor;
2182
      nor := VectorAdd(pos, FAppliedVelocity.AsVector);
2183
      FManager.AddNode(pos);
2184
      FManager.AddNode(nor);
2185
    end;
2186

2187
  end;
2188

2189
  procedure DrawCoM;
2190
  var
2191
    com: TVector;
2192
    size: Single;
2193
  begin
2194
    FManager.FCurrentColor := FManager.DebugOption.CenterOfMassColor;
2195
    size := FManager.DebugOption.DotAxisSize;
2196
    com := GetAbsCom;
2197
    FManager.AddNode(VectorAdd(com, VectorMake(0, 0, size)));
2198
    FManager.AddNode(VectorAdd(com, VectorMake(0, 0, -size)));
2199
    FManager.AddNode(VectorAdd(com, VectorMake(0, size, 0)));
2200
    FManager.AddNode(VectorAdd(com, VectorMake(0, -size, 0)));
2201
    FManager.AddNode(VectorAdd(com, VectorMake(size, 0, 0)));
2202
    FManager.AddNode(VectorAdd(com, VectorMake(-size, 0, 0)));
2203
  end;
2204

2205
begin
2206
  inherited;
2207

2208
  // Move/Rotate NewtonObject if matrix are not equal in design time.
2209
  if (csDesigning in FOwnerBaseSceneObject.ComponentState) then
2210
    if not MatrixEquals(NewtonBodyMatrix, FOwnerBaseSceneObject.AbsoluteMatrix)
2211
      then
2212
      SetNewtonBodyMatrix(FOwnerBaseSceneObject.AbsoluteMatrix);
2213

2214
  NewtonBodyGetAABB(FNewtonBody, @(FAABBmin.AsVector), @(FAABBmax.AsVector));
2215

2216
  if NewtonBodyGetSleepState(FNewtonBody) = 1 then
2217
    FManager.FCurrentColor := FManager.DebugOption.AABBColorSleep
2218
  else
2219
    FManager.FCurrentColor := FManager.DebugOption.AABBColor;
2220

2221
  if mdShowAABB in FManager.DebugOption.NGDManagerDebugs then
2222
    DrawAABB(FAABBmin, FAABBmax);
2223

2224
  if mdShowContact in FManager.DebugOption.NGDManagerDebugs then
2225
    DrawContact;
2226

2227
  DrawForce; // Draw Force, AppliedForce and AppliedVelocity
2228

2229
  if mdShowCenterOfMass in FManager.DebugOption.NGDManagerDebugs then
2230
    DrawCoM;
2231
end;
2232

2233
procedure TGLNGDDynamic.SetAutoSleep(const Value: Boolean);
2234
begin
2235
  FAutoSleep := Value;
2236
  if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
2237
    if Assigned(FManager) then
2238
      NewtonBodySetAutoSleep(FNewtonBody, Ord(FAutoSleep));
2239
end;
2240

2241
procedure TGLNGDDynamic.SetDensity(const Value: Single);
2242
var
2243
  inertia: TVector;
2244
  origin: TVector;
2245
begin
2246
  if Assigned(FManager) then
2247
    if Value >= 0 then
2248
    begin
2249
      FDensity := Value;
2250

2251
      FVolume := NewtonConvexCollisionCalculateVolume(FCollision);
2252
      NewtonConvexCollisionCalculateInertialMatrix(FCollision, @inertia,
2253
        @origin);
2254

2255
      if IsZero(FVolume, epsilon) then
2256
      begin
2257
        FVolume := FNullCollisionVolume;
2258
        inertia := VectorMake(FNullCollisionVolume, FNullCollisionVolume,
2259
          FNullCollisionVolume, 0);
2260
      end;
2261

2262
      FMass := FVolume * FDensity;
2263

2264
      if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
2265
        NewtonBodySetMassMatrix(FNewtonBody, FMass, FMass * inertia.X,
2266
          FMass * inertia.Y, FMass * inertia.Z);
2267

2268
      FCenterOfMass.AsVector := origin;
2269
    end;
2270
end;
2271

2272
procedure TGLNGDDynamic.SetLinearDamping(const Value: Single);
2273
begin
2274
  if (Value >= 0) and (Value <= 1) then
2275
    FLinearDamping := Value;
2276
  if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
2277
    if Assigned(FManager) then
2278
      NewtonBodySetLinearDamping(FNewtonBody, FLinearDamping);
2279
end;
2280

2281
function TGLNGDDynamic.GetOmega: TVector;
2282
begin
2283
  NewtonBodyGetOmega(FNewtonBody, @Result);
2284
end;
2285

2286
procedure TGLNGDDynamic.SetOmega(const Omega: TVector);
2287
begin
2288
  NewtonBodySetOmega(FNewtonBody, @Omega);
2289
end;
2290

2291
function TGLNGDDynamic.GetVelocity: TVector;
2292
begin
2293
  NewtonBodyGetVelocity(FNewtonBody, @Result);
2294
end;
2295

2296
procedure TGLNGDDynamic.SetVelocity(const Velocity: TVector);
2297
begin
2298
  NewtonBodySetVelocity(FNewtonBody, @Velocity);
2299
end;
2300

2301
function TGLNGDDynamic.StoredDensity: Boolean;
2302
begin
2303
  Result := not SameValue(FDensity, 1, epsilon);
2304
end;
2305

2306
function TGLNGDDynamic.StoredLinearDamping: Boolean;
2307
begin
2308
  Result := not SameValue(FLinearDamping, 0.1, epsilon);
2309
end;
2310

2311
function TGLNGDDynamic.StoredNullCollisionVolume: Boolean;
2312
begin
2313
  Result := not SameValue(FNullCollisionVolume, 0, epsilon);
2314
end;
2315

2316
procedure TGLNGDDynamic.WriteToFiler(writer: TWriter);
2317
begin
2318
  inherited;
2319
  with writer do
2320
  begin
2321
    WriteInteger(1); // Archive version
2322
    WriteBoolean(FAutoSleep);
2323
    WriteFloat(FLinearDamping);
2324
    WriteFloat(FDensity);
2325
    WriteBoolean(FUseGravity);
2326
    WriteFloat(FNullCollisionVolume);
2327
  end;
2328
  FForce.WriteToFiler(writer);
2329
  FTorque.WriteToFiler(writer);
2330
  FCenterOfMass.WriteToFiler(writer);
2331
  FAngularDamping.WriteToFiler(writer);
2332
end;
2333

2334
procedure TGLNGDDynamic.ReadFromFiler(reader: TReader);
2335
var
2336
  version: Integer;
2337
begin
2338
  inherited;
2339
  with reader do
2340
  begin
2341
    version := ReadInteger; // read data version
2342
    Assert(version <= 1); // Archive version
2343

2344
    FAutoSleep := ReadBoolean;
2345
    if version <= 0 then
2346
      FLinearDamping := ReadSingle
2347
    else
2348
      FLinearDamping := ReadFloat;
2349
    if version <= 0 then
2350
      FDensity := ReadSingle
2351
    else
2352
      FDensity := ReadFloat;
2353

2354
    // if Version >= 1 then
2355
    FUseGravity := ReadBoolean;
2356

2357
    if version <= 0 then
2358
      FNullCollisionVolume := ReadSingle
2359
    else
2360
      FNullCollisionVolume := ReadFloat;
2361

2362
  end;
2363
  FForce.ReadFromFiler(reader);
2364
  FTorque.ReadFromFiler(reader);
2365
  FCenterOfMass.ReadFromFiler(reader);
2366
  FAngularDamping.ReadFromFiler(reader);
2367
end;
2368

2369
procedure TGLNGDDynamic.Loaded;
2370
begin
2371
  inherited;
2372
  if Assigned(FManager) then
2373
  begin
2374
    SetAutoSleep(FAutoSleep);
2375
    SetLinearDamping(FLinearDamping);
2376
    SetDensity(FDensity);
2377
    NotifyCenterOfMassChange(self);
2378
    NotifyAngularDampingChange(self);
2379
  end;
2380
end;
2381

2382
class procedure TGLNGDDynamic.NewtonApplyForceAndTorque
2383
  (const body: NewtonBody; timestep: NGDFloat; threadIndex: Integer); cdecl;
2384
begin
2385
  TGLNGDDynamic(NewtonBodyGetUserData(body)).FApplyForceAndTorqueEvent(body,
2386
    timestep, threadIndex);
2387
end;
2388

2389
class procedure TGLNGDDynamic.NewtonSetTransform(const body: NewtonBody;
2390
  const matrix: PNGDFloat; threadIndex: Integer); cdecl;
2391
begin
2392
  TGLNGDDynamic(NewtonBodyGetUserData(body)).FSetTransformEvent(body, matrix,
2393
    threadIndex);
2394
end;
2395

2396
procedure TGLNGDDynamic.NotifyAngularDampingChange(Sender: TObject);
2397
begin
2398
  FAngularDamping.OnNotifyChange := nil;
2399
  if (FAngularDamping.X >= 0) and (FAngularDamping.X <= 1) and
2400
    (FAngularDamping.Y >= 0) and (FAngularDamping.Y <= 1) and
2401
    (FAngularDamping.Z >= 0) and (FAngularDamping.Z <= 1) then
2402
    if Assigned(FManager) then
2403
      NewtonBodySetAngularDamping(FNewtonBody, @(FAngularDamping.AsVector));
2404
  FAngularDamping.OnNotifyChange := NotifyAngularDampingChange;
2405
end;
2406

2407
procedure TGLNGDDynamic.NotifyCenterOfMassChange(Sender: TObject);
2408
begin
2409
  FCenterOfMass.OnNotifyChange := nil;
2410
  if Assigned(FManager) then
2411
    NewtonBodySetCentreOfMass(FNewtonBody, @(FCenterOfMass.AsVector));
2412
  FCenterOfMass.OnNotifyChange := NotifyCenterOfMassChange;
2413
end;
2414

2415
procedure TGLNGDDynamic.OnApplyForceAndTorqueEvent(const cbody: NewtonBody;
2416
  timestep: NGDFloat; threadIndex: Integer);
2417
var
2418
  worldGravity: TVector;
2419
begin
2420

2421
  // Read Only: We get the force and torque resulting from every interaction on this body
2422
  NewtonBodyGetForce(cbody, @(FAppliedForce.AsVector));
2423
  NewtonBodyGetTorque(cbody, @(FAppliedTorque.AsVector));
2424

2425
  NewtonBodyGetVelocity(cbody, @(FAppliedVelocity.AsVector));
2426
  NewtonBodyGetOmega(cbody, @(FAppliedOmega.AsVector));
2427

2428
  // Raise Custom event
2429
  if Assigned(FCustomForceAndTorqueEvent) then
2430
    FCustomForceAndTorqueEvent(cbody, timestep, threadIndex)
2431
  else
2432
  begin
2433
    NewtonBodySetForce(cbody, @(Force.AsVector));
2434
    NewtonBodySetTorque(cbody, @(Torque.AsVector));
2435

2436
    // Add Gravity from World
2437
    if FUseGravity then
2438
    begin
2439
      worldGravity := VectorScale(FManager.Gravity.AsVector, FMass);
2440
      NewtonBodyAddForce(cbody, @(worldGravity));
2441
    end;
2442
  end;
2443

2444
end;
2445

2446
procedure TGLNGDDynamic.OnSetTransformEvent(const cbody: NewtonBody;
2447
  const cmatrix: PNGDFloat; threadIndex: Integer);
2448
var
2449
  epsi: Single;
2450
begin
2451
  // The Newton API does not support scale [scale modifie value in matrix],
2452
  // so this line reset scale of the glsceneObject to (1,1,1)
2453
  // to avoid crashing the application
2454
  epsi := 0.0001;
2455
  with FOwnerBaseSceneObject do
2456
    if not SameValue(Scale.X, 1.0, epsi) or not SameValue(Scale.Y, 1.0, epsi)
2457
      or not SameValue(Scale.Z, 1.0, epsi) then
2458
    begin
2459
      Scale.SetVector(1, 1, 1);
2460
      SetNewtonBodyMatrix(AbsoluteMatrix);
2461
    end
2462
    else
2463
      // Make the Position and orientation of the glscene-Object relative to the
2464
      // NewtonBody position and orientation.
2465
      FOwnerBaseSceneObject.AbsoluteMatrix := pMatrix(cmatrix)^;
2466
end;
2467

2468
//------------------------
2469
// TGLNGDStatic
2470
//------------------------
2471

2472
procedure TGLNGDStatic.Render;
2473
begin
2474
  inherited;
2475
  // Move/Rotate NewtonObject if matrix are not equal in run time.
2476
  if not MatrixEquals(NewtonBodyMatrix, FOwnerBaseSceneObject.AbsoluteMatrix)
2477
    then
2478
    SetNewtonBodyMatrix(FOwnerBaseSceneObject.AbsoluteMatrix);
2479

2480
end;
2481

2482
class function TGLNGDStatic.FriendlyName: string;
2483
begin
2484
  Result := 'NGD Static';
2485
end;
2486

2487
//------------------------
2488
// TGLNGDSurfaceItem
2489
//------------------------
2490

2491
function TGLNGDSurfaceItem.GetDisplayName: string;
2492
begin
2493
  if FDisplayName = '' then
2494
    FDisplayName := 'Iron';
2495
  Result := FDisplayName;
2496
end;
2497

2498
procedure TGLNGDSurfaceItem.SetDisplayName(const Value: string);
2499
begin
2500
  inherited;
2501
  FDisplayName := Value;
2502
end;
2503

2504
//------------------------
2505
{ TGLNGDSurfacePair }
2506
//------------------------
2507

2508
constructor TGLNGDSurfacePair.Create(Collection: TCollection);
2509
begin
2510
  inherited;
2511
  FSoftness := 0.1;
2512
  FElasticity := 0.4;
2513
  FCollidable := True;
2514
  FStaticFriction := 0.9;
2515
  FKineticFriction := 0.5;
2516
  FContinuousCollisionMode := False;
2517
  FThickness := False;
2518

2519
  FAABBOverlapEvent := OnNewtonAABBOverlapEvent;
2520
  FContactProcessEvent := OnNewtonContactsProcessEvent;
2521
  FManager := TGLNGDManager(Collection.Owner);
2522
  FManager.RebuildAllMaterial;
2523
end;
2524

2525
class function TGLNGDSurfacePair.NewtonAABBOverlap
2526
  (const material: NewtonMaterial;
2527
  const body0, body1: NewtonBody; threadIndex: Integer): Integer; cdecl;
2528
begin
2529
  Result := Ord(TGLNGDSurfacePair(NewtonMaterialGetMaterialPairUserData(material))
2530
      .FAABBOverlapEvent(material, body0, body1, threadIndex));
2531
end;
2532

2533
class procedure TGLNGDSurfacePair.NewtonContactsProcess
2534
  (const contact: NewtonJoint; timestep: NGDFloat; threadIndex: Integer);
2535
  cdecl;
2536
begin
2537
  TGLNGDSurfacePair(NewtonMaterialGetMaterialPairUserData
2538
   (NewtonContactGetMaterial
2539
     (NewtonContactJointGetFirstContact(contact)))).FContactProcessEvent
2540
	    (contact, timestep, threadIndex);
2541
end;
2542

2543
function TGLNGDSurfacePair.OnNewtonAABBOverlapEvent
2544
  (const cmaterial: NewtonMaterial; const cbody0, cbody1: NewtonBody;
2545
  threadIndex: Integer): Boolean;
2546
begin
2547
  Result := True;
2548
end;
2549

2550
procedure TGLNGDSurfacePair.OnNewtonContactsProcessEvent
2551
  (const ccontact: NewtonJoint; timestep: NGDFloat; threadIndex: Integer);
2552
begin
2553

2554
end;
2555

2556
procedure TGLNGDSurfacePair.SetCollidable(const Value: Boolean);
2557
begin
2558
  FCollidable := Value;
2559
  FManager.RebuildAllMaterial;
2560
end;
2561

2562
procedure TGLNGDSurfacePair.SetContinuousCollisionMode(const Value: Boolean);
2563
begin
2564
  FContinuousCollisionMode := Value;
2565
  FManager.RebuildAllMaterial;
2566
end;
2567

2568
procedure TGLNGDSurfacePair.SetElasticity(const Value: Single);
2569
begin
2570
  if (Value >= 0) then
2571
    FElasticity := Value;
2572
  FManager.RebuildAllMaterial;
2573
end;
2574

2575
procedure TGLNGDSurfacePair.SetKineticFriction(const Value: Single);
2576
begin
2577
  if (Value >= 0) and (Value <= 1) then
2578
    FKineticFriction := Value;
2579
  FManager.RebuildAllMaterial;
2580
end;
2581

2582
procedure TGLNGDSurfacePair.SetMaterialItems(const item1, item2: TGLNGDSurfaceItem);
2583
begin
2584
  FNGDSurfaceItem1 := item1;
2585
  FNGDSurfaceItem2 := item2;
2586
  FManager.RebuildAllMaterial;
2587
end;
2588

2589
procedure TGLNGDSurfacePair.SetSoftness(const Value: Single);
2590
begin
2591
  if (Value >= 0) and (Value <= 1) then
2592
    FSoftness := Value;
2593
  FManager.RebuildAllMaterial;
2594
end;
2595

2596
procedure TGLNGDSurfacePair.SetStaticFriction(const Value: Single);
2597
begin
2598
  if (Value >= 0) and (Value <= 1) then
2599
    FStaticFriction := Value;
2600
  FManager.RebuildAllMaterial;
2601
end;
2602

2603
procedure TGLNGDSurfacePair.SetThickness(const Value: Boolean);
2604
begin
2605
  FThickness := Value;
2606
  FManager.RebuildAllMaterial;
2607
end;
2608

2609
function TGLNGDSurfacePair.StoredElasticity: Boolean;
2610
begin
2611
  Result := not SameValue(FElasticity, 0.4, epsilon);
2612
end;
2613

2614
function TGLNGDSurfacePair.StoredKineticFriction: Boolean;
2615
begin
2616
  Result := not SameValue(FKineticFriction, 0.5, epsilon);
2617
end;
2618

2619
function TGLNGDSurfacePair.StoredSoftness: Boolean;
2620
begin
2621
  Result := not SameValue(FSoftness, 0.1, epsilon);
2622
end;
2623

2624
function TGLNGDSurfacePair.StoredStaticFriction: Boolean;
2625
begin
2626
  Result := not SameValue(FStaticFriction, 0.9, epsilon);
2627
end;
2628

2629
//------------------------
2630
{ TGLNGDJoint }
2631
//------------------------
2632

2633
constructor TGLNGDJoint.Create(Collection: TCollection);
2634
begin
2635
  inherited;
2636
  FCollisionState := False;
2637
  FStiffness := 0.9;
2638
  FNewtonJoint := nil;
2639
  FNewtonUserJoint := nil;
2640
  FParentObject := nil;
2641
  FChildObject := nil;
2642

2643
  FManager := TGLNGDManager(Collection.Owner);
2644

2645
  FBallAndSocketOptions := TGLNGDJointPivot.Create(FManager, self);
2646
  FHingeOptions := TGLNGDJointPin.Create(FManager, self);
2647
  FSliderOptions := TGLNGDJointPin.Create(FManager, self);
2648
  FCorkscrewOptions := TGLNGDJointPin.Create(FManager, self);
2649
  FUniversalOptions := TGLNGDJointPin2.Create(FManager, self);
2650

2651
  FCustomBallAndSocketOptions := TGLNGDJointBallAndSocket.Create(FManager, self);
2652
  FCustomHingeOptions := TGLNGDJointHinge.Create(FManager, self);
2653
  FCustomSliderOptions := TGLNGDJointSlider.Create(FManager, self);
2654
  FKinematicOptions := TGLNGDJointKinematicController.Create;
2655

2656
  FUPVectorDirection := TGLCoordinates.CreateInitialized(self, YHmgVector,
2657
    csVector);
2658
  FUPVectorDirection.OnNotifyChange := FManager.RebuildAllJoint;
2659
end;
2660

2661
destructor TGLNGDJoint.Destroy;
2662
begin
2663
  DestroyNewtonData;
2664

2665
  FParentObject := nil;
2666
  FChildObject := nil;
2667

2668
  // Free options
2669
  FBallAndSocketOptions.Free;
2670
  FHingeOptions.Free;
2671
  FSliderOptions.Free;
2672
  FCorkscrewOptions.Free;
2673
  FUniversalOptions.Free;
2674

2675
  FCustomBallAndSocketOptions.Free;
2676
  FCustomHingeOptions.Free;
2677
  FCustomSliderOptions.Free;
2678
  FKinematicOptions.Free;
2679
  FUPVectorDirection.Free;
2680
  inherited;
2681
end;
2682

2683
procedure TGLNGDJoint.DestroyNewtonData;
2684
begin
2685
  if FNewtonJoint <> nil then
2686
  begin
2687
    Assert((FManager <> nil) and (FManager.FNewtonWorld <> nil));
2688
    NewtonDestroyJoint(FManager.FNewtonWorld, FNewtonJoint);
2689
    FNewtonJoint := nil;
2690
  end;
2691
  if FNewtonUserJoint <> nil then
2692
  begin
2693
   // CustomDestroyJoint(FNewtonUserJoint);
2694
    FNewtonUserJoint := nil;
2695
  end;
2696
end;
2697

2698
procedure TGLNGDJoint.KinematicControllerPick(pickpoint: TVector;
2699
  PickedActions: TGLNGDPickedActions);
2700
begin
2701
  if FJointType = nj_KinematicController then
2702
    if Assigned(FParentObject) then
2703
    begin
2704
      // Creates the joint
2705
      if PickedActions = paAttach then
2706
      begin
2707
        //if not Assigned(FNewtonUserJoint) then
2708
        //  if Assigned(GetNGDDynamic(FParentObject).FNewtonBody) then
2709
        //    FNewtonUserJoint := CreateCustomKinematicController
2710
        //      (GetNGDDynamic(FParentObject).FNewtonBody, @pickpoint);
2711
      end;
2712

2713
      // Change the TargetPoint
2714
      if (PickedActions = paMove) or (PickedActions = paAttach) then
2715
      begin
2716
        if Assigned(FNewtonUserJoint) then
2717
        begin
2718
          //CustomKinematicControllerSetPickMode(FNewtonUserJoint,
2719
          //  Ord(FKinematicOptions.FPickModeLinear));
2720
          //CustomKinematicControllerSetMaxLinearFriction(FNewtonUserJoint,
2721
          //  FKinematicOptions.FLinearFriction);
2722
          //CustomKinematicControllerSetMaxAngularFriction(FNewtonUserJoint,
2723
          //  FKinematicOptions.FAngularFriction);
2724
          //CustomKinematicControllerSetTargetPosit(FNewtonUserJoint, @pickpoint);
2725
        end;
2726
      end;
2727

2728
      // Delete the joint
2729
      if PickedActions = paDetach then
2730
      begin
2731
        if Assigned(FNewtonUserJoint) then
2732
        begin
2733
          //CustomDestroyJoint(FNewtonUserJoint);
2734
          FNewtonUserJoint := nil;
2735
          // Reset autosleep because this joint turns it off
2736
          NewtonBodySetAutoSleep(GetNGDDynamic(FParentObject).FNewtonBody,
2737
            Ord(GetNGDDynamic(FParentObject).AutoSleep));
2738
        end;
2739
        ParentObject := nil;
2740
      end;
2741
    end;
2742
end;
2743

2744
procedure TGLNGDJoint.Render;
2745

2746
  procedure DrawPivot(pivot: TVector);
2747
  var
2748
    size: Single;
2749
  begin
2750
    size := FManager.DebugOption.DotAxisSize;
2751
    FManager.FCurrentColor := FManager.DebugOption.JointPivotColor;
2752
    FManager.AddNode(VectorAdd(pivot, VectorMake(0, 0, size)));
2753
    FManager.AddNode(VectorAdd(pivot, VectorMake(0, 0, -size)));
2754
    FManager.AddNode(VectorAdd(pivot, VectorMake(0, size, 0)));
2755
    FManager.AddNode(VectorAdd(pivot, VectorMake(0, -size, 0)));
2756
    FManager.AddNode(VectorAdd(pivot, VectorMake(size, 0, 0)));
2757
    FManager.AddNode(VectorAdd(pivot, VectorMake(-size, 0, 0)));
2758
  end;
2759

2760
  procedure DrawPin(pin, pivot: TVector);
2761
  begin
2762
    FManager.FCurrentColor := FManager.DebugOption.JointAxisColor;
2763
    FManager.AddNode(VectorAdd(pivot, pin));
2764
    FManager.AddNode(VectorAdd(pivot, VectorNegate(pin)));
2765
  end;
2766

2767
  procedure DrawJoint(pivot: TVector);
2768
  begin
2769
    FManager.FCurrentColor := FManager.DebugOption.CustomColor;
2770
    FManager.AddNode(FParentObject.AbsolutePosition);
2771
    FManager.AddNode(pivot);
2772
    FManager.AddNode(pivot);
2773
    FManager.AddNode(FChildObject.AbsolutePosition);
2774
  end;
2775

2776
  procedure DrawKinematic;
2777
  var
2778
    pickedMatrix: TMatrix;
2779
    size: Single;
2780
  begin
2781
    size := FManager.DebugOption.DotAxisSize;
2782
    //CustomKinematicControllerGetTargetMatrix(FNewtonUserJoint, @pickedMatrix);
2783
    FManager.FCurrentColor := FManager.DebugOption.JointAxisColor;
2784

2785
    FManager.AddNode(FParentObject.AbsolutePosition);
2786
    FManager.AddNode(pickedMatrix.W);
2787

2788
    FManager.FCurrentColor := FManager.DebugOption.JointPivotColor;
2789
    FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(0, 0, size)));
2790
    FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(0, 0, -size)));
2791
    FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(0, size, 0)));
2792
    FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(0, -size, 0)));
2793
    FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(size, 0, 0)));
2794
    FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(-size, 0, 0)));
2795

2796
  end;
2797

2798
begin
2799

2800
  case FJointType of
2801
    nj_BallAndSocket:
2802
      if Assigned(FParentObject) and Assigned(FChildObject) then
2803
      begin
2804
        DrawJoint(FBallAndSocketOptions.FPivotPoint.AsVector);
2805
        DrawPivot(FBallAndSocketOptions.FPivotPoint.AsVector);
2806
      end;
2807

2808
    nj_Hinge:
2809
      if Assigned(FParentObject) and Assigned(FChildObject) then
2810
      begin
2811
        DrawJoint(FHingeOptions.FPivotPoint.AsVector);
2812
        DrawPin(FHingeOptions.FPinDirection.AsVector,
2813
          FHingeOptions.FPivotPoint.AsVector);
2814
        DrawPivot(FHingeOptions.FPivotPoint.AsVector);
2815
      end;
2816

2817
    nj_Slider:
2818
      if Assigned(FParentObject) and Assigned(FChildObject) then
2819
      begin
2820
        DrawJoint(FSliderOptions.FPivotPoint.AsVector);
2821
        DrawPin(FSliderOptions.FPinDirection.AsVector,
2822
          FSliderOptions.FPivotPoint.AsVector);
2823
        DrawPivot(FSliderOptions.FPivotPoint.AsVector);
2824
      end;
2825

2826
    nj_Corkscrew:
2827
      if Assigned(FParentObject) and Assigned(FChildObject) then
2828
      begin
2829
        DrawJoint(FCorkscrewOptions.FPivotPoint.AsVector);
2830
        DrawPin(FCorkscrewOptions.FPinDirection.AsVector,
2831
          FCorkscrewOptions.FPivotPoint.AsVector);
2832
        DrawPivot(FCorkscrewOptions.FPivotPoint.AsVector);
2833
      end;
2834

2835
    nj_Universal:
2836
      if Assigned(FParentObject) and Assigned(FChildObject) then
2837
      begin
2838
        DrawJoint(FUniversalOptions.FPivotPoint.AsVector);
2839
        DrawPin(FUniversalOptions.FPinDirection.AsVector,
2840
          FUniversalOptions.FPivotPoint.AsVector);
2841
        DrawPin(FUniversalOptions.FPinDirection2.AsVector,
2842
          FUniversalOptions.FPivotPoint.AsVector);
2843
        DrawPivot(FUniversalOptions.FPivotPoint.AsVector);
2844
      end;
2845

2846
    nj_CustomBallAndSocket:
2847
      if Assigned(FParentObject) and Assigned(FChildObject) then
2848
      begin
2849
        DrawJoint(FCustomBallAndSocketOptions.FPivotPoint.AsVector);
2850
        DrawPivot(FCustomBallAndSocketOptions.FPivotPoint.AsVector);
2851
      end;
2852

2853
    nj_CustomHinge:
2854
      if Assigned(FParentObject) and Assigned(FChildObject) then
2855
      begin
2856
        DrawJoint(FCustomHingeOptions.FPivotPoint.AsVector);
2857
        DrawPin(FCustomHingeOptions.FPinDirection.AsVector,
2858
          FCustomHingeOptions.FPivotPoint.AsVector);
2859
        DrawPivot(FCustomHingeOptions.FPivotPoint.AsVector);
2860
      end;
2861

2862
    nj_CustomSlider:
2863
      if Assigned(FParentObject) and Assigned(FChildObject) then
2864
      begin
2865
        DrawJoint(FCustomSliderOptions.FPivotPoint.AsVector);
2866
        DrawPin(FCustomSliderOptions.FPinDirection.AsVector,
2867
          FCustomSliderOptions.FPivotPoint.AsVector);
2868
        DrawPivot(FCustomSliderOptions.FPivotPoint.AsVector);
2869
      end;
2870

2871
    nj_UpVector:
2872
      if Assigned(FParentObject) then
2873
      begin // special
2874
        FManager.FCurrentColor := FManager.DebugOption.JointAxisColor;
2875
        FManager.AddNode(FParentObject.AbsolutePosition);
2876
        FManager.AddNode(VectorAdd(FParentObject.AbsolutePosition,
2877
            FUPVectorDirection.AsVector));
2878
      end;
2879

2880
    nj_KinematicController:
2881
      if Assigned(FParentObject) and Assigned(FNewtonUserJoint) then
2882
      begin // special
2883
        DrawKinematic;
2884
      end;
2885

2886
  end;
2887
end;
2888

2889
procedure TGLNGDJoint.SetChildObject(const Value: TGLBaseSceneObject);
2890
begin
2891
  FChildObject := Value;
2892
  FManager.RebuildAllJoint(self);
2893
end;
2894

2895
procedure TGLNGDJoint.SetCollisionState(const Value: Boolean);
2896
begin
2897
  FCollisionState := Value;
2898
  FManager.RebuildAllJoint(self);
2899
end;
2900

2901
procedure TGLNGDJoint.SetJointType(const Value: TGLNGDJoints);
2902
begin
2903
  FJointType := Value;
2904
  FManager.RebuildAllJoint(self);
2905
end;
2906

2907
procedure TGLNGDJoint.SetParentObject(const Value: TGLBaseSceneObject);
2908
begin
2909
  FParentObject := Value;
2910
  FManager.RebuildAllJoint(self);
2911
end;
2912

2913
procedure TGLNGDJoint.SetStiffness(const Value: Single);
2914
begin
2915
  if (Value >= 0) and (Value <= 1) then
2916
  begin
2917
    FStiffness := Value;
2918
    FManager.RebuildAllJoint(self);
2919
  end;
2920
end;
2921

2922
function TGLNGDJoint.StoredStiffness: Boolean;
2923
begin
2924
  Result := not SameValue(FStiffness, 0.9, epsilon);
2925
end;
2926

2927
//------------------------
2928
{ TGLNGDJointPivot }
2929
//------------------------
2930

2931
constructor TGLNGDJointPivot.Create(AOwner: TComponent; aOuter: TGLNGDJoint);
2932
begin
2933
  FManager := AOwner as TGLNGDManager;
2934
  FOuter := aOuter;
2935
  FPivotPoint := TGLCoordinates.CreateInitialized(aOuter, NullHMGPoint,
2936
    csPoint);
2937
  FPivotPoint.OnNotifyChange := FManager.RebuildAllJoint;
2938
end;
2939

2940
destructor TGLNGDJointPivot.Destroy;
2941
begin
2942
  FPivotPoint.Free;
2943
  inherited;
2944
end;
2945

2946
{ TGLNGDJoint.TGLNGDJointPin }
2947

2948
constructor TGLNGDJointPin.Create(AOwner: TComponent; aOuter: TGLNGDJoint);
2949
begin
2950
  inherited;
2951
  FPinDirection := TGLCoordinates.CreateInitialized(aOuter, NullHmgVector,
2952
    csVector);
2953
  FPinDirection.OnNotifyChange := FManager.RebuildAllJoint;
2954
end;
2955

2956
destructor TGLNGDJointPin.Destroy;
2957
begin
2958
  FPinDirection.Free;
2959
  inherited;
2960
end;
2961

2962
//------------------------
2963
{ TGLNGDJointPin2 }
2964
//------------------------
2965

2966
constructor TGLNGDJointPin2.Create(AOwner: TComponent; aOuter: TGLNGDJoint);
2967
begin
2968
  inherited;
2969
  FPinDirection2 := TGLCoordinates.CreateInitialized(aOuter, NullHmgVector,
2970
    csVector);
2971
  FPinDirection2.OnNotifyChange := FManager.RebuildAllJoint;
2972
end;
2973

2974
destructor TGLNGDJointPin2.Destroy;
2975
begin
2976
  FPinDirection2.Free;
2977
  inherited;
2978
end;
2979

2980
//------------------------
2981
{ TGLNGDJointBallAndSocket }
2982
//------------------------
2983

2984
constructor TGLNGDJointBallAndSocket.Create(AOwner: TComponent;
2985
  aOuter: TGLNGDJoint);
2986
begin
2987
  inherited;
2988
  FConeAngle := 90;
2989
  FMinTwistAngle := -90;
2990
  FMaxTwistAngle := 90;
2991
end;
2992

2993
procedure TGLNGDJointBallAndSocket.SetConeAngle(const Value: Single);
2994
begin
2995
  FConeAngle := Value;
2996
  FManager.RebuildAllJoint(FOuter);
2997
end;
2998

2999
procedure TGLNGDJointBallAndSocket.SetMaxTwistAngle(const Value: Single);
3000
begin
3001
  FMaxTwistAngle := Value;
3002
  FManager.RebuildAllJoint(FOuter);
3003
end;
3004

3005
procedure TGLNGDJointBallAndSocket.SetMinTwistAngle(const Value: Single);
3006
begin
3007
  FMinTwistAngle := Value;
3008
  FManager.RebuildAllJoint(FOuter);
3009
end;
3010

3011
function TGLNGDJointBallAndSocket.StoredConeAngle: Boolean;
3012
begin
3013
  Result := not SameValue(FConeAngle, 90, epsilon);
3014
end;
3015

3016
function TGLNGDJointBallAndSocket.StoredMaxTwistAngle: Boolean;
3017
begin
3018
  Result := not SameValue(FMaxTwistAngle, 90, epsilon);
3019
end;
3020

3021
function TGLNGDJointBallAndSocket.StoredMinTwistAngle: Boolean;
3022
begin
3023
  Result := not SameValue(FMinTwistAngle, -90, epsilon);
3024
end;
3025

3026
//------------------------
3027
{ TGLNGDJointHinge }
3028
//------------------------
3029

3030
constructor TGLNGDJointHinge.Create(AOwner: TComponent; aOuter: TGLNGDJoint);
3031
begin
3032
  inherited;
3033
  FMinAngle := -90;
3034
  FMaxAngle := 90;
3035
end;
3036

3037
procedure TGLNGDJointHinge.SetMaxAngle(const Value: Single);
3038
begin
3039
  FMaxAngle := Value;
3040
  FManager.RebuildAllJoint(FOuter);
3041
end;
3042

3043
procedure TGLNGDJointHinge.SetMinAngle(const Value: Single);
3044
begin
3045
  FMinAngle := Value;
3046
  FManager.RebuildAllJoint(FOuter);
3047
end;
3048

3049
function TGLNGDJointHinge.StoredMaxAngle: Boolean;
3050
begin
3051
  Result := not SameValue(FMaxAngle, 90, epsilon);
3052
end;
3053

3054
function TGLNGDJointHinge.StoredMinAngle: Boolean;
3055
begin
3056
  Result := not SameValue(FMinAngle, -90, epsilon);
3057
end;
3058

3059
//------------------------
3060
{ TGLNGDJointSlider }
3061
//------------------------
3062

3063
constructor TGLNGDJointSlider.Create(AOwner: TComponent; aOuter: TGLNGDJoint);
3064
begin
3065
  inherited;
3066
  FMinDistance := -10;
3067
  FMaxDistance := 10;
3068
end;
3069

3070

3071
procedure TGLNGDJointSlider.SetMaxDistance(const Value: Single);
3072
begin
3073
  FMaxDistance := Value;
3074
  FManager.RebuildAllJoint(FOuter);
3075
end;
3076

3077
procedure TGLNGDJointSlider.SetMinDistance(const Value: Single);
3078
begin
3079
  FMinDistance := Value;
3080
  FManager.RebuildAllJoint(FOuter);
3081
end;
3082

3083

3084
function TGLNGDJointSlider.StoredMaxDistance: Boolean;
3085
begin
3086
  Result := not SameValue(FMaxDistance, 10, epsilon);
3087
end;
3088

3089
function TGLNGDJointSlider.StoredMinDistance: Boolean;
3090
begin
3091
  Result := not SameValue(FMinDistance, -10, epsilon);
3092
end;
3093

3094
{ TGLNGDJoint.TGLNGDJointKinematicController }
3095

3096
constructor TGLNGDJointKinematicController.Create;
3097
begin
3098
  FPickModeLinear := False;
3099
  FLinearFriction := 750;
3100
  FAngularFriction := 250;
3101
end;
3102

3103
function TGLNGDJointKinematicController.StoredAngularFriction: Boolean;
3104
begin
3105
  Result := not SameValue(FAngularFriction, 250, epsilon);
3106
end;
3107

3108
function TGLNGDJointKinematicController.StoredLinearFriction: Boolean;
3109
begin
3110
  Result := not SameValue(FLinearFriction, 750, epsilon);
3111
end;
3112

3113
//------------------------
3114
{ TGLNGDBehaviourList }
3115
//------------------------
3116

3117
function TGLNGDBehaviourList.GetBehav(index: Integer): TGLNGDBehaviour;
3118
begin
3119
  Result := Items[index];
3120
end;
3121

3122
procedure TGLNGDBehaviourList.PutBehav(index: Integer; Item: TGLNGDBehaviour);
3123
begin
3124
  inherited put(index, Item);
3125
end;
3126

3127
// ------------------------------------------------------------------
3128
initialization
3129
// ------------------------------------------------------------------
3130

3131
RegisterXCollectionItemClass(TGLNGDDynamic);
3132
RegisterXCollectionItemClass(TGLNGDStatic);
3133

3134
// ------------------------------------------------------------------
3135
finalization
3136
// ------------------------------------------------------------------
3137

3138
UnregisterXCollectionItemClass(TGLNGDDynamic);
3139
UnregisterXCollectionItemClass(TGLNGDStatic);
3140

3141
// CloseNGD;
3142

3143
end.
3144

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.