2
0

GXS.NGDManager.pas 98 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.NGDManager;
  5. (*
  6. The Newton Game Dynamics Manager
  7. *)
  8. interface
  9. uses
  10. System.Classes, // TComponent Tlist TWriter TReader TPersistent
  11. System.SysUtils, // System utilities
  12. System.Math, // Samevalue isZero to compare single
  13. System.Types,
  14. NGD.Import,
  15. Stage.VectorTypes,
  16. Stage.VectorGeometry, // PVector4f TVector4f TMatrix4f PMatrix4f NullHmgVector...
  17. Stage.Manager,
  18. GXS.VectorLists, // TgxAffineVectorList for Tree
  19. GXS.XCollection, // TXCollection file function
  20. GXS.GeometryBB,
  21. GXS.BaseClasses,
  22. GXS.PersistentClasses,
  23. GXS.Scene,
  24. GXS.Coordinates,
  25. GXS.Objects,
  26. GXS.GeomObjects,
  27. GXS.VectorFileObjects, // cube cone freeform...
  28. GXS.Color // For show debug
  29. ;
  30. type
  31. PdFloat = ^dFloat;
  32. TgxNGDHeightField = record
  33. heightArray: array of Word;
  34. width: Integer;
  35. depth: Integer;
  36. gridDiagonals: Boolean;
  37. widthDepthScale: Single;
  38. heightScale: Single;
  39. end;
  40. TgxNGDBehaviour = class;
  41. TgxNGDManager = class;
  42. TgxNGDSurfaceItem = class;
  43. TgxNGDJoint = class;
  44. TgxNGDSolverModels = (smExact = 0, smLinear1, smLinear2, smLinear3, smLinear4,
  45. smLinear5, smLinear6, smLinear7, smLinear8, smLinear9);
  46. TgxNGDFrictionModels = (fmExact = 0, fmAdaptive);
  47. TgxNGDPickedActions = (paAttach = 0, paMove, paDetach);
  48. TgxNGDManagerDebug = (mdShowGeometry, mdShowAABB, mdShowCenterOfMass,
  49. mdShowContact, mdShowJoint, mdShowForce, mdShowAppliedForce,
  50. mdShowAppliedVelocity);
  51. TgxNGDManagerDebugs = set of TgxNGDManagerDebug;
  52. TgxNGDCollisions = (nc_Primitive = 0, nc_Convex, nc_BBox, nc_BSphere, nc_Tree,
  53. nc_Mesh, nc_Null, nc_HeightField, nc_NGDFile);
  54. TgxNGDJoints = (nj_BallAndSocket, nj_Hinge, nj_Slider, nj_Corkscrew,
  55. nj_Universal, nj_CustomBallAndSocket, nj_CustomHinge, nj_CustomSlider,
  56. nj_UpVector, nj_KinematicController);
  57. TgxNGDBehaviourList = class(TList)
  58. protected
  59. function GetBehav(index: Integer): TgxNGDBehaviour;
  60. procedure PutBehav(index: Integer; Item: TgxNGDBehaviour);
  61. public
  62. property ItemsBehav[index: Integer]: TgxNGDBehaviour read GetBehav
  63. write PutBehav; default;
  64. end;
  65. // Events for Newton Callback
  66. TCollisionIteratorEvent = procedure(const userData: Pointer;
  67. vertexCount: Integer; const cfaceArray: PdFloat; faceId: Integer)
  68. of object;
  69. TApplyForceAndTorqueEvent = procedure(const cbody: PNewtonBody;
  70. timestep: dFloat; threadIndex: Integer) of object;
  71. TSetTransformEvent = procedure(const cbody: PNewtonBody;
  72. const cmatrix: PdFloat; threadIndex: Integer) of object;
  73. TSerializeEvent = procedure(serializeHandle: Pointer; const cbuffer: Pointer;
  74. size: Cardinal) of object;
  75. TDeSerializeEvent = procedure(serializeHandle: Pointer; buffer: Pointer;
  76. size: Cardinal) of object;
  77. TAABBOverlapEvent = function(const cmaterial: PNewtonMaterial;
  78. const cbody0: PNewtonBody; const cbody1: PNewtonBody; threadIndex: Integer)
  79. : Boolean of object;
  80. TContactProcessEvent = procedure(const ccontact: PNewtonJoint;
  81. timestep: dFloat; threadIndex: Integer) of object;
  82. TgxNGDDebugOption = class(TPersistent)
  83. strict private
  84. FManager: TgxNGDManager;
  85. FGeomColorDyn: TgxColor; // Green
  86. FGeomColorStat: TgxColor; // Red
  87. FAABBColor: TgxColor; // Yellow
  88. FAABBColorSleep: TgxColor; // Orange
  89. FCenterOfMassColor: TgxColor; // Purple dot
  90. FContactColor: TgxColor; // White
  91. FJointAxisColor: TgxColor; // Blue
  92. FJointPivotColor: TgxColor; // Aquamarine
  93. FForceColor: TgxColor; // Black
  94. FAppliedForceColor: TgxColor; // Silver
  95. FAppliedVelocityColor: TgxColor; // Lime
  96. FCustomColor: TgxColor; // Aqua
  97. FDotAxisSize: Single; // 1
  98. FManagerDebugs: TgxNGDManagerDebugs; // Default All false
  99. procedure SetManagerDebugs(const Value: TgxNGDManagerDebugs);
  100. procedure SetDotAxisSize(const Value: Single);
  101. function StoredDotAxis: Boolean;
  102. public
  103. constructor Create(AOwner: TComponent);
  104. destructor Destroy; override;
  105. published
  106. property GeomColorDyn: TgxColor read FGeomColorDyn write FGeomColorDyn;
  107. property GeomColorStat: TgxColor read FGeomColorStat write FGeomColorStat;
  108. property AABBColor: TgxColor read FAABBColor write FAABBColor;
  109. property AABBColorSleep: TgxColor read FAABBColorSleep
  110. write FAABBColorSleep;
  111. property CenterOfMassColor: TgxColor read FCenterOfMassColor
  112. write FCenterOfMassColor;
  113. property ContactColor: TgxColor read FContactColor write FContactColor;
  114. property JointAxisColor: TgxColor read FJointAxisColor
  115. write FJointAxisColor;
  116. property JointPivotColor: TgxColor read FJointPivotColor
  117. write FJointPivotColor;
  118. property ForceColor: TgxColor read FForceColor write FForceColor;
  119. property AppliedForceColor: TgxColor read FAppliedForceColor
  120. write FAppliedForceColor;
  121. property AppliedVelocityColor: TgxColor read FAppliedVelocityColor
  122. write FAppliedVelocityColor;
  123. property CustomColor: TgxColor read FCustomColor write FCustomColor;
  124. property NGDManagerDebugs: TgxNGDManagerDebugs read FManagerDebugs
  125. write SetManagerDebugs default [];
  126. property DotAxisSize: Single read FDotAxisSize write SetDotAxisSize
  127. stored StoredDotAxis;
  128. end;
  129. TgxNGDManager = class(TComponent)
  130. strict private
  131. FVisible: Boolean; // Show Debug at design time
  132. FVisibleAtRunTime: Boolean; // Show Debug at run time
  133. FDllVersion: Integer;
  134. FSolverModel: TgxNGDSolverModels; // Default=Exact
  135. FFrictionModel: TgxNGDFrictionModels; // Default=Exact
  136. FMinimumFrameRate: Integer; // Default=60
  137. FWorldSizeMin: TgxCoordinates; // Default=-100, -100, -100
  138. FWorldSizeMax: TgxCoordinates; // Default=100, 100, 100
  139. FThreadCount: Integer; // Default=1
  140. FGravity: TgxCoordinates; // Default=(0,-9.81,0)
  141. FNewtonSurfaceItem: TCollection;
  142. FNewtonSurfacePair: TOwnedCollection;
  143. FNewtonJointGroup: TOwnedCollection;
  144. FNewtonDebugOption: TgxNGDDebugOption;
  145. FGLLines: TgxLines;
  146. private
  147. FNewtonWorld: PNewtonWorld;
  148. FNGDBehaviours: TgxNGDBehaviourList;
  149. FCurrentColor: TgxColor;
  150. protected
  151. procedure Loaded; override;
  152. procedure SetVisible(const Value: Boolean);
  153. procedure SetVisibleAtRunTime(const Value: Boolean);
  154. procedure SetSolverModel(const Value: TgxNGDSolverModels);
  155. procedure SetFrictionModel(const Value: TgxNGDFrictionModels);
  156. procedure SetMinimumFrameRate(const Value: Integer);
  157. procedure SetThreadCount(const Value: Integer);
  158. procedure SetGXLines(const Value: TgxLines);
  159. function GetBodyCount: Integer;
  160. function GetConstraintCount: Integer;
  161. procedure AddNode(const coords: TgxCustomCoordinates); overload;
  162. procedure AddNode(const X, Y, Z: Single); overload;
  163. procedure AddNode(const Value: TVector4f); overload;
  164. procedure AddNode(const Value: TAffineVector); overload;
  165. procedure RebuildAllMaterial;
  166. procedure RebuildAllJoint(Sender: TObject);
  167. // Events
  168. procedure NotifyWorldSizeChange(Sender: TObject);
  169. procedure NotifyChange(Sender: TObject); // Debug view
  170. public
  171. constructor Create(AOwner: TComponent); override;
  172. destructor Destroy; override;
  173. procedure Step(deltatime: Single);
  174. published
  175. property Visible: Boolean read FVisible write SetVisible default True;
  176. property VisibleAtRunTime: Boolean read FVisibleAtRunTime
  177. write SetVisibleAtRunTime default False;
  178. property SolverModel: TgxNGDSolverModels read FSolverModel
  179. write SetSolverModel default smExact;
  180. property FrictionModel: TgxNGDFrictionModels read FFrictionModel
  181. write SetFrictionModel default fmExact;
  182. property MinimumFrameRate: Integer read FMinimumFrameRate
  183. write SetMinimumFrameRate default 60;
  184. property ThreadCount: Integer read FThreadCount write SetThreadCount
  185. default 1;
  186. property DllVersion: Integer read FDllVersion;
  187. property NewtonBodyCount: Integer read GetBodyCount;
  188. property NewtonConstraintCount: Integer read GetConstraintCount;
  189. property Gravity: TgxCoordinates read FGravity write FGravity;
  190. property WorldSizeMin: TgxCoordinates read FWorldSizeMin
  191. write FWorldSizeMin;
  192. property WorldSizeMax: TgxCoordinates read FWorldSizeMax
  193. write FWorldSizeMax;
  194. property NewtonSurfaceItem: TCollection read FNewtonSurfaceItem
  195. write FNewtonSurfaceItem;
  196. property NewtonSurfacePair: TOwnedCollection read FNewtonSurfacePair
  197. write FNewtonSurfacePair;
  198. property DebugOption: TgxNGDDebugOption read FNewtonDebugOption
  199. write FNewtonDebugOption;
  200. property Line: TgxLines read FGLLines write SetGXLines;
  201. property NewtonJoint: TOwnedCollection read FNewtonJointGroup
  202. write FNewtonJointGroup;
  203. end;
  204. // Basis structures for behaviour style implementations.
  205. TgxNGDBehaviour = class(TgxBehaviour)
  206. private
  207. FManager: TgxNGDManager;
  208. FManagerName: string;
  209. FInitialized: Boolean;
  210. FNewtonBody: PNewtonBody;
  211. FCollision: PNewtonCollision;
  212. FNewtonBodyMatrix: TMatrix4f; // Position and Orientation
  213. FContinuousCollisionMode: Boolean; // Default=False
  214. FNewtonCollisions: TgxNGDCollisions;
  215. FCollisionIteratorEvent: TCollisionIteratorEvent;
  216. FOwnerBaseSceneObject: TgxBaseSceneObject;
  217. // FNullCollisionMass: Single; // Default=0
  218. FTreeCollisionOptimize: Boolean; // Default=True
  219. FConvexCollisionTolerance: Single; // Default=0.01 1%
  220. FFileCollision: string;
  221. FSurfaceItem: TgxNGDSurfaceItem;
  222. FHeightFieldOptions: TgxNGDHeightField;
  223. protected
  224. procedure Initialize; virtual;
  225. procedure Finalize; virtual;
  226. procedure WriteToFiler(writer: TWriter); override;
  227. procedure ReadFromFiler(reader: TReader); override;
  228. procedure Loaded; override;
  229. procedure SetManager(Value: TgxNGDManager);
  230. procedure SetNewtonBodyMatrix(const Value: TMatrix4f);
  231. procedure SetContinuousCollisionMode(const Value: Boolean);
  232. function GetNewtonBodyMatrix: TMatrix4f;
  233. function GetNewtonBodyAABB: TAABB;
  234. procedure UpdCollision; virtual;
  235. procedure Render; virtual;
  236. procedure SetNewtonCollisions(const Value: TgxNGDCollisions);
  237. procedure SetNewtonSurfaceItem(const Value: TgxNGDSurfaceItem);
  238. procedure SetHeightFieldOptions(const Value: TgxNGDHeightField);
  239. function GetPrimitiveCollision(): PNewtonCollision;
  240. function GetConvexCollision(): PNewtonCollision;
  241. function GetBBoxCollision(): PNewtonCollision;
  242. function GetBSphereCollision(): PNewtonCollision;
  243. function GetTreeCollision(): PNewtonCollision;
  244. function GetMeshCollision(): PNewtonCollision;
  245. function GetNullCollision(): PNewtonCollision;
  246. function GetHeightFieldCollision(): PNewtonCollision;
  247. function GetNGDFileCollision(): PNewtonCollision;
  248. function StoredTolerance: Boolean;
  249. // Event
  250. procedure OnCollisionIteratorEvent(const userData: Pointer;
  251. vertexCount: Integer; const cfaceArray: PdFloat; faceId: Integer);
  252. // CallBack
  253. class procedure NewtonCollisionIterator(const userData: Pointer;
  254. vertexCount: Integer; const faceArray: PdFloat; faceId: Integer);
  255. static; cdecl;
  256. class procedure NewtonSerialize(serializeHandle: Pointer;
  257. const buffer: Pointer; size: Cardinal); static; cdecl;
  258. class procedure NewtonDeserialize(serializeHandle: Pointer; buffer: Pointer;
  259. size: Cardinal); static; cdecl;
  260. public
  261. constructor Create(AOwner: TXCollection); override;
  262. destructor Destroy; override;
  263. procedure Reinitialize;
  264. property Initialized: Boolean read FInitialized;
  265. class function UniqueItem: Boolean; override;
  266. property NewtonBodyMatrix: TMatrix4f read GetNewtonBodyMatrix
  267. write SetNewtonBodyMatrix;
  268. property NewtonBodyAABB: TAABB read GetNewtonBodyAABB;
  269. procedure Serialize(filename: string);
  270. procedure DeSerialize(filename: string);
  271. property HeightFieldOptions: TgxNGDHeightField read FHeightFieldOptions
  272. write SetHeightFieldOptions;
  273. published
  274. property Manager: TgxNGDManager read FManager write SetManager;
  275. property ContinuousCollisionMode: Boolean read FContinuousCollisionMode
  276. write SetContinuousCollisionMode default False;
  277. property NGDNewtonCollisions: TgxNGDCollisions read FNewtonCollisions
  278. write SetNewtonCollisions default nc_Primitive;
  279. property TreeCollisionOptimize: Boolean read FTreeCollisionOptimize
  280. write FTreeCollisionOptimize default True;
  281. property ConvexCollisionTolerance: Single read FConvexCollisionTolerance
  282. write FConvexCollisionTolerance stored StoredTolerance;
  283. property FileCollision: string read FFileCollision write FFileCollision;
  284. property NGDSurfaceItem: TgxNGDSurfaceItem read FSurfaceItem
  285. write SetNewtonSurfaceItem;
  286. end;
  287. TgxNGDDynamic = class(TgxNGDBehaviour)
  288. strict private
  289. FAABBmin: TgxCoordinates;
  290. FAABBmax: TgxCoordinates;
  291. FForce: TgxCoordinates;
  292. FTorque: TgxCoordinates;
  293. FCenterOfMass: TgxCoordinates;
  294. FAutoSleep: Boolean; // Default=True
  295. FLinearDamping: Single; // default=0.1
  296. FAngularDamping: TgxCoordinates; // Default=0.1
  297. FDensity: Single; // Default=1
  298. FUseGravity: Boolean; // Default=True
  299. FNullCollisionVolume: Single; // Default=0
  300. FApplyForceAndTorqueEvent: TApplyForceAndTorqueEvent;
  301. FSetTransformEvent: TSetTransformEvent;
  302. FCustomForceAndTorqueEvent: TApplyForceAndTorqueEvent;
  303. // Read Only
  304. FVolume: Single;
  305. FMass: Single;
  306. FAppliedForce: TgxCoordinates;
  307. FAppliedTorque: TgxCoordinates;
  308. FAppliedOmega: TgxCoordinates;
  309. FAppliedVelocity: TgxCoordinates;
  310. function StoredDensity: Boolean;
  311. function StoredLinearDamping: Boolean;
  312. function StoredNullCollisionVolume: Boolean;
  313. protected
  314. procedure SetAutoSleep(const Value: Boolean);
  315. procedure SetLinearDamping(const Value: Single);
  316. procedure SetDensity(const Value: Single); virtual;
  317. procedure Initialize; override;
  318. procedure Finalize; override;
  319. procedure WriteToFiler(writer: TWriter); override;
  320. procedure ReadFromFiler(reader: TReader); override;
  321. procedure Loaded; override;
  322. procedure Render; override;
  323. // Events
  324. procedure NotifyCenterOfMassChange(Sender: TObject);
  325. procedure NotifyAngularDampingChange(Sender: TObject);
  326. procedure OnApplyForceAndTorqueEvent(const cbody: PNewtonBody;
  327. timestep: dFloat; threadIndex: Integer);
  328. procedure OnSetTransformEvent(const cbody: PNewtonBody;
  329. const cmatrix: PdFloat; threadIndex: Integer);
  330. // Callback
  331. class procedure NewtonApplyForceAndTorque(const body: PNewtonBody;
  332. timestep: dFloat; threadIndex: Integer); static; cdecl;
  333. class procedure NewtonSetTransform(const body: PNewtonBody;
  334. const matrix: PdFloat; threadIndex: Integer); static; cdecl;
  335. public
  336. constructor Create(AOwner: TXCollection); override;
  337. destructor Destroy; override;
  338. procedure AddImpulse(const veloc, pointposit: TVector4f);
  339. function GetOmega: TVector4f;
  340. procedure SetOmega(const Omega: TVector4f);
  341. function GetVelocity: TVector4f;
  342. procedure SetVelocity(const Velocity: TVector4f);
  343. class function FriendlyName: string; override;
  344. property CustomForceAndTorqueEvent: TApplyForceAndTorqueEvent
  345. read FCustomForceAndTorqueEvent write FCustomForceAndTorqueEvent;
  346. property Velocity: TVector4f read GetVelocity write SetVelocity;
  347. property Omega: TVector4f read GetOmega write SetOmega;
  348. published
  349. property Force: TgxCoordinates read FForce write FForce;
  350. property Torque: TgxCoordinates read FTorque write FTorque;
  351. property CenterOfMass: TgxCoordinates read FCenterOfMass
  352. write FCenterOfMass;
  353. property AutoSleep: Boolean read FAutoSleep write SetAutoSleep default True;
  354. property LinearDamping: Single read FLinearDamping write SetLinearDamping
  355. stored StoredLinearDamping;
  356. property AngularDamping: TgxCoordinates read FAngularDamping
  357. write FAngularDamping;
  358. property Density: Single read FDensity write SetDensity
  359. stored StoredDensity;
  360. property UseGravity: Boolean read FUseGravity write FUseGravity
  361. default True;
  362. property NullCollisionVolume: Single read FNullCollisionVolume
  363. write FNullCollisionVolume stored StoredNullCollisionVolume;
  364. // Read Only
  365. property AppliedOmega: TgxCoordinates read FAppliedOmega;
  366. property AppliedVelocity: TgxCoordinates read FAppliedVelocity;
  367. property AppliedForce: TgxCoordinates read FAppliedForce;
  368. property AppliedTorque: TgxCoordinates read FAppliedTorque;
  369. property Volume: Single read FVolume;
  370. property Mass: Single read FMass;
  371. end;
  372. TgxNGDStatic = class(TgxNGDBehaviour)
  373. protected
  374. procedure Render; override;
  375. public
  376. class function FriendlyName: string; override;
  377. published
  378. end;
  379. TgxNGDSurfaceItem = class(TCollectionItem)
  380. private
  381. FDisplayName: string;
  382. protected
  383. function GetDisplayName: string; override;
  384. procedure SetDisplayName(const Value: string); override;
  385. published
  386. property DisplayName;
  387. property ID;
  388. end;
  389. TgxNGDSurfacePair = class(TCollectionItem)
  390. strict private
  391. FManager: TgxNGDManager;
  392. FSurfaceItem1: TgxNGDSurfaceItem;
  393. FSurfaceItem2: TgxNGDSurfaceItem;
  394. FAABBOverlapEvent: TAABBOverlapEvent;
  395. FContactProcessEvent: TContactProcessEvent;
  396. FSoftness: Single; // 0.1
  397. FElasticity: Single; // 0.4
  398. FCollidable: Boolean; // true
  399. FStaticFriction: Single; // 0.9
  400. FKineticFriction: Single; // 0.5
  401. FContinuousCollisionMode: Boolean; // False
  402. FThickness: Boolean; // False
  403. procedure SetCollidable(const Value: Boolean);
  404. procedure SetElasticity(const Value: Single);
  405. procedure SetKineticFriction(const Value: Single);
  406. procedure SetSoftness(const Value: Single);
  407. procedure SetStaticFriction(const Value: Single);
  408. procedure SetContinuousCollisionMode(const Value: Boolean);
  409. procedure SetThickness(const Value: Boolean);
  410. function StoredElasticity: Boolean;
  411. function StoredKineticFriction: Boolean;
  412. function StoredSoftness: Boolean;
  413. function StoredStaticFriction: Boolean;
  414. private
  415. // Callback
  416. class function NewtonAABBOverlap(const material: PNewtonMaterial;
  417. const body0: PNewtonBody; const body1: PNewtonBody; threadIndex: Integer)
  418. : Integer; static; cdecl;
  419. class procedure NewtonContactsProcess(const contact: PNewtonJoint;
  420. timestep: dFloat; threadIndex: Integer); static; cdecl;
  421. // Event
  422. function OnNewtonAABBOverlapEvent(const cmaterial: PNewtonMaterial;
  423. const cbody0: PNewtonBody; const cbody1: PNewtonBody;
  424. threadIndex: Integer): Boolean;
  425. procedure OnNewtonContactsProcessEvent(const ccontact: PNewtonJoint;
  426. timestep: dFloat; threadIndex: Integer);
  427. public
  428. constructor Create(Collection: TCollection); override;
  429. procedure SetMaterialItems(const item1, item2: TgxNGDSurfaceItem);
  430. property NGDSurfaceItem1: TgxNGDSurfaceItem read FSurfaceItem1;
  431. property NGDSurfaceItem2: TgxNGDSurfaceItem read FSurfaceItem2;
  432. published
  433. property Softness: Single read FSoftness write SetSoftness
  434. stored StoredSoftness;
  435. property Elasticity: Single read FElasticity write SetElasticity
  436. stored StoredElasticity;
  437. property Collidable: Boolean read FCollidable write SetCollidable
  438. default True;
  439. property StaticFriction: Single read FStaticFriction write SetStaticFriction
  440. stored StoredStaticFriction;
  441. property KineticFriction: Single read FKineticFriction
  442. write SetKineticFriction stored StoredKineticFriction;
  443. property ContinuousCollisionMode: Boolean read FContinuousCollisionMode
  444. write SetContinuousCollisionMode default False;
  445. property Thickness: Boolean read FThickness write SetThickness
  446. default False;
  447. property ContactProcessEvent: TContactProcessEvent read FContactProcessEvent
  448. write FContactProcessEvent;
  449. property AABBOverlapEvent: TAABBOverlapEvent read FAABBOverlapEvent
  450. write FAABBOverlapEvent;
  451. end;
  452. TgxNGDJointPivot = class(TPersistent)
  453. private
  454. FManager: TgxNGDManager;
  455. FPivotPoint: TgxCoordinates;
  456. FOuter: TgxNGDJoint;
  457. public
  458. constructor Create(AOwner: TComponent; aOuter: TgxNGDJoint); virtual;
  459. destructor Destroy; override;
  460. published
  461. property PivotPoint: TgxCoordinates read FPivotPoint write FPivotPoint;
  462. end;
  463. TgxNGDJointPin = class(TgxNGDJointPivot)
  464. private
  465. FPinDirection: TgxCoordinates;
  466. public
  467. constructor Create(AOwner: TComponent; aOuter: TgxNGDJoint); override;
  468. destructor Destroy; override;
  469. published
  470. property PinDirection: TgxCoordinates read FPinDirection
  471. write FPinDirection;
  472. end;
  473. TgxNGDJointPin2 = class(TgxNGDJointPin)
  474. private
  475. FPinDirection2: TgxCoordinates;
  476. public
  477. constructor Create(AOwner: TComponent; aOuter: TgxNGDJoint); override;
  478. destructor Destroy; override;
  479. published
  480. property PinDirection2: TgxCoordinates read FPinDirection2
  481. write FPinDirection2;
  482. end;
  483. TgxNGDJointBallAndSocket = class(TgxNGDJointPivot)
  484. private
  485. FConeAngle: Single; // 90
  486. FMinTwistAngle: Single; // -90
  487. FMaxTwistAngle: Single; // 90
  488. procedure SetConeAngle(const Value: Single);
  489. procedure SetMaxTwistAngle(const Value: Single);
  490. procedure SetMinTwistAngle(const Value: Single);
  491. function StoredMaxTwistAngle: Boolean;
  492. function StoredMinTwistAngle: Boolean;
  493. function StoredConeAngle: Boolean;
  494. public
  495. constructor Create(AOwner: TComponent; aOuter: TgxNGDJoint); override;
  496. published
  497. property ConeAngle: Single read FConeAngle write SetConeAngle
  498. stored StoredConeAngle;
  499. property MinTwistAngle: Single read FMinTwistAngle write SetMinTwistAngle
  500. stored StoredMinTwistAngle;
  501. property MaxTwistAngle: Single read FMaxTwistAngle write SetMaxTwistAngle
  502. stored StoredMaxTwistAngle;
  503. end;
  504. TgxNGDJointHinge = class(TgxNGDJointPin)
  505. private
  506. FMinAngle: Single; // -90
  507. FMaxAngle: Single; // 90
  508. procedure SetMaxAngle(const Value: Single);
  509. procedure SetMinAngle(const Value: Single);
  510. function StoredMaxAngle: Boolean;
  511. function StoredMinAngle: Boolean;
  512. public
  513. constructor Create(AOwner: TComponent; aOuter: TgxNGDJoint); override;
  514. published
  515. property MinAngle: Single read FMinAngle write SetMinAngle
  516. stored StoredMinAngle;
  517. property MaxAngle: Single read FMaxAngle write SetMaxAngle
  518. stored StoredMaxAngle;
  519. end;
  520. TgxNGDJointSlider = class(TgxNGDJointPin)
  521. private
  522. FMinDistance: Single; // -10
  523. FMaxDistance: Single; // 10
  524. procedure SetMaxDistance(const Value: Single);
  525. procedure SetMinDistance(const Value: Single);
  526. function StoredMaxDistance: Boolean;
  527. function StoredMinDistance: Boolean;
  528. public
  529. constructor Create(AOwner: TComponent; aOuter: TgxNGDJoint); override;
  530. published
  531. property MinDistance: Single read FMinDistance write SetMinDistance
  532. stored StoredMinDistance;
  533. property MaxDistance: Single read FMaxDistance write SetMaxDistance
  534. stored StoredMaxDistance;
  535. end;
  536. TgxNGDJointKinematicController = class(TPersistent)
  537. private
  538. FPickModeLinear: Boolean; // False
  539. FLinearFriction: Single; // 750
  540. FAngularFriction: Single; // 250
  541. function StoredAngularFriction: Boolean;
  542. function StoredLinearFriction: Boolean;
  543. public
  544. constructor Create();
  545. published
  546. property PickModeLinear: Boolean read FPickModeLinear write FPickModeLinear
  547. default False;
  548. property LinearFriction: Single read FLinearFriction write FLinearFriction
  549. stored StoredLinearFriction;
  550. property AngularFriction: Single read FAngularFriction
  551. write FAngularFriction stored StoredAngularFriction;
  552. end;
  553. TgxNGDJoint = class(TCollectionItem)
  554. private
  555. // Global
  556. FManager: TgxNGDManager;
  557. FParentObject: TgxBaseSceneObject;
  558. FJointType: TgxNGDJoints;
  559. FStiffness: Single; // 0.9
  560. // With Two object
  561. // Every joint except nj_UpVector and nj_KinematicController
  562. FChildObject: TgxBaseSceneObject;
  563. FCollisionState: Boolean; // False
  564. // With classic joint
  565. // nj_BallAndSocket, nj_Hinge, nj_Slider, nj_Corkscrew
  566. // nj_Universal, nj_UpVector
  567. FNewtonJoint: PNewtonJoint;
  568. // With CustomJoint
  569. // nj_CustomBallAndSocket, nj_CustomHinge, nj_CustomSlider
  570. // nj_KinematicController
  571. FNewtonUserJoint: Pointer;
  572. // nj_UpVector
  573. FUPVectorDirection: TgxCoordinates;
  574. FBallAndSocketOptions: TgxNGDJointPivot;
  575. FHingeOptions: TgxNGDJointPin;
  576. FSliderOptions: TgxNGDJointPin;
  577. FCorkscrewOptions: TgxNGDJointPin;
  578. FUniversalOptions: TgxNGDJointPin2;
  579. FCustomBallAndSocketOptions: TgxNGDJointBallAndSocket;
  580. FCustomHingeOptions: TgxNGDJointHinge;
  581. FCustomSliderOptions: TgxNGDJointSlider;
  582. FKinematicOptions: TgxNGDJointKinematicController;
  583. procedure SetJointType(const Value: TgxNGDJoints);
  584. procedure SetChildObject(const Value: TgxBaseSceneObject);
  585. procedure SetCollisionState(const Value: Boolean);
  586. procedure SetParentObject(const Value: TgxBaseSceneObject);
  587. procedure SetStiffness(const Value: Single);
  588. procedure Render;
  589. function StoredStiffness: Boolean;
  590. procedure DestroyNewtonData;
  591. public
  592. constructor Create(Collection: TCollection); override;
  593. destructor Destroy; override;
  594. procedure KinematicControllerPick(pickpoint: TVector4f;
  595. PickedActions: TgxNGDPickedActions);
  596. published
  597. property BallAndSocketOptions: TgxNGDJointPivot read FBallAndSocketOptions
  598. write FBallAndSocketOptions;
  599. property HingeOptions: TgxNGDJointPin read FHingeOptions
  600. write FHingeOptions;
  601. property SliderOptions: TgxNGDJointPin read FSliderOptions
  602. write FSliderOptions;
  603. property CorkscrewOptions: TgxNGDJointPin read FCorkscrewOptions
  604. write FCorkscrewOptions;
  605. property UniversalOptions: TgxNGDJointPin2 read FUniversalOptions
  606. write FUniversalOptions;
  607. property CustomBallAndSocketOptions: TgxNGDJointBallAndSocket
  608. read FCustomBallAndSocketOptions write FCustomBallAndSocketOptions;
  609. property CustomHingeOptions: TgxNGDJointHinge read FCustomHingeOptions
  610. write FCustomHingeOptions;
  611. property CustomSliderOptions: TgxNGDJointSlider read FCustomSliderOptions
  612. write FCustomSliderOptions;
  613. property KinematicControllerOptions: TgxNGDJointKinematicController
  614. read FKinematicOptions write FKinematicOptions;
  615. property JointType: TgxNGDJoints read FJointType write SetJointType;
  616. property ParentObject: TgxBaseSceneObject read FParentObject
  617. write SetParentObject;
  618. property ChildObject: TgxBaseSceneObject read FChildObject
  619. write SetChildObject;
  620. property CollisionState: Boolean read FCollisionState
  621. write SetCollisionState default False;
  622. property Stiffness: Single read FStiffness write SetStiffness
  623. stored StoredStiffness;
  624. property UPVectorDirection: TgxCoordinates read FUPVectorDirection
  625. write FUPVectorDirection;
  626. end;
  627. // Global function
  628. function GetNGDStatic(Obj: TgxBaseSceneObject): TgxNGDStatic;
  629. function GetOrCreateNGDStatic(Obj: TgxBaseSceneObject): TgxNGDStatic;
  630. function GetNGDDynamic(Obj: TgxBaseSceneObject): TgxNGDDynamic;
  631. function GetOrCreateNGDDynamic(Obj: TgxBaseSceneObject): TgxNGDDynamic;
  632. function GetBodyFromGLXceneObject(Obj: TgxBaseSceneObject): PNewtonBody;
  633. // =======================================================================
  634. implementation
  635. // =======================================================================
  636. const
  637. epsilon = 0.0000001; // 1E-07
  638. function GetNGDStatic(Obj: TgxBaseSceneObject): TgxNGDStatic;
  639. begin
  640. Result := TgxNGDStatic(Obj.Behaviours.GetByClass(TgxNGDStatic));
  641. end;
  642. function GetOrCreateNGDStatic(Obj: TgxBaseSceneObject): TgxNGDStatic;
  643. begin
  644. Result := TgxNGDStatic(Obj.GetOrCreateBehaviour(TgxNGDStatic));
  645. end;
  646. function GetNGDDynamic(Obj: TgxBaseSceneObject): TgxNGDDynamic;
  647. begin
  648. Result := TgxNGDDynamic(Obj.Behaviours.GetByClass(TgxNGDDynamic));
  649. end;
  650. function GetOrCreateNGDDynamic(Obj: TgxBaseSceneObject): TgxNGDDynamic;
  651. begin
  652. Result := TgxNGDDynamic(Obj.GetOrCreateBehaviour(TgxNGDDynamic));
  653. end;
  654. function GetBodyFromGLXceneObject(Obj: TgxBaseSceneObject): PNewtonBody;
  655. var
  656. Behaviour: TgxNGDBehaviour;
  657. begin
  658. Behaviour := TgxNGDBehaviour(Obj.Behaviours.GetByClass(TgxNGDBehaviour));
  659. Assert(Behaviour <> nil,
  660. 'NGD Behaviour (static or dynamic) is missing for this object');
  661. Result := Behaviour.FNewtonBody;
  662. end;
  663. // ------------------------------------------------------------------
  664. // -------- TgxNGDDebugOption
  665. // ------------------------------------------------------------------
  666. constructor TgxNGDDebugOption.Create(AOwner: TComponent);
  667. begin
  668. FManager := AOwner as TgxNGDManager;
  669. with FManager do
  670. begin
  671. FGeomColorDyn := TgxColor.CreateInitialized(self, clrGreen, NotifyChange);
  672. FGeomColorStat := TgxColor.CreateInitialized(self, clrRed, NotifyChange);
  673. FAABBColor := TgxColor.CreateInitialized(self, clrYellow, NotifyChange);
  674. FAABBColorSleep := TgxColor.CreateInitialized(self, clrOrange,
  675. NotifyChange);
  676. FCenterOfMassColor := TgxColor.CreateInitialized(self, clrPurple,
  677. NotifyChange);
  678. FContactColor := TgxColor.CreateInitialized(self, clrWhite, NotifyChange);
  679. FJointAxisColor := TgxColor.CreateInitialized(self, clrBlue, NotifyChange);
  680. FJointPivotColor := TgxColor.CreateInitialized(self, clrAquamarine,
  681. NotifyChange);
  682. FForceColor := TgxColor.CreateInitialized(self, clrBlack, NotifyChange);
  683. FAppliedForceColor := TgxColor.CreateInitialized(self, clrSilver,
  684. NotifyChange);
  685. FAppliedVelocityColor := TgxColor.CreateInitialized(self, clrLime,
  686. NotifyChange);
  687. FCustomColor := TgxColor.CreateInitialized(self, clrAqua, NotifyChange);
  688. end;
  689. FDotAxisSize := 1;
  690. FManagerDebugs := [];
  691. FManager := AOwner as TgxNGDManager;
  692. end;
  693. destructor TgxNGDDebugOption.Destroy;
  694. begin
  695. FGeomColorDyn.Free;
  696. FGeomColorStat.Free;
  697. FAABBColor.Free;
  698. FAABBColorSleep.Free;
  699. FCenterOfMassColor.Free;
  700. FContactColor.Free;
  701. FJointAxisColor.Free;
  702. FJointPivotColor.Free;
  703. FForceColor.Free;
  704. FAppliedForceColor.Free;
  705. FAppliedVelocityColor.Free;
  706. FCustomColor.Free;
  707. inherited;
  708. end;
  709. procedure TgxNGDDebugOption.SetDotAxisSize(const Value: Single);
  710. begin
  711. FDotAxisSize := Value;
  712. FManager.NotifyChange(self);
  713. end;
  714. procedure TgxNGDDebugOption.SetManagerDebugs(const Value
  715. : TgxNGDManagerDebugs);
  716. begin
  717. FManagerDebugs := Value;
  718. FManager.NotifyChange(self);
  719. end;
  720. function TgxNGDDebugOption.StoredDotAxis: Boolean;
  721. begin
  722. Result := not SameValue(FDotAxisSize, 1, epsilon);
  723. end;
  724. // ------------------------------------------------------------------
  725. { TgxNGDManager }
  726. // ------------------------------------------------------------------
  727. procedure TgxNGDManager.AddNode(const Value: TVector4f);
  728. begin
  729. if Assigned(FGLLines) then
  730. begin
  731. FGLLines.Nodes.AddNode(Value);
  732. with (FGLLines.Nodes.Last as TgxLinesNode) do
  733. Color := FCurrentColor;
  734. end;
  735. end;
  736. procedure TgxNGDManager.AddNode(const coords: TgxCustomCoordinates);
  737. begin
  738. if Assigned(FGLLines) then
  739. begin
  740. FGLLines.Nodes.AddNode(coords);
  741. (FGLLines.Nodes.Last as TgxLinesNode).Color := FCurrentColor;
  742. end;
  743. end;
  744. procedure TgxNGDManager.AddNode(const X, Y, Z: Single);
  745. begin
  746. if Assigned(FGLLines) then
  747. begin
  748. FGLLines.Nodes.AddNode(X, Y, Z);
  749. (FGLLines.Nodes.Last as TgxLinesNode).Color := FCurrentColor;
  750. end;
  751. end;
  752. procedure TgxNGDManager.AddNode(const Value: TAffineVector);
  753. begin
  754. if Assigned(FGLLines) then
  755. begin
  756. FGLLines.Nodes.AddNode(Value);
  757. (FGLLines.Nodes.Last as TgxLinesNode).Color := FCurrentColor;
  758. end;
  759. end;
  760. constructor TgxNGDManager.Create(AOwner: TComponent);
  761. var
  762. minworld, maxworld: TVector4f;
  763. begin
  764. inherited;
  765. FNGDBehaviours := TgxNGDBehaviourList.Create;
  766. FVisible := True;
  767. FVisibleAtRunTime := False;
  768. FSolverModel := smExact;
  769. FFrictionModel := fmExact;
  770. FMinimumFrameRate := 60;
  771. FWorldSizeMin := TgxCoordinates.CreateInitialized(self,
  772. VectorMake(-100, -100, -100, 0), csPoint);
  773. FWorldSizeMax := TgxCoordinates.CreateInitialized(self,
  774. VectorMake(100, 100, 100, 0), csPoint);
  775. // Using Events because we need to call API Function when
  776. // theses TgxCoordinates change.
  777. FWorldSizeMin.OnNotifyChange := NotifyWorldSizeChange;
  778. FWorldSizeMax.OnNotifyChange := NotifyWorldSizeChange;
  779. FThreadCount := 1;
  780. FGravity := TgxCoordinates3.CreateInitialized(self,
  781. VectorMake(0, -9.81, 0, 0), csVector);
  782. FNewtonWorld := NewtonCreate(nil, nil);
  783. FDllVersion := NewtonWorldGetVersion(FNewtonWorld);
  784. // This is to prevent body out the world at startTime
  785. minworld := VectorMake(-1E50, -1E50, -1E50);
  786. maxworld := VectorMake(1E50, 1E50, 1E50);
  787. NewtonSetWorldSize(FNewtonWorld, @minworld, @maxworld);
  788. NewtonWorldSetUserData(FNewtonWorld, self);
  789. FNewtonSurfaceItem := TCollection.Create(TgxNGDSurfaceItem);
  790. FNewtonSurfacePair := TOwnedCollection.Create(self, TgxNGDSurfacePair);
  791. FNewtonJointGroup := TOwnedCollection.Create(self, TgxNGDJoint);
  792. FNewtonDebugOption := TgxNGDDebugOption.Create(self);
  793. RegisterManager(self);
  794. end;
  795. destructor TgxNGDManager.Destroy;
  796. begin
  797. // Destroy joint before body.
  798. FreeAndNil(FNewtonJointGroup);
  799. // Unregister everything
  800. while FNGDBehaviours.Count > 0 do
  801. FNGDBehaviours[0].Manager := nil;
  802. // Clean up everything
  803. FreeAndNil(FNGDBehaviours);
  804. FreeAndNil(FWorldSizeMin);
  805. FreeAndNil(FWorldSizeMax);
  806. FreeAndNil(FGravity);
  807. FreeAndNil(FNewtonSurfaceItem);
  808. FreeAndNil(FNewtonSurfacePair);
  809. FreeAndNil(FNewtonDebugOption);
  810. NewtonDestroyAllBodies(FNewtonWorld);
  811. NewtonMaterialDestroyAllGroupID(FNewtonWorld);
  812. NewtonDestroy(FNewtonWorld);
  813. FNewtonWorld := nil;
  814. DeregisterManager(self);
  815. inherited;
  816. end;
  817. procedure TgxNGDManager.Loaded;
  818. begin
  819. inherited;
  820. NotifyWorldSizeChange(self);
  821. RebuildAllJoint(self);
  822. end;
  823. function TgxNGDManager.GetBodyCount: Integer;
  824. begin
  825. if (csDesigning in ComponentState) then
  826. Result := FNGDBehaviours.Count
  827. else
  828. Result := NewtonWorldGetBodyCount(FNewtonWorld);
  829. end;
  830. function TgxNGDManager.GetConstraintCount: Integer;
  831. begin
  832. if (csDesigning in ComponentState) then
  833. Result := FNewtonJointGroup.Count
  834. else
  835. // Constraint is the number of joint
  836. Result := NewtonWorldGetConstraintCount(FNewtonWorld);
  837. end;
  838. procedure TgxNGDManager.NotifyChange(Sender: TObject);
  839. var
  840. I: Integer;
  841. begin
  842. // This event is raise
  843. // when debugOptions properties are edited,
  844. // when a behavior is initialized/finalize,
  845. // when joints are rebuilded, (runtime only)
  846. // when visible and visibleAtRuntime are edited (designTime only),
  847. // in manager.step, and in SetGLLines.
  848. // Here the manager call render method for bodies and joints in its lists
  849. if not Assigned(FGLLines) then
  850. exit;
  851. FGLLines.Nodes.Clear;
  852. if not Visible then
  853. exit;
  854. if not(csDesigning in ComponentState) then
  855. if not VisibleAtRunTime then
  856. exit;
  857. for I := 0 to FNGDBehaviours.Count - 1 do
  858. FNGDBehaviours[I].Render;
  859. if mdShowJoint in FNewtonDebugOption.NGDManagerDebugs then
  860. for I := 0 to NewtonJoint.Count - 1 do //
  861. (NewtonJoint.Items[I] as TgxNGDJoint).Render;
  862. end;
  863. procedure TgxNGDManager.SetFrictionModel(const Value: TgxNGDFrictionModels);
  864. begin
  865. FFrictionModel := Value;
  866. if not(csDesigning in ComponentState) then
  867. NewtonSetFrictionModel(FNewtonWorld, Ord(FFrictionModel));
  868. end;
  869. procedure TgxNGDManager.SetGXLines(const Value: TgxLines);
  870. begin
  871. if Assigned(FGLLines) then
  872. FGLLines.Nodes.Clear;
  873. FGLLines := Value;
  874. if Assigned(FGLLines) then
  875. begin
  876. FGLLines.SplineMode := lsmSegments;
  877. FGLLines.NodesAspect := lnaInvisible;
  878. FGLLines.Options := [loUseNodeColorForLines];
  879. FGLLines.Pickable := False;
  880. NotifyChange(self);
  881. end;
  882. end;
  883. procedure TgxNGDManager.SetMinimumFrameRate(const Value: Integer);
  884. begin
  885. if (Value >= 60) and (Value <= 1000) then
  886. FMinimumFrameRate := Value;
  887. if not(csDesigning in ComponentState) then
  888. NewtonSetMinimumFrameRate(FNewtonWorld, FMinimumFrameRate);
  889. end;
  890. procedure TgxNGDManager.SetSolverModel(const Value: TgxNGDSolverModels);
  891. begin
  892. FSolverModel := Value;
  893. if not(csDesigning in ComponentState) then
  894. NewtonSetSolverModel(FNewtonWorld, Ord(FSolverModel));
  895. end;
  896. procedure TgxNGDManager.SetThreadCount(const Value: Integer);
  897. begin
  898. if Value > 0 then
  899. FThreadCount := Value;
  900. NewtonSetThreadsCount(FNewtonWorld, FThreadCount);
  901. FThreadCount := NewtonGetThreadsCount(FNewtonWorld);
  902. end;
  903. procedure TgxNGDManager.SetVisible(const Value: Boolean);
  904. begin
  905. FVisible := Value;
  906. if (csDesigning in ComponentState) then
  907. NotifyChange(self);
  908. end;
  909. procedure TgxNGDManager.SetVisibleAtRunTime(const Value: Boolean);
  910. begin
  911. FVisibleAtRunTime := Value;
  912. if (csDesigning in ComponentState) then
  913. NotifyChange(self);
  914. end;
  915. procedure TgxNGDManager.NotifyWorldSizeChange(Sender: TObject);
  916. begin
  917. if not(csDesigning in ComponentState) then
  918. NewtonSetWorldSize(FNewtonWorld, @FWorldSizeMin.AsVector,
  919. @FWorldSizeMax.AsVector);
  920. end;
  921. procedure TgxNGDManager.RebuildAllJoint(Sender: TObject);
  922. procedure BuildBallAndSocket(Joint: TgxNGDJoint);
  923. begin
  924. with Joint do
  925. if Assigned(FParentObject) and Assigned(FChildObject) then
  926. begin
  927. FNewtonJoint := NewtonConstraintCreateBall(FNewtonWorld,
  928. @(FBallAndSocketOptions.FPivotPoint.AsVector),
  929. GetBodyFromGLXceneObject(FChildObject),
  930. GetBodyFromGLXceneObject(FParentObject));
  931. NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
  932. NewtonJointSetStiffness(FNewtonJoint, FStiffness);
  933. end;
  934. end;
  935. procedure BuildHinge(Joint: TgxNGDJoint);
  936. begin
  937. with Joint do
  938. if Assigned(FParentObject) and Assigned(FChildObject) then
  939. begin
  940. FNewtonJoint := NewtonConstraintCreateHinge(FNewtonWorld,
  941. @(FHingeOptions.FPivotPoint.AsVector),
  942. @(FHingeOptions.FPinDirection.AsVector),
  943. GetBodyFromGLXceneObject(FChildObject),
  944. GetBodyFromGLXceneObject(FParentObject));
  945. NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
  946. NewtonJointSetStiffness(FNewtonJoint, FStiffness);
  947. end;
  948. end;
  949. procedure BuildSlider(Joint: TgxNGDJoint);
  950. begin
  951. with Joint do
  952. if Assigned(FParentObject) and Assigned(FChildObject) then
  953. begin
  954. FNewtonJoint := NewtonConstraintCreateSlider(FNewtonWorld,
  955. @(FSliderOptions.FPivotPoint.AsVector),
  956. @(FSliderOptions.FPinDirection.AsVector),
  957. GetBodyFromGLXceneObject(FChildObject),
  958. GetBodyFromGLXceneObject(FParentObject));
  959. NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
  960. NewtonJointSetStiffness(FNewtonJoint, FStiffness);
  961. end;
  962. end;
  963. procedure BuildCorkscrew(Joint: TgxNGDJoint);
  964. begin
  965. with Joint do
  966. if Assigned(FParentObject) and Assigned(FChildObject) then
  967. begin
  968. FNewtonJoint := NewtonConstraintCreateCorkscrew(FNewtonWorld,
  969. @(FCorkscrewOptions.FPivotPoint.AsVector),
  970. @(FCorkscrewOptions.FPinDirection.AsVector),
  971. GetBodyFromGLXceneObject(FChildObject),
  972. GetBodyFromGLXceneObject(FParentObject));
  973. NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
  974. NewtonJointSetStiffness(FNewtonJoint, FStiffness);
  975. end;
  976. end;
  977. procedure BuildUniversal(Joint: TgxNGDJoint);
  978. begin
  979. with Joint do
  980. if Assigned(FParentObject) and Assigned(FChildObject) then
  981. begin
  982. FNewtonJoint := NewtonConstraintCreateUniversal(FNewtonWorld,
  983. @(FUniversalOptions.FPivotPoint.AsVector),
  984. @(FUniversalOptions.FPinDirection.AsVector),
  985. @(FUniversalOptions.FPinDirection2.AsVector),
  986. GetBodyFromGLXceneObject(FChildObject),
  987. GetBodyFromGLXceneObject(FParentObject));
  988. NewtonJointSetCollisionState(FNewtonJoint, Ord(FCollisionState));
  989. NewtonJointSetStiffness(FNewtonJoint, FStiffness);
  990. end;
  991. end;
  992. procedure BuildCustomBallAndSocket(Joint: TgxNGDJoint);
  993. var
  994. pinAndPivot: TMatrix4f;
  995. begin
  996. with Joint do
  997. if Assigned(FParentObject) and Assigned(FChildObject) then
  998. begin
  999. pinAndPivot := IdentityHmgMatrix;
  1000. pinAndPivot.W := FCustomBallAndSocketOptions.FPivotPoint.AsVector;
  1001. (* from dJointLibrary.dll
  1002. FNewtonUserJoint := CreateCustomBallAndSocket(@pinAndPivot,
  1003. GetBodyFromGLSceneObject(FChildObject),
  1004. GetBodyFromGLSceneObject(FParentObject));
  1005. BallAndSocketSetConeAngle(FNewtonUserJoint,
  1006. DegToRadian(FCustomBallAndSocketOptions.FConeAngle));
  1007. BallAndSocketSetTwistAngle(FNewtonUserJoint,
  1008. DegToRadian(FCustomBallAndSocketOptions.FMinTwistAngle),
  1009. DegToRadian(FCustomBallAndSocketOptions.FMaxTwistAngle));
  1010. CustomSetBodiesCollisionState(FNewtonUserJoint, Ord(FCollisionState));
  1011. NewtonJointSetStiffness(CustomGetNewtonJoint(FNewtonUserJoint),
  1012. FStiffness);
  1013. *)
  1014. end;
  1015. end;
  1016. procedure BuildCustomHinge(Joint: TgxNGDJoint);
  1017. var
  1018. pinAndPivot: TMatrix4f;
  1019. bso: TgxBaseSceneObject;
  1020. begin
  1021. { Newton wait from FPinAndPivotMatrix a structure like that:
  1022. First row: the pin direction
  1023. Second and third rows are set to create an orthogonal matrix
  1024. Fourth: The pivot position
  1025. In glscene, the GLBaseSceneObjects direction is the third row,
  1026. because the first row is the right vector (second row is up vector). }
  1027. with Joint do
  1028. if Assigned(FParentObject) and Assigned(FChildObject) then
  1029. begin
  1030. bso := TgxBaseSceneObject.Create(FManager);
  1031. bso.AbsolutePosition := FCustomHingeOptions.FPivotPoint.AsVector;
  1032. bso.AbsoluteDirection := FCustomHingeOptions.FPinDirection.AsVector;
  1033. pinAndPivot := bso.AbsoluteMatrix;
  1034. pinAndPivot.X := bso.AbsoluteMatrix.Z;
  1035. pinAndPivot.Z := bso.AbsoluteMatrix.X;
  1036. bso.Free;
  1037. (* // from dJointLibrary.dll
  1038. FNewtonUserJoint := CreateCustomHinge(@pinAndPivot,
  1039. GetBodyFromGLSceneObject(FChildObject),
  1040. GetBodyFromGLSceneObject(FParentObject));
  1041. HingeEnableLimits(FNewtonUserJoint, 1);
  1042. HingeSetLimits(FNewtonUserJoint,
  1043. DegToRadian(FCustomHingeOptions.FMinAngle),
  1044. DegToRadian(FCustomHingeOptions.FMaxAngle));
  1045. CustomSetBodiesCollisionState(FNewtonUserJoint, Ord(FCollisionState));
  1046. NewtonJointSetStiffness(CustomGetNewtonJoint(FNewtonUserJoint),
  1047. FStiffness);
  1048. CustomSetUserData(FNewtonUserJoint, CustomHingeOptions);
  1049. *)
  1050. end;
  1051. end;
  1052. procedure BuildCustomSlider(Joint: TgxNGDJoint);
  1053. var
  1054. pinAndPivot: TMatrix4f;
  1055. bso: TgxBaseSceneObject;
  1056. begin
  1057. (*
  1058. Newton wait from FPinAndPivotMatrix a structure like that:
  1059. First row: the pin direction
  1060. Second and third rows are set to create an orthogonal matrix
  1061. Fourth: The pivot position
  1062. In GLS.Scene, the GLBaseSceneObjects direction is the third row,
  1063. because the first row is the right vector (second row is up vector).
  1064. *)
  1065. with Joint do
  1066. if Assigned(FParentObject) and Assigned(FChildObject) then
  1067. begin
  1068. bso := TgxBaseSceneObject.Create(FManager);
  1069. bso.AbsolutePosition := FCustomSliderOptions.FPivotPoint.AsVector;
  1070. bso.AbsoluteDirection := FCustomSliderOptions.FPinDirection.AsVector;
  1071. pinAndPivot := bso.AbsoluteMatrix;
  1072. pinAndPivot.X := bso.AbsoluteMatrix.Z;
  1073. pinAndPivot.Z := bso.AbsoluteMatrix.X;
  1074. bso.Free;
  1075. (* from dJointLibrary.dll
  1076. FNewtonUserJoint := CreateCustomSlider(@pinAndPivot,
  1077. GetBodyFromGLSceneObject(FChildObject),
  1078. GetBodyFromGLSceneObject(FParentObject));
  1079. SliderEnableLimits(FNewtonUserJoint, 1);
  1080. SliderSetLimits(FNewtonUserJoint, FCustomSliderOptions.FMinDistance,
  1081. FCustomSliderOptions.FMaxDistance);
  1082. NewtonJointSetStiffness(CustomGetNewtonJoint(FNewtonUserJoint), 0);
  1083. CustomSetBodiesCollisionState(FNewtonUserJoint, Ord(FCollisionState));
  1084. CustomSetUserData(FNewtonUserJoint, CustomSliderOptions);
  1085. *)
  1086. end;
  1087. end;
  1088. procedure BuildUpVector(Joint: TgxNGDJoint);
  1089. begin
  1090. with Joint do
  1091. if Assigned(FParentObject) then
  1092. begin
  1093. FNewtonJoint := NewtonConstraintCreateUpVector(FNewtonWorld,
  1094. @FUPVectorDirection.AsVector,
  1095. GetBodyFromGLXceneObject(FParentObject));
  1096. end;
  1097. end;
  1098. procedure BuildKinematicController(Joint: TgxNGDJoint);
  1099. begin
  1100. // do nothing
  1101. end;
  1102. procedure BuildOneJoint(Joint: TgxNGDJoint);
  1103. begin
  1104. case Joint.FJointType of
  1105. nj_BallAndSocket:
  1106. begin
  1107. Joint.DestroyNewtonData;
  1108. BuildBallAndSocket(Joint);
  1109. end;
  1110. nj_Hinge:
  1111. begin
  1112. Joint.DestroyNewtonData;
  1113. BuildHinge(Joint);
  1114. end;
  1115. nj_Slider:
  1116. begin
  1117. Joint.DestroyNewtonData;
  1118. BuildSlider(Joint);
  1119. end;
  1120. nj_Corkscrew:
  1121. begin
  1122. Joint.DestroyNewtonData;
  1123. BuildCorkscrew(Joint);
  1124. end;
  1125. nj_Universal:
  1126. begin
  1127. Joint.DestroyNewtonData;
  1128. BuildUniversal(Joint);
  1129. end;
  1130. nj_CustomBallAndSocket:
  1131. begin
  1132. Joint.DestroyNewtonData;
  1133. BuildCustomBallAndSocket(Joint);
  1134. end;
  1135. nj_CustomHinge:
  1136. begin
  1137. Joint.DestroyNewtonData;
  1138. BuildCustomHinge(Joint);
  1139. end;
  1140. nj_CustomSlider:
  1141. begin
  1142. Joint.DestroyNewtonData;
  1143. BuildCustomSlider(Joint);
  1144. end;
  1145. nj_UpVector:
  1146. begin
  1147. Joint.DestroyNewtonData;
  1148. BuildUpVector(Joint);
  1149. end;
  1150. nj_KinematicController:
  1151. begin
  1152. // DestroyJoint(Joint);
  1153. // BuildKinematicController(Joint);
  1154. end;
  1155. end;
  1156. end;
  1157. var
  1158. I: Integer;
  1159. begin
  1160. if not(csDesigning in ComponentState) and not(csLoading in ComponentState)
  1161. then
  1162. begin
  1163. if Sender is TgxNGDManager then
  1164. for I := 0 to NewtonJoint.Count - 1 do
  1165. BuildOneJoint(NewtonJoint.Items[I] as TgxNGDJoint);
  1166. if (Sender is TgxNGDJoint) then
  1167. BuildOneJoint((Sender as TgxNGDJoint));
  1168. if Sender is TgxCoordinates then
  1169. BuildOneJoint(((Sender as TgxCoordinates).Owner as TgxNGDJoint));
  1170. NotifyChange(self);
  1171. end;
  1172. end;
  1173. procedure TgxNGDManager.RebuildAllMaterial;
  1174. procedure BuildMaterialPair;
  1175. var
  1176. I, ID0, ID1: Integer;
  1177. begin
  1178. for I := 0 to FNewtonSurfacePair.Count - 1 do
  1179. with (FNewtonSurfacePair.Items[I] as TgxNGDSurfacePair) do
  1180. begin
  1181. if Assigned(NGDSurfaceItem1) and Assigned(NGDSurfaceItem2) then
  1182. begin
  1183. ID0 := NGDSurfaceItem1.ID;
  1184. ID1 := NGDSurfaceItem2.ID;
  1185. NewtonMaterialSetContinuousCollisionMode(FNewtonWorld, ID0, ID1,
  1186. Ord(ContinuousCollisionMode));
  1187. if Thickness then
  1188. NewtonMaterialSetSurfaceThickness(FNewtonWorld, ID0, ID1, 1);
  1189. NewtonMaterialSetDefaultSoftness(FNewtonWorld, ID0, ID1, Softness);
  1190. NewtonMaterialSetDefaultElasticity(FNewtonWorld, ID0, ID1,
  1191. Elasticity);
  1192. NewtonMaterialSetDefaultCollidable(FNewtonWorld, ID0, ID1,
  1193. Ord(Collidable));
  1194. NewtonMaterialSetDefaultFriction(FNewtonWorld, ID0, ID1,
  1195. StaticFriction, KineticFriction);
  1196. NewtonMaterialSetCollisionCallback(FNewtonWorld, ID0, ID1,
  1197. FNewtonSurfacePair.Items[I], @TgxNGDSurfacePair.NewtonAABBOverlap,
  1198. @TgxNGDSurfacePair.NewtonContactsProcess);
  1199. end;
  1200. end;
  1201. end;
  1202. var
  1203. I: Integer;
  1204. maxID: Integer;
  1205. begin
  1206. maxID := 0;
  1207. if not(csDesigning in ComponentState) then
  1208. begin
  1209. // for newton materials
  1210. NewtonMaterialDestroyAllGroupID(FNewtonWorld);
  1211. // Creates materialID
  1212. for I := 0 to FNewtonSurfaceItem.Count - 1 do
  1213. maxID := MaxInteger((FNewtonSurfaceItem.Items[I] as TgxNGDSurfaceItem)
  1214. .ID, maxID);
  1215. for I := 0 to maxID - 1 do
  1216. NewtonMaterialCreateGroupID(FNewtonWorld);
  1217. // assign matID to bodies
  1218. for I := 0 to FNGDBehaviours.Count - 1 do
  1219. with FNGDBehaviours[I] do
  1220. if Assigned(FSurfaceItem) then
  1221. NewtonBodySetMaterialGroupID(FNewtonBody, FSurfaceItem.ID)
  1222. else
  1223. NewtonBodySetMaterialGroupID(FNewtonBody, 0);
  1224. // Set values to newton material pair :callback userdata friction...
  1225. BuildMaterialPair;
  1226. end;
  1227. end;
  1228. procedure TgxNGDManager.Step(deltatime: Single);
  1229. begin
  1230. if not(csDesigning in ComponentState) then
  1231. NewtonUpdate(FNewtonWorld, deltatime);
  1232. NotifyChange(self);
  1233. end;
  1234. // ---------------------------
  1235. // TgxNGDBehaviour
  1236. // ---------------------------
  1237. constructor TgxNGDBehaviour.Create(AOwner: TXCollection);
  1238. begin
  1239. inherited;
  1240. FInitialized := False;
  1241. FOwnerBaseSceneObject := OwnerBaseSceneObject;
  1242. FContinuousCollisionMode := False;
  1243. FNewtonBody := nil;
  1244. FCollision := nil;
  1245. FNewtonCollisions := nc_Primitive;
  1246. FCollisionIteratorEvent := OnCollisionIteratorEvent;
  1247. FTreeCollisionOptimize := True;
  1248. FConvexCollisionTolerance := 0.01;
  1249. FFileCollision := '';
  1250. name := 'NGD Static';
  1251. end;
  1252. destructor TgxNGDBehaviour.Destroy;
  1253. begin
  1254. if Assigned(FManager) then
  1255. Manager := nil; // This will call finalize
  1256. inherited;
  1257. end;
  1258. procedure TgxNGDBehaviour.Finalize;
  1259. var
  1260. I: Integer;
  1261. begin
  1262. FInitialized := False;
  1263. if Assigned(FManager) then
  1264. begin
  1265. if Assigned(FManager.NewtonJoint) then
  1266. for I := FManager.NewtonJoint.Count - 1 downto 0 do
  1267. begin
  1268. if ((FManager.NewtonJoint.Items[I] as TgxNGDJoint)
  1269. .ParentObject = FOwnerBaseSceneObject) or
  1270. ((FManager.NewtonJoint.Items[I] as TgxNGDJoint)
  1271. .ChildObject = FOwnerBaseSceneObject) then
  1272. begin
  1273. FManager.NewtonJoint.Items[I].Free;
  1274. end;
  1275. end;
  1276. NewtonDestroyBody(FManager.FNewtonWorld, FNewtonBody);
  1277. FNewtonBody := nil;
  1278. FCollision := nil;
  1279. end;
  1280. end;
  1281. function TgxNGDBehaviour.GetBBoxCollision: PNewtonCollision;
  1282. var
  1283. vc: array [0 .. 7] of TVector4f;
  1284. I: Integer;
  1285. begin
  1286. for I := 0 to 8 - 1 do
  1287. vc[I] := AABBToBB(FOwnerBaseSceneObject.AxisAlignedBoundingBoxEx).BBox[I];
  1288. Result := NewtonCreateConvexHull(FManager.FNewtonWorld, 8, @vc[0],
  1289. SizeOf(TVector4f), 0.01, 0, nil);
  1290. end;
  1291. function TgxNGDBehaviour.GetBSphereCollision: PNewtonCollision;
  1292. var
  1293. boundingSphere: TBSphere;
  1294. collisionOffsetMatrix: TMatrix4f;
  1295. begin
  1296. AABBToBSphere(FOwnerBaseSceneObject.AxisAlignedBoundingBoxEx, boundingSphere);
  1297. collisionOffsetMatrix := IdentityHmgMatrix;
  1298. collisionOffsetMatrix.W := VectorMake(boundingSphere.Center, 1);
  1299. Result := NewtonCreateSphere(FManager.FNewtonWorld, boundingSphere.Radius,
  1300. boundingSphere.Radius, boundingSphere.Radius, 0, @collisionOffsetMatrix);
  1301. end;
  1302. function TgxNGDBehaviour.GetConvexCollision: PNewtonCollision;
  1303. var
  1304. I, J: Integer;
  1305. vertexArray: array of TVertex;
  1306. begin
  1307. if FOwnerBaseSceneObject is TgxBaseMesh then
  1308. begin
  1309. with (FOwnerBaseSceneObject as TgxBaseMesh) do
  1310. begin
  1311. for I := 0 to MeshObjects.Count - 1 do
  1312. for J := 0 to MeshObjects[I].Vertices.Count - 1 do
  1313. begin
  1314. SetLength(vertexArray, Length(vertexArray) + 1);
  1315. vertexArray[Length(vertexArray) - 1] := MeshObjects[I].Vertices[J];
  1316. end;
  1317. if Length(vertexArray) > 0 then
  1318. Result := NewtonCreateConvexHull(FManager.FNewtonWorld,
  1319. Length(vertexArray), @vertexArray[0], SizeOf(TVertex),
  1320. FConvexCollisionTolerance, 0, nil)
  1321. else
  1322. Result := GetNullCollision;
  1323. end;
  1324. end
  1325. else
  1326. Result := GetNullCollision;
  1327. end;
  1328. function TgxNGDBehaviour.GetHeightFieldCollision: PNewtonCollision;
  1329. var
  1330. I: Integer;
  1331. attributeMap: array of ShortInt;
  1332. begin
  1333. SetLength(attributeMap, Length(FHeightFieldOptions.heightArray));
  1334. for I := 0 to Length(FHeightFieldOptions.heightArray) - 1 do
  1335. attributeMap[I] := 0;
  1336. Result := NewtonCreateHeightFieldCollision(FManager.FNewtonWorld,
  1337. FHeightFieldOptions.width, FHeightFieldOptions.depth,
  1338. Ord(FHeightFieldOptions.gridDiagonals),
  1339. PUnsigned_short(FHeightFieldOptions.heightArray), P2Char(attributeMap),
  1340. FHeightFieldOptions.widthDepthScale, FHeightFieldOptions.heightScale, 0);
  1341. end;
  1342. function TgxNGDBehaviour.GetMeshCollision: PNewtonCollision;
  1343. var
  1344. collisionArray: array of PNewtonCollision;
  1345. I, J: Integer;
  1346. vertexArray: array of TVertex;
  1347. begin
  1348. if FOwnerBaseSceneObject is TgxBaseMesh then
  1349. begin
  1350. with (FOwnerBaseSceneObject as TgxBaseMesh) do
  1351. begin
  1352. // Iterate trough mesh of GLobject
  1353. for I := 0 to MeshObjects.Count - 1 do
  1354. begin
  1355. // Iterate trough vertices of mesh
  1356. for J := 0 to MeshObjects[I].Vertices.Count - 1 do
  1357. begin
  1358. SetLength(vertexArray, Length(vertexArray) + 1);
  1359. vertexArray[Length(vertexArray) - 1] := MeshObjects[I].Vertices[J];
  1360. end;
  1361. if Length(vertexArray) > 3 then
  1362. begin
  1363. SetLength(collisionArray, Length(collisionArray) + 1);
  1364. collisionArray[Length(collisionArray) - 1] :=
  1365. NewtonCreateConvexHull(FManager.FNewtonWorld, Length(vertexArray),
  1366. @vertexArray[0], SizeOf(TVertex),
  1367. FConvexCollisionTolerance, 0, nil);
  1368. // Remove last collision if the newton function was not successful
  1369. if collisionArray[Length(collisionArray) - 1] = nil then
  1370. SetLength(collisionArray, Length(collisionArray) - 1);
  1371. end;
  1372. SetLength(vertexArray, 0);
  1373. end;
  1374. if Length(collisionArray) > 0 then
  1375. Result := NewtonCreateCompoundCollision(FManager.FNewtonWorld,
  1376. Length(collisionArray),
  1377. TCollisionPrimitiveArray(@collisionArray[0]), 0)
  1378. else
  1379. Result := GetNullCollision;
  1380. end;
  1381. end
  1382. else
  1383. Result := GetNullCollision;
  1384. end;
  1385. function TgxNGDBehaviour.GetNewtonBodyMatrix: TMatrix4f;
  1386. begin
  1387. if Assigned(FManager) then
  1388. NewtonBodyGetmatrix(FNewtonBody, @FNewtonBodyMatrix);
  1389. Result := FNewtonBodyMatrix;
  1390. end;
  1391. function TgxNGDBehaviour.GetNewtonBodyAABB: TAABB;
  1392. begin
  1393. if Assigned(FManager) then
  1394. NewtonBodyGetAABB(FNewtonBody, @(Result.min), @(Result.max));
  1395. end;
  1396. function TgxNGDBehaviour.GetNGDFileCollision: PNewtonCollision;
  1397. var
  1398. MyFile: TFileStream;
  1399. begin
  1400. if FileExists(FFileCollision) then
  1401. begin
  1402. MyFile := TFileStream.Create(FFileCollision, fmOpenRead);
  1403. Result := NewtonCreateCollisionFromSerialization(FManager.FNewtonWorld,
  1404. @TgxNGDBehaviour.NewtonDeserialize, Pointer(MyFile));
  1405. MyFile.Free;
  1406. end
  1407. else
  1408. Result := NewtonCreateNull(FManager.FNewtonWorld);
  1409. end;
  1410. function TgxNGDBehaviour.GetNullCollision: PNewtonCollision;
  1411. begin
  1412. Result := NewtonCreateNull(FManager.FNewtonWorld);
  1413. end;
  1414. function TgxNGDBehaviour.GetPrimitiveCollision: PNewtonCollision;
  1415. var
  1416. collisionOffsetMatrix: TMatrix4f; // For cone capsule and cylinder
  1417. begin
  1418. collisionOffsetMatrix := IdentityHmgMatrix;
  1419. if (FOwnerBaseSceneObject is TgxCube) then
  1420. begin
  1421. with (FOwnerBaseSceneObject as TgxCube) do
  1422. Result := NewtonCreateBox(FManager.FNewtonWorld, CubeWidth, CubeHeight,
  1423. CubeDepth, 0, @collisionOffsetMatrix);
  1424. end
  1425. else if (FOwnerBaseSceneObject is TgxSphere) then
  1426. begin
  1427. with (FOwnerBaseSceneObject as TgxSphere) do
  1428. Result := NewtonCreateSphere(FManager.FNewtonWorld, Radius, Radius,
  1429. Radius, 0, @collisionOffsetMatrix);
  1430. end
  1431. else if (FOwnerBaseSceneObject is TgxCone) then
  1432. begin
  1433. collisionOffsetMatrix := MatrixMultiply(collisionOffsetMatrix,
  1434. CreateRotationMatrixZ(Pi / 2.0));
  1435. with (FOwnerBaseSceneObject as TgxCone) do
  1436. Result := NewtonCreateCone(FManager.FNewtonWorld, BottomRadius, Height, 0,
  1437. @collisionOffsetMatrix);
  1438. end
  1439. else if (FOwnerBaseSceneObject is TgxCapsule) then
  1440. begin
  1441. collisionOffsetMatrix := MatrixMultiply(collisionOffsetMatrix,
  1442. CreateRotationMatrixY(Pi / 2.0));
  1443. with (FOwnerBaseSceneObject as TgxCapsule) do
  1444. // Use Cylinder shape for buoyancy
  1445. Result := NewtonCreateCapsule(FManager.FNewtonWorld, Radius,
  1446. Height + 2 * Radius, 0, @collisionOffsetMatrix);
  1447. end
  1448. else if (FOwnerBaseSceneObject is TgxCylinder) then
  1449. begin
  1450. collisionOffsetMatrix := MatrixMultiply(collisionOffsetMatrix,
  1451. CreateRotationMatrixZ(Pi / 2.0));
  1452. with (FOwnerBaseSceneObject as TgxCylinder) do
  1453. Result := NewtonCreateCylinder(FManager.FNewtonWorld, BottomRadius,
  1454. Height, 0, @collisionOffsetMatrix);
  1455. end
  1456. else
  1457. Result := GetNullCollision;
  1458. end;
  1459. function TgxNGDBehaviour.GetTreeCollision: PNewtonCollision;
  1460. var
  1461. meshIndex, triangleIndex: Integer;
  1462. triangleList: TgxAffineVectorList;
  1463. v: array [0 .. 2] of TAffineVector;
  1464. begin
  1465. if FOwnerBaseSceneObject is TgxBaseMesh then
  1466. begin
  1467. with (FOwnerBaseSceneObject as TgxBaseMesh) do
  1468. begin
  1469. Result := NewtonCreateTreeCollision(FManager.FNewtonWorld, 0);
  1470. NewtonTreeCollisionBeginBuild(Result);
  1471. for meshIndex := 0 to MeshObjects.Count - 1 do
  1472. begin
  1473. triangleList := MeshObjects[meshIndex].ExtractTriangles;
  1474. for triangleIndex := 0 to triangleList.Count - 1 do
  1475. begin
  1476. if triangleIndex mod 3 = 0 then
  1477. begin
  1478. v[0] := triangleList.Items[triangleIndex];
  1479. // ScaleVector(v[0], FOwnerBaseSceneObject.Scale.X);
  1480. v[1] := triangleList.Items[triangleIndex + 1];
  1481. // ScaleVector(v[1], FOwnerBaseSceneObject.Scale.Y);
  1482. v[2] := triangleList.Items[triangleIndex + 2];
  1483. // ScaleVector(v[2], FOwnerBaseSceneObject.Scale.Z);
  1484. NewtonTreeCollisionAddFace(Result, 3, @(v),
  1485. SizeOf(TAffineVector), 1);
  1486. end;
  1487. end;
  1488. triangleList.Free;
  1489. end;
  1490. NewtonTreeCollisionEndBuild(Result, Ord(FTreeCollisionOptimize));
  1491. end;
  1492. end
  1493. else
  1494. Result := GetNullCollision;
  1495. end;
  1496. procedure TgxNGDBehaviour.Initialize;
  1497. begin
  1498. FInitialized := True;
  1499. if Assigned(FManager) then
  1500. begin
  1501. // Create NewtonBody with null collision
  1502. FCollision := NewtonCreateNull(FManager.FNewtonWorld);
  1503. FNewtonBodyMatrix := FOwnerBaseSceneObject.AbsoluteMatrix;
  1504. FNewtonBody := NewtonCreateBody(FManager.FNewtonWorld, FCollision,
  1505. @FNewtonBodyMatrix);
  1506. // Release NewtonCollision
  1507. NewtonReleaseCollision(FManager.FNewtonWorld, FCollision);
  1508. // Set Link between glscene and newton
  1509. NewtonBodySetUserdata(FNewtonBody, self);
  1510. // Set position and orientation
  1511. SetNewtonBodyMatrix(FOwnerBaseSceneObject.AbsoluteMatrix);
  1512. // Set Collision
  1513. UpdCollision;
  1514. end;
  1515. end;
  1516. procedure TgxNGDBehaviour.Loaded;
  1517. var
  1518. mng: TComponent;
  1519. begin
  1520. inherited;
  1521. if FManagerName <> '' then
  1522. begin
  1523. mng := FindManager(TgxNGDManager, FManagerName);
  1524. if Assigned(mng) then
  1525. Manager := TgxNGDManager(mng);
  1526. FManagerName := '';
  1527. end;
  1528. if Assigned(FManager) then
  1529. begin
  1530. SetContinuousCollisionMode(FContinuousCollisionMode);
  1531. end;
  1532. end;
  1533. class procedure TgxNGDBehaviour.NewtonCollisionIterator(const userData: Pointer;
  1534. vertexCount: Integer; const faceArray: PdFloat; faceId: Integer)cdecl;
  1535. begin
  1536. TgxNGDBehaviour(userData).FCollisionIteratorEvent(userData, vertexCount,
  1537. faceArray, faceId);
  1538. end;
  1539. // Serializes are called by NGDBehaviour to save and load collision in file
  1540. // It's better to save/load big collisions [over 50000 polygones] to reduce
  1541. // loading time
  1542. class procedure TgxNGDBehaviour.NewtonDeserialize(serializeHandle,
  1543. buffer: Pointer; size: Cardinal)cdecl;
  1544. begin
  1545. TFileStream(serializeHandle).read(buffer^, size);
  1546. end;
  1547. class procedure TgxNGDBehaviour.NewtonSerialize(serializeHandle: Pointer;
  1548. const buffer: Pointer; size: Cardinal)cdecl;
  1549. begin
  1550. TFileStream(serializeHandle).write(buffer^, size);
  1551. end;
  1552. procedure TgxNGDBehaviour.OnCollisionIteratorEvent(const userData: Pointer;
  1553. vertexCount: Integer; const cfaceArray: PdFloat; faceId: Integer);
  1554. var
  1555. I: Integer;
  1556. v0, v1: array [0 .. 2] of Single;
  1557. vA: array of Single;
  1558. begin
  1559. // This algorithme draw Collision Shape for Debuggin.
  1560. // Taken to Sascha Willems in SDLNewton-Demo at
  1561. // http://www.saschawillems.de/?page_id=82
  1562. // Leave if there is no or to much vertex
  1563. if (vertexCount = 0) then
  1564. exit;
  1565. SetLength(vA, vertexCount * 3);
  1566. Move(cfaceArray^, vA[0], vertexCount * 3 * SizeOf(Single));
  1567. v0[0] := vA[(vertexCount - 1) * 3];
  1568. v0[1] := vA[(vertexCount - 1) * 3 + 1];
  1569. v0[2] := vA[(vertexCount - 1) * 3 + 2];
  1570. for I := 0 to vertexCount - 1 do
  1571. begin
  1572. v1[0] := vA[I * 3];
  1573. v1[1] := vA[I * 3 + 1];
  1574. v1[2] := vA[I * 3 + 2];
  1575. FManager.AddNode(v0[0], v0[1], v0[2]);
  1576. FManager.AddNode(v1[0], v1[1], v1[2]);
  1577. v0 := v1;
  1578. end;
  1579. end;
  1580. procedure TgxNGDBehaviour.Reinitialize;
  1581. begin
  1582. if Initialized then
  1583. begin
  1584. // Set Appropriate NewtonCollision
  1585. UpdCollision();
  1586. // Set position and orientation
  1587. SetNewtonBodyMatrix(FOwnerBaseSceneObject.AbsoluteMatrix);
  1588. end;
  1589. Loaded;
  1590. end;
  1591. procedure TgxNGDBehaviour.Render;
  1592. var
  1593. M: TMatrix4f;
  1594. begin
  1595. // Rebuild collision in design time
  1596. if (csDesigning in FOwnerBaseSceneObject.ComponentState) then
  1597. Reinitialize;
  1598. if self is TgxNGDDynamic then
  1599. FManager.FCurrentColor := FManager.DebugOption.GeomColorDyn
  1600. else
  1601. FManager.FCurrentColor := FManager.DebugOption.GeomColorStat;
  1602. M := FOwnerBaseSceneObject.AbsoluteMatrix;
  1603. if mdShowGeometry in FManager.DebugOption.NGDManagerDebugs then
  1604. NewtonCollisionForEachPolygonDo(FCollision, @M,
  1605. @TgxNGDBehaviour.NewtonCollisionIterator, self);
  1606. end;
  1607. // In this procedure, we assign collision to body
  1608. // [Because when initialised, the collision for body is type NULL]
  1609. procedure TgxNGDBehaviour.UpdCollision;
  1610. var
  1611. collisionInfoRecord: TNewtonCollisionInfoRecord;
  1612. begin
  1613. case FNewtonCollisions of
  1614. nc_Primitive:
  1615. FCollision := GetPrimitiveCollision;
  1616. nc_Convex:
  1617. FCollision := GetConvexCollision;
  1618. nc_BBox:
  1619. FCollision := GetBBoxCollision;
  1620. nc_BSphere:
  1621. FCollision := GetBSphereCollision;
  1622. nc_Tree:
  1623. FCollision := GetTreeCollision;
  1624. nc_Mesh:
  1625. FCollision := GetMeshCollision;
  1626. nc_Null:
  1627. FCollision := GetNullCollision;
  1628. nc_HeightField:
  1629. FCollision := GetHeightFieldCollision;
  1630. nc_NGDFile:
  1631. FCollision := GetNGDFileCollision;
  1632. end;
  1633. if Assigned(FCollision) then
  1634. begin
  1635. NewtonBodySetCollision(FNewtonBody, FCollision);
  1636. // The API Ask for releasing Collision to avoid memory leak
  1637. NewtonCollisionGetInfo(FCollision, @collisionInfoRecord);
  1638. if collisionInfoRecord.m_collisionType > 2 then
  1639. NewtonReleaseCollision(FManager.FNewtonWorld, FCollision);
  1640. end;
  1641. end;
  1642. procedure TgxNGDBehaviour.SetContinuousCollisionMode(const Value: Boolean);
  1643. begin
  1644. // for continue collision to be active the continue collision mode must on
  1645. // the material pair of the colliding bodies as well as on at
  1646. // least one of the two colliding bodies.
  1647. // see NewtonBodySetContinuousCollisionMode
  1648. // see NewtonMaterialSetContinuousCollisionMode
  1649. FContinuousCollisionMode := Value;
  1650. if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
  1651. if Assigned(FManager) then
  1652. NewtonBodySetContinuousCollisionMode(FNewtonBody, Ord(Value));
  1653. end;
  1654. procedure TgxNGDBehaviour.SetHeightFieldOptions(const Value: TgxNGDHeightField);
  1655. begin
  1656. FHeightFieldOptions := Value;
  1657. Reinitialize;
  1658. end;
  1659. procedure TgxNGDBehaviour.SetManager(Value: TgxNGDManager);
  1660. begin
  1661. if FManager <> Value then
  1662. begin
  1663. if Assigned(FManager) then
  1664. begin
  1665. if Initialized then
  1666. Finalize;
  1667. FManager.FNGDBehaviours.Remove(self);
  1668. // FManager.NotifyChange(self);
  1669. end;
  1670. FManager := Value;
  1671. if Assigned(FManager) then
  1672. begin
  1673. Initialize;
  1674. FManager.FNGDBehaviours.Add(self);
  1675. FManager.NotifyChange(self);
  1676. end;
  1677. end;
  1678. end;
  1679. procedure TgxNGDBehaviour.SetNewtonBodyMatrix(const Value: TMatrix4f);
  1680. begin
  1681. FNewtonBodyMatrix := Value;
  1682. if Assigned(FManager) then
  1683. NewtonBodySetmatrix(FNewtonBody, @FNewtonBodyMatrix);
  1684. end;
  1685. procedure TgxNGDBehaviour.SetNewtonCollisions(const Value: TgxNGDCollisions);
  1686. begin
  1687. FNewtonCollisions := Value;
  1688. if Assigned(FManager) then
  1689. UpdCollision;
  1690. end;
  1691. procedure TgxNGDBehaviour.SetNewtonSurfaceItem(const Value: TgxNGDSurfaceItem);
  1692. begin
  1693. FSurfaceItem := Value;
  1694. FManager.RebuildAllMaterial;
  1695. end;
  1696. function TgxNGDBehaviour.StoredTolerance: Boolean;
  1697. begin
  1698. Result := not SameValue(FConvexCollisionTolerance, 0.01, epsilon);
  1699. end;
  1700. class function TgxNGDBehaviour.UniqueItem: Boolean;
  1701. begin
  1702. Result := True;
  1703. end;
  1704. procedure TgxNGDBehaviour.ReadFromFiler(reader: TReader);
  1705. var
  1706. version: Integer;
  1707. begin
  1708. inherited;
  1709. with reader do
  1710. begin
  1711. version := ReadInteger; // read data version
  1712. Assert(version <= 1); // Archive version
  1713. FManagerName := ReadString;
  1714. FContinuousCollisionMode := ReadBoolean;
  1715. read(FNewtonCollisions, SizeOf(TgxNGDCollisions));
  1716. FTreeCollisionOptimize := ReadBoolean;
  1717. if version <= 0 then
  1718. FConvexCollisionTolerance := ReadSingle
  1719. else
  1720. FConvexCollisionTolerance := ReadFloat;
  1721. FFileCollision := ReadString;
  1722. end;
  1723. end;
  1724. procedure TgxNGDBehaviour.WriteToFiler(writer: TWriter);
  1725. begin
  1726. inherited;
  1727. with writer do
  1728. begin
  1729. WriteInteger(1); // Archive version
  1730. if Assigned(FManager) then
  1731. WriteString(FManager.GetNamePath)
  1732. else
  1733. WriteString('');
  1734. WriteBoolean(FContinuousCollisionMode);
  1735. write(FNewtonCollisions, SizeOf(TgxNGDCollisions));
  1736. WriteBoolean(FTreeCollisionOptimize);
  1737. WriteFloat(FConvexCollisionTolerance);
  1738. WriteString(FFileCollision);
  1739. end;
  1740. end;
  1741. procedure TgxNGDBehaviour.Serialize(filename: string);
  1742. var
  1743. MyFile: TFileStream;
  1744. begin
  1745. MyFile := TFileStream.Create(filename, fmCreate or fmOpenReadWrite);
  1746. NewtonCollisionSerialize(FManager.FNewtonWorld, FCollision,
  1747. @TgxNGDBehaviour.NewtonSerialize, Pointer(MyFile));
  1748. MyFile.Free;
  1749. end;
  1750. procedure TgxNGDBehaviour.DeSerialize(filename: string);
  1751. var
  1752. MyFile: TFileStream;
  1753. collisionInfoRecord: TNewtonCollisionInfoRecord;
  1754. begin
  1755. MyFile := TFileStream.Create(filename, fmOpenRead);
  1756. FCollision := NewtonCreateCollisionFromSerialization(FManager.FNewtonWorld,
  1757. @TgxNGDBehaviour.NewtonDeserialize, Pointer(MyFile));
  1758. // SetCollision;
  1759. NewtonBodySetCollision(FNewtonBody, FCollision);
  1760. // Release collision
  1761. NewtonCollisionGetInfo(FCollision, @collisionInfoRecord);
  1762. if collisionInfoRecord.m_collisionType > 2 then
  1763. NewtonReleaseCollision(FManager.FNewtonWorld, FCollision);
  1764. MyFile.Free;
  1765. end;
  1766. // -------------------------------------
  1767. // TgxNGDDynamic
  1768. // -------------------------------------
  1769. procedure TgxNGDDynamic.AddImpulse(const veloc, pointposit: TVector4f);
  1770. begin
  1771. if Assigned(FNewtonBody) then
  1772. NewtonBodyAddImpulse(FNewtonBody, @veloc, @pointposit);
  1773. end;
  1774. constructor TgxNGDDynamic.Create(AOwner: TXCollection);
  1775. begin
  1776. inherited;
  1777. FAutoSleep := True;
  1778. FLinearDamping := 0.1;
  1779. FAngularDamping := TgxCoordinates.CreateInitialized(self,
  1780. VectorMake(0.1, 0.1, 0.1, 0), csPoint);
  1781. FAngularDamping.OnNotifyChange := NotifyAngularDampingChange;
  1782. FDensity := 1;
  1783. FVolume := 1;
  1784. FForce := TgxCoordinates.CreateInitialized(self, NullHmgVector, csVector);
  1785. FTorque := TgxCoordinates.CreateInitialized(self, NullHmgVector, csVector);
  1786. FCenterOfMass := TgxCoordinates.CreateInitialized(self,
  1787. NullHmgVector, csPoint);
  1788. FCenterOfMass.OnNotifyChange := NotifyCenterOfMassChange;
  1789. FAABBmin := TgxCoordinates.CreateInitialized(self, NullHmgVector, csPoint);
  1790. FAABBmax := TgxCoordinates.CreateInitialized(self, NullHmgVector, csPoint);
  1791. FAppliedOmega := TgxCoordinates.CreateInitialized(self, NullHmgVector,
  1792. csVector);
  1793. FAppliedVelocity := TgxCoordinates.CreateInitialized(self, NullHmgVector,
  1794. csVector);
  1795. FAppliedForce := TgxCoordinates.CreateInitialized(self, NullHmgVector,
  1796. csVector);
  1797. FAppliedTorque := TgxCoordinates.CreateInitialized(self, NullHmgVector,
  1798. csVector);
  1799. FUseGravity := True;
  1800. FNullCollisionVolume := 0;
  1801. FApplyForceAndTorqueEvent := OnApplyForceAndTorqueEvent;
  1802. FSetTransformEvent := OnSetTransformEvent;
  1803. name := 'NGD Dynamic'
  1804. end;
  1805. destructor TgxNGDDynamic.Destroy;
  1806. begin
  1807. // Clean up everything
  1808. FAngularDamping.Free;
  1809. FForce.Free;
  1810. FTorque.Free;
  1811. FCenterOfMass.Free;
  1812. FAABBmin.Free;
  1813. FAABBmax.Free;
  1814. FAppliedForce.Free;
  1815. FAppliedTorque.Free;
  1816. FAppliedVelocity.Free;
  1817. FAppliedOmega.Free;
  1818. inherited;
  1819. end;
  1820. procedure TgxNGDDynamic.Finalize;
  1821. begin
  1822. if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
  1823. if Assigned(FManager) then
  1824. begin
  1825. // Removing Callback
  1826. NewtonBodySetForceAndTorqueCallback(FNewtonBody, nil);
  1827. NewtonBodySetTransformCallback(FNewtonBody, nil);
  1828. end;
  1829. inherited;
  1830. end;
  1831. class function TgxNGDDynamic.FriendlyName: string;
  1832. begin
  1833. Result := 'NGD Dynamic';
  1834. end;
  1835. procedure TgxNGDDynamic.Initialize;
  1836. begin
  1837. inherited;
  1838. if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
  1839. if Assigned(FManager) then
  1840. begin
  1841. // Set Density, Mass and inertie matrix
  1842. SetDensity(FDensity);
  1843. // Set Callback
  1844. NewtonBodySetForceAndTorqueCallback(FNewtonBody,
  1845. @TgxNGDDynamic.NewtonApplyForceAndTorque);
  1846. NewtonBodySetTransformCallback(FNewtonBody,
  1847. @TgxNGDDynamic.NewtonSetTransform);
  1848. end;
  1849. end;
  1850. procedure TgxNGDDynamic.Render;
  1851. procedure DrawAABB(min, max: TgxCoordinates3);
  1852. begin
  1853. {
  1854. // H________G
  1855. // /. /|
  1856. // / . / |
  1857. // D__._____C |
  1858. // | . | |
  1859. // | E.-----|--F
  1860. // | . | /
  1861. // |. |/
  1862. // A________B
  1863. }
  1864. // Back
  1865. FManager.AddNode(min.X, min.Y, min.Z); // E
  1866. FManager.AddNode(max.X, min.Y, min.Z); // F
  1867. FManager.AddNode(max.X, min.Y, min.Z); // F
  1868. FManager.AddNode(max.X, max.Y, min.Z); // G
  1869. FManager.AddNode(max.X, max.Y, min.Z); // G
  1870. FManager.AddNode(min.X, max.Y, min.Z); // H
  1871. FManager.AddNode(min.X, max.Y, min.Z); // H
  1872. FManager.AddNode(min.X, min.Y, min.Z); // E
  1873. // Front
  1874. FManager.AddNode(min.X, min.Y, max.Z); // A
  1875. FManager.AddNode(max.X, min.Y, max.Z); // B
  1876. FManager.AddNode(max.X, min.Y, max.Z); // B
  1877. FManager.AddNode(max.X, max.Y, max.Z); // C
  1878. FManager.AddNode(max.X, max.Y, max.Z); // C
  1879. FManager.AddNode(min.X, max.Y, max.Z); // D
  1880. FManager.AddNode(min.X, max.Y, max.Z); // D
  1881. FManager.AddNode(min.X, min.Y, max.Z); // A
  1882. // Edges
  1883. FManager.AddNode(min.X, min.Y, max.Z); // A
  1884. FManager.AddNode(min.X, min.Y, min.Z); // E
  1885. FManager.AddNode(max.X, min.Y, max.Z); // B
  1886. FManager.AddNode(max.X, min.Y, min.Z); // F
  1887. FManager.AddNode(max.X, max.Y, max.Z); // C
  1888. FManager.AddNode(max.X, max.Y, min.Z); // G
  1889. FManager.AddNode(min.X, max.Y, max.Z); // D
  1890. FManager.AddNode(min.X, max.Y, min.Z); // H
  1891. end;
  1892. procedure DrawContact;
  1893. var
  1894. cnt: PNewtonJoint;
  1895. thisContact: PNewtonJoint;
  1896. material: PNewtonMaterial;
  1897. pos, nor: TVector4f;
  1898. begin
  1899. FManager.FCurrentColor := FManager.DebugOption.ContactColor;
  1900. cnt := NewtonBodyGetFirstContactJoint(FNewtonBody);
  1901. while cnt <> nil do
  1902. begin
  1903. thisContact := NewtonContactJointGetFirstContact(cnt);
  1904. while thisContact <> nil do
  1905. begin
  1906. material := NewtonContactGetMaterial(thisContact);
  1907. NewtonMaterialGetContactPositionAndNormal(material, FNewtonBody,
  1908. @pos, @nor);
  1909. FManager.AddNode(pos);
  1910. nor := VectorAdd(pos, nor);
  1911. FManager.AddNode(nor);
  1912. thisContact := NewtonContactJointGetNextContact(cnt, thisContact);
  1913. end;
  1914. cnt := NewtonBodyGetNextContactJoint(FNewtonBody, cnt);
  1915. end;
  1916. end;
  1917. function GetAbsCom(): TVector4f;
  1918. var
  1919. M: TMatrix4f;
  1920. begin
  1921. NewtonBodyGetCentreOfMass(FNewtonBody, @Result);
  1922. M := IdentityHmgMatrix;
  1923. M.W := Result;
  1924. M.W.W := 1;
  1925. M := MatrixMultiply(M, FOwnerBaseSceneObject.AbsoluteMatrix);
  1926. Result := M.W;
  1927. end;
  1928. procedure DrawForce;
  1929. var
  1930. pos: TVector4f;
  1931. nor: TVector4f;
  1932. begin
  1933. pos := GetAbsCom;
  1934. if mdShowForce in FManager.DebugOption.NGDManagerDebugs then
  1935. begin
  1936. FManager.FCurrentColor := FManager.DebugOption.ForceColor;
  1937. nor := VectorAdd(pos, FForce.AsVector);
  1938. FManager.AddNode(pos);
  1939. FManager.AddNode(nor);
  1940. end;
  1941. if mdShowAppliedForce in FManager.DebugOption.NGDManagerDebugs then
  1942. begin
  1943. FManager.FCurrentColor := FManager.DebugOption.AppliedForceColor;
  1944. nor := VectorAdd(pos, FAppliedForce.AsVector);
  1945. FManager.AddNode(pos);
  1946. FManager.AddNode(nor);
  1947. end;
  1948. if mdShowAppliedVelocity in FManager.DebugOption.NGDManagerDebugs then
  1949. begin
  1950. FManager.FCurrentColor := FManager.DebugOption.AppliedVelocityColor;
  1951. nor := VectorAdd(pos, FAppliedVelocity.AsVector);
  1952. FManager.AddNode(pos);
  1953. FManager.AddNode(nor);
  1954. end;
  1955. end;
  1956. procedure DrawCoM;
  1957. var
  1958. com: TVector4f;
  1959. size: Single;
  1960. begin
  1961. FManager.FCurrentColor := FManager.DebugOption.CenterOfMassColor;
  1962. size := FManager.DebugOption.DotAxisSize;
  1963. com := GetAbsCom;
  1964. FManager.AddNode(VectorAdd(com, VectorMake(0, 0, size)));
  1965. FManager.AddNode(VectorAdd(com, VectorMake(0, 0, -size)));
  1966. FManager.AddNode(VectorAdd(com, VectorMake(0, size, 0)));
  1967. FManager.AddNode(VectorAdd(com, VectorMake(0, -size, 0)));
  1968. FManager.AddNode(VectorAdd(com, VectorMake(size, 0, 0)));
  1969. FManager.AddNode(VectorAdd(com, VectorMake(-size, 0, 0)));
  1970. end;
  1971. begin
  1972. inherited;
  1973. // Move/Rotate NewtonObject if matrix are not equal in design time.
  1974. if (csDesigning in FOwnerBaseSceneObject.ComponentState) then
  1975. if not MatrixEquals(NewtonBodyMatrix, FOwnerBaseSceneObject.AbsoluteMatrix)
  1976. then
  1977. SetNewtonBodyMatrix(FOwnerBaseSceneObject.AbsoluteMatrix);
  1978. NewtonBodyGetAABB(FNewtonBody, @(FAABBmin.AsVector), @(FAABBmax.AsVector));
  1979. if NewtonBodyGetSleepState(FNewtonBody) = 1 then
  1980. FManager.FCurrentColor := FManager.DebugOption.AABBColorSleep
  1981. else
  1982. FManager.FCurrentColor := FManager.DebugOption.AABBColor;
  1983. if mdShowAABB in FManager.DebugOption.NGDManagerDebugs then
  1984. DrawAABB(FAABBmin, FAABBmax);
  1985. if mdShowContact in FManager.DebugOption.NGDManagerDebugs then
  1986. DrawContact;
  1987. DrawForce; // Draw Force, AppliedForce and AppliedVelocity
  1988. if mdShowCenterOfMass in FManager.DebugOption.NGDManagerDebugs then
  1989. DrawCoM;
  1990. end;
  1991. procedure TgxNGDDynamic.SetAutoSleep(const Value: Boolean);
  1992. begin
  1993. FAutoSleep := Value;
  1994. if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
  1995. if Assigned(FManager) then
  1996. NewtonBodySetAutoSleep(FNewtonBody, Ord(FAutoSleep));
  1997. end;
  1998. procedure TgxNGDDynamic.SetDensity(const Value: Single);
  1999. var
  2000. inertia: TVector4f;
  2001. origin: TVector4f;
  2002. begin
  2003. if Assigned(FManager) then
  2004. if Value >= 0 then
  2005. begin
  2006. FDensity := Value;
  2007. FVolume := NewtonConvexCollisionCalculateVolume(FCollision);
  2008. NewtonConvexCollisionCalculateInertialMatrix(FCollision,
  2009. @inertia, @origin);
  2010. if IsZero(FVolume, epsilon) then
  2011. begin
  2012. FVolume := FNullCollisionVolume;
  2013. inertia := VectorMake(FNullCollisionVolume, FNullCollisionVolume,
  2014. FNullCollisionVolume, 0);
  2015. end;
  2016. FMass := FVolume * FDensity;
  2017. if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
  2018. NewtonBodySetMassMatrix(FNewtonBody, FMass, FMass * inertia.X,
  2019. FMass * inertia.Y, FMass * inertia.Z);
  2020. FCenterOfMass.AsVector := origin;
  2021. end;
  2022. end;
  2023. procedure TgxNGDDynamic.SetLinearDamping(const Value: Single);
  2024. begin
  2025. if (Value >= 0) and (Value <= 1) then
  2026. FLinearDamping := Value;
  2027. if not(csDesigning in FOwnerBaseSceneObject.ComponentState) then
  2028. if Assigned(FManager) then
  2029. NewtonBodySetLinearDamping(FNewtonBody, FLinearDamping);
  2030. end;
  2031. function TgxNGDDynamic.GetOmega: TVector4f;
  2032. begin
  2033. NewtonBodyGetOmega(FNewtonBody, @Result);
  2034. end;
  2035. procedure TgxNGDDynamic.SetOmega(const Omega: TVector4f);
  2036. begin
  2037. NewtonBodySetOmega(FNewtonBody, @Omega);
  2038. end;
  2039. function TgxNGDDynamic.GetVelocity: TVector4f;
  2040. begin
  2041. NewtonBodyGetVelocity(FNewtonBody, @Result);
  2042. end;
  2043. procedure TgxNGDDynamic.SetVelocity(const Velocity: TVector4f);
  2044. begin
  2045. NewtonBodySetVelocity(FNewtonBody, @Velocity);
  2046. end;
  2047. function TgxNGDDynamic.StoredDensity: Boolean;
  2048. begin
  2049. Result := not SameValue(FDensity, 1, epsilon);
  2050. end;
  2051. function TgxNGDDynamic.StoredLinearDamping: Boolean;
  2052. begin
  2053. Result := not SameValue(FLinearDamping, 0.1, epsilon);
  2054. end;
  2055. function TgxNGDDynamic.StoredNullCollisionVolume: Boolean;
  2056. begin
  2057. Result := not SameValue(FNullCollisionVolume, 0, epsilon);
  2058. end;
  2059. // WriteToFiler
  2060. //
  2061. procedure TgxNGDDynamic.WriteToFiler(writer: TWriter);
  2062. begin
  2063. inherited;
  2064. with writer do
  2065. begin
  2066. WriteInteger(1); // Archive version
  2067. WriteBoolean(FAutoSleep);
  2068. WriteFloat(FLinearDamping);
  2069. WriteFloat(FDensity);
  2070. WriteBoolean(FUseGravity);
  2071. WriteFloat(FNullCollisionVolume);
  2072. end;
  2073. FForce.WriteToFiler(writer);
  2074. FTorque.WriteToFiler(writer);
  2075. FCenterOfMass.WriteToFiler(writer);
  2076. FAngularDamping.WriteToFiler(writer);
  2077. end;
  2078. // ReadFromFiler
  2079. //
  2080. procedure TgxNGDDynamic.ReadFromFiler(reader: TReader);
  2081. var
  2082. version: Integer;
  2083. begin
  2084. inherited;
  2085. with reader do
  2086. begin
  2087. version := ReadInteger; // read data version
  2088. Assert(version <= 1); // Archive version
  2089. FAutoSleep := ReadBoolean;
  2090. if version <= 0 then
  2091. FLinearDamping := ReadSingle
  2092. else
  2093. FLinearDamping := ReadFloat;
  2094. if version <= 0 then
  2095. FDensity := ReadSingle
  2096. else
  2097. FDensity := ReadFloat;
  2098. // if Version >= 1 then
  2099. FUseGravity := ReadBoolean;
  2100. if version <= 0 then
  2101. FNullCollisionVolume := ReadSingle
  2102. else
  2103. FNullCollisionVolume := ReadFloat;
  2104. end;
  2105. FForce.ReadFromFiler(reader);
  2106. FTorque.ReadFromFiler(reader);
  2107. FCenterOfMass.ReadFromFiler(reader);
  2108. FAngularDamping.ReadFromFiler(reader);
  2109. end;
  2110. procedure TgxNGDDynamic.Loaded;
  2111. begin
  2112. inherited;
  2113. if Assigned(FManager) then
  2114. begin
  2115. SetAutoSleep(FAutoSleep);
  2116. SetLinearDamping(FLinearDamping);
  2117. SetDensity(FDensity);
  2118. NotifyCenterOfMassChange(self);
  2119. NotifyAngularDampingChange(self);
  2120. end;
  2121. end;
  2122. class procedure TgxNGDDynamic.NewtonApplyForceAndTorque(const body: PNewtonBody;
  2123. timestep: dFloat; threadIndex: Integer); cdecl;
  2124. begin
  2125. TgxNGDDynamic(NewtonBodyGetUserData(body)).FApplyForceAndTorqueEvent(body,
  2126. timestep, threadIndex);
  2127. end;
  2128. class procedure TgxNGDDynamic.NewtonSetTransform(const body: PNewtonBody;
  2129. const matrix: PdFloat; threadIndex: Integer); cdecl;
  2130. begin
  2131. TgxNGDDynamic(NewtonBodyGetUserData(body)).FSetTransformEvent(body, matrix,
  2132. threadIndex);
  2133. end;
  2134. procedure TgxNGDDynamic.NotifyAngularDampingChange(Sender: TObject);
  2135. begin
  2136. FAngularDamping.OnNotifyChange := nil;
  2137. if (FAngularDamping.X >= 0) and (FAngularDamping.X <= 1) and
  2138. (FAngularDamping.Y >= 0) and (FAngularDamping.Y <= 1) and
  2139. (FAngularDamping.Z >= 0) and (FAngularDamping.Z <= 1) then
  2140. if Assigned(FManager) then
  2141. NewtonBodySetAngularDamping(FNewtonBody, @(FAngularDamping.AsVector));
  2142. FAngularDamping.OnNotifyChange := NotifyAngularDampingChange;
  2143. end;
  2144. procedure TgxNGDDynamic.NotifyCenterOfMassChange(Sender: TObject);
  2145. begin
  2146. FCenterOfMass.OnNotifyChange := nil;
  2147. if Assigned(FManager) then
  2148. NewtonBodySetCentreOfMass(FNewtonBody, @(FCenterOfMass.AsVector));
  2149. FCenterOfMass.OnNotifyChange := NotifyCenterOfMassChange;
  2150. end;
  2151. procedure TgxNGDDynamic.OnApplyForceAndTorqueEvent(const cbody: PNewtonBody;
  2152. timestep: dFloat; threadIndex: Integer);
  2153. var
  2154. worldGravity: TVector4f;
  2155. begin
  2156. // Read Only: We get the force and torque resulting from every interaction on this body
  2157. NewtonBodyGetForce(cbody, @(FAppliedForce.AsVector));
  2158. NewtonBodyGetTorque(cbody, @(FAppliedTorque.AsVector));
  2159. NewtonBodyGetVelocity(cbody, @(FAppliedVelocity.AsVector));
  2160. NewtonBodyGetOmega(cbody, @(FAppliedOmega.AsVector));
  2161. // Raise Custom event
  2162. if Assigned(FCustomForceAndTorqueEvent) then
  2163. FCustomForceAndTorqueEvent(cbody, timestep, threadIndex)
  2164. else
  2165. begin
  2166. NewtonBodySetForce(cbody, @(Force.AsVector));
  2167. NewtonBodySetTorque(cbody, @(Torque.AsVector));
  2168. // Add Gravity from World
  2169. if FUseGravity then
  2170. begin
  2171. worldGravity := VectorScale(FManager.Gravity.AsVector, FMass);
  2172. NewtonBodyAddForce(cbody, @(worldGravity));
  2173. end;
  2174. end;
  2175. end;
  2176. procedure TgxNGDDynamic.OnSetTransformEvent(const cbody: PNewtonBody;
  2177. const cmatrix: PdFloat; threadIndex: Integer);
  2178. var
  2179. epsi: Single;
  2180. begin
  2181. // The Newton API does not support scale [scale modifie value in matrix],
  2182. // so this line reset scale of the GLXceneObject to (1,1,1)
  2183. // to avoid crashing the application
  2184. epsi := 0.0001;
  2185. with FOwnerBaseSceneObject do
  2186. if not SameValue(Scale.X, 1.0, epsi) or not SameValue(Scale.Y, 1.0, epsi) or
  2187. not SameValue(Scale.Z, 1.0, epsi) then
  2188. begin
  2189. Scale.SetVector(1, 1, 1);
  2190. SetNewtonBodyMatrix(AbsoluteMatrix);
  2191. end
  2192. else
  2193. // Make the Position and orientation of the glscene-Object relative to the
  2194. // NewtonBody position and orientation.
  2195. FOwnerBaseSceneObject.AbsoluteMatrix := PMatrix4f(cmatrix)^;
  2196. end;
  2197. // ------------------------------------------------------------------
  2198. // TgxNGDStatic
  2199. // ------------------------------------------------------------------
  2200. procedure TgxNGDStatic.Render;
  2201. begin
  2202. inherited;
  2203. // Move/Rotate NewtonObject if matrix are not equal in run time.
  2204. if not MatrixEquals(NewtonBodyMatrix, FOwnerBaseSceneObject.AbsoluteMatrix)
  2205. then
  2206. SetNewtonBodyMatrix(FOwnerBaseSceneObject.AbsoluteMatrix);
  2207. end;
  2208. class function TgxNGDStatic.FriendlyName: string;
  2209. begin
  2210. Result := 'NGD Static';
  2211. end;
  2212. // ------------------------
  2213. // TgxNGDSurfaceItem
  2214. // ------------------------
  2215. function TgxNGDSurfaceItem.GetDisplayName: string;
  2216. begin
  2217. if FDisplayName = '' then
  2218. FDisplayName := 'Iron';
  2219. Result := FDisplayName;
  2220. end;
  2221. procedure TgxNGDSurfaceItem.SetDisplayName(const Value: string);
  2222. begin
  2223. inherited;
  2224. FDisplayName := Value;
  2225. end;
  2226. // =------------------------------------
  2227. // TgxNGDSurfacePair
  2228. // =------------------------------------
  2229. constructor TgxNGDSurfacePair.Create(Collection: TCollection);
  2230. begin
  2231. inherited;
  2232. FSoftness := 0.1;
  2233. FElasticity := 0.4;
  2234. FCollidable := True;
  2235. FStaticFriction := 0.9;
  2236. FKineticFriction := 0.5;
  2237. FContinuousCollisionMode := False;
  2238. FThickness := False;
  2239. FAABBOverlapEvent := OnNewtonAABBOverlapEvent;
  2240. FContactProcessEvent := OnNewtonContactsProcessEvent;
  2241. FManager := TgxNGDManager(Collection.Owner);
  2242. FManager.RebuildAllMaterial;
  2243. end;
  2244. class function TgxNGDSurfacePair.NewtonAABBOverlap(const material
  2245. : PNewtonMaterial; const body0, body1: PNewtonBody; threadIndex: Integer)
  2246. : Integer; cdecl;
  2247. begin
  2248. Result := Ord(TgxNGDSurfacePair(NewtonMaterialGetMaterialPairUserData
  2249. (material)).FAABBOverlapEvent(material, body0, body1, threadIndex));
  2250. end;
  2251. class procedure TgxNGDSurfacePair.NewtonContactsProcess(const contact
  2252. : PNewtonJoint; timestep: dFloat; threadIndex: Integer); cdecl;
  2253. begin
  2254. TgxNGDSurfacePair(NewtonMaterialGetMaterialPairUserData
  2255. (NewtonContactGetMaterial(NewtonContactJointGetFirstContact(contact))))
  2256. .FContactProcessEvent(contact, timestep, threadIndex);
  2257. end;
  2258. function TgxNGDSurfacePair.OnNewtonAABBOverlapEvent(const cmaterial
  2259. : PNewtonMaterial; const cbody0, cbody1: PNewtonBody;
  2260. threadIndex: Integer): Boolean;
  2261. begin
  2262. Result := True;
  2263. end;
  2264. procedure TgxNGDSurfacePair.OnNewtonContactsProcessEvent(const ccontact
  2265. : PNewtonJoint; timestep: dFloat; threadIndex: Integer);
  2266. begin
  2267. end;
  2268. procedure TgxNGDSurfacePair.SetCollidable(const Value: Boolean);
  2269. begin
  2270. FCollidable := Value;
  2271. FManager.RebuildAllMaterial;
  2272. end;
  2273. procedure TgxNGDSurfacePair.SetContinuousCollisionMode(const Value: Boolean);
  2274. begin
  2275. FContinuousCollisionMode := Value;
  2276. FManager.RebuildAllMaterial;
  2277. end;
  2278. procedure TgxNGDSurfacePair.SetElasticity(const Value: Single);
  2279. begin
  2280. if (Value >= 0) then
  2281. FElasticity := Value;
  2282. FManager.RebuildAllMaterial;
  2283. end;
  2284. procedure TgxNGDSurfacePair.SetKineticFriction(const Value: Single);
  2285. begin
  2286. if (Value >= 0) and (Value <= 1) then
  2287. FKineticFriction := Value;
  2288. FManager.RebuildAllMaterial;
  2289. end;
  2290. procedure TgxNGDSurfacePair.SetMaterialItems(const item1,
  2291. item2: TgxNGDSurfaceItem);
  2292. begin
  2293. FSurfaceItem1 := item1;
  2294. FSurfaceItem2 := item2;
  2295. FManager.RebuildAllMaterial;
  2296. end;
  2297. procedure TgxNGDSurfacePair.SetSoftness(const Value: Single);
  2298. begin
  2299. if (Value >= 0) and (Value <= 1) then
  2300. FSoftness := Value;
  2301. FManager.RebuildAllMaterial;
  2302. end;
  2303. procedure TgxNGDSurfacePair.SetStaticFriction(const Value: Single);
  2304. begin
  2305. if (Value >= 0) and (Value <= 1) then
  2306. FStaticFriction := Value;
  2307. FManager.RebuildAllMaterial;
  2308. end;
  2309. procedure TgxNGDSurfacePair.SetThickness(const Value: Boolean);
  2310. begin
  2311. FThickness := Value;
  2312. FManager.RebuildAllMaterial;
  2313. end;
  2314. function TgxNGDSurfacePair.StoredElasticity: Boolean;
  2315. begin
  2316. Result := not SameValue(FElasticity, 0.4, epsilon);
  2317. end;
  2318. function TgxNGDSurfacePair.StoredKineticFriction: Boolean;
  2319. begin
  2320. Result := not SameValue(FKineticFriction, 0.5, epsilon);
  2321. end;
  2322. function TgxNGDSurfacePair.StoredSoftness: Boolean;
  2323. begin
  2324. Result := not SameValue(FSoftness, 0.1, epsilon);
  2325. end;
  2326. function TgxNGDSurfacePair.StoredStaticFriction: Boolean;
  2327. begin
  2328. Result := not SameValue(FStaticFriction, 0.9, epsilon);
  2329. end;
  2330. // ------------------------
  2331. // TgxNGDJoint
  2332. // ------------------------
  2333. constructor TgxNGDJoint.Create(Collection: TCollection);
  2334. begin
  2335. inherited;
  2336. FCollisionState := False;
  2337. FStiffness := 0.9;
  2338. FNewtonJoint := nil;
  2339. FNewtonUserJoint := nil;
  2340. FParentObject := nil;
  2341. FChildObject := nil;
  2342. FManager := TgxNGDManager(Collection.Owner);
  2343. FBallAndSocketOptions := TgxNGDJointPivot.Create(FManager, self);
  2344. FHingeOptions := TgxNGDJointPin.Create(FManager, self);
  2345. FSliderOptions := TgxNGDJointPin.Create(FManager, self);
  2346. FCorkscrewOptions := TgxNGDJointPin.Create(FManager, self);
  2347. FUniversalOptions := TgxNGDJointPin2.Create(FManager, self);
  2348. FCustomBallAndSocketOptions := TgxNGDJointBallAndSocket.Create
  2349. (FManager, self);
  2350. FCustomHingeOptions := TgxNGDJointHinge.Create(FManager, self);
  2351. FCustomSliderOptions := TgxNGDJointSlider.Create(FManager, self);
  2352. FKinematicOptions := TgxNGDJointKinematicController.Create;
  2353. FUPVectorDirection := TgxCoordinates.CreateInitialized(self, YHmgVector,
  2354. csVector);
  2355. FUPVectorDirection.OnNotifyChange := FManager.RebuildAllJoint;
  2356. end;
  2357. destructor TgxNGDJoint.Destroy;
  2358. begin
  2359. DestroyNewtonData;
  2360. FParentObject := nil;
  2361. FChildObject := nil;
  2362. // Free options
  2363. FBallAndSocketOptions.Free;
  2364. FHingeOptions.Free;
  2365. FSliderOptions.Free;
  2366. FCorkscrewOptions.Free;
  2367. FUniversalOptions.Free;
  2368. FCustomBallAndSocketOptions.Free;
  2369. FCustomHingeOptions.Free;
  2370. FCustomSliderOptions.Free;
  2371. FKinematicOptions.Free;
  2372. FUPVectorDirection.Free;
  2373. inherited;
  2374. end;
  2375. procedure TgxNGDJoint.DestroyNewtonData;
  2376. begin
  2377. if FNewtonJoint <> nil then
  2378. begin
  2379. Assert((FManager <> nil) and (FManager.FNewtonWorld <> nil));
  2380. NewtonDestroyJoint(FManager.FNewtonWorld, FNewtonJoint);
  2381. FNewtonJoint := nil;
  2382. end;
  2383. if FNewtonUserJoint <> nil then
  2384. begin
  2385. (* CustomDestroyJoint(FNewtonUserJoint); *) //from dJointLibrary.dll
  2386. FNewtonUserJoint := nil;
  2387. end;
  2388. end;
  2389. procedure TgxNGDJoint.KinematicControllerPick(pickpoint: TVector4f;
  2390. PickedActions: TgxNGDPickedActions);
  2391. begin
  2392. (* CustomDestroyJoint(FNewtonUserJoint); //from dJointLibrary.dll
  2393. if FJointType = nj_KinematicController then
  2394. if Assigned(FParentObject) then
  2395. begin
  2396. // Creates the joint
  2397. if PickedActions = paAttach then
  2398. begin
  2399. if not Assigned(FNewtonUserJoint) then
  2400. if Assigned(GetNGDDynamic(FParentObject).FNewtonBody) then
  2401. FNewtonUserJoint := CreateCustomKinematicController
  2402. (GetNGDDynamic(FParentObject).FNewtonBody, @pickpoint);
  2403. end;
  2404. // Change the TargetPoint
  2405. if (PickedActions = paMove) or (PickedActions = paAttach) then
  2406. begin
  2407. if Assigned(FNewtonUserJoint) then
  2408. begin
  2409. CustomKinematicControllerSetPickMode(FNewtonUserJoint,
  2410. Ord(FKinematicOptions.FPickModeLinear));
  2411. CustomKinematicControllerSetMaxLinearFriction(FNewtonUserJoint,
  2412. FKinematicOptions.FLinearFriction);
  2413. CustomKinematicControllerSetMaxAngularFriction(FNewtonUserJoint,
  2414. FKinematicOptions.FAngularFriction);
  2415. CustomKinematicControllerSetTargetPosit(FNewtonUserJoint, @pickpoint);
  2416. end;
  2417. end;
  2418. // Delete the joint
  2419. if PickedActions = paDetach then
  2420. begin
  2421. if Assigned(FNewtonUserJoint) then
  2422. begin
  2423. CustomDestroyJoint(FNewtonUserJoint);
  2424. FNewtonUserJoint := nil;
  2425. // Reset autosleep because this joint turns it off
  2426. NewtonBodySetAutoSleep(GetNGDDynamic(FParentObject).FNewtonBody,
  2427. Ord(GetNGDDynamic(FParentObject).AutoSleep));
  2428. end;
  2429. ParentObject := nil;
  2430. end;
  2431. end;
  2432. *)
  2433. end;
  2434. procedure TgxNGDJoint.Render;
  2435. procedure DrawPivot(pivot: TVector4f);
  2436. var
  2437. size: Single;
  2438. begin
  2439. size := FManager.DebugOption.DotAxisSize;
  2440. FManager.FCurrentColor := FManager.DebugOption.JointPivotColor;
  2441. FManager.AddNode(VectorAdd(pivot, VectorMake(0, 0, size)));
  2442. FManager.AddNode(VectorAdd(pivot, VectorMake(0, 0, -size)));
  2443. FManager.AddNode(VectorAdd(pivot, VectorMake(0, size, 0)));
  2444. FManager.AddNode(VectorAdd(pivot, VectorMake(0, -size, 0)));
  2445. FManager.AddNode(VectorAdd(pivot, VectorMake(size, 0, 0)));
  2446. FManager.AddNode(VectorAdd(pivot, VectorMake(-size, 0, 0)));
  2447. end;
  2448. procedure DrawPin(pin, pivot: TVector4f);
  2449. begin
  2450. FManager.FCurrentColor := FManager.DebugOption.JointAxisColor;
  2451. FManager.AddNode(VectorAdd(pivot, pin));
  2452. FManager.AddNode(VectorAdd(pivot, VectorNegate(pin)));
  2453. end;
  2454. procedure DrawJoint(pivot: TVector4f);
  2455. begin
  2456. FManager.FCurrentColor := FManager.DebugOption.CustomColor;
  2457. FManager.AddNode(FParentObject.AbsolutePosition);
  2458. FManager.AddNode(pivot);
  2459. FManager.AddNode(pivot);
  2460. FManager.AddNode(FChildObject.AbsolutePosition);
  2461. end;
  2462. procedure DrawKinematic;
  2463. var
  2464. pickedMatrix: TMatrix4f;
  2465. size: Single;
  2466. begin
  2467. size := FManager.DebugOption.DotAxisSize;
  2468. /// From dJointLibrary.dll
  2469. /// CustomKinematicControllerGetTargetMatrix(FNewtonUserJoint, @pickedMatrix);
  2470. FManager.FCurrentColor := FManager.DebugOption.JointAxisColor;
  2471. FManager.AddNode(FParentObject.AbsolutePosition);
  2472. FManager.AddNode(pickedMatrix.W);
  2473. FManager.FCurrentColor := FManager.DebugOption.JointPivotColor;
  2474. FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(0, 0, size)));
  2475. FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(0, 0, -size)));
  2476. FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(0, size, 0)));
  2477. FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(0, -size, 0)));
  2478. FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(size, 0, 0)));
  2479. FManager.AddNode(VectorAdd(pickedMatrix.W, VectorMake(-size, 0, 0)));
  2480. end;
  2481. begin
  2482. case FJointType of
  2483. nj_BallAndSocket:
  2484. if Assigned(FParentObject) and Assigned(FChildObject) then
  2485. begin
  2486. DrawJoint(FBallAndSocketOptions.FPivotPoint.AsVector);
  2487. DrawPivot(FBallAndSocketOptions.FPivotPoint.AsVector);
  2488. end;
  2489. nj_Hinge:
  2490. if Assigned(FParentObject) and Assigned(FChildObject) then
  2491. begin
  2492. DrawJoint(FHingeOptions.FPivotPoint.AsVector);
  2493. DrawPin(FHingeOptions.FPinDirection.AsVector,
  2494. FHingeOptions.FPivotPoint.AsVector);
  2495. DrawPivot(FHingeOptions.FPivotPoint.AsVector);
  2496. end;
  2497. nj_Slider:
  2498. if Assigned(FParentObject) and Assigned(FChildObject) then
  2499. begin
  2500. DrawJoint(FSliderOptions.FPivotPoint.AsVector);
  2501. DrawPin(FSliderOptions.FPinDirection.AsVector,
  2502. FSliderOptions.FPivotPoint.AsVector);
  2503. DrawPivot(FSliderOptions.FPivotPoint.AsVector);
  2504. end;
  2505. nj_Corkscrew:
  2506. if Assigned(FParentObject) and Assigned(FChildObject) then
  2507. begin
  2508. DrawJoint(FCorkscrewOptions.FPivotPoint.AsVector);
  2509. DrawPin(FCorkscrewOptions.FPinDirection.AsVector,
  2510. FCorkscrewOptions.FPivotPoint.AsVector);
  2511. DrawPivot(FCorkscrewOptions.FPivotPoint.AsVector);
  2512. end;
  2513. nj_Universal:
  2514. if Assigned(FParentObject) and Assigned(FChildObject) then
  2515. begin
  2516. DrawJoint(FUniversalOptions.FPivotPoint.AsVector);
  2517. DrawPin(FUniversalOptions.FPinDirection.AsVector,
  2518. FUniversalOptions.FPivotPoint.AsVector);
  2519. DrawPin(FUniversalOptions.FPinDirection2.AsVector,
  2520. FUniversalOptions.FPivotPoint.AsVector);
  2521. DrawPivot(FUniversalOptions.FPivotPoint.AsVector);
  2522. end;
  2523. nj_CustomBallAndSocket:
  2524. if Assigned(FParentObject) and Assigned(FChildObject) then
  2525. begin
  2526. DrawJoint(FCustomBallAndSocketOptions.FPivotPoint.AsVector);
  2527. DrawPivot(FCustomBallAndSocketOptions.FPivotPoint.AsVector);
  2528. end;
  2529. nj_CustomHinge:
  2530. if Assigned(FParentObject) and Assigned(FChildObject) then
  2531. begin
  2532. DrawJoint(FCustomHingeOptions.FPivotPoint.AsVector);
  2533. DrawPin(FCustomHingeOptions.FPinDirection.AsVector,
  2534. FCustomHingeOptions.FPivotPoint.AsVector);
  2535. DrawPivot(FCustomHingeOptions.FPivotPoint.AsVector);
  2536. end;
  2537. nj_CustomSlider:
  2538. if Assigned(FParentObject) and Assigned(FChildObject) then
  2539. begin
  2540. DrawJoint(FCustomSliderOptions.FPivotPoint.AsVector);
  2541. DrawPin(FCustomSliderOptions.FPinDirection.AsVector,
  2542. FCustomSliderOptions.FPivotPoint.AsVector);
  2543. DrawPivot(FCustomSliderOptions.FPivotPoint.AsVector);
  2544. end;
  2545. nj_UpVector:
  2546. if Assigned(FParentObject) then
  2547. begin // special
  2548. FManager.FCurrentColor := FManager.DebugOption.JointAxisColor;
  2549. FManager.AddNode(FParentObject.AbsolutePosition);
  2550. FManager.AddNode(VectorAdd(FParentObject.AbsolutePosition,
  2551. FUPVectorDirection.AsVector));
  2552. end;
  2553. nj_KinematicController:
  2554. if Assigned(FParentObject) and Assigned(FNewtonUserJoint) then
  2555. begin // special
  2556. DrawKinematic;
  2557. end;
  2558. end;
  2559. end;
  2560. procedure TgxNGDJoint.SetChildObject(const Value: TgxBaseSceneObject);
  2561. begin
  2562. FChildObject := Value;
  2563. FManager.RebuildAllJoint(self);
  2564. end;
  2565. procedure TgxNGDJoint.SetCollisionState(const Value: Boolean);
  2566. begin
  2567. FCollisionState := Value;
  2568. FManager.RebuildAllJoint(self);
  2569. end;
  2570. procedure TgxNGDJoint.SetJointType(const Value: TgxNGDJoints);
  2571. begin
  2572. FJointType := Value;
  2573. FManager.RebuildAllJoint(self);
  2574. end;
  2575. procedure TgxNGDJoint.SetParentObject(const Value: TgxBaseSceneObject);
  2576. begin
  2577. FParentObject := Value;
  2578. FManager.RebuildAllJoint(self);
  2579. end;
  2580. procedure TgxNGDJoint.SetStiffness(const Value: Single);
  2581. begin
  2582. if (Value >= 0) and (Value <= 1) then
  2583. begin
  2584. FStiffness := Value;
  2585. FManager.RebuildAllJoint(self);
  2586. end;
  2587. end;
  2588. function TgxNGDJoint.StoredStiffness: Boolean;
  2589. begin
  2590. Result := not SameValue(FStiffness, 0.9, epsilon);
  2591. end;
  2592. // ------------------------------------------------------------------
  2593. // TgxNGDJoint.TgxNGDJointPivot
  2594. // ------------------------------------------------------------------
  2595. constructor TgxNGDJointPivot.Create(AOwner: TComponent; aOuter: TgxNGDJoint);
  2596. begin
  2597. FManager := AOwner as TgxNGDManager;
  2598. FOuter := aOuter;
  2599. FPivotPoint := TgxCoordinates.CreateInitialized(aOuter, NullHMGPoint,
  2600. csPoint);
  2601. FPivotPoint.OnNotifyChange := FManager.RebuildAllJoint;
  2602. end;
  2603. destructor TgxNGDJointPivot.Destroy;
  2604. begin
  2605. FPivotPoint.Free;
  2606. inherited;
  2607. end;
  2608. // ------------------------------------------------------------------
  2609. // TgxNGDJoint.TgxNGDJointPin
  2610. // ------------------------------------------------------------------
  2611. constructor TgxNGDJointPin.Create(AOwner: TComponent; aOuter: TgxNGDJoint);
  2612. begin
  2613. inherited;
  2614. FPinDirection := TgxCoordinates.CreateInitialized(aOuter, NullHmgVector,
  2615. csVector);
  2616. FPinDirection.OnNotifyChange := FManager.RebuildAllJoint;
  2617. end;
  2618. destructor TgxNGDJointPin.Destroy;
  2619. begin
  2620. FPinDirection.Free;
  2621. inherited;
  2622. end;
  2623. // ------------------------------------------------------------------
  2624. // TgxNGDJoint.TgxNGDJointPin2
  2625. // ------------------------------------------------------------------
  2626. constructor TgxNGDJointPin2.Create(AOwner: TComponent; aOuter: TgxNGDJoint);
  2627. begin
  2628. inherited;
  2629. FPinDirection2 := TgxCoordinates.CreateInitialized(aOuter, NullHmgVector,
  2630. csVector);
  2631. FPinDirection2.OnNotifyChange := FManager.RebuildAllJoint;
  2632. end;
  2633. destructor TgxNGDJointPin2.Destroy;
  2634. begin
  2635. FPinDirection2.Free;
  2636. inherited;
  2637. end;
  2638. // ------------------------------------------------------------------
  2639. // TgxNGDJoint.TgxNGDJointBallAndSocket
  2640. // ------------------------------------------------------------------
  2641. constructor TgxNGDJointBallAndSocket.Create(AOwner: TComponent;
  2642. aOuter: TgxNGDJoint);
  2643. begin
  2644. inherited;
  2645. FConeAngle := 90;
  2646. FMinTwistAngle := -90;
  2647. FMaxTwistAngle := 90;
  2648. end;
  2649. procedure TgxNGDJointBallAndSocket.SetConeAngle(const Value: Single);
  2650. begin
  2651. FConeAngle := Value;
  2652. FManager.RebuildAllJoint(FOuter);
  2653. end;
  2654. procedure TgxNGDJointBallAndSocket.SetMaxTwistAngle(const Value: Single);
  2655. begin
  2656. FMaxTwistAngle := Value;
  2657. FManager.RebuildAllJoint(FOuter);
  2658. end;
  2659. procedure TgxNGDJointBallAndSocket.SetMinTwistAngle(const Value: Single);
  2660. begin
  2661. FMinTwistAngle := Value;
  2662. FManager.RebuildAllJoint(FOuter);
  2663. end;
  2664. function TgxNGDJointBallAndSocket.StoredConeAngle: Boolean;
  2665. begin
  2666. Result := not SameValue(FConeAngle, 90, epsilon);
  2667. end;
  2668. function TgxNGDJointBallAndSocket.StoredMaxTwistAngle: Boolean;
  2669. begin
  2670. Result := not SameValue(FMaxTwistAngle, 90, epsilon);
  2671. end;
  2672. function TgxNGDJointBallAndSocket.StoredMinTwistAngle: Boolean;
  2673. begin
  2674. Result := not SameValue(FMinTwistAngle, -90, epsilon);
  2675. end;
  2676. // ------------------------------------------------------------------
  2677. // TgxNGDJoint.TgxNGDJointHinge
  2678. // ------------------------------------------------------------------
  2679. constructor TgxNGDJointHinge.Create(AOwner: TComponent; aOuter: TgxNGDJoint);
  2680. begin
  2681. inherited;
  2682. FMinAngle := -90;
  2683. FMaxAngle := 90;
  2684. end;
  2685. procedure TgxNGDJointHinge.SetMaxAngle(const Value: Single);
  2686. begin
  2687. FMaxAngle := Value;
  2688. FManager.RebuildAllJoint(FOuter);
  2689. end;
  2690. procedure TgxNGDJointHinge.SetMinAngle(const Value: Single);
  2691. begin
  2692. FMinAngle := Value;
  2693. FManager.RebuildAllJoint(FOuter);
  2694. end;
  2695. function TgxNGDJointHinge.StoredMaxAngle: Boolean;
  2696. begin
  2697. Result := not SameValue(FMaxAngle, 90, epsilon);
  2698. end;
  2699. function TgxNGDJointHinge.StoredMinAngle: Boolean;
  2700. begin
  2701. Result := not SameValue(FMinAngle, -90, epsilon);
  2702. end;
  2703. // ------------------------------------------------------------------
  2704. // TgxNGDJoint.TgxNGDJointSlider
  2705. // ------------------------------------------------------------------
  2706. constructor TgxNGDJointSlider.Create(AOwner: TComponent; aOuter: TgxNGDJoint);
  2707. begin
  2708. inherited;
  2709. FMinDistance := -10;
  2710. FMaxDistance := 10;
  2711. end;
  2712. procedure TgxNGDJointSlider.SetMaxDistance(const Value: Single);
  2713. begin
  2714. FMaxDistance := Value;
  2715. FManager.RebuildAllJoint(FOuter);
  2716. end;
  2717. procedure TgxNGDJointSlider.SetMinDistance(const Value: Single);
  2718. begin
  2719. FMinDistance := Value;
  2720. FManager.RebuildAllJoint(FOuter);
  2721. end;
  2722. function TgxNGDJointSlider.StoredMaxDistance: Boolean;
  2723. begin
  2724. Result := not SameValue(FMaxDistance, 10, epsilon);
  2725. end;
  2726. function TgxNGDJointSlider.StoredMinDistance: Boolean;
  2727. begin
  2728. Result := not SameValue(FMinDistance, -10, epsilon);
  2729. end;
  2730. // ----------------------------------
  2731. // TgxNGDJointKinematicController
  2732. // ----------------------------------
  2733. constructor TgxNGDJointKinematicController.Create;
  2734. begin
  2735. FPickModeLinear := False;
  2736. FLinearFriction := 750;
  2737. FAngularFriction := 250;
  2738. end;
  2739. function TgxNGDJointKinematicController.StoredAngularFriction: Boolean;
  2740. begin
  2741. Result := not SameValue(FAngularFriction, 250, epsilon);
  2742. end;
  2743. function TgxNGDJointKinematicController.StoredLinearFriction: Boolean;
  2744. begin
  2745. Result := not SameValue(FLinearFriction, 750, epsilon);
  2746. end;
  2747. // ------------------------------------------------------------------
  2748. // TgxNGDBehaviourList
  2749. // ------------------------------------------------------------------
  2750. function TgxNGDBehaviourList.GetBehav(index: Integer): TgxNGDBehaviour;
  2751. begin
  2752. Result := Items[index];
  2753. end;
  2754. procedure TgxNGDBehaviourList.PutBehav(index: Integer; Item: TgxNGDBehaviour);
  2755. begin
  2756. inherited put(index, Item);
  2757. end;
  2758. initialization
  2759. // ------------------------------------------------------------------
  2760. RegisterXCollectionItemClass(TgxNGDDynamic);
  2761. RegisterXCollectionItemClass(TgxNGDStatic);
  2762. // ------------------------------------------------------------------
  2763. finalization
  2764. // ------------------------------------------------------------------
  2765. UnregisterXCollectionItemClass(TgxNGDDynamic);
  2766. UnregisterXCollectionItemClass(TgxNGDStatic);
  2767. // CloseNGD;
  2768. end.