2
0

GLS.NGDManager.pas 97 KB

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