GXS.ODEManager.pas 140 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.ODEManager;
  5. (*
  6. An ODE Manager for GXScene.
  7. Notes:
  8. This code is still under development so any part of it may change at anytime.
  9. *)
  10. interface
  11. uses
  12. Winapi.OpenGL,
  13. System.Classes,
  14. System.SysUtils,
  15. System.Math,
  16. GXS.XOpenGL,
  17. GXS.XCollection,
  18. Stage.VectorGeometry,
  19. Stage.Manager,
  20. GXS.Scene,
  21. GXS.Texture,
  22. GXS.Objects,
  23. GXS.PersistentClasses,
  24. GXS.VectorLists,
  25. GXS.Color,
  26. GXS.Coordinates,
  27. GXS.RenderContextInfo,
  28. GXS.State,
  29. Stage.VectorTypes,
  30. GXS.TerrainRenderer,
  31. GXS.Graph,
  32. GXS.ODEUtils,
  33. ODE.Import;
  34. type
  35. TgxODECustomCollisionEvent = procedure(Geom1, Geom2: PdxGeom) of object;
  36. TgxODECollisionEvent = procedure(Sender: TObject; Object1, Object2: TObject;
  37. var Contact: TdContact; var HandleCollision: Boolean) of object;
  38. TgxODEObjectCollisionEvent = procedure(Sender: TObject; Object2: TObject;
  39. var Contact: TdContact; var HandleCollision: Boolean) of object;
  40. TgxODECollisionSurfaceMode = (csmMu2, csmFDir1, csmBounce, csmSoftERP,
  41. csmSoftCFM, csmMotion1, csmMotion2, csmSlip1, csmSlip2);
  42. TgxSurfaceModes = set of TgxODECollisionSurfaceMode;
  43. TgxODESolverMethod = (osmDefault, osmStepFast, osmQuickStep);
  44. TgxODEElements = class;
  45. TgxODEBehaviour = class;
  46. TgxODEElementBase = class;
  47. TgxODEJointBase = class;
  48. TgxODEManager = class(TComponent)
  49. private
  50. FWorld: PdxWorld;
  51. FSpace: PdxSpace;
  52. FContactGroup: TdJointGroupID;
  53. FGravity: TgxCoordinates;
  54. FOnCollision: TgxODECollisionEvent;
  55. FOnCustomCollision: TgxODECustomCollisionEvent;
  56. FNumContactJoints, FMaxContacts: Integer;
  57. FODEBehaviours: TgxPersistentObjectList;
  58. FRFContactList: TList;
  59. FIterations: Integer;
  60. FSolver: TgxODESolverMethod;
  61. FContacts: array of TdContact;
  62. FContactGeoms: array of TdContactGeom;
  63. FRenderPoint: TgxRenderPoint;
  64. FVisible,
  65. FVisibleAtRunTime: Boolean;
  66. FGeomColorDynD,
  67. FGeomColorDynE,
  68. FGeomColorStat: TgxColor;
  69. protected
  70. procedure Loaded; override;
  71. procedure CalcContact(Object1, Object2: TObject; var Contact: TdContact);
  72. procedure Collision(g1, g2: PdxGeom);
  73. procedure GravityChange(Sender: TObject);
  74. procedure SetMaxContacts(const Value: Integer);
  75. procedure SetGravity(Value: TgxCoordinates);
  76. procedure SetIterations(const val: Integer);
  77. function GetODEBehaviour(index: Integer): TgxODEBehaviour;
  78. procedure RegisterODEBehaviour(ODEBehaviour: TgxODEBehaviour);
  79. procedure UnregisterODEBehaviour(ODEBehaviour: TgxODEBehaviour);
  80. procedure SetRenderPoint(const Value: TgxRenderPoint);
  81. procedure RenderEvent(Sender: TObject; var rci: TgxRenderContextInfo);
  82. procedure RenderPointFreed(Sender: TObject);
  83. procedure SetVisible(const Value: Boolean);
  84. procedure SetVisibleAtRunTime(const Value: Boolean);
  85. procedure SetGeomColorDynE(const Value: TgxColor);
  86. procedure GeomColorChangeDynE(Sender: TObject);
  87. procedure SetGeomColorDynD(const Value: TgxColor);
  88. procedure GeomColorChangeDynD(Sender: TObject);
  89. procedure SetGeomColorStat(const Value: TgxColor);
  90. procedure GeomColorChangeStat(Sender: TObject);
  91. property ODEBehaviours[index: Integer]: TgxODEBehaviour read GetODEBehaviour;
  92. public
  93. constructor Create(AOwner: TComponent); override;
  94. destructor Destroy; override;
  95. procedure Step(deltaTime: double);
  96. procedure NotifyChange(Sender: TObject);
  97. property World: PdxWorld read FWorld;
  98. property Space: PdxSpace read FSpace;
  99. property ContactGroup: TdJointGroupID read FContactGroup;
  100. property NumContactJoints: Integer read FNumContactJoints;
  101. published
  102. property Gravity: TgxCoordinates read FGravity write SetGravity;
  103. property OnCollision: TgxODECollisionEvent read FOnCollision write FOnCollision;
  104. property OnCustomCollision: TgxODECustomCollisionEvent read FOnCustomCollision write FOnCustomCollision;
  105. property Solver: TgxODESolverMethod read FSolver write FSolver;
  106. property Iterations: Integer read FIterations write SetIterations;
  107. property MaxContacts: Integer read FMaxContacts write SetMaxContacts;
  108. property RenderPoint: TgxRenderPoint read FRenderPoint write SetRenderPoint;
  109. property Visible: Boolean read FVisible write SetVisible;
  110. property VisibleAtRunTime: Boolean read FVisibleAtRunTime write SetVisibleAtRunTime;
  111. property GeomColorDynD: TgxColor read FGeomColorDynD write SetGeomColorDynD;
  112. property GeomColorDynE: TgxColor read FGeomColorDynE write SetGeomColorDynE;
  113. property GeomColorStat: TgxColor read FGeomColorStat write SetGeomColorStat;
  114. end;
  115. TgxODECollisionSurface = class(TPersistent)
  116. private
  117. FOwner: TPersistent;
  118. FSurfaceParams: TdSurfaceParameters;
  119. FRFCoeff: Single;
  120. FRFEnabled: Boolean;
  121. protected
  122. procedure WriteToFiler(writer: TWriter);
  123. procedure ReadFromFiler(reader: TReader);
  124. function GetSurfaceMode: TgxSurfaceModes;
  125. function GetMu: TdReal;
  126. function GetMu2: TdReal;
  127. function GetBounce: TdReal;
  128. function GetBounce_Vel: TdReal;
  129. function GetSoftERP: TdReal;
  130. function GetSoftCFM: TdReal;
  131. function GetMotion1: TdReal;
  132. function GetMotion2: TdReal;
  133. function GetSlip1: TdReal;
  134. function GetSlip2: TdReal;
  135. procedure SetSurfaceMode(Value: TgxSurfaceModes);
  136. procedure SetMu(Value: TdReal);
  137. procedure SetMu2(Value: TdReal);
  138. procedure SetBounce(Value: TdReal);
  139. procedure SetBounce_Vel(Value: TdReal);
  140. procedure SetSoftERP(Value: TdReal);
  141. procedure SetSoftCFM(Value: TdReal);
  142. procedure SetMotion1(Value: TdReal);
  143. procedure SetMotion2(Value: TdReal);
  144. procedure SetSlip1(Value: TdReal);
  145. procedure SetSlip2(Value: TdReal);
  146. public
  147. constructor Create(AOwner: TPersistent);
  148. function GetOwner: TPersistent; override;
  149. procedure Assign(Source: TPersistent); override;
  150. published
  151. property RollingFrictionCoeff: Single read FRFCoeff write FRFCoeff;
  152. property RollingFrictionEnabled: Boolean read FRFEnabled write FRFEnabled;
  153. property SurfaceMode: TgxSurfaceModes read GetSurfaceMode
  154. write SetSurfaceMode;
  155. property Mu: TdReal read GetMu write SetMu;
  156. property Mu2: TdReal read GetMu2 write SetMu2;
  157. property Bounce: TdReal read GetBounce write SetBounce;
  158. property Bounce_Vel: TdReal read GetBounce_Vel write SetBounce_Vel;
  159. property SoftERP: TdReal read GetSoftERP write SetSoftERP;
  160. property SoftCFM: TdReal read GetSoftCFM write SetSoftCFM;
  161. property Motion1: TdReal read GetMotion1 write SetMotion1;
  162. property Motion2: TdReal read GetMotion2 write SetMotion2;
  163. property Slip1: TdReal read GetSlip1 write SetSlip1;
  164. property Slip2: TdReal read GetSlip2 write SetSlip2;
  165. end;
  166. TgxODEElementClass = class of TgxODEElementBase;
  167. // Basis structures for behaviour style implementations.
  168. TgxODEBehaviour = class(TgxBehaviour)
  169. private
  170. FManager: TgxODEManager;
  171. FManagerName: String;
  172. FSurface: TgxODECollisionSurface;
  173. FOnCollision: TgxODEObjectCollisionEvent;
  174. FInitialized: Boolean;
  175. FOwnerBaseSceneObject: TgxBaseSceneObject;
  176. protected
  177. procedure Initialize; virtual;
  178. procedure Finalize; virtual;
  179. procedure WriteToFiler(writer: TWriter); override;
  180. procedure ReadFromFiler(reader: TReader); override;
  181. procedure Loaded; override;
  182. procedure SetManager(Value: TgxODEManager);
  183. procedure SetSurface(Value: TgxODECollisionSurface);
  184. function GetAbsoluteMatrix: TMatrix4f;
  185. public
  186. constructor Create(AOwner: TXCollection); override;
  187. destructor Destroy; override;
  188. procedure NotifyChange(Sender: TObject);
  189. procedure Render(var rci: TgxRenderContextInfo); virtual;
  190. procedure Reinitialize;
  191. property Initialized: Boolean read FInitialized;
  192. property AbsoluteMatrix: TMatrix4f read GetAbsoluteMatrix;
  193. published
  194. property Manager: TgxODEManager read FManager write SetManager;
  195. property Surface: TgxODECollisionSurface read FSurface write SetSurface;
  196. property OnCollision: TgxODEObjectCollisionEvent read FOnCollision
  197. write FOnCollision;
  198. end;
  199. TgxODEDynamic = class(TgxODEBehaviour)
  200. private
  201. FBody: PdxBody;
  202. FMass: TdMass;
  203. FElements: TgxODEElements;
  204. FEnabled: Boolean;
  205. FJointRegister: TList;
  206. protected
  207. procedure Initialize; override;
  208. procedure Finalize; override;
  209. procedure WriteToFiler(writer: TWriter); override;
  210. procedure ReadFromFiler(reader: TReader); override;
  211. procedure SetMass(const Value: TdMass);
  212. function GetMass: TdMass;
  213. procedure AlignBodyToMatrix(Mat: TMatrix4f);
  214. procedure SetEnabled(const Value: Boolean);
  215. function GetEnabled: Boolean;
  216. procedure RegisterJoint(Joint: TgxODEJointBase);
  217. procedure UnregisterJoint(Joint: TgxODEJointBase);
  218. public
  219. constructor Create(AOwner: TXCollection); override;
  220. destructor Destroy; override;
  221. procedure Render(var rci: TgxRenderContextInfo); override;
  222. class function FriendlyName: String; override;
  223. class function UniqueItem: Boolean; override;
  224. function AddNewElement(AChild: TgxODEElementClass): TgxODEElementBase; virtual;
  225. procedure AlignObject;
  226. function CalculateMass: TdMass;
  227. procedure CalibrateCenterOfMass;
  228. procedure AddForce(Force: TAffineVector);
  229. procedure AddForceAtPos(Force, Pos: TAffineVector);
  230. procedure AddForceAtRelPos(Force, Pos: TAffineVector);
  231. procedure AddRelForce(Force: TAffineVector);
  232. procedure AddRelForceAtPos(Force, Pos: TAffineVector);
  233. procedure AddRelForceAtRelPos(Force, Pos: TAffineVector);
  234. procedure AddTorque(Torque: TAffineVector);
  235. procedure AddRelTorque(Torque: TAffineVector);
  236. property Body: PdxBody read FBody;
  237. property Mass: TdMass read GetMass write SetMass;
  238. published
  239. property Elements: TgxODEElements read FElements;
  240. property Enabled: Boolean read GetEnabled write SetEnabled;
  241. end;
  242. TgxODEStatic = class(TgxODEBehaviour)
  243. private
  244. FElements: TgxODEElements;
  245. protected
  246. procedure Initialize; override;
  247. procedure Finalize; override;
  248. procedure WriteToFiler(writer: TWriter); override;
  249. procedure ReadFromFiler(reader: TReader); override;
  250. procedure AlignElements;
  251. public
  252. constructor Create(AOwner: TXCollection); override;
  253. destructor Destroy; override;
  254. procedure Render(var rci: TgxRenderContextInfo); override;
  255. class function FriendlyName: String; override;
  256. class function UniqueItem: Boolean; override;
  257. function AddNewElement(AChild: TgxODEElementClass): TgxODEElementBase; virtual;
  258. published
  259. property Elements: TgxODEElements read FElements;
  260. end;
  261. TgxODEElements = class(TXCollection)
  262. private
  263. function GetElement(index: Integer): TgxODEElementBase;
  264. public
  265. destructor Destroy; override;
  266. class function ItemsClass: TXCollectionItemClass; override;
  267. procedure Initialize;
  268. procedure Finalize;
  269. procedure NotifyChange(Sender: TObject);
  270. procedure Render(var rci: TgxRenderContextInfo);
  271. property Element[index: Integer]: TgxODEElementBase read GetElement;
  272. end;
  273. TgxODEElementBase = class(TXCollectionItem)
  274. private
  275. FMass: TdMass;
  276. FDensity: TdReal;
  277. FGeomTransform,
  278. FGeomElement: PdxGeom;
  279. FPosition,
  280. FDirection,
  281. FUp: TgxCoordinates;
  282. FLocalMatrix: TMatrix4f;
  283. FRealignODE,
  284. FInitialized,
  285. FDynamic,
  286. FIsCalculating: Boolean;
  287. protected
  288. procedure Initialize; virtual;
  289. procedure Finalize; virtual;
  290. function CalculateMass: TdMass; virtual;
  291. procedure ODERebuild; virtual;
  292. procedure NotifyChange(Sender: TObject);
  293. procedure CoordinateChanged(Sender: TObject);
  294. procedure WriteToFiler(writer: TWriter); override;
  295. procedure ReadFromFiler(reader: TReader); override;
  296. function IsODEInitialized: Boolean;
  297. procedure AlignGeomElementToMatrix(Mat: TMatrix4f); virtual;
  298. procedure SetGeomElement(aGeom: PdxGeom);
  299. procedure RebuildMatrix;
  300. procedure RebuildVectors;
  301. procedure SetDensity(const Value: TdReal);
  302. procedure SetMatrix(const Value: TMatrix4f);
  303. function GetMatrix: TMatrix4f;
  304. procedure SetPosition(const Value: TgxCoordinates);
  305. procedure SetDirection(const Value: TgxCoordinates);
  306. procedure SetUp(const Value: TgxCoordinates);
  307. public
  308. constructor Create(AOwner: TXCollection); override;
  309. destructor Destroy; override;
  310. procedure Render(var rci: TgxRenderContextInfo); virtual;
  311. function AbsoluteMatrix: TMatrix4f;
  312. function AbsolutePosition: TAffineVector;
  313. property Matrix: TMatrix4f read GetMatrix write SetMatrix;
  314. property GeomTransform: PdxGeom read FGeomTransform;
  315. property Geom: PdxGeom read FGeomElement;
  316. property Initialized: Boolean read FInitialized;
  317. published
  318. property Density: TdReal read FDensity write SetDensity;
  319. property Position: TgxCoordinates read FPosition write SetPosition;
  320. property Direction: TgxCoordinates read FDirection write SetDirection;
  321. property Up: TgxCoordinates read FUp write SetUp;
  322. end;
  323. // ODE box implementation.
  324. TgxODEElementBox = class(TgxODEElementBase)
  325. private
  326. FBoxWidth,
  327. FBoxHeight,
  328. FBoxDepth: TdReal;
  329. protected
  330. procedure Initialize; override;
  331. function CalculateMass: TdMass; override;
  332. procedure ODERebuild; override;
  333. procedure WriteToFiler(writer: TWriter); override;
  334. procedure ReadFromFiler(reader: TReader); override;
  335. function GetBoxWidth: TdReal;
  336. function GetBoxHeight: TdReal;
  337. function GetBoxDepth: TdReal;
  338. procedure SetBoxWidth(const Value: TdReal);
  339. procedure SetBoxHeight(const Value: TdReal);
  340. procedure SetBoxDepth(const Value: TdReal);
  341. public
  342. constructor Create(AOwner: TXCollection); override;
  343. procedure Render(var rci: TgxRenderContextInfo); override;
  344. class function FriendlyName: String; override;
  345. class function FriendlyDescription: String; override;
  346. class function ItemCategory: String; override;
  347. published
  348. property BoxWidth: TdReal read GetBoxWidth write SetBoxWidth;
  349. property BoxHeight: TdReal read GetBoxHeight write SetBoxHeight;
  350. property BoxDepth: TdReal read GetBoxDepth write SetBoxDepth;
  351. end;
  352. // ODE sphere implementation.
  353. TgxODEElementSphere = class(TgxODEElementBase)
  354. private
  355. FRadius: TdReal;
  356. protected
  357. procedure Initialize; override;
  358. function CalculateMass: TdMass; override;
  359. procedure ODERebuild; override;
  360. procedure WriteToFiler(writer: TWriter); override;
  361. procedure ReadFromFiler(reader: TReader); override;
  362. function GetRadius: TdReal;
  363. procedure SetRadius(const Value: TdReal);
  364. public
  365. constructor Create(AOwner: TXCollection); override;
  366. procedure Render(var rci: TgxRenderContextInfo); override;
  367. class function FriendlyName: String; override;
  368. class function FriendlyDescription: String; override;
  369. class function ItemCategory: String; override;
  370. published
  371. property Radius: TdReal read GetRadius write SetRadius;
  372. end;
  373. // ODE capped cylinder implementation.
  374. TgxODEElementCapsule = class(TgxODEElementBase)
  375. private
  376. FRadius,
  377. FLength: TdReal;
  378. protected
  379. procedure Initialize; override;
  380. function CalculateMass: TdMass; override;
  381. procedure ODERebuild; override;
  382. procedure WriteToFiler(writer: TWriter); override;
  383. procedure ReadFromFiler(reader: TReader); override;
  384. function GetRadius: TdReal;
  385. function GetLength: TdReal;
  386. procedure SetRadius(const Value: TdReal);
  387. procedure SetLength(const Value: TdReal);
  388. public
  389. constructor Create(AOwner: TXCollection); override;
  390. procedure Render(var rci: TgxRenderContextInfo); override;
  391. class function FriendlyName: String; override;
  392. class function FriendlyDescription: String; override;
  393. class function ItemCategory: String; override;
  394. published
  395. property Radius: TdReal read GetRadius write SetRadius;
  396. property Length: TdReal read GetLength write SetLength;
  397. end;
  398. // ODE cylinder implementation.
  399. TgxODEElementCylinder = class(TgxODEElementBase)
  400. private
  401. FRadius, FLength: TdReal;
  402. protected
  403. procedure Initialize; override;
  404. function CalculateMass: TdMass; override;
  405. procedure ODERebuild; override;
  406. procedure WriteToFiler(writer: TWriter); override;
  407. procedure ReadFromFiler(reader: TReader); override;
  408. function GetRadius: TdReal;
  409. function GetLength: TdReal;
  410. procedure SetRadius(const Value: TdReal);
  411. procedure SetLength(const Value: TdReal);
  412. public
  413. constructor Create(AOwner: TXCollection); override;
  414. procedure Render(var rci: TgxRenderContextInfo); override;
  415. class function FriendlyName: String; override;
  416. class function FriendlyDescription: String; override;
  417. class function ItemCategory: String; override;
  418. published
  419. property Radius: TdReal read GetRadius write SetRadius;
  420. property Length: TdReal read GetLength write SetLength;
  421. end;
  422. // ODE tri-mesh implementation.
  423. TgxODEElementTriMesh = class(TgxODEElementBase)
  424. private
  425. FTriMeshData: PdxTriMeshData;
  426. FVertices: TgxAffineVectorList;
  427. FIndices: TgxIntegerList;
  428. protected
  429. procedure Initialize; override;
  430. procedure Finalize; override;
  431. function CalculateMass: TdMass; override;
  432. procedure WriteToFiler(writer: TWriter); override;
  433. procedure ReadFromFiler(reader: TReader); override;
  434. procedure SetVertices(const Value: TgxAffineVectorList);
  435. procedure SetIndices(const Value: TgxIntegerList);
  436. public
  437. constructor Create(AOwner: TXCollection); override;
  438. destructor Destroy; override;
  439. class function FriendlyName: String; override;
  440. class function FriendlyDescription: String; override;
  441. class function ItemCategory: String; override;
  442. procedure RefreshTriMeshData;
  443. property Vertices: TgxAffineVectorList read FVertices write SetVertices;
  444. property Indices: TgxIntegerList read FIndices write SetIndices;
  445. end;
  446. // ODE plane implementation.
  447. TgxODEElementPlane = class(TgxODEElementBase)
  448. protected
  449. procedure Initialize; override;
  450. procedure WriteToFiler(writer: TWriter); override;
  451. procedure ReadFromFiler(reader: TReader); override;
  452. procedure AlignGeomElementToMatrix(Mat: TMatrix4f); override;
  453. public
  454. class function FriendlyName: String; override;
  455. class function FriendlyDescription: String; override;
  456. class function ItemCategory: String; override;
  457. class function CanAddTo(collection: TXCollection): Boolean; override;
  458. end;
  459. // An XCollection decendant for ODE Joints.
  460. TgxODEJoints = class(TXCollection)
  461. protected
  462. function GetJoint(index: Integer): TgxODEJointBase;
  463. public
  464. class function ItemsClass: TXCollectionItemClass; override;
  465. procedure Initialize;
  466. procedure Finalize;
  467. property Joint[index: Integer]: TgxODEJointBase read GetJoint; default;
  468. end;
  469. { Component front-end for storing ODE Joints. }
  470. TgxODEJointList = class(TComponent)
  471. private
  472. FJoints: TgxODEJoints;
  473. protected
  474. procedure WriteJoints(stream: TStream);
  475. procedure ReadJoints(stream: TStream);
  476. procedure DefineProperties(Filer: TFiler); override;
  477. procedure Loaded; override;
  478. procedure Notification(AComponent: TComponent;
  479. Operation: TOperation); override;
  480. public
  481. constructor Create(AOwner: TComponent); override;
  482. destructor Destroy; override;
  483. published
  484. property Joints: TgxODEJoints read FJoints;
  485. end;
  486. TJointOption = (joBothObjectsMustBeAssigned);
  487. TJointOptions = set of TJointOption;
  488. { Base structures for ODE Joints. }
  489. TgxODEJointBase = class(TXCollectionItem)
  490. private
  491. FJointID: TdJointID;
  492. FObject1, FObject2: TgxBaseSceneObject;
  493. FManager: TgxODEManager;
  494. FObject1Name, FObject2Name, FManagerName: String;
  495. FInitialized, FEnabled: Boolean;
  496. FJointOptions: TJointOptions;
  497. protected
  498. procedure WriteToFiler(writer: TWriter); override;
  499. procedure ReadFromFiler(reader: TReader); override;
  500. procedure Loaded; override;
  501. function IsODEInitialized: Boolean;
  502. procedure RegisterJointWithObject(Obj: TgxBaseSceneObject);
  503. procedure UnregisterJointWithObject(Obj: TgxBaseSceneObject);
  504. procedure Attach;
  505. procedure SetManager(const Value: TgxODEManager);
  506. procedure SetObject1(const Value: TgxBaseSceneObject);
  507. procedure SetObject2(const Value: TgxBaseSceneObject);
  508. procedure SetEnabled(const Value: Boolean);
  509. procedure SetJointOptions(const Value: TJointOptions);
  510. property JointOptions: TJointOptions read FJointOptions
  511. write SetJointOptions;
  512. public
  513. constructor Create(AOwner: TXCollection); override;
  514. destructor Destroy; override;
  515. procedure StructureChanged; virtual;
  516. procedure Initialize; virtual;
  517. procedure Finalize; virtual;
  518. function IsAttached: Boolean;
  519. procedure DoLoaded;
  520. property JointID: TdJointID read FJointID;
  521. property Initialized: Boolean read FInitialized;
  522. published
  523. property Manager: TgxODEManager read FManager write SetManager;
  524. property Object1: TgxBaseSceneObject read FObject1 write SetObject1;
  525. property Object2: TgxBaseSceneObject read FObject2 write SetObject2;
  526. property Enabled: Boolean read FEnabled write SetEnabled;
  527. end;
  528. TgxODESetParamCallback = function(Param: Integer; const Value: TdReal): Boolean of object;
  529. TgxODEGetParamCallback = function(Param: Integer; var Value: TdReal): Boolean of object;
  530. TgxODEJointParams = class(TPersistent)
  531. private
  532. FOwner: TPersistent;
  533. FSetCallback: TgxODESetParamCallback;
  534. FGetCallback: TgxODEGetParamCallback;
  535. FLoStop,
  536. FHiStop,
  537. FVel,
  538. FFMax,
  539. FFudgeFactor,
  540. FBounce,
  541. FCFM,
  542. FStopERP,
  543. FStopCFM,
  544. FSuspensionERP,
  545. FSuspensionCFM: TdReal;
  546. FFlagLoStop,
  547. FFlagHiStop,
  548. FFlagVel,
  549. FFlagFMax,
  550. FFlagFudgeFactor,
  551. FFlagBounce,
  552. FFlagCFM,
  553. FFlagStopERP,
  554. FFlagStopCFM,
  555. FFlagSuspensionERP,
  556. FFlagSuspensionCFM: Boolean;
  557. protected
  558. function GetLoStop: TdReal;
  559. function GetHiStop: TdReal;
  560. function GetVel: TdReal;
  561. function GetFMax: TdReal;
  562. function GetFudgeFactor: TdReal;
  563. function GetBounce: TdReal;
  564. function GetCFM: TdReal;
  565. function GetStopERP: TdReal;
  566. function GetStopCFM: TdReal;
  567. function GetSuspensionERP: TdReal;
  568. function GetSuspensionCFM: TdReal;
  569. procedure SetLoStop(const Value: TdReal);
  570. procedure SetHiStop(const Value: TdReal);
  571. procedure SetVel(const Value: TdReal);
  572. procedure SetFMax(const Value: TdReal);
  573. procedure SetFudgeFactor(const Value: TdReal);
  574. procedure SetBounce(const Value: TdReal);
  575. procedure SetCFM(const Value: TdReal);
  576. procedure SetStopERP(const Value: TdReal);
  577. procedure SetStopCFM(const Value: TdReal);
  578. procedure SetSuspensionERP(const Value: TdReal);
  579. procedure SetSuspensionCFM(const Value: TdReal);
  580. procedure WriteToFiler(writer: TWriter);
  581. procedure ReadFromFiler(reader: TReader);
  582. public
  583. constructor Create(AOwner: TPersistent);
  584. function GetOwner: TPersistent; override;
  585. procedure Assign(Source: TPersistent); override;
  586. procedure ApplyFlagged;
  587. property SetCallback: TgxODESetParamCallback read FSetCallback write FSetCallback;
  588. property GetCallback: TgxODEGetParamCallback read FGetCallback write FGetCallback;
  589. published
  590. property LoStop: TdReal read GetLoStop write SetLoStop;
  591. property HiStop: TdReal read GetHiStop write SetHiStop;
  592. property Vel: TdReal read GetVel write SetVel;
  593. property FMax: TdReal read GetFMax write SetFMax;
  594. property FudgeFactor: TdReal read GetFudgeFactor write SetFudgeFactor;
  595. property Bounce: TdReal read GetBounce write SetBounce;
  596. property CFM: TdReal read GetCFM write SetCFM;
  597. property StopERP: TdReal read GetStopERP write SetStopERP;
  598. property StopCFM: TdReal read GetStopCFM write SetStopCFM;
  599. property SuspensionERP: TdReal read GetSuspensionERP write SetSuspensionERP;
  600. property SuspensionCFM: TdReal read GetSuspensionCFM write SetSuspensionCFM;
  601. end;
  602. // ODE hinge joint implementation.
  603. TgxODEJointHinge = class(TgxODEJointBase)
  604. private
  605. FAnchor,
  606. FAxis: TgxCoordinates;
  607. FAxisParams: TgxODEJointParams;
  608. protected
  609. procedure WriteToFiler(writer: TWriter); override;
  610. procedure ReadFromFiler(reader: TReader); override;
  611. procedure SetAnchor(const Value: TgxCoordinates);
  612. procedure SetAxis(const Value: TgxCoordinates);
  613. procedure AnchorChange(Sender: TObject);
  614. procedure AxisChange(Sender: TObject);
  615. procedure SetAxisParams(const Value: TgxODEJointParams);
  616. function SetAxisParam(Param: Integer; const Value: TdReal): Boolean;
  617. function GetAxisParam(Param: Integer; var Value: TdReal): Boolean;
  618. public
  619. constructor Create(AOwner: TXCollection); override;
  620. destructor Destroy; override;
  621. procedure StructureChanged; override;
  622. procedure Initialize; override;
  623. class function FriendlyName: String; override;
  624. class function FriendlyDescription: String; override;
  625. published
  626. property Anchor: TgxCoordinates read FAnchor write SetAnchor;
  627. property Axis: TgxCoordinates read FAxis write SetAxis;
  628. property AxisParams: TgxODEJointParams read FAxisParams write SetAxisParams;
  629. end;
  630. // ODE ball joint implementation
  631. TgxODEJointBall = class(TgxODEJointBase)
  632. private
  633. FAnchor: TgxCoordinates;
  634. protected
  635. procedure WriteToFiler(writer: TWriter); override;
  636. procedure ReadFromFiler(reader: TReader); override;
  637. procedure SetAnchor(const Value: TgxCoordinates);
  638. procedure AnchorChange(Sender: TObject);
  639. public
  640. constructor Create(AOwner: TXCollection); override;
  641. destructor Destroy; override;
  642. procedure StructureChanged; override;
  643. procedure Initialize; override;
  644. class function FriendlyName: String; override;
  645. class function FriendlyDescription: String; override;
  646. published
  647. property Anchor: TgxCoordinates read FAnchor write SetAnchor;
  648. end;
  649. // ODE slider joint implementation
  650. TgxODEJointSlider = class(TgxODEJointBase)
  651. private
  652. FAxis: TgxCoordinates;
  653. FAxisParams: TgxODEJointParams;
  654. protected
  655. procedure WriteToFiler(writer: TWriter); override;
  656. procedure ReadFromFiler(reader: TReader); override;
  657. procedure SetAxis(const Value: TgxCoordinates);
  658. procedure AxisChange(Sender: TObject);
  659. procedure SetAxisParams(const Value: TgxODEJointParams);
  660. function SetAxisParam(Param: Integer; const Value: TdReal): Boolean;
  661. function GetAxisParam(Param: Integer; var Value: TdReal): Boolean;
  662. public
  663. constructor Create(AOwner: TXCollection); override;
  664. destructor Destroy; override;
  665. procedure StructureChanged; override;
  666. procedure Initialize; override;
  667. class function FriendlyName: String; override;
  668. class function FriendlyDescription: String; override;
  669. published
  670. property Axis: TgxCoordinates read FAxis write SetAxis;
  671. property AxisParams: TgxODEJointParams read FAxisParams write SetAxisParams;
  672. end;
  673. { ODE fixed joint implementation. }
  674. TgxODEJointFixed = class(TgxODEJointBase)
  675. protected
  676. procedure WriteToFiler(writer: TWriter); override;
  677. procedure ReadFromFiler(reader: TReader); override;
  678. public
  679. class function FriendlyName: String; override;
  680. class function FriendlyDescription: String; override;
  681. procedure Initialize; override;
  682. end;
  683. { ODE hinge2 joint implementation. }
  684. TgxODEJointHinge2 = class(TgxODEJointBase)
  685. private
  686. FAnchor, FAxis1, FAxis2: TgxCoordinates;
  687. FAxis1Params, FAxis2Params: TgxODEJointParams;
  688. protected
  689. procedure WriteToFiler(writer: TWriter); override;
  690. procedure ReadFromFiler(reader: TReader); override;
  691. procedure SetAnchor(const Value: TgxCoordinates);
  692. procedure SetAxis1(const Value: TgxCoordinates);
  693. procedure SetAxis2(const Value: TgxCoordinates);
  694. procedure AnchorChange(Sender: TObject);
  695. procedure Axis1Change(Sender: TObject);
  696. procedure Axis2Change(Sender: TObject);
  697. procedure SetAxis1Params(const Value: TgxODEJointParams);
  698. procedure SetAxis2Params(const Value: TgxODEJointParams);
  699. function SetAxis1Param(Param: Integer; const Value: TdReal): Boolean;
  700. function SetAxis2Param(Param: Integer; const Value: TdReal): Boolean;
  701. function GetAxis1Param(Param: Integer; var Value: TdReal): Boolean;
  702. function GetAxis2Param(Param: Integer; var Value: TdReal): Boolean;
  703. public
  704. constructor Create(AOwner: TXCollection); override;
  705. destructor Destroy; override;
  706. procedure StructureChanged; override;
  707. procedure Initialize; override;
  708. class function FriendlyName: String; override;
  709. class function FriendlyDescription: String; override;
  710. published
  711. property Anchor: TgxCoordinates read FAnchor write SetAnchor;
  712. property Axis1: TgxCoordinates read FAxis1 write SetAxis1;
  713. property Axis2: TgxCoordinates read FAxis2 write SetAxis2;
  714. property Axis1Params: TgxODEJointParams read FAxis1Params write SetAxis1Params;
  715. property Axis2Params: TgxODEJointParams read FAxis2Params write SetAxis2Params;
  716. end;
  717. // ODE universal joint implementation
  718. TgxODEJointUniversal = class(TgxODEJointBase)
  719. private
  720. FAnchor,
  721. FAxis1,
  722. FAxis2: TgxCoordinates;
  723. FAxis1Params,
  724. FAxis2Params: TgxODEJointParams;
  725. protected
  726. procedure WriteToFiler(writer: TWriter); override;
  727. procedure ReadFromFiler(reader: TReader); override;
  728. procedure SetAnchor(const Value: TgxCoordinates);
  729. procedure SetAxis1(const Value: TgxCoordinates);
  730. procedure SetAxis2(const Value: TgxCoordinates);
  731. procedure AnchorChange(Sender: TObject);
  732. procedure Axis1Change(Sender: TObject);
  733. procedure Axis2Change(Sender: TObject);
  734. procedure SetAxis1Params(const Value: TgxODEJointParams);
  735. procedure SetAxis2Params(const Value: TgxODEJointParams);
  736. function SetAxis1Param(Param: Integer; const Value: TdReal): Boolean;
  737. function SetAxis2Param(Param: Integer; const Value: TdReal): Boolean;
  738. function GetAxis1Param(Param: Integer; var Value: TdReal): Boolean;
  739. function GetAxis2Param(Param: Integer; var Value: TdReal): Boolean;
  740. public
  741. constructor Create(AOwner: TXCollection); override;
  742. destructor Destroy; override;
  743. procedure Initialize; override;
  744. procedure StructureChanged; override;
  745. class function FriendlyName: String; override;
  746. class function FriendlyDescription: String; override;
  747. published
  748. property Anchor: TgxCoordinates read FAnchor write SetAnchor;
  749. property Axis1: TgxCoordinates read FAxis1 write SetAxis1;
  750. property Axis2: TgxCoordinates read FAxis2 write SetAxis2;
  751. property Axis1Params: TgxODEJointParams read FAxis1Params write SetAxis1Params;
  752. property Axis2Params: TgxODEJointParams read FAxis2Params write SetAxis2Params;
  753. end;
  754. TgxODEContactPoint = class
  755. public
  756. Position: TAffineVector;
  757. Normal: TAffineVector;
  758. Depth: Single;
  759. end;
  760. (*The custom collider is designed for generic contact handling. There is a
  761. contact point generator for sphere, box, capped cylinder, cylinder and cone geoms.
  762. Once the contact points for a collision are generated the abstract Collide
  763. function is called to generate the depth and the contact position and normal.
  764. These points are then sorted and the deepest are applied to ODE *)
  765. TgxODECustomCollider = class(TgxODEBehaviour)
  766. private
  767. FGeom: PdxGeom;
  768. FContactList,
  769. FContactCache: TList;
  770. FTransform: TMatrix4f;
  771. FContactResolution: Single;
  772. FRenderContacts: Boolean;
  773. FContactRenderPoints: TgxAffineVectorList;
  774. FPointSize: Single;
  775. FContactColor: TgxColor;
  776. protected
  777. procedure Initialize; override;
  778. procedure Finalize; override;
  779. procedure WriteToFiler(writer: TWriter); override;
  780. procedure ReadFromFiler(reader: TReader); override;
  781. // Test a position for a collision and fill out the contact information.
  782. function Collide(aPos: TAffineVector; var Depth: Single;
  783. var cPos, cNorm: TAffineVector): Boolean; virtual; abstract;
  784. // Clears the contact list so it's ready for another collision.
  785. procedure ClearContacts;
  786. // Add a contact point to the list for ApplyContacts to processes.
  787. procedure AddContact(x, y, z: TdReal); overload;
  788. procedure AddContact(pos: TAffineVector); overload;
  789. // Sort the current contact list and apply the deepest to ODE.
  790. function ApplyContacts(o1, o2: PdxGeom; flags: Integer;
  791. contact: PdContactGeom; skip: Integer): Integer;
  792. // Set the transform used that transforms contact points generated with AddContact
  793. procedure SetTransform(ATransform: TMatrix4f);
  794. procedure SetContactResolution(const Value: Single);
  795. procedure SetRenderContacts(const Value: Boolean);
  796. procedure SetPointSize(const Value: Single);
  797. procedure SetContactColor(const Value: TgxColor);
  798. public
  799. constructor Create(AOwner: TXCollection); override;
  800. destructor Destroy; override;
  801. procedure Render(var rci: TgxRenderContextInfo); override;
  802. property Geom: PdxGeom read FGeom;
  803. published
  804. (* Defines the resolution of the contact points created for the colliding
  805. Geom. The number of contact points generated change base don the size
  806. of the object and the ContactResolution. Lower values generate higher
  807. resolution contact boundaries, and thus smoother but slower collisions. *)
  808. property ContactResolution: Single read FContactResolution write SetContactResolution;
  809. (* Toggle contact point rendering on and off. (Rendered through the assigned
  810. Manager.RenderPoint. *)
  811. property RenderContacts: Boolean read FRenderContacts write SetRenderContacts;
  812. // Contact point rendering size (in pixels).
  813. property PointSize: Single read FPointSize write SetPointSize;
  814. // Contact point rendering color.
  815. property ContactColor: TgxColor read FContactColor write SetContactColor;
  816. end;
  817. (* Add this behaviour to a TgxHeightField or TgxTerrainRenderer to enable
  818. height based collisions for spheres, boxes, capped cylinders, cylinders and cones. *)
  819. TgxODEHeightField = class(TgxODECustomCollider)
  820. protected
  821. procedure WriteToFiler(writer: TWriter); override;
  822. procedure ReadFromFiler(reader: TReader); override;
  823. function Collide(aPos: TAffineVector; var Depth: Single;
  824. var cPos, cNorm: TAffineVector): Boolean; override;
  825. public
  826. constructor Create(AOwner: TXCollection); override;
  827. class function FriendlyName: string; override;
  828. class function FriendlyDescription: string; override;
  829. class function UniqueItem: Boolean; override;
  830. class function CanAddTo(collection: TXCollection): Boolean; override;
  831. end;
  832. (* ODE nearCallBack, throws near callback to the collision procedure
  833. of the ODE manager linked by the Data pointer *)
  834. procedure nearCallBack(Data: Pointer; o1, o2: PdxGeom); cdecl;
  835. { Helper functions for extracting data from objects with different inheritance. }
  836. function GetBodyFromObject(anObject: TObject): PdxBody;
  837. function GetBodyFromGLXceneObject(anObject: TgxBaseSceneObject): PdxBody;
  838. function GetSurfaceFromObject(anObject: TObject): TgxODECollisionSurface;
  839. // GLODEObject register methods (used for joint object persistence)
  840. procedure RegisterGLXceneObject(anObject: TgxBaseSceneObject);
  841. procedure UnregisterGLXceneObject(anObject: TgxBaseSceneObject);
  842. function GetGLXceneObject(anObjectName: String): TgxBaseSceneObject;
  843. // Get and GetOrCreate functions for ode behaviours
  844. function GetOdeStatic(obj: TgxBaseSceneObject): TgxODEStatic;
  845. function GetOrCreateOdeStatic(obj: TgxBaseSceneObject): TgxODEStatic;
  846. function GetOdeDynamic(obj: TgxBaseSceneObject): TgxODEDynamic;
  847. function GetOrCreateOdeDynamic(obj: TgxBaseSceneObject): TgxODEDynamic;
  848. // Get and GetOrCreate functions for ODE HeightField
  849. function GetODEHeightField(obj: TgxBaseSceneObject): TgxODEHeightField;
  850. function GetOrCreateODEHeightField(obj: TgxBaseSceneObject): TgxODEHeightField;
  851. var
  852. vODEObjectRegister: TList;
  853. vCustomColliderClass: TdGeomClass;
  854. vCustomColliderClassNum: Integer;
  855. implementation // ------------------------------------------------------------
  856. procedure nearCallBack(Data: Pointer; o1, o2: PdxGeom); cdecl;
  857. begin
  858. TgxODEManager(Data).Collision(o1, o2);
  859. end;
  860. function GetBodyFromObject(anObject: TObject): PdxBody;
  861. begin
  862. Result := nil;
  863. if Assigned(anObject) then
  864. if anObject is TgxODEDynamic then
  865. Result := TgxODEDynamic(anObject).Body;
  866. end;
  867. function GetBodyFromGLXceneObject(anObject: TgxBaseSceneObject): PdxBody;
  868. var
  869. temp: TgxODEDynamic;
  870. begin
  871. Result := nil;
  872. if Assigned(anObject) then
  873. begin
  874. temp := TgxODEDynamic(anObject.Behaviours.GetByClass(TgxODEDynamic));
  875. if temp <> nil then
  876. Result := temp.Body;
  877. end;
  878. end;
  879. function GetSurfaceFromObject(anObject: TObject): TgxODECollisionSurface;
  880. var
  881. ODEBehaviour: TgxODEBehaviour;
  882. begin
  883. Result := nil;
  884. if Assigned(anObject) then
  885. if anObject is TgxODEBehaviour then
  886. Result := TgxODEBehaviour(anObject).Surface
  887. else
  888. begin
  889. if (anObject is TgxBaseSceneObject) then
  890. begin
  891. ODEBehaviour := TgxODEBehaviour(TgxBaseSceneObject(anObject)
  892. .Behaviours.GetByClass(TgxODEBehaviour));
  893. if Assigned(ODEBehaviour) then
  894. Result := ODEBehaviour.Surface
  895. end;
  896. end;
  897. end;
  898. function IsGLODEObject(Obj: TgxBaseSceneObject): Boolean;
  899. var
  900. temp: TgxODEDynamic;
  901. begin
  902. Result := False;
  903. if Assigned(Obj) then
  904. begin
  905. temp := TgxODEDynamic(Obj.Behaviours.GetByClass(TgxODEDynamic));
  906. Result := Assigned(temp);
  907. end;
  908. end;
  909. procedure RegisterGLXceneObject(anObject: TgxBaseSceneObject);
  910. begin
  911. if vODEObjectRegister.IndexOf(anObject) = -1 then
  912. vODEObjectRegister.Add(anObject);
  913. end;
  914. procedure UnregisterGLXceneObject(anObject: TgxBaseSceneObject);
  915. begin
  916. vODEObjectRegister.Remove(anObject);
  917. end;
  918. function GetGLXceneObject(anObjectName: String): TgxBaseSceneObject;
  919. var
  920. i: Integer;
  921. begin
  922. Result := nil;
  923. for i := 0 to vODEObjectRegister.Count - 1 do
  924. if TgxBaseSceneObject(vODEObjectRegister[i]).GetNamePath = anObjectName
  925. then
  926. begin
  927. Result := vODEObjectRegister[i];
  928. Exit;
  929. end;
  930. end;
  931. function GetOdeStatic(Obj: TgxBaseSceneObject): TgxODEStatic;
  932. begin
  933. Result := TgxODEStatic(Obj.Behaviours.GetByClass(TgxODEStatic));
  934. end;
  935. function GetOrCreateOdeStatic(Obj: TgxBaseSceneObject): TgxODEStatic;
  936. begin
  937. Result := TgxODEStatic(Obj.GetOrCreateBehaviour(TgxODEStatic));
  938. end;
  939. function GetOdeDynamic(Obj: TgxBaseSceneObject): TgxODEDynamic;
  940. begin
  941. Result := TgxODEDynamic(Obj.Behaviours.GetByClass(TgxODEDynamic));
  942. end;
  943. function GetOrCreateOdeDynamic(Obj: TgxBaseSceneObject): TgxODEDynamic;
  944. begin
  945. Result := TgxODEDynamic(Obj.GetOrCreateBehaviour(TgxODEDynamic));
  946. end;
  947. function GetODEHeightField(obj: TgxBaseSceneObject): TgxODEHeightField;
  948. begin
  949. Result:= TgxODEHeightField(obj.Behaviours.GetByClass(TgxODEHeightField));
  950. end;
  951. function GetOrCreateODEHeightField(obj: TgxBaseSceneObject): TgxODEHeightField;
  952. begin
  953. Result:= TgxODEHeightField(obj.GetOrCreateBehaviour(TgxODEHeightField));
  954. end;
  955. function GetColliderFromGeom(aGeom: PdxGeom): TgxODECustomCollider;
  956. var
  957. temp: TObject;
  958. begin
  959. Result:= nil;
  960. temp:= dGeomGetData(aGeom);
  961. if Assigned(temp) then
  962. if temp is TgxODECustomCollider then
  963. Result:= TgxODECustomCollider(temp);
  964. end;
  965. function ContactSort(Item1, Item2: Pointer): Integer;
  966. var
  967. c1, c2: TgxODEContactPoint;
  968. begin
  969. c1 := TgxODEContactPoint(Item1);
  970. c2 := TgxODEContactPoint(Item2);
  971. if c1.Depth > c2.Depth then
  972. result := -1
  973. else if c1.Depth = c2.Depth then
  974. result := 0
  975. else
  976. result := 1;
  977. end;
  978. function CollideSphere(o1, o2: PdxGeom; flags: Integer; contact: PdContactGeom;
  979. skip: Integer): Integer; cdecl;
  980. var
  981. Collider: TgxODECustomCollider;
  982. i, j, res: Integer;
  983. pos: PdVector3;
  984. R: PdMatrix3;
  985. rmat, mat: TMatrix4f;
  986. rad, dx, dy, dz: TdReal;
  987. begin
  988. Result := 0;
  989. Collider := GetColliderFromGeom(o1);
  990. if not Assigned(Collider) then
  991. exit;
  992. pos := dGeomGetPosition(o2);
  993. R := dGeomGetRotation(o2);
  994. ODERToSceneMatrix(mat, R^, pos^);
  995. Collider.SetTransform(mat);
  996. rad := dGeomSphereGetRadius(o2);
  997. res := Round(10 * rad / Collider.ContactResolution);
  998. if res < 8 then
  999. res := 8;
  1000. Collider.AddContact(0, 0, -rad);
  1001. Collider.AddContact(0, 0, rad);
  1002. rmat := CreateRotationMatrixZ(2 * Pi / res);
  1003. for i := 0 to res - 1 do
  1004. begin
  1005. mat := MatrixMultiply(rmat, mat);
  1006. Collider.SetTransform(mat);
  1007. for j := -(res div 2) + 1 to (res div 2) - 1 do
  1008. begin
  1009. dx := rad * cos(j * Pi / res);
  1010. dy := 0;
  1011. dz := rad * sin(j * Pi / res);
  1012. Collider.AddContact(dx, dy, dz);
  1013. end;
  1014. end;
  1015. Result := Collider.ApplyContacts(o1, o2, flags, contact, skip);
  1016. Collider.SetTransform(IdentityHMGMatrix);
  1017. end;
  1018. function CollideBox(o1, o2: PdxGeom; flags: Integer; contact: PdContactGeom;
  1019. skip: Integer): Integer; cdecl;
  1020. var
  1021. Collider: TgxODECustomCollider;
  1022. i, j, res: Integer;
  1023. rcpres, len1, len2: Single;
  1024. s: TdVector3;
  1025. pos: PdVector3;
  1026. R: PdMatrix3;
  1027. mat: TMatrix4f;
  1028. begin
  1029. Result := 0;
  1030. Collider := GetColliderFromGeom(o1);
  1031. if not Assigned(Collider) then
  1032. exit;
  1033. pos := dGeomGetPosition(o2);
  1034. R := dGeomGetRotation(o2);
  1035. ODERToSceneMatrix(mat, R^, pos^);
  1036. Collider.SetTransform(mat);
  1037. dGeomBoxGetLengths(o2, s);
  1038. res := Round(Sqrt(MaxFloat([s[0], s[1], s[2]])) / Collider.ContactResolution);
  1039. if res < 1 then
  1040. res := 1;
  1041. rcpres := 1 / res;
  1042. s[0] := 0.5 * s[0];
  1043. s[1] := 0.5 * s[1];
  1044. s[2] := 0.5 * s[2];
  1045. with Collider do
  1046. begin
  1047. // Corners
  1048. AddContact(s[0], s[1], s[2]);
  1049. AddContact(s[0], s[1], -s[2]);
  1050. AddContact(s[0], -s[1], s[2]);
  1051. AddContact(s[0], -s[1], -s[2]);
  1052. AddContact(-s[0], s[1], s[2]);
  1053. AddContact(-s[0], s[1], -s[2]);
  1054. AddContact(-s[0], -s[1], s[2]);
  1055. AddContact(-s[0], -s[1], -s[2]);
  1056. // Edges
  1057. for i := -(res - 1) to (res - 1) do
  1058. begin
  1059. len1 := i * rcpres * s[0];
  1060. AddContact(len1, s[1], s[2]);
  1061. AddContact(len1, s[1], -s[2]);
  1062. AddContact(len1, -s[1], s[2]);
  1063. AddContact(len1, -s[1], -s[2]);
  1064. len1 := i * rcpres * s[1];
  1065. AddContact(s[0], len1, s[2]);
  1066. AddContact(s[0], len1, -s[2]);
  1067. AddContact(-s[0], len1, s[2]);
  1068. AddContact(-s[0], len1, -s[2]);
  1069. len1 := i * rcpres * s[2];
  1070. AddContact(s[0], s[1], len1);
  1071. AddContact(s[0], -s[1], len1);
  1072. AddContact(-s[0], s[1], len1);
  1073. AddContact(-s[0], -s[1], len1);
  1074. end;
  1075. // Faces
  1076. for i := -(res - 1) to (res - 1) do
  1077. for j := -(res - 1) to (res - 1) do
  1078. begin
  1079. len1 := i * rcpres * s[0];
  1080. len2 := j * rcpres * s[1];
  1081. AddContact(len1, len2, s[2]);
  1082. AddContact(len1, len2, -s[2]);
  1083. len2 := j * rcpres * s[2];
  1084. AddContact(len1, s[1], len2);
  1085. AddContact(len1, -s[1], len2);
  1086. len1 := i * rcpres * s[1];
  1087. AddContact(s[0], len1, len2);
  1088. AddContact(-s[0], len1, len2);
  1089. end;
  1090. end;
  1091. Result := Collider.ApplyContacts(o1, o2, flags, contact, skip);
  1092. Collider.SetTransform(IdentityHMGMatrix);
  1093. end;
  1094. function CollideCapsule(o1, o2: PdxGeom; flags: Integer; contact: PdContactGeom;
  1095. skip: Integer): Integer; cdecl;
  1096. var
  1097. Collider: TgxODECustomCollider;
  1098. i, j, res: Integer;
  1099. pos: PdVector3;
  1100. R: PdMatrix3;
  1101. mat, rmat: TMatrix4f;
  1102. rad, len, dx, dy, dz: TdReal;
  1103. begin
  1104. Result := 0;
  1105. Collider := GetColliderFromGeom(o1);
  1106. if not Assigned(Collider) then
  1107. exit;
  1108. pos := dGeomGetPosition(o2);
  1109. R := dGeomGetRotation(o2);
  1110. ODERToSceneMatrix(mat, R^, pos^);
  1111. Collider.SetTransform(mat);
  1112. dGeomCapsuleGetParams(o2, rad, len);
  1113. res := Round(5 * MaxFloat(4 * rad, len) / Collider.ContactResolution);
  1114. if res < 8 then
  1115. res := 8;
  1116. rmat := CreateRotationMatrixZ(2 * Pi / res);
  1117. with Collider do
  1118. begin
  1119. AddContact(0, 0, -rad - 0.5 * len);
  1120. AddContact(0, 0, rad + 0.5 * len);
  1121. for i := 0 to res - 1 do
  1122. begin
  1123. mat := MatrixMultiply(rmat, mat);
  1124. SetTransform(mat);
  1125. for j := 0 to res do
  1126. AddContact(rad, 0, len * (j / res - 0.5));
  1127. for j := 1 to (res div 2) - 1 do
  1128. begin
  1129. dx := rad * cos(j * Pi / res);
  1130. dy := 0;
  1131. dz := rad * sin(j * Pi / res);
  1132. Collider.AddContact(dx, dy, -dz - 0.5 * len);
  1133. Collider.AddContact(dx, dy, dz + 0.5 * len);
  1134. end;
  1135. end;
  1136. end;
  1137. Result := Collider.ApplyContacts(o1, o2, flags, contact, skip);
  1138. Collider.SetTransform(IdentityHMGMatrix);
  1139. end;
  1140. function CollideCylinder(o1, o2: PdxGeom; flags: Integer;
  1141. contact: PdContactGeom; skip: Integer): Integer; cdecl;
  1142. var
  1143. Collider: TgxODECustomCollider;
  1144. i, j, res: Integer;
  1145. pos: PdVector3;
  1146. R: PdMatrix3;
  1147. mat: TMatrix4f;
  1148. rad, len, dx, dy: TdReal;
  1149. begin
  1150. Result := 0;
  1151. Collider := GetColliderFromGeom(o1);
  1152. if not Assigned(Collider) then
  1153. exit;
  1154. pos := dGeomGetPosition(o2);
  1155. R := dGeomGetRotation(o2);
  1156. ODERToSceneMatrix(mat, R^, pos^);
  1157. Collider.SetTransform(mat);
  1158. dGeomCylinderGetParams(o2, rad, len);
  1159. res := Round(5 * MaxFloat(4 * rad, len) / Collider.ContactResolution);
  1160. if res < 8 then
  1161. res := 8;
  1162. with Collider do
  1163. begin
  1164. AddContact(0, -0.5 * len, 0);
  1165. AddContact(0, 0.5 * len, 0);
  1166. for i := 0 to res - 1 do
  1167. begin
  1168. SinCosine(2 * Pi * i / res, rad, dy, dx);
  1169. AddContact(dx, -0.5 * len, dy);
  1170. AddContact(dx, 0, dy);
  1171. AddContact(dx, 0.5 * len, dy);
  1172. for j := 0 to res do
  1173. AddContact(dx, len * (j / res - 0.5), dy);
  1174. for j := 1 to (res div 2) - 1 do
  1175. begin
  1176. SinCosine(2 * Pi * i / res, rad * j / (res div 2), dy, dx);
  1177. AddContact(dx, -0.5 * len, dy);
  1178. AddContact(dx, 0.5 * len, dy);
  1179. end;
  1180. end;
  1181. end;
  1182. Result := Collider.ApplyContacts(o1, o2, flags, contact, skip);
  1183. Collider.SetTransform(IdentityHMGMatrix);
  1184. end;
  1185. function GetCustomColliderFn(num: Integer): TdColliderFn; cdecl;
  1186. begin
  1187. if num = dSphereClass then
  1188. Result := CollideSphere
  1189. else if num = dBoxClass then
  1190. Result := CollideBox
  1191. else if num = dCapsuleClass then
  1192. Result := CollideCapsule
  1193. else if num = dCylinderClass then
  1194. Result := CollideCylinder
  1195. else
  1196. Result := nil;
  1197. end;
  1198. // ---------------
  1199. // --------------- TgxODEManager ---------------
  1200. // ---------------
  1201. constructor TgxODEManager.Create(AOwner: TComponent);
  1202. begin
  1203. FWorld := nil;
  1204. if not InitODE('') then
  1205. raise Exception.Create('ODE failed to initialize.');
  1206. inherited;
  1207. FODEBehaviours := TgxPersistentObjectList.Create;
  1208. FRFContactList := TList.Create;
  1209. FGravity := TgxCoordinates.CreateInitialized(Self, NullHmgPoint, csVector);
  1210. FGravity.OnNotifyChange := GravityChange;
  1211. FSolver := osmDefault;
  1212. FIterations := 3;
  1213. MaxContacts := 8;
  1214. if not(csDesigning in ComponentState) then
  1215. begin
  1216. FWorld := dWorldCreate;
  1217. FSpace := dHashSpaceCreate(nil);
  1218. dWorldSetCFM(FWorld, 1E-5);
  1219. dWorldSetQuickStepNumIterations(FWorld, FIterations);
  1220. FContactGroup := dJointGroupCreate(100);
  1221. end;
  1222. FGeomColorDynD := TgxColor.CreateInitialized(Self, clrRed, GeomColorChangeDynD);
  1223. FGeomColorDynE := TgxColor.CreateInitialized(Self, clrLime, GeomColorChangeDynE);
  1224. FGeomColorStat := TgxColor.CreateInitialized(Self, clrBlue, GeomColorChangeStat);
  1225. RegisterManager(Self);
  1226. end;
  1227. destructor TgxODEManager.Destroy;
  1228. begin
  1229. RenderPoint := nil;
  1230. // Unregister everything
  1231. while FODEBehaviours.Count > 0 do
  1232. ODEBehaviours[0].Manager := nil;
  1233. // Clean up everything
  1234. FODEBehaviours.Free;
  1235. FGravity.Free;
  1236. FRFContactList.Free;
  1237. if Assigned(FWorld) then
  1238. begin
  1239. dJointGroupEmpty(FContactGroup);
  1240. dJointGroupDestroy(FContactGroup);
  1241. dSpaceDestroy(FSpace);
  1242. dWorldDestroy(FWorld);
  1243. end;
  1244. FGeomColorDynD.Free;
  1245. FGeomColorDynE.Free;
  1246. FGeomColorStat.Free;
  1247. DeregisterManager(Self);
  1248. inherited Destroy;
  1249. end;
  1250. procedure TgxODEManager.RegisterODEBehaviour(ODEBehaviour: TgxODEBehaviour);
  1251. begin
  1252. FODEBehaviours.Add(ODEBehaviour);
  1253. end;
  1254. procedure TgxODEManager.UnregisterODEBehaviour(ODEBehaviour: TgxODEBehaviour);
  1255. begin
  1256. FODEBehaviours.Remove(ODEBehaviour);
  1257. end;
  1258. procedure TgxODEManager.Loaded;
  1259. begin
  1260. GravityChange(Self);
  1261. end;
  1262. procedure TgxODEManager.SetGravity(Value: TgxCoordinates);
  1263. begin
  1264. FGravity.SetPoint(Value.DirectX, Value.DirectY, Value.DirectZ);
  1265. end;
  1266. procedure TgxODEManager.GravityChange(Sender: TObject);
  1267. begin
  1268. if Assigned(FWorld) then
  1269. dWorldSetGravity(FWorld, FGravity.X, FGravity.Y, FGravity.Z);
  1270. end;
  1271. procedure TgxODEManager.CalcContact(Object1, Object2: TObject; var Contact: TdContact);
  1272. var
  1273. Surface1, Surface2: TgxODECollisionSurface;
  1274. Body1, Body2: PdxBody;
  1275. begin
  1276. Surface1 := GetSurfaceFromObject(Object1);
  1277. Surface2 := GetSurfaceFromObject(Object2);
  1278. if not(Assigned(Surface1) and Assigned(Surface2)) then
  1279. Exit;
  1280. with Contact.Surface do
  1281. begin
  1282. // Average the involved contact information and assign it to the contact.
  1283. // Better methods for contact calculation will be looked into in the future.
  1284. mode := Surface1.FSurfaceParams.mode or Surface2.FSurfaceParams.mode;
  1285. Mu := (Surface1.Mu + Surface2.Mu) * 0.5;
  1286. Mu2 := (Surface1.Mu2 + Surface2.Mu2) * 0.5;
  1287. Bounce := (Surface1.Bounce + Surface2.Bounce) * 0.5;
  1288. Bounce_Vel := (Surface1.Bounce_Vel + Surface2.Bounce_Vel) * 0.5;
  1289. soft_erp := (Surface1.SoftERP + Surface2.SoftERP) * 0.5;
  1290. soft_cfm := (Surface1.SoftCFM + Surface2.SoftCFM) * 0.5;
  1291. Motion1 := (Surface1.Motion1 + Surface2.Motion1) * 0.5;
  1292. Motion2 := (Surface1.Motion2 + Surface2.Motion2) * 0.5;
  1293. Slip1 := (Surface1.Slip1 + Surface2.Slip1) * 0.5;
  1294. Slip2 := (Surface1.Slip2 + Surface2.Slip2) * 0.5;
  1295. end;
  1296. // Rolling friction
  1297. Body1 := GetBodyFromObject(Object1);
  1298. Body2 := GetBodyFromObject(Object2);
  1299. if (Surface1.RollingFrictionEnabled) and Assigned(Body1) then
  1300. FRFContactList.Add(Object1);
  1301. if (Surface2.RollingFrictionEnabled) and Assigned(Body2) then
  1302. FRFContactList.Add(Object2);
  1303. end;
  1304. procedure TgxODEManager.Collision(g1, g2: PdxGeom);
  1305. var
  1306. i, flags, num_contacts: Integer;
  1307. Obj1, Obj2: Pointer;
  1308. b1, b2: PdxBody;
  1309. Joint: TdJointID;
  1310. HandleCollision: Boolean;
  1311. begin
  1312. // Check for custom collision handling event
  1313. if Assigned(FOnCustomCollision) then
  1314. begin
  1315. FOnCustomCollision(g1, g2);
  1316. Exit;
  1317. end;
  1318. Obj1 := dGeomGetData(g1);
  1319. Obj2 := dGeomGetData(g2);
  1320. b1 := dGeomGetBody(g1);
  1321. b2 := dGeomGetBody(g2);
  1322. // don't create contact between static objects
  1323. if not Assigned(b1) and not Assigned(b2) then
  1324. Exit;
  1325. if Assigned(b1) and Assigned(b2) then
  1326. if dAreConnected(b1, b2) = 1 then
  1327. Exit;
  1328. // Get the collisions
  1329. flags := $0000FFFF and FMaxContacts;
  1330. num_contacts := dCollide(g1, g2, flags, FContactGeoms[0], SizeOf(TdContactGeom));
  1331. // Set up the initial contact info
  1332. for i := 0 to num_contacts - 1 do
  1333. begin
  1334. FContacts[i].Geom := FContactGeoms[i];
  1335. end;
  1336. for i := 0 to num_contacts - 1 do
  1337. begin
  1338. HandleCollision := True;
  1339. if Assigned(Obj1) and Assigned(Obj2) then
  1340. begin
  1341. // Calculate the contact based on Obj1 and Obj2 surface info
  1342. CalcContact(Obj1, Obj2, FContacts[i]);
  1343. if Assigned(FOnCollision) then
  1344. begin
  1345. // Fire the Scene level OnCollision event for last minute
  1346. // customization to the contact before the contact joint
  1347. // is created
  1348. FOnCollision(Self, Obj1, Obj2, FContacts[i], HandleCollision);
  1349. end;
  1350. // Fire the OnCollision event for each object
  1351. if TObject(Obj1) is TgxODEBehaviour then
  1352. if Assigned(TgxODEBehaviour(Obj1).FOnCollision) then
  1353. TgxODEBehaviour(Obj1).FOnCollision(Self, Obj2, FContacts[i], HandleCollision);
  1354. if TObject(Obj2) is TgxODEBehaviour then
  1355. if Assigned(TgxODEBehaviour(Obj2).FOnCollision) then
  1356. TgxODEBehaviour(Obj2).FOnCollision(Self, Obj1, FContacts[i], HandleCollision);
  1357. end
  1358. else
  1359. begin
  1360. // Default surface values
  1361. FContacts[i].Surface.Mu := 1000;
  1362. end;
  1363. if HandleCollision then
  1364. begin
  1365. // Create and assign the contact joint
  1366. Joint := dJointCreateContact(FWorld, FContactGroup, @FContacts[i]);
  1367. dJointAttach(Joint, b1, b2);
  1368. // Increment the number of contact joints this step
  1369. Inc(FNumContactJoints);
  1370. end;
  1371. end;
  1372. end;
  1373. procedure TgxODEManager.Step(deltaTime: double);
  1374. var
  1375. i: Integer;
  1376. vec: PdVector3;
  1377. Body: PdxBody;
  1378. Coeff: Single;
  1379. begin
  1380. if not Assigned(World) then
  1381. Exit;
  1382. // Reset the contact joint counter
  1383. FNumContactJoints := 0;
  1384. // Align static elements to their GLScene parent objects
  1385. for i := 0 to FODEBehaviours.Count - 1 do
  1386. if ODEBehaviours[i] is TgxODEStatic then
  1387. if ODEBehaviours[i].Initialized then
  1388. TgxODEStatic(ODEBehaviours[i]).AlignElements;
  1389. // Run ODE collisions and step the scene
  1390. dSpaceCollide(FSpace, Self, nearCallBack);
  1391. case FSolver of
  1392. osmDefault:
  1393. dWorldStep(FWorld, deltaTime);
  1394. osmQuickStep:
  1395. dWorldQuickStep(FWorld, deltaTime);
  1396. end;
  1397. dJointGroupEmpty(FContactGroup);
  1398. // Align dynamic objects to their ODE bodies
  1399. for i := 0 to FODEBehaviours.Count - 1 do
  1400. if ODEBehaviours[i] is TgxODEDynamic then
  1401. if ODEBehaviours[i].Initialized then
  1402. TgxODEDynamic(ODEBehaviours[i]).AlignObject;
  1403. // Process rolling friction
  1404. Coeff := 0;
  1405. Body := nil;
  1406. while FRFContactList.Count > 0 do
  1407. begin
  1408. if TObject(FRFContactList[0]) is TgxODEDynamic then
  1409. begin
  1410. Body := TgxODEDynamic(FRFContactList[0]).Body;
  1411. Coeff := 1 - (TgxODEDynamic(FRFContactList[0])
  1412. .Surface.RollingFrictionCoeff / TgxODEDynamic(FRFContactList[0])
  1413. .Mass.Mass);
  1414. end;
  1415. vec := dBodyGetAngularVel(Body);
  1416. dBodySetAngularVel(Body, vec[0] * Coeff, vec[1] * Coeff, vec[2] * Coeff);
  1417. FRFContactList.Delete(0);
  1418. end;
  1419. end;
  1420. procedure TgxODEManager.NotifyChange(Sender: TObject);
  1421. begin
  1422. if Assigned(RenderPoint) then
  1423. RenderPoint.StructureChanged;
  1424. end;
  1425. procedure TgxODEManager.SetIterations(const val: Integer);
  1426. begin
  1427. FIterations := val;
  1428. if Assigned(FWorld) then
  1429. dWorldSetQuickStepNumIterations(FWorld, FIterations);
  1430. end;
  1431. procedure TgxODEManager.SetMaxContacts(const Value: Integer);
  1432. begin
  1433. if Value <> FMaxContacts then
  1434. begin
  1435. FMaxContacts := Value;
  1436. SetLength(FContacts, FMaxContacts);
  1437. SetLength(FContactGeoms, FMaxContacts);
  1438. end;
  1439. end;
  1440. function TgxODEManager.GetODEBehaviour(index: Integer): TgxODEBehaviour;
  1441. begin
  1442. Result := TgxODEBehaviour(FODEBehaviours[index]);
  1443. end;
  1444. procedure TgxODEManager.SetRenderPoint(const Value: TgxRenderPoint);
  1445. begin
  1446. if FRenderPoint <> Value then
  1447. begin
  1448. if Assigned(FRenderPoint) then
  1449. FRenderPoint.UnRegisterCallBack(RenderEvent);
  1450. FRenderPoint := Value;
  1451. if Assigned(FRenderPoint) then
  1452. FRenderPoint.RegisterCallBack(RenderEvent, RenderPointFreed);
  1453. end;
  1454. end;
  1455. procedure TgxODEManager.RenderEvent(Sender: TObject;
  1456. var rci: TgxRenderContextInfo);
  1457. var
  1458. i: Integer;
  1459. begin
  1460. if not Visible then
  1461. Exit;
  1462. if not(csDesigning in ComponentState) then
  1463. if not VisibleAtRunTime then
  1464. Exit;
  1465. glPushAttrib(GL_ENABLE_BIT + GL_CURRENT_BIT + GL_POLYGON_BIT);
  1466. glDisable(GL_LIGHTING);
  1467. glEnable(GL_POLYGON_OFFSET_LINE);
  1468. glPolygonOffset(1, 2);
  1469. for i := 0 to FODEBehaviours.Count - 1 do
  1470. begin
  1471. if ODEBehaviours[i] is TgxODEDynamic then
  1472. if TgxODEDynamic(ODEBehaviours[i]).GetEnabled then
  1473. glColor4fv(@GeomColorDynE.AsAddress^)
  1474. else
  1475. glColor4fv(@GeomColorDynD.AsAddress^)
  1476. else
  1477. glColor4fv(@GeomColorStat.AsAddress^);
  1478. ODEBehaviours[i].Render(rci);
  1479. end;
  1480. end;
  1481. procedure TgxODEManager.RenderPointFreed(Sender: TObject);
  1482. begin
  1483. FRenderPoint := nil;
  1484. end;
  1485. procedure TgxODEManager.SetVisible(const Value: Boolean);
  1486. begin
  1487. if Value <> FVisible then
  1488. begin
  1489. FVisible := Value;
  1490. NotifyChange(Self);
  1491. end;
  1492. end;
  1493. procedure TgxODEManager.SetVisibleAtRunTime(const Value: Boolean);
  1494. begin
  1495. if Value <> FVisibleAtRunTime then
  1496. begin
  1497. FVisibleAtRunTime := Value;
  1498. NotifyChange(Self);
  1499. end;
  1500. end;
  1501. procedure TgxODEManager.SetGeomColorDynD(const Value: TgxColor);
  1502. begin
  1503. FGeomColorDynD.Assign(Value);
  1504. NotifyChange(Self);
  1505. end;
  1506. procedure TgxODEManager.GeomColorChangeDynD(Sender: TObject);
  1507. begin
  1508. NotifyChange(Self);
  1509. end;
  1510. procedure TgxODEManager.SetGeomColorDynE(const Value: TgxColor);
  1511. begin
  1512. FGeomColorDynE.Assign(Value);
  1513. NotifyChange(Self);
  1514. end;
  1515. procedure TgxODEManager.GeomColorChangeDynE(Sender: TObject);
  1516. begin
  1517. NotifyChange(Self);
  1518. end;
  1519. procedure TgxODEManager.SetGeomColorStat(const Value: TgxColor);
  1520. begin
  1521. FGeomColorStat.Assign(Value);
  1522. NotifyChange(Self);
  1523. end;
  1524. procedure TgxODEManager.GeomColorChangeStat(Sender: TObject);
  1525. begin
  1526. NotifyChange(Self);
  1527. end;
  1528. // ---------------
  1529. // --------------- TgxODECollisionSurface ---------------
  1530. // ---------------
  1531. constructor TgxODECollisionSurface.Create(AOwner: TPersistent);
  1532. begin
  1533. inherited Create;
  1534. FOwner := AOwner;
  1535. Mu := 1000;
  1536. RollingFrictionEnabled := False;
  1537. RollingFrictionCoeff := 0.001; // Larger Coeff = more friction
  1538. end;
  1539. function TgxODECollisionSurface.GetOwner: TPersistent;
  1540. begin
  1541. Result := FOwner;
  1542. end;
  1543. procedure TgxODECollisionSurface.Assign(Source: TPersistent);
  1544. begin
  1545. inherited;
  1546. if not Assigned(Source) then
  1547. Exit;
  1548. if Source is TgxODECollisionSurface then
  1549. begin
  1550. RollingFrictionCoeff := TgxODECollisionSurface(Source).RollingFrictionCoeff;
  1551. RollingFrictionEnabled := TgxODECollisionSurface(Source).RollingFrictionEnabled;
  1552. SurfaceMode := TgxODECollisionSurface(Source).SurfaceMode;
  1553. Mu := TgxODECollisionSurface(Source).Mu;
  1554. Mu2 := TgxODECollisionSurface(Source).Mu2;
  1555. Bounce := TgxODECollisionSurface(Source).Bounce;
  1556. Bounce_Vel := TgxODECollisionSurface(Source).Bounce_Vel;
  1557. SoftERP := TgxODECollisionSurface(Source).SoftERP;
  1558. SoftCFM := TgxODECollisionSurface(Source).SoftCFM;
  1559. Motion1 := TgxODECollisionSurface(Source).Motion1;
  1560. Motion2 := TgxODECollisionSurface(Source).Motion2;
  1561. Slip1 := TgxODECollisionSurface(Source).Slip1;
  1562. Slip2 := TgxODECollisionSurface(Source).Slip2;
  1563. end;
  1564. end;
  1565. procedure TgxODECollisionSurface.WriteToFiler(writer: TWriter);
  1566. var
  1567. mode: TgxSurfaceModes;
  1568. begin
  1569. with writer do
  1570. begin
  1571. WriteInteger(0);
  1572. WriteFloat(RollingFrictionCoeff);
  1573. WriteBoolean(RollingFrictionEnabled);
  1574. mode := SurfaceMode;
  1575. Write(mode, SizeOf(TgxSurfaceModes));
  1576. WriteFloat(Mu);
  1577. WriteFloat(Mu2);
  1578. WriteFloat(Bounce);
  1579. WriteFloat(Bounce_Vel);
  1580. WriteFloat(SoftERP);
  1581. WriteFloat(SoftCFM);
  1582. WriteFloat(Motion1);
  1583. WriteFloat(Motion2);
  1584. WriteFloat(Slip1);
  1585. WriteFloat(Slip2);
  1586. end;
  1587. end;
  1588. procedure TgxODECollisionSurface.ReadFromFiler(reader: TReader);
  1589. var
  1590. archiveVersion: Integer;
  1591. mode: TgxSurfaceModes;
  1592. begin
  1593. with reader do
  1594. begin
  1595. archiveVersion := ReadInteger;
  1596. Assert(archiveVersion = 0);
  1597. RollingFrictionCoeff := ReadFloat;
  1598. RollingFrictionEnabled := ReadBoolean;
  1599. Read(mode, SizeOf(TgxSurfaceModes));
  1600. SurfaceMode := mode;
  1601. Mu := ReadFloat;
  1602. Mu2 := ReadFloat;
  1603. Bounce := ReadFloat;
  1604. Bounce_Vel := ReadFloat;
  1605. SoftERP := ReadFloat;
  1606. SoftCFM := ReadFloat;
  1607. Motion1 := ReadFloat;
  1608. Motion2 := ReadFloat;
  1609. Slip1 := ReadFloat;
  1610. Slip2 := ReadFloat;
  1611. end;
  1612. end;
  1613. // GetSurfaceMode
  1614. //
  1615. function TgxODECollisionSurface.GetSurfaceMode: TgxSurfaceModes;
  1616. var
  1617. ASurfaceModes: TgxSurfaceModes;
  1618. begin
  1619. ASurfaceModes := [];
  1620. if (FSurfaceParams.mode and dContactSlip2) <> 0 then
  1621. ASurfaceModes := ASurfaceModes + [csmSlip2];
  1622. if (FSurfaceParams.mode and dContactSlip1) <> 0 then
  1623. ASurfaceModes := ASurfaceModes + [csmSlip1];
  1624. if (FSurfaceParams.mode and dContactMotion2) <> 0 then
  1625. ASurfaceModes := ASurfaceModes + [csmMotion2];
  1626. if (FSurfaceParams.mode and dContactMotion1) <> 0 then
  1627. ASurfaceModes := ASurfaceModes + [csmMotion1];
  1628. if (FSurfaceParams.mode and dContactSoftCFM) <> 0 then
  1629. ASurfaceModes := ASurfaceModes + [csmSoftCFM];
  1630. if (FSurfaceParams.mode and dContactSoftERP) <> 0 then
  1631. ASurfaceModes := ASurfaceModes + [csmSoftERP];
  1632. if (FSurfaceParams.mode and dContactBounce) <> 0 then
  1633. ASurfaceModes := ASurfaceModes + [csmBounce];
  1634. if (FSurfaceParams.mode and dContactFDir1) <> 0 then
  1635. ASurfaceModes := ASurfaceModes + [csmFDir1];
  1636. if (FSurfaceParams.mode and dContactMu2) <> 0 then
  1637. ASurfaceModes := ASurfaceModes + [csmMu2];
  1638. Result := ASurfaceModes;
  1639. end;
  1640. procedure TgxODECollisionSurface.SetSurfaceMode(Value: TgxSurfaceModes);
  1641. var
  1642. AMode: Integer;
  1643. begin
  1644. AMode := 0;
  1645. if csmSlip2 in Value then
  1646. AMode := AMode or dContactSlip2;
  1647. if csmSlip1 in Value then
  1648. AMode := AMode or dContactSlip1;
  1649. if csmMotion2 in Value then
  1650. AMode := AMode or dContactMotion2;
  1651. if csmMotion1 in Value then
  1652. AMode := AMode or dContactMotion1;
  1653. if csmSoftCFM in Value then
  1654. AMode := AMode or dContactSoftCFM;
  1655. if csmSoftERP in Value then
  1656. AMode := AMode or dContactSoftERP;
  1657. if csmBounce in Value then
  1658. AMode := AMode or dContactBounce;
  1659. if csmFDir1 in Value then
  1660. AMode := AMode or dContactFDir1;
  1661. if csmMu2 in Value then
  1662. AMode := AMode or dContactMu2;
  1663. FSurfaceParams.mode := AMode;
  1664. end;
  1665. function TgxODECollisionSurface.GetMu: TdReal;
  1666. begin
  1667. Result := FSurfaceParams.Mu;
  1668. end;
  1669. function TgxODECollisionSurface.GetMu2: TdReal;
  1670. begin
  1671. Result := FSurfaceParams.Mu2;
  1672. end;
  1673. function TgxODECollisionSurface.GetBounce: TdReal;
  1674. begin
  1675. Result := FSurfaceParams.Bounce;
  1676. end;
  1677. function TgxODECollisionSurface.GetBounce_Vel: TdReal;
  1678. begin
  1679. Result := FSurfaceParams.Bounce_Vel;
  1680. end;
  1681. function TgxODECollisionSurface.GetSoftERP: TdReal;
  1682. begin
  1683. Result := FSurfaceParams.soft_erp;
  1684. end;
  1685. function TgxODECollisionSurface.GetSoftCFM: TdReal;
  1686. begin
  1687. Result := FSurfaceParams.soft_cfm;
  1688. end;
  1689. function TgxODECollisionSurface.GetMotion1: TdReal;
  1690. begin
  1691. Result := FSurfaceParams.Motion1;
  1692. end;
  1693. function TgxODECollisionSurface.GetMotion2: TdReal;
  1694. begin
  1695. Result := FSurfaceParams.Motion2;
  1696. end;
  1697. function TgxODECollisionSurface.GetSlip1: TdReal;
  1698. begin
  1699. Result := FSurfaceParams.Slip1;
  1700. end;
  1701. function TgxODECollisionSurface.GetSlip2: TdReal;
  1702. begin
  1703. Result := FSurfaceParams.Slip2;
  1704. end;
  1705. procedure TgxODECollisionSurface.SetMu(Value: TdReal);
  1706. begin
  1707. FSurfaceParams.Mu := Value;
  1708. end;
  1709. procedure TgxODECollisionSurface.SetMu2(Value: TdReal);
  1710. begin
  1711. FSurfaceParams.Mu2 := Value;
  1712. end;
  1713. procedure TgxODECollisionSurface.SetBounce(Value: TdReal);
  1714. begin
  1715. FSurfaceParams.Bounce := Value;
  1716. end;
  1717. procedure TgxODECollisionSurface.SetBounce_Vel(Value: TdReal);
  1718. begin
  1719. FSurfaceParams.Bounce_Vel := Value;
  1720. end;
  1721. procedure TgxODECollisionSurface.SetSoftERP(Value: TdReal);
  1722. begin
  1723. FSurfaceParams.soft_erp := Value;
  1724. end;
  1725. procedure TgxODECollisionSurface.SetSoftCFM(Value: TdReal);
  1726. begin
  1727. FSurfaceParams.soft_cfm := Value;
  1728. end;
  1729. procedure TgxODECollisionSurface.SetMotion1(Value: TdReal);
  1730. begin
  1731. FSurfaceParams.Motion1 := Value;
  1732. end;
  1733. procedure TgxODECollisionSurface.SetMotion2(Value: TdReal);
  1734. begin
  1735. FSurfaceParams.Motion2 := Value;
  1736. end;
  1737. procedure TgxODECollisionSurface.SetSlip1(Value: TdReal);
  1738. begin
  1739. FSurfaceParams.Slip1 := Value;
  1740. end;
  1741. procedure TgxODECollisionSurface.SetSlip2(Value: TdReal);
  1742. begin
  1743. FSurfaceParams.Slip2 := Value;
  1744. end;
  1745. // ---------------
  1746. // --------------- TgxODEBehaviour --------------
  1747. // ---------------
  1748. constructor TgxODEBehaviour.Create(AOwner: TXCollection);
  1749. begin
  1750. inherited;
  1751. FSurface := TgxODECollisionSurface.Create(Self);
  1752. FInitialized := False;
  1753. FOwnerBaseSceneObject := OwnerBaseSceneObject;
  1754. if Assigned(FOwnerBaseSceneObject) then
  1755. RegisterGLXceneObject(OwnerBaseSceneObject);
  1756. end;
  1757. destructor TgxODEBehaviour.Destroy;
  1758. begin
  1759. if Assigned(Manager) then
  1760. Manager := nil;
  1761. if Assigned(FOwnerBaseSceneObject) then
  1762. UnregisterGLXceneObject(FOwnerBaseSceneObject);
  1763. FSurface.Free;
  1764. inherited;
  1765. end;
  1766. procedure TgxODEBehaviour.Initialize;
  1767. begin
  1768. FInitialized := True;
  1769. end;
  1770. procedure TgxODEBehaviour.Finalize;
  1771. begin
  1772. FInitialized := False;
  1773. end;
  1774. procedure TgxODEBehaviour.Reinitialize;
  1775. begin
  1776. if Initialized then
  1777. Finalize;
  1778. Initialize;
  1779. end;
  1780. procedure TgxODEBehaviour.WriteToFiler(writer: TWriter);
  1781. begin
  1782. inherited;
  1783. with writer do
  1784. begin
  1785. WriteInteger(0); // Archive version
  1786. if Assigned(FManager) then
  1787. WriteString(FManager.GetNamePath)
  1788. else
  1789. WriteString('');
  1790. Surface.WriteToFiler(writer);
  1791. end;
  1792. end;
  1793. procedure TgxODEBehaviour.ReadFromFiler(reader: TReader);
  1794. begin
  1795. inherited;
  1796. with reader do
  1797. begin
  1798. Assert(ReadInteger = 0); // Archive version
  1799. FManagerName := ReadString;
  1800. Surface.ReadFromFiler(reader);
  1801. end;
  1802. end;
  1803. procedure TgxODEBehaviour.Loaded;
  1804. var
  1805. mng: TComponent;
  1806. begin
  1807. inherited;
  1808. if FManagerName <> '' then
  1809. begin
  1810. mng := FindManager(TgxODEManager, FManagerName);
  1811. if Assigned(mng) then
  1812. Manager := TgxODEManager(mng);
  1813. FManagerName := '';
  1814. end
  1815. end;
  1816. procedure TgxODEBehaviour.Render(var rci: TgxRenderContextInfo);
  1817. begin
  1818. // virtual
  1819. end;
  1820. procedure TgxODEBehaviour.NotifyChange(Sender: TObject);
  1821. begin
  1822. if Assigned(Manager) then
  1823. Manager.NotifyChange(Self);
  1824. end;
  1825. procedure TgxODEBehaviour.SetManager(Value: TgxODEManager);
  1826. begin
  1827. if FManager <> Value then
  1828. begin
  1829. if Assigned(FManager) then
  1830. begin
  1831. if Initialized then
  1832. Finalize;
  1833. FManager.UnregisterODEBehaviour(Self);
  1834. end;
  1835. FManager := Value;
  1836. if Assigned(FManager) then
  1837. begin
  1838. if not(csDesigning in TComponent(Owner.Owner).ComponentState) then
  1839. // mrqzzz moved here
  1840. Initialize;
  1841. FManager.RegisterODEBehaviour(Self);
  1842. end;
  1843. end;
  1844. end;
  1845. procedure TgxODEBehaviour.SetSurface(Value: TgxODECollisionSurface);
  1846. begin
  1847. FSurface.Assign(Value);
  1848. end;
  1849. function TgxODEBehaviour.GetAbsoluteMatrix: TMatrix4f;
  1850. begin
  1851. Result := IdentityHMGMatrix;
  1852. if Assigned(Owner.Owner) then
  1853. if Owner.Owner is TgxBaseSceneObject then
  1854. Result := TgxBaseSceneObject(Owner.Owner).AbsoluteMatrix;
  1855. end;
  1856. // ---------------
  1857. // --------------- TgxODEDynamic ---------------
  1858. // ---------------
  1859. constructor TgxODEDynamic.Create(AOwner: TXCollection);
  1860. begin
  1861. inherited;
  1862. FElements := TgxODEElements.Create(Self);
  1863. FJointRegister := TList.Create;
  1864. FEnabled := True;
  1865. end;
  1866. destructor TgxODEDynamic.Destroy;
  1867. begin
  1868. FElements.Free;
  1869. FJointRegister.Free;
  1870. inherited;
  1871. end;
  1872. procedure TgxODEDynamic.Render(var rci: TgxRenderContextInfo);
  1873. var
  1874. Mat: TMatrix4f;
  1875. begin
  1876. if Assigned(Owner.Owner) then
  1877. begin
  1878. rci.PipelineTransformation.Push;
  1879. Mat := TgxBaseSceneObject(Owner.Owner).AbsoluteMatrix;
  1880. rci.PipelineTransformation.ModelMatrix^ := Mat;
  1881. end;
  1882. Elements.Render(rci);
  1883. if Assigned(Owner.Owner) then
  1884. rci.PipelineTransformation.Pop;
  1885. end;
  1886. class function TgxODEDynamic.FriendlyName: String;
  1887. begin
  1888. Result := 'ODE Dynamic';
  1889. end;
  1890. procedure TgxODEDynamic.Initialize;
  1891. var
  1892. i: Integer;
  1893. begin
  1894. if (not Assigned(Manager)) or Assigned(FBody) or (FInitialized) then
  1895. Exit;
  1896. if not Assigned(Manager.World) then
  1897. Exit;
  1898. FBody := dBodyCreate(Manager.World);
  1899. AlignBodyToMatrix(OwnerBaseSceneObject.AbsoluteMatrix);
  1900. dMassSetZero(FMass);
  1901. FElements.Initialize;
  1902. CalculateMass;
  1903. CalibrateCenterOfMass;
  1904. if (FMass.Mass > 0) and (FBody <> nil) then // mrqzzz
  1905. dBodySetMass(FBody, @FMass);
  1906. Enabled := FEnabled;
  1907. for i := 0 to FJointRegister.Count - 1 do
  1908. TgxODEJointBase(FJointRegister[i]).Attach;
  1909. inherited;
  1910. end;
  1911. procedure TgxODEDynamic.Finalize;
  1912. var
  1913. i: Integer;
  1914. begin
  1915. if not FInitialized then
  1916. Exit;
  1917. FElements.Finalize;
  1918. if Assigned(FBody) then
  1919. begin
  1920. dBodyDestroy(FBody);
  1921. FBody := nil;
  1922. end;
  1923. dMassSetZero(FMass);
  1924. for i := 0 to FJointRegister.Count - 1 do
  1925. TgxODEJointBase(FJointRegister[i]).Attach;
  1926. inherited;
  1927. end;
  1928. procedure TgxODEDynamic.WriteToFiler(writer: TWriter);
  1929. begin
  1930. inherited;
  1931. with writer do
  1932. begin
  1933. WriteInteger(1); // Archive version
  1934. FElements.WriteToFiler(writer);
  1935. writer.WriteBoolean(FEnabled);
  1936. end;
  1937. end;
  1938. procedure TgxODEDynamic.ReadFromFiler(reader: TReader);
  1939. var
  1940. archiveVersion: Integer;
  1941. begin
  1942. inherited;
  1943. with reader do
  1944. begin
  1945. archiveVersion := ReadInteger;
  1946. Assert((archiveVersion >= 0) and (archiveVersion <= 1)); // Archive version
  1947. // version 0
  1948. FElements.ReadFromFiler(reader);
  1949. // version 1
  1950. if archiveVersion >= 1 then
  1951. begin
  1952. FEnabled := ReadBoolean;
  1953. end;
  1954. end;
  1955. end;
  1956. procedure TgxODEDynamic.RegisterJoint(Joint: TgxODEJointBase);
  1957. begin
  1958. if FJointRegister.IndexOf(Joint) = -1 then
  1959. FJointRegister.Add(Joint);
  1960. end;
  1961. procedure TgxODEDynamic.UnregisterJoint(Joint: TgxODEJointBase);
  1962. begin
  1963. if FJointRegister.IndexOf(Joint) > -1 then
  1964. FJointRegister.Remove(Joint);
  1965. end;
  1966. function TgxODEDynamic.AddNewElement(AChild: TgxODEElementClass): TgxODEElementBase;
  1967. var
  1968. calcmass: TdMass;
  1969. begin
  1970. Result := AChild.Create(FElements);
  1971. // FElements.Add(Result);
  1972. Result.Initialize;
  1973. calcmass := CalculateMass;
  1974. if (calcmass.Mass > 0) and (FBody <> nil) then // mrqzzz
  1975. dBodySetMass(FBody, @calcmass);
  1976. end;
  1977. procedure TgxODEDynamic.AlignObject;
  1978. var
  1979. Pos: PdVector3;
  1980. R: PdMatrix3;
  1981. m: TMatrix4f;
  1982. begin
  1983. Pos := dBodyGetPosition(Body);
  1984. R := dBodyGetRotation(Body);
  1985. ODERToSceneMatrix(m, R^, Pos^);
  1986. if OwnerBaseSceneObject.Parent is TgxBaseSceneObject then
  1987. m := MatrixMultiply(m, OwnerBaseSceneObject.Parent.InvAbsoluteMatrix);
  1988. OwnerBaseSceneObject.Matrix^ := m;
  1989. end;
  1990. procedure TgxODEDynamic.AlignBodyToMatrix(Mat: TMatrix4f);
  1991. var
  1992. R: TdMatrix3;
  1993. begin
  1994. if not Assigned(FBody) then
  1995. Exit;
  1996. R[0] := Mat.X.X;
  1997. R[1] := Mat.Y.X;
  1998. R[2] := Mat.Z.X;
  1999. R[3] := 0;
  2000. R[4] := Mat.X.Y;
  2001. R[5] := Mat.Y.Y;
  2002. R[6] := Mat.Z.Y;
  2003. R[7] := 0;
  2004. R[8] := Mat.X.Z;
  2005. R[9] := Mat.Y.Z;
  2006. R[10] := Mat.Z.Z;
  2007. R[11] := 0;
  2008. dBodySetRotation(FBody, R);
  2009. dBodySetPosition(FBody, Mat.W.X, Mat.W.Y, Mat.W.Z);
  2010. end;
  2011. // CalculateMass
  2012. //
  2013. function TgxODEDynamic.CalculateMass: TdMass;
  2014. var
  2015. i: Integer;
  2016. m: TdMass;
  2017. begin
  2018. dMassSetZero(FMass);
  2019. for i := 0 to Elements.Count - 1 do
  2020. begin
  2021. m := TgxODEElementBase(Elements[i]).CalculateMass;
  2022. dMassAdd(FMass, m);
  2023. end;
  2024. Result := FMass;
  2025. end;
  2026. procedure TgxODEDynamic.CalibrateCenterOfMass;
  2027. var
  2028. Pos: TAffineVector;
  2029. begin
  2030. SetAffineVector(Pos, FMass.c[0], FMass.c[1], FMass.c[2]);
  2031. NegateVector(Pos);
  2032. dMassTranslate(FMass, Pos.X, Pos.Y, Pos.Z);
  2033. end;
  2034. function TgxODEDynamic.GetMass: TdMass;
  2035. begin
  2036. dBodyGetMass(FBody, FMass);
  2037. Result := FMass;
  2038. end;
  2039. procedure TgxODEDynamic.SetMass(const Value: TdMass);
  2040. begin
  2041. FMass := Value;
  2042. if FMass.Mass > 0 then
  2043. dBodySetMass(FBody, @FMass);
  2044. end;
  2045. class function TgxODEDynamic.UniqueItem: Boolean;
  2046. begin
  2047. Result := True;
  2048. end;
  2049. procedure TgxODEDynamic.SetEnabled(const Value: Boolean);
  2050. begin
  2051. FEnabled := Value;
  2052. if Assigned(FBody) then
  2053. begin
  2054. if FEnabled then
  2055. dBodyEnable(FBody)
  2056. else
  2057. dBodyDisable(FBody);
  2058. end;
  2059. end;
  2060. function TgxODEDynamic.GetEnabled: Boolean;
  2061. begin
  2062. if Assigned(FBody) then
  2063. FEnabled := (dBodyIsEnabled(FBody) = 1);
  2064. Result := FEnabled;
  2065. end;
  2066. procedure TgxODEDynamic.AddForce(Force: TAffineVector);
  2067. begin
  2068. if Assigned(FBody) then
  2069. dBodyAddForce(FBody, Force.X, Force.Y, Force.Z);
  2070. end;
  2071. procedure TgxODEDynamic.AddForceAtPos(Force, Pos: TAffineVector);
  2072. begin
  2073. if Assigned(FBody) then
  2074. dBodyAddForceAtPos(FBody, Force.X, Force.Y, Force.Z, Pos.X, Pos.Y, Pos.Z);
  2075. end;
  2076. procedure TgxODEDynamic.AddForceAtRelPos(Force, Pos: TAffineVector);
  2077. begin
  2078. if Assigned(FBody) then
  2079. dBodyAddForceAtRelPos(FBody, Force.X, Force.Y, Force.Z, Pos.X,
  2080. Pos.Y, Pos.Z);
  2081. end;
  2082. procedure TgxODEDynamic.AddRelForce(Force: TAffineVector);
  2083. begin
  2084. if Assigned(FBody) then
  2085. dBodyAddRelForce(FBody, Force.X, Force.Y, Force.Z);
  2086. end;
  2087. procedure TgxODEDynamic.AddRelForceAtPos(Force, Pos: TAffineVector);
  2088. begin
  2089. if Assigned(FBody) then
  2090. dBodyAddForceAtPos(FBody, Force.X, Force.Y, Force.Z, Pos.X, Pos.Y, Pos.Z);
  2091. end;
  2092. procedure TgxODEDynamic.AddRelForceAtRelPos(Force, Pos: TAffineVector);
  2093. begin
  2094. if Assigned(FBody) then
  2095. dBodyAddRelForceAtRelPos(FBody, Force.X, Force.Y, Force.Z, Pos.X, Pos.Y, Pos.Z);
  2096. end;
  2097. procedure TgxODEDynamic.AddTorque(Torque: TAffineVector);
  2098. begin
  2099. if Assigned(FBody) then
  2100. dBodyAddTorque(FBody, Torque.X, Torque.Y, Torque.Z);
  2101. end;
  2102. procedure TgxODEDynamic.AddRelTorque(Torque: TAffineVector);
  2103. begin
  2104. if Assigned(FBody) then
  2105. dBodyAddRelTorque(FBody, Torque.X, Torque.Y, Torque.Z);
  2106. end;
  2107. // ---------------
  2108. // --------------- TgxODEStatic ---------------
  2109. // ---------------
  2110. constructor TgxODEStatic.Create(AOwner: TXCollection);
  2111. begin
  2112. inherited;
  2113. FElements := TgxODEElements.Create(Self);
  2114. end;
  2115. destructor TgxODEStatic.Destroy;
  2116. begin
  2117. FElements.Free;
  2118. inherited;
  2119. end;
  2120. procedure TgxODEStatic.Render(var rci: TgxRenderContextInfo);
  2121. var
  2122. Mat: TMatrix4f;
  2123. begin
  2124. if Assigned(Owner.Owner) then
  2125. begin
  2126. rci.PipelineTransformation.Push;
  2127. Mat := TgxBaseSceneObject(Owner.Owner).AbsoluteMatrix;
  2128. rci.PipelineTransformation.ModelMatrix^ := Mat;
  2129. end;
  2130. Elements.Render(rci);
  2131. if Assigned(Owner.Owner) then
  2132. rci.PipelineTransformation.Pop;
  2133. end;
  2134. class function TgxODEStatic.FriendlyName: String;
  2135. begin
  2136. Result := 'ODE Static';
  2137. end;
  2138. class function TgxODEStatic.UniqueItem: Boolean;
  2139. begin
  2140. Result := True;
  2141. end;
  2142. procedure TgxODEStatic.Initialize;
  2143. begin
  2144. if (not Assigned(Manager)) or (FInitialized) then
  2145. Exit;
  2146. if not Assigned(Manager.Space) then
  2147. Exit;
  2148. FElements.Initialize;
  2149. inherited;
  2150. end;
  2151. procedure TgxODEStatic.Finalize;
  2152. begin
  2153. if not FInitialized then
  2154. Exit;
  2155. FElements.Finalize;
  2156. inherited;
  2157. end;
  2158. procedure TgxODEStatic.WriteToFiler(writer: TWriter);
  2159. begin
  2160. inherited;
  2161. with writer do
  2162. begin
  2163. WriteInteger(0); // Archive version
  2164. FElements.WriteToFiler(writer);
  2165. end;
  2166. end;
  2167. procedure TgxODEStatic.ReadFromFiler(reader: TReader);
  2168. begin
  2169. inherited;
  2170. with reader do
  2171. begin
  2172. Assert(ReadInteger = 0); // Archive version
  2173. FElements.ReadFromFiler(reader);
  2174. end;
  2175. end;
  2176. function TgxODEStatic.AddNewElement(AChild: TgxODEElementClass): TgxODEElementBase;
  2177. begin
  2178. Result := nil;
  2179. if not Assigned(Manager) then
  2180. Exit;
  2181. Result := AChild.Create(FElements);
  2182. FElements.Add(Result);
  2183. Result.Initialize;
  2184. end;
  2185. procedure TgxODEStatic.AlignElements;
  2186. var
  2187. i: Integer;
  2188. begin
  2189. if not FInitialized then
  2190. Exit;
  2191. for i := 0 to FElements.Count - 1 do
  2192. TgxODEElementBase(FElements[i]).AlignGeomElementToMatrix
  2193. (TgxODEElementBase(FElements[i]).AbsoluteMatrix);
  2194. end;
  2195. // ---------------
  2196. // --------------- TgxODEElements ---------------
  2197. // ---------------
  2198. destructor TgxODEElements.Destroy;
  2199. begin
  2200. Finalize;
  2201. inherited;
  2202. end;
  2203. function TgxODEElements.GetElement(index: Integer): TgxODEElementBase;
  2204. begin
  2205. Result := TgxODEElementBase(Items[index]);
  2206. end;
  2207. class function TgxODEElements.ItemsClass: TXCollectionItemClass;
  2208. begin
  2209. Result := TgxODEElementBase;
  2210. end;
  2211. procedure TgxODEElements.Initialize;
  2212. var
  2213. i: Integer;
  2214. begin
  2215. for i := 0 to Count - 1 do
  2216. TgxODEElementBase(Items[i]).Initialize;
  2217. end;
  2218. procedure TgxODEElements.Finalize;
  2219. var
  2220. i: Integer;
  2221. begin
  2222. for i := 0 to Count - 1 do
  2223. TgxODEElementBase(Items[i]).Finalize;
  2224. end;
  2225. procedure TgxODEElements.Render(var rci: TgxRenderContextInfo);
  2226. var
  2227. i: Integer;
  2228. begin
  2229. for i := 0 to Count - 1 do
  2230. TgxODEElementBase(Items[i]).Render(rci);
  2231. end;
  2232. procedure TgxODEElements.NotifyChange(Sender: TObject);
  2233. begin
  2234. if Assigned(Owner) then
  2235. if Owner is TgxODEBehaviour then
  2236. TgxODEBehaviour(Owner).NotifyChange(Self);
  2237. end;
  2238. // ---------------
  2239. // --------------- TgxODEElementBase ---------------
  2240. // ---------------
  2241. constructor TgxODEElementBase.Create(AOwner: TXCollection);
  2242. begin
  2243. inherited;
  2244. FPosition := TgxCoordinates.CreateInitialized(Self, NullHmgPoint, csPoint);
  2245. FPosition.OnNotifyChange := NotifyChange;
  2246. FDirection := TgxCoordinates.CreateInitialized(Self, ZHmgVector, csVector);
  2247. FDirection.OnNotifyChange := CoordinateChanged;
  2248. FUp := TgxCoordinates.CreateInitialized(Self, YHmgVector, csVector);
  2249. FUp.OnNotifyChange := CoordinateChanged;
  2250. FDensity := 1;
  2251. FInitialized := False;
  2252. FDynamic := (Owner.Owner is TgxODEDynamic);
  2253. FLocalMatrix := IdentityHMGMatrix;
  2254. FIsCalculating := False;
  2255. end;
  2256. destructor TgxODEElementBase.Destroy;
  2257. begin
  2258. if FInitialized then
  2259. Finalize;
  2260. FPosition.Free;
  2261. FDirection.Free;
  2262. FUp.Free;
  2263. inherited;
  2264. end;
  2265. procedure TgxODEElementBase.Render(var rci: TgxRenderContextInfo);
  2266. begin
  2267. // Override this procedure with element drawing OpenGL code
  2268. end;
  2269. procedure TgxODEElementBase.Initialize;
  2270. var
  2271. Manager: TgxODEManager;
  2272. Body: PdxBody;
  2273. begin
  2274. Manager := nil;
  2275. Body := nil;
  2276. if Owner.Owner is TgxODEBehaviour then
  2277. Manager := TgxODEBehaviour(Owner.Owner).Manager;
  2278. if not Assigned(Manager) then
  2279. Exit;
  2280. if FDynamic then
  2281. begin
  2282. if Owner.Owner is TgxODEDynamic then
  2283. Body := TgxODEDynamic(Owner.Owner).Body;
  2284. if not Assigned(Body) then
  2285. Exit;
  2286. end;
  2287. if not Assigned(Manager.World) then
  2288. Exit;
  2289. if FDynamic then
  2290. begin
  2291. FGeomTransform := dCreateGeomTransform(Manager.Space);
  2292. dGeomSetBody(FGeomTransform, Body);
  2293. dGeomTransformSetCleanup(FGeomTransform, 0);
  2294. dGeomTransformSetGeom(FGeomTransform, FGeomElement);
  2295. dGeomSetData(FGeomTransform, Owner.Owner);
  2296. AlignGeomElementToMatrix(FLocalMatrix);
  2297. end
  2298. else
  2299. begin
  2300. dSpaceAdd(Manager.Space, FGeomElement);
  2301. dGeomSetData(FGeomElement, Owner.Owner);
  2302. AlignGeomElementToMatrix(AbsoluteMatrix);
  2303. end;
  2304. FInitialized := True;
  2305. end;
  2306. procedure TgxODEElementBase.Finalize;
  2307. begin
  2308. if not FInitialized then
  2309. Exit;
  2310. if Assigned(FGeomTransform) then
  2311. begin
  2312. dGeomDestroy(FGeomTransform);
  2313. FGeomTransform := nil;
  2314. end;
  2315. if Assigned(FGeomElement) then
  2316. begin
  2317. dGeomDestroy(FGeomElement);
  2318. FGeomElement := nil;
  2319. end;
  2320. FInitialized := False;
  2321. end;
  2322. procedure TgxODEElementBase.WriteToFiler(writer: TWriter);
  2323. begin
  2324. inherited;
  2325. with writer do
  2326. begin
  2327. WriteInteger(0); // Archive version
  2328. FPosition.WriteToFiler(writer);
  2329. FDirection.WriteToFiler(writer);
  2330. FUp.WriteToFiler(writer);
  2331. WriteFloat(Density);
  2332. end;
  2333. end;
  2334. procedure TgxODEElementBase.ReadFromFiler(reader: TReader);
  2335. begin
  2336. inherited;
  2337. with reader do
  2338. begin
  2339. Assert(ReadInteger = 0); // Archive version
  2340. FPosition.ReadFromFiler(reader);
  2341. FDirection.ReadFromFiler(reader);
  2342. FUp.ReadFromFiler(reader);
  2343. Density := ReadFloat;
  2344. end;
  2345. NotifyChange(Self);
  2346. end;
  2347. function TgxODEElementBase.AbsoluteMatrix: TMatrix4f;
  2348. var
  2349. Mat: TMatrix4f;
  2350. begin
  2351. Mat := IdentityHMGMatrix;
  2352. if Owner.Owner is TgxODEBehaviour then
  2353. Mat := TgxODEBehaviour(Owner.Owner).AbsoluteMatrix;
  2354. Result := MatrixMultiply(Mat, FLocalMatrix);
  2355. end;
  2356. function TgxODEElementBase.AbsolutePosition: TAffineVector;
  2357. begin
  2358. Result := AffineVectorMake(AbsoluteMatrix.W);
  2359. end;
  2360. procedure TgxODEElementBase.AlignGeomElementToMatrix(Mat: TMatrix4f);
  2361. var
  2362. R: TdMatrix3;
  2363. begin
  2364. if not Assigned(FGeomElement) then
  2365. Exit;
  2366. dGeomSetPosition(FGeomElement, Mat.W.X, Mat.W.Y, Mat.W.Z);
  2367. R[0] := Mat.X.X;
  2368. R[1] := Mat.Y.X;
  2369. R[2] := Mat.Z.X;
  2370. R[3] := 0;
  2371. R[4] := Mat.X.Y;
  2372. R[5] := Mat.Y.Y;
  2373. R[6] := Mat.Z.Y;
  2374. R[7] := 0;
  2375. R[8] := Mat.X.Z;
  2376. R[9] := Mat.Y.Z;
  2377. R[10] := Mat.Z.Z;
  2378. R[11] := 0;
  2379. dGeomSetRotation(FGeomElement, R);
  2380. FRealignODE := False;
  2381. end;
  2382. procedure TgxODEElementBase.SetGeomElement(aGeom: PdxGeom);
  2383. begin
  2384. FGeomElement := aGeom;
  2385. end;
  2386. function TgxODEElementBase.IsODEInitialized: Boolean;
  2387. var
  2388. Manager: TgxODEManager;
  2389. begin
  2390. Result := False;
  2391. Manager := nil;
  2392. if Owner.Owner is TgxODEBehaviour then
  2393. Manager := TgxODEBehaviour(Owner.Owner).Manager;
  2394. if not Assigned(Manager) then
  2395. Exit;
  2396. Result := Assigned(Manager.Space);
  2397. end;
  2398. function TgxODEElementBase.CalculateMass: TdMass;
  2399. var
  2400. R: TdMatrix3;
  2401. begin
  2402. R[0] := FLocalMatrix.X.X;
  2403. R[1] := FLocalMatrix.Y.X;
  2404. R[2] := FLocalMatrix.Z.X;
  2405. R[3] := 0;
  2406. R[4] := FLocalMatrix.X.Y;
  2407. R[5] := FLocalMatrix.Y.Y;
  2408. R[6] := FLocalMatrix.Z.Y;
  2409. R[7] := 0;
  2410. R[8] := FLocalMatrix.X.Z;
  2411. R[9] := FLocalMatrix.Y.Z;
  2412. R[10] := FLocalMatrix.Z.Z;
  2413. R[11] := 0;
  2414. dMassRotate(FMass, R);
  2415. dMassTranslate(FMass, FLocalMatrix.W.X, FLocalMatrix.W.Y, FLocalMatrix.W.Z);
  2416. Result := FMass;
  2417. end;
  2418. procedure TgxODEElementBase.CoordinateChanged(Sender: TObject);
  2419. var
  2420. rightVector: TVector4f;
  2421. begin
  2422. if FIsCalculating then
  2423. Exit;
  2424. FIsCalculating := True;
  2425. try
  2426. if Sender = FDirection then
  2427. begin
  2428. if FDirection.VectorLength = 0 then
  2429. FDirection.DirectVector := ZHmgVector;
  2430. FDirection.Normalize;
  2431. rightVector := VectorCrossProduct(FDirection.AsVector, FUp.AsVector);
  2432. if VectorLength(rightVector) < 1E-5 then
  2433. begin
  2434. rightVector := VectorCrossProduct(ZHmgVector, FUp.AsVector);
  2435. if VectorLength(rightVector) < 1E-5 then
  2436. rightVector := VectorCrossProduct(XHmgVector, FUp.AsVector);
  2437. end;
  2438. FUp.DirectVector := VectorCrossProduct(rightVector, FDirection.AsVector);
  2439. FUp.Normalize;
  2440. end
  2441. else if Sender = FUp then
  2442. begin
  2443. if FUp.VectorLength = 0 then
  2444. FUp.DirectVector := YHmgVector;
  2445. FUp.Normalize;
  2446. rightVector := VectorCrossProduct(FDirection.AsVector, FUp.AsVector);
  2447. if VectorLength(rightVector) < 1E-5 then
  2448. begin
  2449. rightVector := VectorCrossProduct(ZHmgVector, FUp.AsVector);
  2450. if VectorLength(rightVector) < 1E-5 then
  2451. rightVector := VectorCrossProduct(XHmgVector, FUp.AsVector);
  2452. end;
  2453. FDirection.DirectVector := VectorCrossProduct(FUp.AsVector, rightVector);
  2454. FDirection.Normalize;
  2455. end;
  2456. NotifyChange(Self);
  2457. finally
  2458. FIsCalculating := False;
  2459. end;
  2460. end;
  2461. procedure TgxODEElementBase.NotifyChange(Sender: TObject);
  2462. begin
  2463. RebuildMatrix;
  2464. ODERebuild;
  2465. end;
  2466. function TgxODEElementBase.GetMatrix: TMatrix4f;
  2467. begin
  2468. Result := FLocalMatrix;
  2469. end;
  2470. procedure TgxODEElementBase.RebuildMatrix;
  2471. begin
  2472. VectorCrossProduct(FUp.AsVector, FDirection.AsVector, FLocalMatrix.X);
  2473. SetVector(FLocalMatrix.Y, FUp.AsVector);
  2474. SetVector(FLocalMatrix.Z, FDirection.AsVector);
  2475. SetVector(FLocalMatrix.W, FPosition.AsVector);
  2476. end;
  2477. procedure TgxODEElementBase.RebuildVectors;
  2478. begin
  2479. FUp.SetVector(FLocalMatrix.Y.X, FLocalMatrix.Y.Y, FLocalMatrix.Y.Z);
  2480. FDirection.SetVector(FLocalMatrix.Z.X, FLocalMatrix.Z.Y, FLocalMatrix.Z.Z);
  2481. FPosition.SetPoint(FLocalMatrix.W.X, FLocalMatrix.W.Y, FLocalMatrix.W.Z);
  2482. end;
  2483. procedure TgxODEElementBase.SetDensity(const Value: TdReal);
  2484. begin
  2485. FDensity := Value;
  2486. end;
  2487. procedure TgxODEElementBase.SetMatrix(const Value: TMatrix4f);
  2488. begin
  2489. FLocalMatrix := Value;
  2490. RebuildVectors;
  2491. ODERebuild;
  2492. end;
  2493. procedure TgxODEElementBase.ODERebuild;
  2494. begin
  2495. if Initialized then
  2496. begin
  2497. if FDynamic then
  2498. begin
  2499. CalculateMass;
  2500. AlignGeomElementToMatrix(FLocalMatrix);
  2501. end
  2502. else
  2503. AlignGeomElementToMatrix(AbsoluteMatrix);
  2504. end;
  2505. if Assigned(Owner) then
  2506. TgxODEElements(Owner).NotifyChange(Self);
  2507. end;
  2508. procedure TgxODEElementBase.SetPosition(const Value: TgxCoordinates);
  2509. begin
  2510. FPosition.Assign(Value);
  2511. end;
  2512. procedure TgxODEElementBase.SetDirection(const Value: TgxCoordinates);
  2513. begin
  2514. FDirection.Assign(Value);
  2515. end;
  2516. procedure TgxODEElementBase.SetUp(const Value: TgxCoordinates);
  2517. begin
  2518. FUp.Assign(Value);
  2519. end;
  2520. // ---------------
  2521. // --------------- TgxODEElementBox ---------------
  2522. // ---------------
  2523. procedure TgxODEElementBox.Render(var rci: TgxRenderContextInfo);
  2524. begin
  2525. glPushMatrix;
  2526. glMultMatrixf(@FLocalMatrix);
  2527. glBegin(GL_LINE_LOOP);
  2528. glVertex3f(-FBoxWidth / 2, -FBoxHeight / 2, -FBoxDepth / 2);
  2529. glVertex3f(-FBoxWidth / 2, FBoxHeight / 2, -FBoxDepth / 2);
  2530. glVertex3f(-FBoxWidth / 2, FBoxHeight / 2, FBoxDepth / 2);
  2531. glVertex3f(-FBoxWidth / 2, -FBoxHeight / 2, FBoxDepth / 2);
  2532. glEnd;
  2533. glBegin(GL_LINE_LOOP);
  2534. glVertex3f(FBoxWidth / 2, FBoxHeight / 2, FBoxDepth / 2);
  2535. glVertex3f(FBoxWidth / 2, -FBoxHeight / 2, FBoxDepth / 2);
  2536. glVertex3f(FBoxWidth / 2, -FBoxHeight / 2, -FBoxDepth / 2);
  2537. glVertex3f(FBoxWidth / 2, FBoxHeight / 2, -FBoxDepth / 2);
  2538. glEnd;
  2539. glBegin(GL_LINES);
  2540. glVertex3f(-FBoxWidth / 2, FBoxHeight / 2, -FBoxDepth / 2);
  2541. glVertex3f(FBoxWidth / 2, FBoxHeight / 2, -FBoxDepth / 2);
  2542. glVertex3f(-FBoxWidth / 2, -FBoxHeight / 2, FBoxDepth / 2);
  2543. glVertex3f(FBoxWidth / 2, -FBoxHeight / 2, FBoxDepth / 2);
  2544. glVertex3f(-FBoxWidth / 2, -FBoxHeight / 2, -FBoxDepth / 2);
  2545. glVertex3f(FBoxWidth / 2, -FBoxHeight / 2, -FBoxDepth / 2);
  2546. glVertex3f(-FBoxWidth / 2, FBoxHeight / 2, FBoxDepth / 2);
  2547. glVertex3f(FBoxWidth / 2, FBoxHeight / 2, FBoxDepth / 2);
  2548. glEnd;
  2549. glPopMatrix;
  2550. end;
  2551. constructor TgxODEElementBox.Create(AOwner: TXCollection);
  2552. begin
  2553. inherited;
  2554. BoxWidth := 1;
  2555. BoxHeight := 1;
  2556. BoxDepth := 1;
  2557. end;
  2558. procedure TgxODEElementBox.Initialize;
  2559. begin
  2560. if FInitialized then
  2561. Exit;
  2562. if not IsODEInitialized then
  2563. Exit;
  2564. FGeomElement := dCreateBox(nil, FBoxWidth, FBoxHeight, FBoxDepth);
  2565. inherited;
  2566. end;
  2567. procedure TgxODEElementBox.WriteToFiler(writer: TWriter);
  2568. begin
  2569. inherited;
  2570. with writer do
  2571. begin
  2572. WriteInteger(0); // Archive version
  2573. WriteFloat(BoxWidth);
  2574. WriteFloat(BoxHeight);
  2575. WriteFloat(BoxDepth);
  2576. end;
  2577. end;
  2578. procedure TgxODEElementBox.ReadFromFiler(reader: TReader);
  2579. begin
  2580. inherited;
  2581. with reader do
  2582. begin
  2583. Assert(ReadInteger = 0); // Archive version
  2584. BoxWidth := ReadFloat;
  2585. BoxHeight := ReadFloat;
  2586. BoxDepth := ReadFloat;
  2587. end;
  2588. end;
  2589. class function TgxODEElementBox.FriendlyName: String;
  2590. begin
  2591. Result := 'Box';
  2592. end;
  2593. class function TgxODEElementBox.FriendlyDescription: String;
  2594. begin
  2595. Result := 'The ODE box element implementation';
  2596. end;
  2597. class function TgxODEElementBox.ItemCategory: String;
  2598. begin
  2599. Result := 'Primitives';
  2600. end;
  2601. function TgxODEElementBox.CalculateMass: TdMass;
  2602. begin
  2603. dMassSetBox(FMass, FDensity, BoxWidth, BoxHeight, BoxDepth);
  2604. Result := inherited CalculateMass;
  2605. end;
  2606. function TgxODEElementBox.GetBoxWidth: TdReal;
  2607. var
  2608. vec: TdVector3;
  2609. begin
  2610. if Assigned(FGeomTransform) then
  2611. begin
  2612. dGeomBoxGetLengths(Geom, vec);
  2613. FBoxWidth := vec[0];
  2614. end;
  2615. Result := FBoxWidth;
  2616. end;
  2617. function TgxODEElementBox.GetBoxHeight: TdReal;
  2618. var
  2619. vec: TdVector3;
  2620. begin
  2621. if Assigned(FGeomTransform) then
  2622. begin
  2623. dGeomBoxGetLengths(Geom, vec);
  2624. FBoxHeight := vec[1];
  2625. end;
  2626. Result := FBoxHeight;
  2627. end;
  2628. function TgxODEElementBox.GetBoxDepth: TdReal;
  2629. var
  2630. vec: TdVector3;
  2631. begin
  2632. if Assigned(FGeomTransform) then
  2633. begin
  2634. dGeomBoxGetLengths(Geom, vec);
  2635. FBoxDepth := vec[2];
  2636. end;
  2637. Result := FBoxDepth;
  2638. end;
  2639. procedure TgxODEElementBox.ODERebuild;
  2640. begin
  2641. if Assigned(Geom) then
  2642. dGeomBoxSetLengths(Geom, FBoxWidth, FBoxHeight, FBoxDepth);
  2643. inherited;
  2644. end;
  2645. procedure TgxODEElementBox.SetBoxWidth(const Value: TdReal);
  2646. begin
  2647. FBoxWidth := Value;
  2648. ODERebuild;
  2649. end;
  2650. procedure TgxODEElementBox.SetBoxHeight(const Value: TdReal);
  2651. begin
  2652. FBoxHeight := Value;
  2653. ODERebuild;
  2654. end;
  2655. procedure TgxODEElementBox.SetBoxDepth(const Value: TdReal);
  2656. begin
  2657. FBoxDepth := Value;
  2658. ODERebuild;
  2659. end;
  2660. // ---------------
  2661. // --------------- TgxODEElementSphere ---------------
  2662. // ---------------
  2663. procedure TgxODEElementSphere.Render(var rci: TgxRenderContextInfo);
  2664. var
  2665. AngTop, AngBottom, AngStart, AngStop, StepV, StepH: double;
  2666. SinP, CosP, SinP2, CosP2, SinT, CosT, Phi, Phi2, Theta: double;
  2667. FTop, FBottom, FStart, FStop: Single;
  2668. i, J, FSlices, FStacks: Integer;
  2669. begin
  2670. glPushMatrix;
  2671. glMultMatrixf(@FLocalMatrix);
  2672. glScalef(Radius, Radius, Radius);
  2673. FTop := 90;
  2674. FBottom := -90;
  2675. FStart := 0;
  2676. FStop := 360;
  2677. FSlices := 16;
  2678. FStacks := 16;
  2679. AngTop := DegToRadian(FTop);
  2680. AngBottom := DegToRadian(FBottom);
  2681. AngStart := DegToRadian(FStart);
  2682. AngStop := DegToRadian(FStop);
  2683. StepH := (AngStop - AngStart) / FSlices;
  2684. StepV := (AngTop - AngBottom) / FStacks;
  2685. Phi := AngTop;
  2686. Phi2 := Phi - StepV;
  2687. for J := 0 to FStacks - 1 do
  2688. begin
  2689. Theta := AngStart;
  2690. SinCosine(Phi, SinP, CosP);
  2691. SinCosine(Phi2, SinP2, CosP2);
  2692. glBegin(GL_LINE_LOOP);
  2693. for i := 0 to FSlices do
  2694. begin
  2695. SinCosine(Theta, SinT, CosT);
  2696. glVertex3f(CosP * SinT, SinP, CosP * CosT);
  2697. Theta := Theta + StepH;
  2698. end;
  2699. glEnd;
  2700. Phi := Phi2;
  2701. Phi2 := Phi2 - StepV;
  2702. end;
  2703. Phi := AngTop;
  2704. Phi2 := Phi - StepV;
  2705. for J := 0 to FStacks - 1 do
  2706. begin
  2707. Theta := AngStart;
  2708. SinCos(Phi, SinP, CosP);
  2709. SinCos(Phi2, SinP2, CosP2);
  2710. glBegin(GL_LINE_LOOP);
  2711. for i := 0 to FSlices do
  2712. begin
  2713. SinCos(Theta, SinT, CosT);
  2714. glVertex3f(SinP, CosP * SinT, CosP * CosT);
  2715. Theta := Theta + StepH;
  2716. end;
  2717. glEnd;
  2718. Phi := Phi2;
  2719. Phi2 := Phi2 - StepV;
  2720. end;
  2721. glPopMatrix;
  2722. end;
  2723. constructor TgxODEElementSphere.Create(AOwner: TXCollection);
  2724. begin
  2725. inherited;
  2726. FRadius := 0.5;
  2727. end;
  2728. procedure TgxODEElementSphere.Initialize;
  2729. begin
  2730. if FInitialized then
  2731. Exit;
  2732. if not IsODEInitialized then
  2733. Exit;
  2734. FGeomElement := dCreateSphere(nil, FRadius);
  2735. inherited;
  2736. end;
  2737. procedure TgxODEElementSphere.WriteToFiler(writer: TWriter);
  2738. begin
  2739. inherited;
  2740. with writer do
  2741. begin
  2742. WriteInteger(0); // Archive version
  2743. WriteFloat(Radius);
  2744. end;
  2745. end;
  2746. procedure TgxODEElementSphere.ReadFromFiler(reader: TReader);
  2747. begin
  2748. inherited;
  2749. with reader do
  2750. begin
  2751. Assert(ReadInteger = 0); // Archive version
  2752. Radius := ReadFloat;
  2753. end;
  2754. end;
  2755. class function TgxODEElementSphere.FriendlyName: String;
  2756. begin
  2757. Result := 'Sphere';
  2758. end;
  2759. class function TgxODEElementSphere.FriendlyDescription: String;
  2760. begin
  2761. Result := 'The ODE sphere element implementation';
  2762. end;
  2763. class function TgxODEElementSphere.ItemCategory: String;
  2764. begin
  2765. Result := 'Primitives';
  2766. end;
  2767. function TgxODEElementSphere.CalculateMass: TdMass;
  2768. begin
  2769. dMassSetSphere(FMass, FDensity, Radius);
  2770. Result := inherited CalculateMass;
  2771. end;
  2772. function TgxODEElementSphere.GetRadius: TdReal;
  2773. begin
  2774. if Assigned(FGeomElement) then
  2775. FRadius := dGeomSphereGetRadius(FGeomElement);
  2776. Result := FRadius;
  2777. end;
  2778. procedure TgxODEElementSphere.ODERebuild;
  2779. begin
  2780. if Assigned(Geom) then
  2781. begin
  2782. dGeomSphereSetRadius(Geom, FRadius);
  2783. end;
  2784. inherited;
  2785. end;
  2786. procedure TgxODEElementSphere.SetRadius(const Value: TdReal);
  2787. begin
  2788. FRadius := Value;
  2789. ODERebuild;
  2790. end;
  2791. // ---------------
  2792. // --------------- TgxODEElementCapsule ---------------
  2793. // ---------------
  2794. procedure TgxODEElementCapsule.Render(var rci: TgxRenderContextInfo);
  2795. var
  2796. i, J, Stacks, Slices: Integer;
  2797. begin
  2798. glPushMatrix;
  2799. glMultMatrixf(@FLocalMatrix);
  2800. Stacks := 8;
  2801. Slices := 16;
  2802. // Middle horizontal circles
  2803. for J := 0 to Stacks - 1 do
  2804. begin
  2805. glBegin(GL_LINE_LOOP);
  2806. for i := 0 to Slices - 1 do
  2807. glVertex3f(FRadius * sin(2 * i * PI / Slices),
  2808. FRadius * cos(2 * i * PI / Slices), -FLength / 2 + FLength * J /
  2809. (Stacks - 1));
  2810. glEnd;
  2811. end;
  2812. // Middle vertical lines
  2813. glBegin(GL_LINES);
  2814. for i := 0 to (Slices div 2) - 1 do
  2815. begin
  2816. glVertex3f(FRadius * sin(2 * i * PI / Slices),
  2817. FRadius * cos(2 * i * PI / Slices), -FLength / 2);
  2818. glVertex3f(FRadius * sin(2 * i * PI / Slices),
  2819. FRadius * cos(2 * i * PI / Slices), FLength / 2);
  2820. glVertex3f(-FRadius * sin(2 * i * PI / Slices),
  2821. -FRadius * cos(2 * i * PI / Slices), -FLength / 2);
  2822. glVertex3f(-FRadius * sin(2 * i * PI / Slices),
  2823. -FRadius * cos(2 * i * PI / Slices), FLength / 2);
  2824. end;
  2825. glEnd;
  2826. // Cap XZ half-circles
  2827. glPushMatrix;
  2828. for J := 0 to (Slices div 2) - 1 do
  2829. begin
  2830. // Top
  2831. glBegin(GL_LINE_STRIP);
  2832. for i := 0 to Slices do
  2833. glVertex3f(FRadius * cos(i * PI / Slices), 0,
  2834. FRadius * sin(i * PI / Slices) + FLength / 2);
  2835. glEnd;
  2836. // Bottom
  2837. glBegin(GL_LINE_STRIP);
  2838. for i := 0 to Slices do
  2839. glVertex3f(FRadius * cos(i * PI / Slices), 0,
  2840. -(FRadius * sin(i * PI / Slices) + FLength / 2));
  2841. glEnd;
  2842. glRotatef(360 / Slices, 0, 0, 1);
  2843. end;
  2844. glPopMatrix;
  2845. glPopMatrix;
  2846. end;
  2847. constructor TgxODEElementCapsule.Create(AOwner: TXCollection);
  2848. begin
  2849. inherited;
  2850. FRadius := 0.5;
  2851. FLength := 1;
  2852. end;
  2853. procedure TgxODEElementCapsule.Initialize;
  2854. begin
  2855. if FInitialized then
  2856. Exit;
  2857. if not IsODEInitialized then
  2858. Exit;
  2859. FGeomElement := dCreateCapsule(nil, FRadius, FLength);
  2860. inherited;
  2861. end;
  2862. procedure TgxODEElementCapsule.WriteToFiler(writer: TWriter);
  2863. begin
  2864. inherited;
  2865. with writer do
  2866. begin
  2867. WriteInteger(0); // Archive version
  2868. WriteFloat(Radius);
  2869. WriteFloat(Length);
  2870. end;
  2871. end;
  2872. procedure TgxODEElementCapsule.ReadFromFiler(reader: TReader);
  2873. begin
  2874. inherited;
  2875. with reader do
  2876. begin
  2877. Assert(ReadInteger = 0); // Archive version
  2878. Radius := ReadFloat;
  2879. Length := ReadFloat;
  2880. end;
  2881. end;
  2882. class function TgxODEElementCapsule.FriendlyName: String;
  2883. begin
  2884. Result := 'Capsule';
  2885. end;
  2886. class function TgxODEElementCapsule.FriendlyDescription: String;
  2887. begin
  2888. Result := 'The ODE capped cylinder element implementation';
  2889. end;
  2890. class function TgxODEElementCapsule.ItemCategory: String;
  2891. begin
  2892. Result := 'Primitives';
  2893. end;
  2894. function TgxODEElementCapsule.CalculateMass: TdMass;
  2895. begin
  2896. dMassSetCapsule(FMass, FDensity, 3, FRadius, FLength);
  2897. Result := inherited CalculateMass;
  2898. end;
  2899. function TgxODEElementCapsule.GetRadius: TdReal;
  2900. var
  2901. rad, len: TdReal;
  2902. begin
  2903. if Assigned(FGeomElement) then
  2904. begin
  2905. dGeomCapsuleGetParams(Geom, rad, len);
  2906. FRadius := rad;
  2907. end;
  2908. Result := FRadius;
  2909. end;
  2910. function TgxODEElementCapsule.GetLength: TdReal;
  2911. var
  2912. rad, len: TdReal;
  2913. begin
  2914. if Assigned(FGeomElement) then
  2915. begin
  2916. dGeomCapsuleGetParams(Geom, rad, len);
  2917. FLength := len;
  2918. end;
  2919. Result := FLength;
  2920. end;
  2921. procedure TgxODEElementCapsule.ODERebuild;
  2922. begin
  2923. if Assigned(Geom) then
  2924. dGeomCapsuleSetParams(Geom, FRadius, FLength);
  2925. inherited;
  2926. end;
  2927. procedure TgxODEElementCapsule.SetRadius(const Value: TdReal);
  2928. begin
  2929. FRadius := Value;
  2930. ODERebuild;
  2931. end;
  2932. procedure TgxODEElementCapsule.SetLength(const Value: TdReal);
  2933. begin
  2934. FLength := Value;
  2935. ODERebuild;
  2936. end;
  2937. // ---------------
  2938. // --------------- TgxODEElementCylinder ---------------
  2939. // ---------------
  2940. procedure TgxODEElementCylinder.Render(var rci: TgxRenderContextInfo);
  2941. var
  2942. i, J, Stacks, Slices: Integer;
  2943. begin
  2944. glPushMatrix;
  2945. glMultMatrixf(@FLocalMatrix);
  2946. Stacks := 8;
  2947. Slices := 16;
  2948. // Middle horizontal circles
  2949. for J := 0 to Stacks - 1 do
  2950. begin
  2951. glBegin(GL_LINE_LOOP);
  2952. for i := 0 to Slices - 1 do
  2953. glVertex3f(FRadius * sin(2 * i * PI / Slices), -FLength / 2 + FLength * J
  2954. / (Stacks - 1), FRadius * cos(2 * i * PI / Slices));
  2955. glEnd;
  2956. end;
  2957. // Middle vertical lines
  2958. glBegin(GL_LINES);
  2959. for i := 0 to (Slices div 2) - 1 do
  2960. begin
  2961. glVertex3f(FRadius * sin(2 * i * PI / Slices), -FLength / 2,
  2962. FRadius * cos(2 * i * PI / Slices));
  2963. glVertex3f(FRadius * sin(2 * i * PI / Slices), FLength / 2,
  2964. FRadius * cos(2 * i * PI / Slices));
  2965. glVertex3f(-FRadius * sin(2 * i * PI / Slices), -FLength / 2,
  2966. -FRadius * cos(2 * i * PI / Slices));
  2967. glVertex3f(-FRadius * sin(2 * i * PI / Slices), FLength / 2,
  2968. -FRadius * cos(2 * i * PI / Slices));
  2969. end;
  2970. glEnd;
  2971. // Caps
  2972. glPushMatrix;
  2973. for J := 0 to (Slices div 2) - 1 do
  2974. begin
  2975. glBegin(GL_LINES);
  2976. glVertex3f(-FRadius, FLength / 2, 0);
  2977. glVertex3f(FRadius, FLength / 2, 0);
  2978. glVertex3f(-FRadius, -FLength / 2, 0);
  2979. glVertex3f(FRadius, -FLength / 2, 0);
  2980. glEnd;
  2981. glRotatef(360 / Slices, 0, 1, 0);
  2982. end;
  2983. glPopMatrix;
  2984. glPopMatrix;
  2985. end;
  2986. constructor TgxODEElementCylinder.Create(AOwner: TXCollection);
  2987. begin
  2988. inherited;
  2989. FRadius := 0.5;
  2990. FLength := 1;
  2991. end;
  2992. procedure TgxODEElementCylinder.Initialize;
  2993. begin
  2994. if FInitialized then
  2995. Exit;
  2996. if not IsODEInitialized then
  2997. Exit;
  2998. FGeomElement := dCreateCylinder(nil, FRadius, FLength);
  2999. inherited;
  3000. end;
  3001. procedure TgxODEElementCylinder.WriteToFiler(writer: TWriter);
  3002. begin
  3003. inherited;
  3004. with writer do
  3005. begin
  3006. WriteInteger(0); // Archive version
  3007. WriteFloat(Radius);
  3008. WriteFloat(Length);
  3009. end;
  3010. end;
  3011. procedure TgxODEElementCylinder.ReadFromFiler(reader: TReader);
  3012. begin
  3013. inherited;
  3014. with reader do
  3015. begin
  3016. Assert(ReadInteger = 0); // Archive version
  3017. Radius := ReadFloat;
  3018. Length := ReadFloat;
  3019. end;
  3020. end;
  3021. class function TgxODEElementCylinder.FriendlyName: String;
  3022. begin
  3023. Result := 'Cylinder';
  3024. end;
  3025. class function TgxODEElementCylinder.FriendlyDescription: String;
  3026. begin
  3027. Result := 'The ODE cylinder element implementation';
  3028. end;
  3029. class function TgxODEElementCylinder.ItemCategory: String;
  3030. begin
  3031. Result := 'Primitives';
  3032. end;
  3033. function TgxODEElementCylinder.CalculateMass: TdMass;
  3034. begin
  3035. dMassSetCylinder(FMass, FDensity, 3, FRadius, FLength);
  3036. Result := inherited CalculateMass;
  3037. end;
  3038. function TgxODEElementCylinder.GetRadius: TdReal;
  3039. var
  3040. rad, len: TdReal;
  3041. begin
  3042. if Assigned(FGeomElement) then
  3043. begin
  3044. dGeomCylinderGetParams(Geom, rad, len);
  3045. FRadius := rad;
  3046. end;
  3047. Result := FRadius;
  3048. end;
  3049. function TgxODEElementCylinder.GetLength: TdReal;
  3050. var
  3051. rad, len: TdReal;
  3052. begin
  3053. if Assigned(FGeomElement) then
  3054. begin
  3055. dGeomCylinderGetParams(Geom, rad, len);
  3056. FLength := len;
  3057. end;
  3058. Result := FLength;
  3059. end;
  3060. procedure TgxODEElementCylinder.ODERebuild;
  3061. begin
  3062. if Assigned(Geom) then
  3063. dGeomCylinderSetParams(Geom, FRadius, FLength);
  3064. inherited;
  3065. end;
  3066. procedure TgxODEElementCylinder.SetRadius(const Value: TdReal);
  3067. begin
  3068. FRadius := Value;
  3069. ODERebuild;
  3070. end;
  3071. procedure TgxODEElementCylinder.SetLength(const Value: TdReal);
  3072. begin
  3073. FLength := Value;
  3074. ODERebuild;
  3075. end;
  3076. // ---------------
  3077. // --------------- TgxODEElementTriMesh ---------------
  3078. // ---------------
  3079. constructor TgxODEElementTriMesh.Create(AOwner: TXCollection);
  3080. begin
  3081. inherited;
  3082. FVertices := TgxAffineVectorList.Create;
  3083. FIndices := TgxIntegerList.Create;
  3084. end;
  3085. destructor TgxODEElementTriMesh.Destroy;
  3086. begin
  3087. FVertices.Free;
  3088. FIndices.Free;
  3089. inherited;
  3090. end;
  3091. procedure TgxODEElementTriMesh.Initialize;
  3092. begin
  3093. if not IsODEInitialized then
  3094. Exit;
  3095. if FInitialized or not((FVertices.Count > 0) and (FIndices.Count > 0)) then
  3096. Exit;
  3097. FTriMeshData := dGeomTriMeshDataCreate;
  3098. dGeomTriMeshDataBuildSingle(FTriMeshData, @FVertices.List[0],
  3099. 3 * SizeOf(Single), FVertices.Count, @FIndices.List[0], FIndices.Count,
  3100. 3 * SizeOf(Integer));
  3101. FGeomElement := dCreateTriMesh(nil, FTriMeshData, nil, nil, nil);
  3102. inherited;
  3103. end;
  3104. procedure TgxODEElementTriMesh.Finalize;
  3105. begin
  3106. if not FInitialized then
  3107. Exit;
  3108. if Assigned(FTriMeshData) then
  3109. dGeomTriMeshDataDestroy(FTriMeshData);
  3110. inherited;
  3111. end;
  3112. procedure TgxODEElementTriMesh.WriteToFiler(writer: TWriter);
  3113. begin
  3114. inherited;
  3115. with writer do
  3116. begin
  3117. WriteInteger(0); // Archive version
  3118. end;
  3119. end;
  3120. procedure TgxODEElementTriMesh.ReadFromFiler(reader: TReader);
  3121. begin
  3122. inherited;
  3123. with reader do
  3124. begin
  3125. Assert(ReadInteger = 0); // Archive version
  3126. end;
  3127. end;
  3128. class function TgxODEElementTriMesh.FriendlyName: String;
  3129. begin
  3130. Result := 'Tri-Mesh';
  3131. end;
  3132. class function TgxODEElementTriMesh.FriendlyDescription: String;
  3133. begin
  3134. Result := 'The ODE tri-mesh element implementation';
  3135. end;
  3136. class function TgxODEElementTriMesh.ItemCategory: String;
  3137. begin
  3138. Result := 'Meshes';
  3139. end;
  3140. function TgxODEElementTriMesh.CalculateMass: TdMass;
  3141. var
  3142. R: Single;
  3143. min, max: TAffineVector;
  3144. begin
  3145. if Vertices.Count > 0 then
  3146. begin
  3147. Vertices.GetExtents(min, max);
  3148. R := MaxFloat(VectorLength(min), VectorLength(max));
  3149. end
  3150. else
  3151. R := 1;
  3152. dMassSetSphere(FMass, FDensity, R);
  3153. Result := inherited CalculateMass;
  3154. end;
  3155. procedure TgxODEElementTriMesh.SetVertices(const Value: TgxAffineVectorList);
  3156. begin
  3157. FVertices.Assign(Value);
  3158. RefreshTriMeshData;
  3159. end;
  3160. procedure TgxODEElementTriMesh.SetIndices(const Value: TgxIntegerList);
  3161. begin
  3162. FIndices.Assign(Value);
  3163. RefreshTriMeshData;
  3164. end;
  3165. procedure TgxODEElementTriMesh.RefreshTriMeshData;
  3166. begin
  3167. if FInitialized then
  3168. Finalize;
  3169. Initialize;
  3170. end;
  3171. // ---------------
  3172. // --------------- TgxODEElementPlane ---------------
  3173. // ---------------
  3174. procedure TgxODEElementPlane.Initialize;
  3175. begin
  3176. if FInitialized then
  3177. Exit;
  3178. if not IsODEInitialized then
  3179. Exit;
  3180. FGeomElement := dCreatePlane(nil, 0, 0, 1, 0);
  3181. inherited;
  3182. end;
  3183. procedure TgxODEElementPlane.WriteToFiler(writer: TWriter);
  3184. begin
  3185. // ArchiveVersion 1, added inherited call
  3186. writer.WriteInteger(1);
  3187. inherited;
  3188. end;
  3189. procedure TgxODEElementPlane.ReadFromFiler(reader: TReader);
  3190. var
  3191. archiveVersion: Integer;
  3192. begin
  3193. archiveVersion := reader.ReadInteger;
  3194. Assert(archiveVersion in [0 .. 1]);
  3195. if archiveVersion >= 1 then
  3196. inherited;
  3197. end;
  3198. class function TgxODEElementPlane.FriendlyName: String;
  3199. begin
  3200. Result := 'Plane';
  3201. end;
  3202. class function TgxODEElementPlane.FriendlyDescription: String;
  3203. begin
  3204. Result := 'The ODE plane element implementation';
  3205. end;
  3206. class function TgxODEElementPlane.ItemCategory: String;
  3207. begin
  3208. Result := 'Primitives';
  3209. end;
  3210. class function TgxODEElementPlane.CanAddTo(collection: TXCollection): Boolean;
  3211. begin
  3212. Result := False;
  3213. if Assigned(TgxODEElements(collection).Owner) then
  3214. if TgxODEElements(collection).Owner is TgxODEStatic then
  3215. Result := True;
  3216. end;
  3217. procedure TgxODEElementPlane.AlignGeomElementToMatrix(Mat: TMatrix4f);
  3218. var
  3219. d: Single;
  3220. begin
  3221. if not Assigned(FGeomElement) then
  3222. Exit;
  3223. d := VectorDotProduct(Mat.Z, Mat.W);
  3224. dGeomPlaneSetParams(FGeomElement, Mat.Z.X, Mat.Z.Y, Mat.Z.Z, d);
  3225. end;
  3226. // ---------------
  3227. // --------------- TgxODEJoints ---------------
  3228. // ---------------
  3229. class function TgxODEJoints.ItemsClass: TXCollectionItemClass;
  3230. begin
  3231. Result := TgxODEJointBase;
  3232. end;
  3233. procedure TgxODEJoints.Initialize;
  3234. var
  3235. i: Integer;
  3236. begin
  3237. for i := 0 to Count - 1 do
  3238. Joint[i].Initialize;
  3239. end;
  3240. procedure TgxODEJoints.Finalize;
  3241. var
  3242. i: Integer;
  3243. begin
  3244. for i := 0 to Count - 1 do
  3245. Joint[i].Finalize;
  3246. end;
  3247. function TgxODEJoints.GetJoint(index: Integer): TgxODEJointBase;
  3248. begin
  3249. Result := TgxODEJointBase(Items[index]);
  3250. end;
  3251. // ---------------
  3252. // --------------- TgxODEJointList ---------------
  3253. // ---------------
  3254. constructor TgxODEJointList.Create(AOwner: TComponent);
  3255. begin
  3256. inherited;
  3257. FJoints := TgxODEJoints.Create(Self);
  3258. end;
  3259. destructor TgxODEJointList.Destroy;
  3260. begin
  3261. FJoints.Free;
  3262. inherited;
  3263. end;
  3264. procedure TgxODEJointList.DefineProperties(Filer: TFiler);
  3265. begin
  3266. inherited;
  3267. Filer.DefineBinaryProperty('ODEJointsData', ReadJoints, WriteJoints,
  3268. (Assigned(FJoints) and (FJoints.Count > 0)));
  3269. end;
  3270. procedure TgxODEJointList.WriteJoints(stream: TStream);
  3271. var
  3272. writer: TWriter;
  3273. begin
  3274. writer := TWriter.Create(stream, 16384);
  3275. try
  3276. Joints.WriteToFiler(writer);
  3277. finally
  3278. writer.Free;
  3279. end;
  3280. end;
  3281. procedure TgxODEJointList.ReadJoints(stream: TStream);
  3282. var
  3283. reader: TReader;
  3284. begin
  3285. reader := TReader.Create(stream, 16384);
  3286. try
  3287. Joints.ReadFromFiler(reader);
  3288. finally
  3289. reader.Free;
  3290. end;
  3291. end;
  3292. procedure TgxODEJointList.Loaded;
  3293. var
  3294. i: Integer;
  3295. begin
  3296. inherited;
  3297. for i := 0 to FJoints.Count - 1 do
  3298. FJoints[i].Loaded;
  3299. end;
  3300. procedure TgxODEJointList.Notification(AComponent: TComponent;
  3301. Operation: TOperation);
  3302. var
  3303. i: Integer;
  3304. begin
  3305. inherited;
  3306. if (Operation = opRemove) and (AComponent is TgxBaseSceneObject) then
  3307. for i := 0 to Joints.Count - 1 do
  3308. begin
  3309. if TgxBaseSceneObject(AComponent) = Joints[i].Object1 then
  3310. Joints[i].Object1 := nil;
  3311. if TgxBaseSceneObject(AComponent) = Joints[i].Object2 then
  3312. Joints[i].Object2 := nil;
  3313. end;
  3314. end;
  3315. // ---------------
  3316. // --------------- TgxODEJointBase ---------------
  3317. // ---------------
  3318. constructor TgxODEJointBase.Create(AOwner: TXCollection);
  3319. begin
  3320. inherited;
  3321. FJointID := nil;
  3322. FEnabled := True;
  3323. FInitialized := False;
  3324. end;
  3325. destructor TgxODEJointBase.Destroy;
  3326. begin
  3327. Finalize;
  3328. inherited;
  3329. end;
  3330. procedure TgxODEJointBase.Initialize;
  3331. begin
  3332. if not IsODEInitialized then
  3333. Exit;
  3334. if Assigned(FObject1) then
  3335. RegisterJointWithObject(FObject1);
  3336. if Assigned(FObject2) then
  3337. RegisterJointWithObject(FObject2);
  3338. Attach;
  3339. FInitialized := True;
  3340. end;
  3341. procedure TgxODEJointBase.Finalize;
  3342. begin
  3343. if not Initialized then
  3344. Exit;
  3345. if Assigned(FObject1) then
  3346. UnregisterJointWithObject(FObject1);
  3347. if Assigned(FObject2) then
  3348. UnregisterJointWithObject(FObject2);
  3349. if FJointID <> nil then
  3350. dJointDestroy(FJointID);
  3351. FInitialized := False;
  3352. end;
  3353. procedure TgxODEJointBase.WriteToFiler(writer: TWriter);
  3354. begin
  3355. inherited;
  3356. with writer do
  3357. begin
  3358. WriteInteger(0); // Archive version
  3359. if Assigned(FManager) then
  3360. WriteString(FManager.GetNamePath)
  3361. else
  3362. WriteString('');
  3363. if Assigned(FObject1) then
  3364. WriteString(FObject1.GetNamePath)
  3365. else
  3366. WriteString('');
  3367. if Assigned(FObject2) then
  3368. WriteString(FObject2.GetNamePath)
  3369. else
  3370. WriteString('');
  3371. WriteBoolean(FEnabled);
  3372. end;
  3373. end;
  3374. procedure TgxODEJointBase.ReadFromFiler(reader: TReader);
  3375. begin
  3376. inherited;
  3377. with reader do
  3378. begin
  3379. Assert(ReadInteger = 0); // Archive version
  3380. FManagerName := ReadString;
  3381. FObject1Name := ReadString;
  3382. FObject2Name := ReadString;
  3383. FEnabled := ReadBoolean;
  3384. end;
  3385. end;
  3386. procedure TgxODEJointBase.Loaded;
  3387. begin
  3388. DoLoaded;
  3389. end;
  3390. procedure TgxODEJointBase.RegisterJointWithObject(Obj: TgxBaseSceneObject);
  3391. var
  3392. temp: TgxODEDynamic;
  3393. begin
  3394. if Assigned(Obj) then
  3395. begin
  3396. temp := TgxODEDynamic(Obj.Behaviours.GetByClass(TgxODEDynamic));
  3397. if Assigned(temp) then
  3398. temp.RegisterJoint(Self);
  3399. end;
  3400. end;
  3401. procedure TgxODEJointBase.UnregisterJointWithObject(Obj: TgxBaseSceneObject);
  3402. var
  3403. temp: TgxODEDynamic;
  3404. begin
  3405. if Assigned(Obj) then
  3406. begin
  3407. temp := TgxODEDynamic(Obj.Behaviours.GetByClass(TgxODEDynamic));
  3408. if Assigned(temp) then
  3409. temp.UnregisterJoint(Self);
  3410. end;
  3411. end;
  3412. function TgxODEJointBase.IsODEInitialized: Boolean;
  3413. begin
  3414. Result := False;
  3415. if not Assigned(Manager) then
  3416. Exit;
  3417. Result := Assigned(Manager.World);
  3418. end;
  3419. procedure TgxODEJointBase.Attach;
  3420. var
  3421. Body1, Body2: PdxBody;
  3422. begin
  3423. if (FJointID = nil) or not FInitialized then
  3424. Exit;
  3425. if Enabled then
  3426. begin
  3427. Body1 := GetBodyFromGLXceneObject(FObject1);
  3428. Body2 := GetBodyFromGLXceneObject(FObject2);
  3429. end
  3430. else
  3431. begin
  3432. Body1 := nil;
  3433. Body2 := nil;
  3434. end;
  3435. if (joBothObjectsMustBeAssigned in JointOptions) then
  3436. if not(Assigned(Body1) and Assigned(Body2)) then
  3437. Exit;
  3438. dJointAttach(FJointID, Body1, Body2);
  3439. if Assigned(Body1) or Assigned(Body2) then
  3440. StructureChanged;
  3441. end;
  3442. procedure TgxODEJointBase.SetManager(const Value: TgxODEManager);
  3443. begin
  3444. if FManager <> Value then
  3445. begin
  3446. if Assigned(FManager) then
  3447. if not(csDesigning in FManager.ComponentState) then
  3448. Finalize;
  3449. FManager := Value;
  3450. if Assigned(FManager) then
  3451. if not(csDesigning in FManager.ComponentState) then
  3452. Initialize;
  3453. end;
  3454. end;
  3455. procedure TgxODEJointBase.SetObject1(const Value: TgxBaseSceneObject);
  3456. begin
  3457. if FObject1 <> Value then
  3458. begin
  3459. if Assigned(FObject1) then
  3460. UnregisterJointWithObject(FObject1);
  3461. FObject1 := Value;
  3462. if Assigned(FObject1) then
  3463. if IsGLODEObject(FObject1) then
  3464. RegisterJointWithObject(FObject1)
  3465. else
  3466. FObject1 := nil;
  3467. Attach;
  3468. end;
  3469. end;
  3470. procedure TgxODEJointBase.SetObject2(const Value: TgxBaseSceneObject);
  3471. begin
  3472. if FObject2 <> Value then
  3473. begin
  3474. if Assigned(FObject2) then
  3475. UnregisterJointWithObject(FObject2);
  3476. FObject2 := Value;
  3477. if Assigned(FObject2) then
  3478. if IsGLODEObject(FObject2) then
  3479. RegisterJointWithObject(FObject2)
  3480. else
  3481. FObject2 := nil;
  3482. Attach;
  3483. end;
  3484. end;
  3485. procedure TgxODEJointBase.SetEnabled(const Value: Boolean);
  3486. begin
  3487. if FEnabled <> Value then
  3488. begin
  3489. FEnabled := Value;
  3490. if IsODEInitialized then
  3491. Attach;
  3492. end;
  3493. end;
  3494. procedure TgxODEJointBase.StructureChanged;
  3495. begin
  3496. // nothing yet
  3497. end;
  3498. procedure TgxODEJointBase.DoLoaded;
  3499. var
  3500. mng: TComponent;
  3501. Obj: TgxBaseSceneObject;
  3502. begin
  3503. inherited;
  3504. if FManagerName <> '' then
  3505. begin
  3506. mng := FindManager(TgxODEManager, FManagerName);
  3507. if Assigned(mng) then
  3508. Manager := TgxODEManager(mng);
  3509. FManagerName := '';
  3510. end;
  3511. if FObject1Name <> '' then
  3512. begin
  3513. Obj := GetGLXceneObject(FObject1Name);
  3514. if Assigned(Obj) then
  3515. Object1 := Obj;
  3516. FObject1Name := '';
  3517. end;
  3518. if FObject2Name <> '' then
  3519. begin
  3520. Obj := GetGLXceneObject(FObject2Name);
  3521. if Assigned(Obj) then
  3522. Object2 := Obj;
  3523. FObject2Name := '';
  3524. end;
  3525. Attach;
  3526. end;
  3527. function TgxODEJointBase.IsAttached: Boolean;
  3528. var
  3529. Body1, Body2: PdxBody;
  3530. begin
  3531. Result := False;
  3532. if JointID <> nil then
  3533. begin
  3534. Body1 := dJointGetBody(JointID, 0);
  3535. Body2 := dJointGetBody(JointID, 1);
  3536. if joBothObjectsMustBeAssigned in JointOptions then
  3537. Result := Assigned(Body1) and Assigned(Body2)
  3538. else
  3539. Result := Assigned(Body1) or Assigned(Body2);
  3540. end;
  3541. end;
  3542. procedure TgxODEJointBase.SetJointOptions(const Value: TJointOptions);
  3543. begin
  3544. if Value <> FJointOptions then
  3545. begin
  3546. FJointOptions := Value;
  3547. Attach;
  3548. end;
  3549. end;
  3550. // ---------------
  3551. // --------------- TgxODEJointParams ---------------
  3552. // ---------------
  3553. constructor TgxODEJointParams.Create(AOwner: TPersistent);
  3554. begin
  3555. inherited Create;
  3556. FOwner := AOwner;
  3557. end;
  3558. function TgxODEJointParams.GetOwner: TPersistent;
  3559. begin
  3560. Result := FOwner;
  3561. end;
  3562. procedure TgxODEJointParams.Assign(Source: TPersistent);
  3563. begin
  3564. inherited;
  3565. if not Assigned(Source) then
  3566. Exit;
  3567. if Source is TgxODEJointParams then
  3568. begin
  3569. LoStop := TgxODEJointParams(Source).LoStop;
  3570. HiStop := TgxODEJointParams(Source).HiStop;
  3571. Vel := TgxODEJointParams(Source).Vel;
  3572. FMax := TgxODEJointParams(Source).FMax;
  3573. FudgeFactor := TgxODEJointParams(Source).FudgeFactor;
  3574. Bounce := TgxODEJointParams(Source).Bounce;
  3575. CFM := TgxODEJointParams(Source).CFM;
  3576. StopERP := TgxODEJointParams(Source).StopERP;
  3577. StopCFM := TgxODEJointParams(Source).StopCFM;
  3578. SuspensionERP := TgxODEJointParams(Source).SuspensionERP;
  3579. SuspensionCFM := TgxODEJointParams(Source).SuspensionCFM;
  3580. end;
  3581. end;
  3582. procedure TgxODEJointParams.WriteToFiler(writer: TWriter);
  3583. begin
  3584. with writer do
  3585. begin
  3586. WriteInteger(0); // Archive version
  3587. WriteFloat(LoStop);
  3588. WriteFloat(HiStop);
  3589. WriteFloat(Vel);
  3590. WriteFloat(FMax);
  3591. WriteFloat(FudgeFactor);
  3592. WriteFloat(Bounce);
  3593. WriteFloat(CFM);
  3594. WriteFloat(StopERP);
  3595. WriteFloat(StopCFM);
  3596. WriteFloat(SuspensionERP);
  3597. WriteFloat(SuspensionCFM);
  3598. end;
  3599. end;
  3600. procedure TgxODEJointParams.ReadFromFiler(reader: TReader);
  3601. var
  3602. archiveVersion: Integer;
  3603. begin
  3604. with reader do
  3605. begin
  3606. archiveVersion := ReadInteger;
  3607. Assert(archiveVersion = 0);
  3608. LoStop := ReadFloat;
  3609. HiStop := ReadFloat;
  3610. Vel := ReadFloat;
  3611. FMax := ReadFloat;
  3612. FudgeFactor := ReadFloat;
  3613. Bounce := ReadFloat;
  3614. CFM := ReadFloat;
  3615. StopERP := ReadFloat;
  3616. StopCFM := ReadFloat;
  3617. SuspensionERP := ReadFloat;
  3618. SuspensionCFM := ReadFloat;
  3619. end;
  3620. end;
  3621. function TgxODEJointParams.GetLoStop: TdReal;
  3622. begin
  3623. if Assigned(GetCallback) then
  3624. GetCallback(dParamLoStop1, FLoStop);
  3625. Result := FLoStop;
  3626. end;
  3627. function TgxODEJointParams.GetHiStop: TdReal;
  3628. begin
  3629. if Assigned(GetCallback) then
  3630. GetCallback(dParamHiStop1, FHiStop);
  3631. Result := FHiStop;
  3632. end;
  3633. function TgxODEJointParams.GetVel: TdReal;
  3634. begin
  3635. if Assigned(GetCallback) then
  3636. GetCallback(dParamVel1, FVel);
  3637. Result := FVel;
  3638. end;
  3639. function TgxODEJointParams.GetFMax: TdReal;
  3640. begin
  3641. if Assigned(GetCallback) then
  3642. GetCallback(dParamFMax1, FFMax);
  3643. Result := FFMax;
  3644. end;
  3645. function TgxODEJointParams.GetFudgeFactor: TdReal;
  3646. begin
  3647. if Assigned(GetCallback) then
  3648. GetCallback(dParamFudgeFactor1, FFudgeFactor);
  3649. Result := FFudgeFactor;
  3650. end;
  3651. function TgxODEJointParams.GetBounce: TdReal;
  3652. begin
  3653. if Assigned(GetCallback) then
  3654. GetCallback(dParamBounce1, FBounce);
  3655. Result := FBounce;
  3656. end;
  3657. function TgxODEJointParams.GetCFM: TdReal;
  3658. begin
  3659. if Assigned(GetCallback) then
  3660. GetCallback(dParamCFM1, FCFM);
  3661. Result := FCFM;
  3662. end;
  3663. function TgxODEJointParams.GetStopERP: TdReal;
  3664. begin
  3665. if Assigned(GetCallback) then
  3666. GetCallback(dParamStopERP1, FStopERP);
  3667. Result := FStopERP;
  3668. end;
  3669. function TgxODEJointParams.GetStopCFM: TdReal;
  3670. begin
  3671. if Assigned(GetCallback) then
  3672. GetCallback(dParamStopCFM1, FStopCFM);
  3673. Result := FStopCFM;
  3674. end;
  3675. function TgxODEJointParams.GetSuspensionERP: TdReal;
  3676. begin
  3677. if Assigned(GetCallback) then
  3678. GetCallback(dParamSuspensionERP, FSuspensionERP);
  3679. Result := FSuspensionERP;
  3680. end;
  3681. function TgxODEJointParams.GetSuspensionCFM: TdReal;
  3682. begin
  3683. if Assigned(GetCallback) then
  3684. GetCallback(dParamSuspensionCFM, FSuspensionCFM);
  3685. Result := FSuspensionCFM;
  3686. end;
  3687. procedure TgxODEJointParams.SetLoStop(const Value: TdReal);
  3688. begin
  3689. if Value <> FLoStop then
  3690. begin
  3691. FLoStop := Value;
  3692. if Assigned(SetCallback) then
  3693. FFlagLoStop := not SetCallback(dParamLoStop1, FLoStop)
  3694. else
  3695. FFlagLoStop := True;
  3696. end;
  3697. end;
  3698. procedure TgxODEJointParams.SetHiStop(const Value: TdReal);
  3699. begin
  3700. if Value <> FHiStop then
  3701. begin
  3702. FHiStop := Value;
  3703. if Assigned(SetCallback) then
  3704. FFlagHiStop := not SetCallback(dParamHiStop1, FHiStop)
  3705. else
  3706. FFlagHiStop := True;
  3707. end;
  3708. end;
  3709. procedure TgxODEJointParams.SetVel(const Value: TdReal);
  3710. begin
  3711. if Value <> FVel then
  3712. begin
  3713. FVel := Value;
  3714. if Assigned(SetCallback) then
  3715. FFlagVel := not SetCallback(dParamVel1, FVel)
  3716. else
  3717. FFlagVel := True;
  3718. end;
  3719. end;
  3720. procedure TgxODEJointParams.SetFMax(const Value: TdReal);
  3721. begin
  3722. if Value <> FFMax then
  3723. begin
  3724. FFMax := Value;
  3725. if Assigned(SetCallback) then
  3726. FFlagFMax := not SetCallback(dParamFMax1, FFMax)
  3727. else
  3728. FFlagFMax := True;
  3729. end;
  3730. end;
  3731. procedure TgxODEJointParams.SetFudgeFactor(const Value: TdReal);
  3732. begin
  3733. if Value <> FFudgeFactor then
  3734. begin
  3735. FFudgeFactor := Value;
  3736. if Assigned(SetCallback) then
  3737. FFlagFudgeFactor := not SetCallback(dParamFudgeFactor1, FFudgeFactor)
  3738. else
  3739. FFlagFudgeFactor := True;
  3740. end;
  3741. end;
  3742. procedure TgxODEJointParams.SetBounce(const Value: TdReal);
  3743. begin
  3744. if Value <> FBounce then
  3745. begin
  3746. FBounce := Value;
  3747. if Assigned(SetCallback) then
  3748. FFlagBounce := not SetCallback(dParamBounce1, FBounce)
  3749. else
  3750. FFlagBounce := True;
  3751. end;
  3752. end;
  3753. procedure TgxODEJointParams.SetCFM(const Value: TdReal);
  3754. begin
  3755. if Value <> FCFM then
  3756. begin
  3757. FCFM := Value;
  3758. if Assigned(SetCallback) then
  3759. FFlagCFM := not SetCallback(dParamCFM1, FCFM)
  3760. else
  3761. FFlagCFM := True;
  3762. end;
  3763. end;
  3764. procedure TgxODEJointParams.SetStopERP(const Value: TdReal);
  3765. begin
  3766. if Value <> FStopERP then
  3767. begin
  3768. FStopERP := Value;
  3769. if Assigned(SetCallback) then
  3770. FFlagStopERP := not SetCallback(dParamStopERP1, FStopERP)
  3771. else
  3772. FFlagStopERP := True;
  3773. end;
  3774. end;
  3775. procedure TgxODEJointParams.SetStopCFM(const Value: TdReal);
  3776. begin
  3777. if Value <> FStopCFM then
  3778. begin
  3779. FStopCFM := Value;
  3780. if Assigned(SetCallback) then
  3781. FFlagStopCFM := not SetCallback(dParamStopCFM1, FStopCFM)
  3782. else
  3783. FFlagStopCFM := True;
  3784. end;
  3785. end;
  3786. procedure TgxODEJointParams.SetSuspensionERP(const Value: TdReal);
  3787. begin
  3788. if Value <> FSuspensionERP then
  3789. begin
  3790. FSuspensionERP := Value;
  3791. if Assigned(SetCallback) then
  3792. FFlagSuspensionERP := not SetCallback(dParamSuspensionERP, FSuspensionERP)
  3793. else
  3794. FFlagSuspensionERP := True;
  3795. end;
  3796. end;
  3797. procedure TgxODEJointParams.SetSuspensionCFM(const Value: TdReal);
  3798. begin
  3799. if Value <> FSuspensionCFM then
  3800. begin
  3801. FSuspensionCFM := Value;
  3802. if Assigned(SetCallback) then
  3803. FFlagSuspensionCFM := not SetCallback(dParamSuspensionCFM, FSuspensionCFM)
  3804. else
  3805. FFlagSuspensionCFM := True;
  3806. end;
  3807. end;
  3808. procedure TgxODEJointParams.ApplyFlagged;
  3809. begin
  3810. if not Assigned(SetCallback) then
  3811. Exit;
  3812. if FFlagLoStop then
  3813. SetCallback(dParamLoStop1, FLoStop);
  3814. if FFlagHiStop then
  3815. SetCallback(dParamHiStop1, FHiStop);
  3816. if FFlagVel then
  3817. SetCallback(dParamVel1, FVel);
  3818. if FFlagFMax then
  3819. SetCallback(dParamFMax1, FFMax);
  3820. if FFlagFudgeFactor then
  3821. SetCallback(dParamFudgeFactor1, FFudgeFactor);
  3822. if FFlagBounce then
  3823. SetCallback(dParamBounce1, FBounce);
  3824. if FFlagCFM then
  3825. SetCallback(dParamCFM1, FCFM);
  3826. if FFlagStopERP then
  3827. SetCallback(dParamStopERP1, FStopERP);
  3828. if FFlagStopCFM then
  3829. SetCallback(dParamStopCFM1, FStopCFM);
  3830. if FFlagSuspensionERP then
  3831. SetCallback(dParamSuspensionERP, FSuspensionERP);
  3832. if FFlagSuspensionCFM then
  3833. SetCallback(dParamSuspensionCFM, FSuspensionCFM);
  3834. end;
  3835. // ---------------
  3836. // --------------- TgxODEJointHinge ---------------
  3837. // ---------------
  3838. constructor TgxODEJointHinge.Create(AOwner: TXCollection);
  3839. begin
  3840. inherited;
  3841. FAnchor := TgxCoordinates.CreateInitialized(Self, NullHmgPoint, csPoint);
  3842. FAnchor.OnNotifyChange := AnchorChange;
  3843. FAxis := TgxCoordinates.CreateInitialized(Self, ZHmgVector, csVector);
  3844. FAxis.OnNotifyChange := AxisChange;
  3845. FAxisParams := TgxODEJointParams.Create(Self);
  3846. FAxisParams.SetCallback := SetAxisParam;
  3847. FAxisParams.GetCallback := GetAxisParam;
  3848. end;
  3849. destructor TgxODEJointHinge.Destroy;
  3850. begin
  3851. FAnchor.Free;
  3852. FAxis.Free;
  3853. FAxisParams.Free;
  3854. inherited;
  3855. end;
  3856. procedure TgxODEJointHinge.Initialize;
  3857. begin
  3858. if (not IsODEInitialized) or (FInitialized) then
  3859. Exit;
  3860. FJointID := dJointCreateHinge(FManager.World, nil);
  3861. inherited;
  3862. end;
  3863. procedure TgxODEJointHinge.WriteToFiler(writer: TWriter);
  3864. begin
  3865. inherited;
  3866. with writer do
  3867. begin
  3868. WriteInteger(0); // Archive version
  3869. FAnchor.WriteToFiler(writer);
  3870. FAxis.WriteToFiler(writer);
  3871. FAxisParams.WriteToFiler(writer);
  3872. end;
  3873. end;
  3874. procedure TgxODEJointHinge.ReadFromFiler(reader: TReader);
  3875. begin
  3876. inherited;
  3877. with reader do
  3878. begin
  3879. Assert(ReadInteger = 0); // Archive version
  3880. FAnchor.ReadFromFiler(reader);
  3881. FAxis.ReadFromFiler(reader);
  3882. FAxisParams.ReadFromFiler(reader);
  3883. end;
  3884. end;
  3885. procedure TgxODEJointHinge.StructureChanged;
  3886. begin
  3887. AnchorChange(nil);
  3888. AxisChange(nil);
  3889. FAxisParams.ApplyFlagged;
  3890. end;
  3891. procedure TgxODEJointHinge.AnchorChange(Sender: TObject);
  3892. begin
  3893. if IsAttached then
  3894. dJointSetHingeAnchor(FJointID, FAnchor.X, FAnchor.Y, FAnchor.Z);
  3895. end;
  3896. procedure TgxODEJointHinge.AxisChange(Sender: TObject);
  3897. var
  3898. vec: TVector4f;
  3899. begin
  3900. vec := FAxis.DirectVector;
  3901. NormalizeVector(vec);
  3902. FAxis.DirectVector := vec;
  3903. if IsAttached then
  3904. dJointSetHingeAxis(FJointID, FAxis.X, FAxis.Y, FAxis.Z);
  3905. end;
  3906. class function TgxODEJointHinge.FriendlyName: String;
  3907. begin
  3908. Result := 'Hinge';
  3909. end;
  3910. class function TgxODEJointHinge.FriendlyDescription: String;
  3911. begin
  3912. Result := 'ODE Hinge joint';
  3913. end;
  3914. procedure TgxODEJointHinge.SetAnchor(const Value: TgxCoordinates);
  3915. begin
  3916. FAnchor.Assign(Value);
  3917. end;
  3918. procedure TgxODEJointHinge.SetAxis(const Value: TgxCoordinates);
  3919. begin
  3920. FAxis.Assign(Value);
  3921. end;
  3922. procedure TgxODEJointHinge.SetAxisParams(const Value: TgxODEJointParams);
  3923. begin
  3924. AxisParams.Assign(Value);
  3925. end;
  3926. function TgxODEJointHinge.SetAxisParam(Param: Integer; const Value: TdReal): Boolean;
  3927. begin
  3928. if IsAttached then
  3929. begin
  3930. dJointSetHingeParam(JointID, Param, Value);
  3931. Result := True;
  3932. end
  3933. else
  3934. Result := False;
  3935. end;
  3936. function TgxODEJointHinge.GetAxisParam(Param: Integer; var Value: TdReal): Boolean;
  3937. begin
  3938. if IsAttached then
  3939. begin
  3940. Value := dJointGetHingeParam(JointID, Param);
  3941. Result := True;
  3942. end
  3943. else
  3944. Result := False;
  3945. end;
  3946. // ---------------
  3947. // --------------- TgxODEJointBall ---------------
  3948. // ---------------
  3949. constructor TgxODEJointBall.Create(AOwner: TXCollection);
  3950. begin
  3951. inherited;
  3952. FAnchor := TgxCoordinates.CreateInitialized(Self, NullHmgPoint, csPoint);
  3953. FAnchor.OnNotifyChange := AnchorChange;
  3954. end;
  3955. destructor TgxODEJointBall.Destroy;
  3956. begin
  3957. FAnchor.Free;
  3958. inherited;
  3959. end;
  3960. procedure TgxODEJointBall.Initialize;
  3961. begin
  3962. if (not IsODEInitialized) or (FInitialized) then
  3963. Exit;
  3964. FJointID := dJointCreateBall(FManager.World, nil);
  3965. inherited;
  3966. end;
  3967. procedure TgxODEJointBall.WriteToFiler(writer: TWriter);
  3968. begin
  3969. inherited;
  3970. with writer do
  3971. begin
  3972. WriteInteger(0); // Archive version
  3973. FAnchor.WriteToFiler(writer);
  3974. end;
  3975. end;
  3976. procedure TgxODEJointBall.ReadFromFiler(reader: TReader);
  3977. begin
  3978. inherited;
  3979. with reader do
  3980. begin
  3981. Assert(ReadInteger = 0); // Archive version
  3982. FAnchor.ReadFromFiler(reader);
  3983. end;
  3984. end;
  3985. procedure TgxODEJointBall.StructureChanged;
  3986. begin
  3987. AnchorChange(nil);
  3988. end;
  3989. procedure TgxODEJointBall.AnchorChange(Sender: TObject);
  3990. begin
  3991. if IsAttached then
  3992. dJointSetBallAnchor(FJointID, FAnchor.X, FAnchor.Y, FAnchor.Z);
  3993. end;
  3994. class function TgxODEJointBall.FriendlyName: String;
  3995. begin
  3996. Result := 'Ball';
  3997. end;
  3998. class function TgxODEJointBall.FriendlyDescription: String;
  3999. begin
  4000. Result := 'ODE Ball joint implementation';
  4001. end;
  4002. procedure TgxODEJointBall.SetAnchor(const Value: TgxCoordinates);
  4003. begin
  4004. FAnchor.Assign(Value);
  4005. end;
  4006. // ---------------
  4007. // --------------- TgxODEJointSlider ---------------
  4008. // ---------------
  4009. constructor TgxODEJointSlider.Create(AOwner: TXCollection);
  4010. begin
  4011. inherited;
  4012. FAxis := TgxCoordinates.CreateInitialized(Self, ZHmgVector, csVector);
  4013. FAxis.OnNotifyChange := AxisChange;
  4014. FAxisParams := TgxODEJointParams.Create(Self);
  4015. FAxisParams.SetCallback := SetAxisParam;
  4016. FAxisParams.GetCallback := GetAxisParam;
  4017. end;
  4018. destructor TgxODEJointSlider.Destroy;
  4019. begin
  4020. FAxis.Free;
  4021. FAxisParams.Free;
  4022. inherited;
  4023. end;
  4024. procedure TgxODEJointSlider.Initialize;
  4025. begin
  4026. if (not IsODEInitialized) or (FInitialized) then
  4027. Exit;
  4028. FJointID := dJointCreateSlider(FManager.World, nil);
  4029. inherited;
  4030. end;
  4031. procedure TgxODEJointSlider.WriteToFiler(writer: TWriter);
  4032. begin
  4033. inherited;
  4034. with writer do
  4035. begin
  4036. WriteInteger(0); // Archive version
  4037. FAxis.WriteToFiler(writer);
  4038. FAxisParams.WriteToFiler(writer);
  4039. end;
  4040. end;
  4041. procedure TgxODEJointSlider.ReadFromFiler(reader: TReader);
  4042. begin
  4043. inherited;
  4044. with reader do
  4045. begin
  4046. Assert(ReadInteger = 0); // Archive version
  4047. FAxis.ReadFromFiler(reader);
  4048. FAxisParams.ReadFromFiler(reader);
  4049. end;
  4050. end;
  4051. procedure TgxODEJointSlider.StructureChanged;
  4052. begin
  4053. AxisChange(nil);
  4054. AxisParams.ApplyFlagged;
  4055. end;
  4056. procedure TgxODEJointSlider.AxisChange(Sender: TObject);
  4057. var
  4058. vec: TVector4f;
  4059. begin
  4060. vec := FAxis.DirectVector;
  4061. NormalizeVector(vec);
  4062. FAxis.DirectVector := vec;
  4063. if IsAttached then
  4064. dJointSetSliderAxis(FJointID, FAxis.X, FAxis.Y, FAxis.Z);
  4065. end;
  4066. class function TgxODEJointSlider.FriendlyName: String;
  4067. begin
  4068. Result := 'Slider';
  4069. end;
  4070. class function TgxODEJointSlider.FriendlyDescription: String;
  4071. begin
  4072. Result := 'ODE Slider joint implementation';
  4073. end;
  4074. procedure TgxODEJointSlider.SetAxis(const Value: TgxCoordinates);
  4075. begin
  4076. FAxis.Assign(Value);
  4077. end;
  4078. procedure TgxODEJointSlider.SetAxisParams(const Value: TgxODEJointParams);
  4079. begin
  4080. AxisParams.Assign(Value);
  4081. end;
  4082. function TgxODEJointSlider.SetAxisParam(Param: Integer;
  4083. const Value: TdReal): Boolean;
  4084. begin
  4085. if IsAttached then
  4086. begin
  4087. dJointSetSliderParam(JointID, Param, Value);
  4088. Result := True;
  4089. end
  4090. else
  4091. Result := False;
  4092. end;
  4093. function TgxODEJointSlider.GetAxisParam(Param: Integer; var Value: TdReal): Boolean;
  4094. begin
  4095. if IsAttached then
  4096. begin
  4097. Value := dJointGetSliderParam(JointID, Param);
  4098. Result := True;
  4099. end
  4100. else
  4101. Result := False;
  4102. end;
  4103. // ---------------
  4104. // --------------- TgxODEJointFixed ---------------
  4105. // ---------------
  4106. procedure TgxODEJointFixed.Initialize;
  4107. begin
  4108. if (not IsODEInitialized) or (FInitialized) then
  4109. Exit;
  4110. FJointID := dJointCreateFixed(FManager.World, nil);
  4111. inherited;
  4112. end;
  4113. procedure TgxODEJointFixed.WriteToFiler(writer: TWriter);
  4114. begin
  4115. inherited;
  4116. with writer do
  4117. begin
  4118. WriteInteger(0); // Archive version
  4119. end;
  4120. end;
  4121. procedure TgxODEJointFixed.ReadFromFiler(reader: TReader);
  4122. begin
  4123. inherited;
  4124. with reader do
  4125. begin
  4126. Assert(ReadInteger = 0); // Archive version
  4127. end;
  4128. end;
  4129. class function TgxODEJointFixed.FriendlyName: String;
  4130. begin
  4131. Result := 'Fixed';
  4132. end;
  4133. class function TgxODEJointFixed.FriendlyDescription: String;
  4134. begin
  4135. Result := 'ODE Fixed joint implementation';
  4136. end;
  4137. // ---------------
  4138. // --------------- TgxODEJointHinge2 ---------------
  4139. // ---------------
  4140. constructor TgxODEJointHinge2.Create(AOwner: TXCollection);
  4141. begin
  4142. inherited;
  4143. FAnchor := TgxCoordinates.CreateInitialized(Self, NullHmgPoint, csPoint);
  4144. FAnchor.OnNotifyChange := AnchorChange;
  4145. FAxis1 := TgxCoordinates.CreateInitialized(Self, ZHmgVector, csVector);
  4146. FAxis1.OnNotifyChange := Axis1Change;
  4147. FAxis2 := TgxCoordinates.CreateInitialized(Self, ZHmgVector, csVector);
  4148. FAxis2.OnNotifyChange := Axis2Change;
  4149. FAxis1Params := TgxODEJointParams.Create(Self);
  4150. FAxis1Params.SetCallback := SetAxis1Param;
  4151. FAxis1Params.GetCallback := GetAxis1Param;
  4152. FAxis2Params := TgxODEJointParams.Create(Self);
  4153. FAxis2Params.SetCallback := SetAxis2Param;
  4154. FAxis2Params.GetCallback := GetAxis2Param;
  4155. JointOptions := [joBothObjectsMustBeAssigned];
  4156. end;
  4157. destructor TgxODEJointHinge2.Destroy;
  4158. begin
  4159. FAnchor.Free;
  4160. FAxis1.Free;
  4161. FAxis2.Free;
  4162. FAxis1Params.Free;
  4163. FAxis2Params.Free;
  4164. inherited;
  4165. end;
  4166. procedure TgxODEJointHinge2.Initialize;
  4167. begin
  4168. if (not IsODEInitialized) or (FInitialized) then
  4169. Exit;
  4170. FJointID := dJointCreateHinge2(FManager.World, nil);
  4171. inherited;
  4172. end;
  4173. procedure TgxODEJointHinge2.WriteToFiler(writer: TWriter);
  4174. begin
  4175. inherited;
  4176. with writer do
  4177. begin
  4178. WriteInteger(0); // Archive version
  4179. FAnchor.WriteToFiler(writer);
  4180. FAxis1.WriteToFiler(writer);
  4181. FAxis2.WriteToFiler(writer);
  4182. FAxis1Params.WriteToFiler(writer);
  4183. FAxis2Params.WriteToFiler(writer);
  4184. end;
  4185. end;
  4186. procedure TgxODEJointHinge2.ReadFromFiler(reader: TReader);
  4187. begin
  4188. inherited;
  4189. with reader do
  4190. begin
  4191. Assert(ReadInteger = 0); // Archive version
  4192. FAnchor.ReadFromFiler(reader);
  4193. FAxis1.ReadFromFiler(reader);
  4194. FAxis2.ReadFromFiler(reader);
  4195. FAxis1Params.ReadFromFiler(reader);
  4196. FAxis2Params.ReadFromFiler(reader);
  4197. end;
  4198. end;
  4199. procedure TgxODEJointHinge2.StructureChanged;
  4200. begin
  4201. AnchorChange(nil);
  4202. Axis1Change(nil);
  4203. Axis2Change(nil);
  4204. Axis1Params.ApplyFlagged;
  4205. Axis2Params.ApplyFlagged;
  4206. end;
  4207. procedure TgxODEJointHinge2.AnchorChange(Sender: TObject);
  4208. begin
  4209. if IsAttached then
  4210. dJointSetHinge2Anchor(FJointID, FAnchor.X, FAnchor.Y, FAnchor.Z);
  4211. end;
  4212. procedure TgxODEJointHinge2.Axis1Change(Sender: TObject);
  4213. var
  4214. vec: TVector4f;
  4215. begin
  4216. vec := FAxis1.DirectVector;
  4217. NormalizeVector(vec);
  4218. FAxis1.DirectVector := vec;
  4219. if IsAttached then
  4220. dJointSetHinge2Axis1(FJointID, FAxis1.X, FAxis1.Y, FAxis1.Z);
  4221. end;
  4222. procedure TgxODEJointHinge2.Axis2Change(Sender: TObject);
  4223. var
  4224. vec: TVector4f;
  4225. begin
  4226. vec := FAxis2.DirectVector;
  4227. NormalizeVector(vec);
  4228. FAxis2.DirectVector := vec;
  4229. if IsAttached then
  4230. dJointSetHinge2Axis2(FJointID, FAxis2.X, FAxis2.Y, FAxis2.Z);
  4231. end;
  4232. class function TgxODEJointHinge2.FriendlyName: String;
  4233. begin
  4234. Result := 'Hinge2';
  4235. end;
  4236. class function TgxODEJointHinge2.FriendlyDescription: String;
  4237. begin
  4238. Result := 'ODE Double Axis Hinge joint implementation';
  4239. end;
  4240. procedure TgxODEJointHinge2.SetAnchor(const Value: TgxCoordinates);
  4241. begin
  4242. FAnchor.Assign(Value);
  4243. end;
  4244. procedure TgxODEJointHinge2.SetAxis1(const Value: TgxCoordinates);
  4245. begin
  4246. FAxis1.Assign(Value);
  4247. end;
  4248. procedure TgxODEJointHinge2.SetAxis2(const Value: TgxCoordinates);
  4249. begin
  4250. FAxis2.Assign(Value);
  4251. end;
  4252. procedure TgxODEJointHinge2.SetAxis1Params(const Value: TgxODEJointParams);
  4253. begin
  4254. Axis1Params.Assign(Value);
  4255. end;
  4256. procedure TgxODEJointHinge2.SetAxis2Params(const Value: TgxODEJointParams);
  4257. begin
  4258. Axis2Params.Assign(Value);
  4259. end;
  4260. function TgxODEJointHinge2.SetAxis1Param(Param: Integer; const Value: TdReal): Boolean;
  4261. begin
  4262. if IsAttached then
  4263. begin
  4264. dJointSetHinge2Param(JointID, Param, Value);
  4265. Result := True;
  4266. end
  4267. else
  4268. Result := False;
  4269. end;
  4270. function TgxODEJointHinge2.SetAxis2Param(Param: Integer; const Value: TdReal): Boolean;
  4271. begin
  4272. if IsAttached then
  4273. begin
  4274. dJointSetHinge2Param(JointID, dParamLoStop2 + Param, Value);
  4275. Result := True;
  4276. end
  4277. else
  4278. Result := False;
  4279. end;
  4280. function TgxODEJointHinge2.GetAxis1Param(Param: Integer; var Value: TdReal): Boolean;
  4281. begin
  4282. if IsAttached then
  4283. begin
  4284. Value := dJointGetHinge2Param(JointID, Param);
  4285. Result := True;
  4286. end
  4287. else
  4288. Result := False;
  4289. end;
  4290. function TgxODEJointHinge2.GetAxis2Param(Param: Integer; var Value: TdReal): Boolean;
  4291. begin
  4292. if IsAttached then
  4293. begin
  4294. Value := dJointGetHinge2Param(JointID, dParamLoStop2 + Param);
  4295. Result := True;
  4296. end
  4297. else
  4298. Result := False;
  4299. end;
  4300. // ---------------
  4301. // --------------- TgxODEJointUniversal ---------------
  4302. // ---------------
  4303. constructor TgxODEJointUniversal.Create(AOwner: TXCollection);
  4304. begin
  4305. inherited;
  4306. FAnchor := TgxCoordinates.CreateInitialized(Self, NullHmgPoint, csPoint);
  4307. FAnchor.OnNotifyChange := AnchorChange;
  4308. FAxis1 := TgxCoordinates.CreateInitialized(Self, ZHmgVector, csVector);
  4309. FAxis1.OnNotifyChange := Axis1Change;
  4310. FAxis2 := TgxCoordinates.CreateInitialized(Self, XHmgVector, csVector);
  4311. FAxis2.OnNotifyChange := Axis2Change;
  4312. FAxis1Params := TgxODEJointParams.Create(Self);
  4313. FAxis1Params.SetCallback := SetAxis1Param;
  4314. FAxis1Params.GetCallback := GetAxis1Param;
  4315. FAxis2Params := TgxODEJointParams.Create(Self);
  4316. FAxis2Params.SetCallback := SetAxis2Param;
  4317. FAxis2Params.GetCallback := GetAxis2Param;
  4318. JointOptions := [joBothObjectsMustBeAssigned];
  4319. end;
  4320. destructor TgxODEJointUniversal.Destroy;
  4321. begin
  4322. FAnchor.Free;
  4323. FAxis1.Free;
  4324. FAxis2.Free;
  4325. FAxis1Params.Free;
  4326. FAxis2Params.Free;
  4327. inherited;
  4328. end;
  4329. procedure TgxODEJointUniversal.Initialize;
  4330. begin
  4331. if (not IsODEInitialized) or (FInitialized) then
  4332. Exit;
  4333. FJointID := dJointCreateUniversal(FManager.World, nil);
  4334. inherited;
  4335. end;
  4336. procedure TgxODEJointUniversal.WriteToFiler(writer: TWriter);
  4337. begin
  4338. inherited;
  4339. with writer do
  4340. begin
  4341. WriteInteger(0); // Archive version
  4342. FAnchor.WriteToFiler(writer);
  4343. FAxis1.WriteToFiler(writer);
  4344. FAxis2.WriteToFiler(writer);
  4345. FAxis1Params.WriteToFiler(writer);
  4346. FAxis2Params.WriteToFiler(writer);
  4347. end;
  4348. end;
  4349. procedure TgxODEJointUniversal.ReadFromFiler(reader: TReader);
  4350. begin
  4351. inherited;
  4352. with reader do
  4353. begin
  4354. Assert(ReadInteger = 0); // Archive version
  4355. FAnchor.ReadFromFiler(reader);
  4356. FAxis1.ReadFromFiler(reader);
  4357. FAxis2.ReadFromFiler(reader);
  4358. FAxis1Params.ReadFromFiler(reader);
  4359. FAxis2Params.ReadFromFiler(reader);
  4360. end;
  4361. end;
  4362. procedure TgxODEJointUniversal.StructureChanged;
  4363. begin
  4364. AnchorChange(nil);
  4365. Axis1Change(nil);
  4366. Axis2Change(nil);
  4367. Axis1Params.ApplyFlagged;
  4368. Axis2Params.ApplyFlagged;
  4369. end;
  4370. procedure TgxODEJointUniversal.AnchorChange(Sender: TObject);
  4371. begin
  4372. if IsAttached then
  4373. dJointSetUniversalAnchor(FJointID, FAnchor.X, FAnchor.Y, FAnchor.Z);
  4374. end;
  4375. procedure TgxODEJointUniversal.Axis1Change(Sender: TObject);
  4376. var
  4377. vec: TVector4f;
  4378. begin
  4379. vec := FAxis1.DirectVector;
  4380. NormalizeVector(vec);
  4381. FAxis1.DirectVector := vec;
  4382. if IsAttached then
  4383. dJointSetUniversalAxis1(FJointID, FAxis1.X, FAxis1.Y, FAxis1.Z);
  4384. end;
  4385. procedure TgxODEJointUniversal.Axis2Change(Sender: TObject);
  4386. var
  4387. vec: TVector4f;
  4388. begin
  4389. vec := FAxis2.DirectVector;
  4390. NormalizeVector(vec);
  4391. FAxis2.DirectVector := vec;
  4392. if IsAttached then
  4393. dJointSetUniversalAxis2(FJointID, FAxis2.X, FAxis2.Y, FAxis2.Z);
  4394. end;
  4395. class function TgxODEJointUniversal.FriendlyName: String;
  4396. begin
  4397. Result := 'Universal';
  4398. end;
  4399. class function TgxODEJointUniversal.FriendlyDescription: String;
  4400. begin
  4401. Result := 'ODE Universal joint implementation';
  4402. end;
  4403. procedure TgxODEJointUniversal.SetAnchor(const Value: TgxCoordinates);
  4404. begin
  4405. FAnchor.Assign(Value);
  4406. end;
  4407. procedure TgxODEJointUniversal.SetAxis1(const Value: TgxCoordinates);
  4408. begin
  4409. FAxis1.Assign(Value);
  4410. end;
  4411. procedure TgxODEJointUniversal.SetAxis2(const Value: TgxCoordinates);
  4412. begin
  4413. FAxis2.Assign(Value);
  4414. end;
  4415. procedure TgxODEJointUniversal.SetAxis1Params(const Value: TgxODEJointParams);
  4416. begin
  4417. Axis1Params.Assign(Value);
  4418. end;
  4419. procedure TgxODEJointUniversal.SetAxis2Params(const Value: TgxODEJointParams);
  4420. begin
  4421. Axis2Params.Assign(Value);
  4422. end;
  4423. function TgxODEJointUniversal.SetAxis1Param(Param: Integer; const Value: TdReal): Boolean;
  4424. begin
  4425. if IsAttached then
  4426. begin
  4427. dJointSetUniversalParam(JointID, Param, Value);
  4428. Result := True;
  4429. end
  4430. else
  4431. Result := False;
  4432. end;
  4433. function TgxODEJointUniversal.SetAxis2Param(Param: Integer; const Value: TdReal): Boolean;
  4434. begin
  4435. if IsAttached then
  4436. begin
  4437. dJointSetUniversalParam(JointID, dParamLoStop2 + Param, Value);
  4438. Result := True;
  4439. end
  4440. else
  4441. Result := False;
  4442. end;
  4443. function TgxODEJointUniversal.GetAxis1Param(Param: Integer; var Value: TdReal): Boolean;
  4444. begin
  4445. if IsAttached then
  4446. begin
  4447. Value := dJointGetUniversalParam(JointID, Param);
  4448. Result := True;
  4449. end
  4450. else
  4451. Result := False;
  4452. end;
  4453. function TgxODEJointUniversal.GetAxis2Param(Param: Integer; var Value: TdReal): Boolean;
  4454. begin
  4455. if IsAttached then
  4456. begin
  4457. Value := dJointGetUniversalParam(JointID, dParamLoStop2 + Param);
  4458. Result := True;
  4459. end
  4460. else
  4461. Result := False;
  4462. end;
  4463. // ---------------
  4464. // --------------- TgxODECustomCollider --------------
  4465. // ---------------
  4466. constructor TgxODECustomCollider.Create(AOwner: TXCollection);
  4467. begin
  4468. inherited;
  4469. FContactList := TList.Create;
  4470. FContactCache := TList.Create;
  4471. FContactResolution := 1;
  4472. FRenderContacts := False;
  4473. FContactRenderPoints := TgxAffineVectorList.Create;
  4474. FContactColor := TgxColor.CreateInitialized(Self, clrRed, NotifyChange);
  4475. FPointSize := 3;
  4476. end;
  4477. destructor TgxODECustomCollider.Destroy;
  4478. var
  4479. i: Integer;
  4480. begin
  4481. FContactList.Free;
  4482. for i := 0 to FContactCache.Count - 1 do
  4483. TgxODEContactPoint(FContactCache[i]).Free;
  4484. FContactCache.Free;
  4485. FContactRenderPoints.Free;
  4486. FContactColor.Free;
  4487. inherited;
  4488. end;
  4489. procedure TgxODECustomCollider.Initialize;
  4490. begin
  4491. if not Assigned(Manager) then
  4492. exit;
  4493. if not Assigned(Manager.Space) then
  4494. exit;
  4495. if vCustomColliderClassNum = 0 then
  4496. begin
  4497. with vCustomColliderClass do
  4498. begin
  4499. bytes := 0;
  4500. Collider := GetCustomColliderFn;
  4501. aabb := dInfiniteAABB;
  4502. aabb_test := nil;
  4503. dtor := nil;
  4504. end;
  4505. vCustomColliderClassNum := dCreateGeomClass(vCustomColliderClass);
  4506. end;
  4507. FGeom := dCreateGeom(vCustomColliderClassNum);
  4508. dGeomSetData(FGeom, Self);
  4509. dSpaceAdd(Manager.Space, FGeom);
  4510. inherited;
  4511. end;
  4512. procedure TgxODECustomCollider.Finalize;
  4513. begin
  4514. if not Initialized then
  4515. exit;
  4516. if Assigned(FGeom) then
  4517. begin
  4518. dGeomDestroy(FGeom);
  4519. FGeom := nil;
  4520. end;
  4521. inherited;
  4522. end;
  4523. procedure TgxODECustomCollider.WriteToFiler(writer: TWriter);
  4524. begin
  4525. inherited;
  4526. with writer do
  4527. begin
  4528. WriteInteger(0); // Archive version
  4529. WriteFloat(FContactResolution);
  4530. WriteBoolean(FRenderContacts);
  4531. WriteFloat(FPointSize);
  4532. Write(PByte(FContactColor.AsAddress)^, 4);
  4533. end;
  4534. end;
  4535. procedure TgxODECustomCollider.ReadFromFiler(reader: TReader);
  4536. var
  4537. archiveVersion: Integer;
  4538. begin
  4539. inherited;
  4540. with reader do
  4541. begin
  4542. archiveVersion := ReadInteger;
  4543. Assert(archiveVersion = 0); // Archive version
  4544. FContactResolution := ReadFloat;
  4545. FRenderContacts := ReadBoolean;
  4546. FPointSize := ReadFloat;
  4547. Read(PByte(FContactColor.AsAddress)^, 4);
  4548. end;
  4549. end;
  4550. procedure TgxODECustomCollider.ClearContacts;
  4551. begin
  4552. FContactList.Clear;
  4553. end;
  4554. procedure TgxODECustomCollider.AddContact(x, y, z: TdReal);
  4555. begin
  4556. AddContact(AffineVectorMake(x, y, z));
  4557. end;
  4558. procedure TgxODECustomCollider.AddContact(pos: TAffineVector);
  4559. var
  4560. absPos, colPos, colNorm: TAffineVector;
  4561. Depth: Single;
  4562. ContactPoint: TgxODEContactPoint;
  4563. begin
  4564. absPos := AffineVectorMake(VectorTransform(PointMake(pos), FTransform));
  4565. if Collide(absPos, Depth, colPos, colNorm) then
  4566. begin
  4567. if FContactList.Count < FContactCache.Count then
  4568. ContactPoint := FContactCache[FContactList.Count]
  4569. else
  4570. begin
  4571. ContactPoint := TgxODEContactPoint.Create;
  4572. FContactCache.Add(ContactPoint);
  4573. end;
  4574. ContactPoint.Position := colPos;
  4575. ContactPoint.Normal := colNorm;
  4576. ContactPoint.Depth := Depth;
  4577. FContactList.Add(ContactPoint);
  4578. end;
  4579. if FRenderContacts and Manager.Visible and Manager.VisibleAtRunTime then
  4580. FContactRenderPoints.Add(absPos);
  4581. end;
  4582. function TgxODECustomCollider.ApplyContacts(o1, o2: PdxGeom; flags: Integer;
  4583. contact: PdContactGeom; skip: Integer): Integer;
  4584. var
  4585. i, maxContacts: Integer;
  4586. begin
  4587. FContactList.Sort(ContactSort);
  4588. Result := 0;
  4589. maxContacts := flags and $FFFF;
  4590. try
  4591. for i := 0 to FContactList.Count - 1 do
  4592. begin
  4593. if Result >= maxContacts then
  4594. Exit;
  4595. with TgxODEContactPoint(FContactList[i]) do
  4596. begin
  4597. contact.Depth := Depth;
  4598. contact.pos[0] := Position.x;
  4599. contact.pos[1] := Position.y;
  4600. contact.pos[2] := Position.z;
  4601. contact.pos[3] := 1;
  4602. contact.Normal[0] := -Normal.x;
  4603. contact.Normal[1] := -Normal.y;
  4604. contact.Normal[2] := -Normal.z;
  4605. contact.Normal[3] := 0;
  4606. end;
  4607. contact.g1 := o1;
  4608. contact.g2 := o2;
  4609. contact := PdContactGeom(Integer(contact) + skip);
  4610. Inc(Result);
  4611. end;
  4612. finally
  4613. ClearContacts;
  4614. end;
  4615. end;
  4616. procedure TgxODECustomCollider.SetTransform(ATransform: TMatrix4f);
  4617. begin
  4618. FTransform := ATransform;
  4619. end;
  4620. procedure TgxODECustomCollider.SetContactResolution(const Value: Single);
  4621. begin
  4622. FContactResolution := Value;
  4623. if FContactResolution <= 0 then
  4624. FContactResolution := 0.01;
  4625. end;
  4626. procedure TgxODECustomCollider.Render(var rci: TgxRenderContextInfo);
  4627. var
  4628. i: Integer;
  4629. begin
  4630. if FRenderContacts and (FContactRenderPoints.Count>0) then
  4631. begin
  4632. glPushAttrib(GL_CURRENT_BIT);
  4633. glColor3fv(PGLfloat(FContactColor.AsAddress));
  4634. glPointSize(FPointSize);
  4635. glBegin(GL_POINTS);
  4636. for i := 0 to FContactRenderPoints.Count - 1 do
  4637. glVertex3fv(@FContactRenderPoints.List[i]);
  4638. glEnd;
  4639. glPopAttrib;
  4640. end;
  4641. FContactRenderPoints.Clear;
  4642. end;
  4643. procedure TgxODECustomCollider.SetRenderContacts(const Value: Boolean);
  4644. begin
  4645. if Value <> FRenderContacts then
  4646. begin
  4647. FRenderContacts := Value;
  4648. NotifyChange(Self);
  4649. end;
  4650. end;
  4651. procedure TgxODECustomCollider.SetContactColor(const Value: TgxColor);
  4652. begin
  4653. FContactColor.Assign(Value);
  4654. end;
  4655. procedure TgxODECustomCollider.SetPointSize(const Value: Single);
  4656. begin
  4657. if Value <> FPointSize then
  4658. begin
  4659. FPointSize := Value;
  4660. NotifyChange(Self);
  4661. end;
  4662. end;
  4663. // ---------------
  4664. // --------------- TgxODEHeightField --------------
  4665. // ---------------
  4666. constructor TgxODEHeightField.Create(AOwner: TXCollection);
  4667. var
  4668. Allow: Boolean;
  4669. begin
  4670. Allow := False;
  4671. if Assigned(AOwner) then
  4672. begin
  4673. if Assigned(AOwner.Owner) then
  4674. begin
  4675. if ((AOwner.Owner) is TgxTerrainRenderer) or
  4676. ((AOwner.Owner) is TgxHeightField) then
  4677. Allow := True;
  4678. end;
  4679. end;
  4680. if not Allow then
  4681. raise Exception.Create
  4682. ('This element must be a behaviour of a TgxTerrainRenderer or TgxHeightField');
  4683. inherited Create(AOwner);
  4684. end;
  4685. procedure TgxODEHeightField.WriteToFiler(writer: TWriter);
  4686. begin
  4687. inherited;
  4688. with writer do
  4689. begin
  4690. WriteInteger(0); // Archive version
  4691. end;
  4692. end;
  4693. procedure TgxODEHeightField.ReadFromFiler(reader: TReader);
  4694. var
  4695. archiveVersion: Integer;
  4696. begin
  4697. inherited;
  4698. with reader do
  4699. begin
  4700. archiveVersion := ReadInteger;
  4701. Assert(archiveVersion = 0); // Archive version
  4702. end;
  4703. end;
  4704. class function TgxODEHeightField.FriendlyName: string;
  4705. begin
  4706. Result := 'ODE HeightField Collider';
  4707. end;
  4708. class function TgxODEHeightField.FriendlyDescription: string;
  4709. begin
  4710. Result := 'A custom ODE collider powered by it''s parent TgxTerrainRenderer or TgxHeightField';
  4711. end;
  4712. class function TgxODEHeightField.UniqueItem: Boolean;
  4713. begin
  4714. Result := True;
  4715. end;
  4716. class function TgxODEHeightField.CanAddTo(collection: TXCollection): Boolean;
  4717. begin
  4718. Result := False;
  4719. if collection is TgxBehaviours then
  4720. if Assigned(TgxBehaviours(collection).Owner) then
  4721. if (TgxBehaviours(collection).Owner is TgxHeightField)
  4722. or (TgxBehaviours(collection).Owner is TgxTerrainRenderer) then
  4723. Result := True;
  4724. end;
  4725. function TgxODEHeightField.Collide(aPos: TAffineVector; var Depth: Single;
  4726. var cPos, cNorm: TAffineVector): Boolean;
  4727. function AbsoluteToLocal(vec: TVector4f): TVector4f;
  4728. var
  4729. mat: TMatrix4f;
  4730. begin
  4731. if Owner.Owner is TgxHeightField then
  4732. Result := TgxHeightField(Owner.Owner).AbsoluteToLocal(vec)
  4733. else if Owner.Owner is TgxTerrainRenderer then
  4734. begin
  4735. mat := TgxTerrainRenderer(Owner.Owner).AbsoluteMatrix;
  4736. NormalizeMatrix(mat);
  4737. InvertMatrix(mat);
  4738. Result := VectorTransform(vec, mat);
  4739. end
  4740. else
  4741. Assert(False);
  4742. end;
  4743. function LocalToAbsolute(vec: TVector4f): TVector4f;
  4744. var
  4745. mat: TMatrix4f;
  4746. begin
  4747. if Owner.Owner is TgxHeightField then
  4748. Result := TgxHeightField(Owner.Owner).LocalToAbsolute(vec)
  4749. else if Owner.Owner is TgxTerrainRenderer then
  4750. begin
  4751. mat := TgxTerrainRenderer(Owner.Owner).AbsoluteMatrix;
  4752. NormalizeMatrix(mat);
  4753. Result := VectorTransform(vec, mat);
  4754. end
  4755. else
  4756. Assert(False);
  4757. end;
  4758. function GetHeight(pos: TVector4f; var height: Single): Boolean;
  4759. var
  4760. dummy1: TVector4f;
  4761. dummy2: TTexPoint;
  4762. begin
  4763. Result := False;
  4764. if Owner.Owner is TgxTerrainRenderer then
  4765. begin
  4766. height := TgxTerrainRenderer(Owner.Owner).InterpolatedHeight(LocalToAbsolute(pos));
  4767. Result := True;
  4768. end
  4769. else
  4770. if Owner.Owner is TgxHeightField then
  4771. begin
  4772. if Assigned(TgxHeightField(Owner.Owner).OnGetHeight) then
  4773. begin
  4774. TgxHeightField(Owner.Owner).OnGetHeight(pos.x, pos.y, height, dummy1, dummy2);
  4775. Result := True;
  4776. end;
  4777. end;
  4778. end;
  4779. const
  4780. cDelta = 0.1;
  4781. var
  4782. localPos: TVector4f;
  4783. height: Single;
  4784. temp1, temp2: TAffineVector;
  4785. begin
  4786. localPos := AbsoluteToLocal(PointMake(aPos));
  4787. if GetHeight(localPos, height) then
  4788. begin
  4789. Depth := height - localPos.z;
  4790. Result := (Depth > 0);
  4791. if Result then
  4792. begin
  4793. localPos.z := height;
  4794. cPos := AffineVectorMake(LocalToAbsolute(localPos));
  4795. temp1.x:= localPos.x + cDelta;
  4796. temp1.y := localPos.y;
  4797. temp1.z := localPos.z;
  4798. GetHeight(PointMake(temp1), temp1.z);
  4799. temp2.x := localPos.x;
  4800. temp2.y := localPos.y + cDelta;
  4801. temp2.z := localPos.z;
  4802. GetHeight(PointMake(temp2), temp2.z);
  4803. cNorm := CalcPlaneNormal(AffineVectorMake(localPos), temp1, temp2);
  4804. cNorm := AffineVectorMake(LocalToAbsolute(VectorMake(cNorm)));
  4805. end;
  4806. end
  4807. else
  4808. Result := False;
  4809. end;
  4810. // ------------------------------------------------------------------
  4811. initialization
  4812. // ------------------------------------------------------------------
  4813. vODEObjectRegister := TList.Create;
  4814. RegisterXCollectionItemClass(TgxODEDynamic);
  4815. RegisterXCollectionItemClass(TgxODEStatic);
  4816. RegisterXCollectionItemClass(TgxODEElementBox);
  4817. RegisterXCollectionItemClass(TgxODEElementSphere);
  4818. RegisterXCollectionItemClass(TgxODEElementCapsule);
  4819. RegisterXCollectionItemClass(TgxODEElementCylinder);
  4820. RegisterXCollectionItemClass(TgxODEElementTriMesh);
  4821. RegisterXCollectionItemClass(TgxODEElementPlane);
  4822. RegisterXCollectionItemClass(TgxODEJointHinge);
  4823. RegisterXCollectionItemClass(TgxODEJointBall);
  4824. RegisterXCollectionItemClass(TgxODEJointSlider);
  4825. RegisterXCollectionItemClass(TgxODEJointFixed);
  4826. RegisterXCollectionItemClass(TgxODEJointHinge2);
  4827. RegisterXCollectionItemClass(TgxODEJointUniversal);
  4828. RegisterXCollectionItemClass(TgxODEHeightField);
  4829. // ------------------------------------------------------------------
  4830. finalization
  4831. // ------------------------------------------------------------------
  4832. vODEObjectRegister.Free;
  4833. UnregisterXCollectionItemClass(TgxODEDynamic);
  4834. UnregisterXCollectionItemClass(TgxODEStatic);
  4835. UnregisterXCollectionItemClass(TgxODEElementBox);
  4836. UnregisterXCollectionItemClass(TgxODEElementSphere);
  4837. UnregisterXCollectionItemClass(TgxODEElementCapsule);
  4838. UnregisterXCollectionItemClass(TgxODEElementCylinder);
  4839. UnregisterXCollectionItemClass(TgxODEElementTriMesh);
  4840. UnregisterXCollectionItemClass(TgxODEElementPlane);
  4841. UnregisterXCollectionItemClass(TgxODEJointHinge);
  4842. UnregisterXCollectionItemClass(TgxODEJointBall);
  4843. UnregisterXCollectionItemClass(TgxODEJointSlider);
  4844. UnregisterXCollectionItemClass(TgxODEJointFixed);
  4845. UnregisterXCollectionItemClass(TgxODEJointHinge2);
  4846. UnregisterXCollectionItemClass(TgxODEJointUniversal);
  4847. UnregisterXCollectionItemClass(TgxODEHeightField);
  4848. // CloseODE;
  4849. end.