Physics.ODEManager.pas 140 KB

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