GXS.VectorFileObjects.pas 218 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.VectorFileObjects;
  5. (*
  6. Vector File related objects for GLScene
  7. The history is logged in a former GLS version of the unit.
  8. *)
  9. interface
  10. {$I Stage.Defines.inc}
  11. uses
  12. Winapi.OpenGL,
  13. Winapi.OpenGLext,
  14. System.Classes,
  15. System.Math,
  16. System.SysUtils,
  17. System.Types,
  18. Stage.VectorTypes,
  19. Stage.VectorGeometry,
  20. Stage.Strings,
  21. Stage.Utils,
  22. Stage.TextureFormat,
  23. GXS.BaseClasses,
  24. GXS.GeometryBB,
  25. GXS.VectorLists,
  26. GXS.PersistentClasses,
  27. GXS.Coordinates,
  28. GXS.XOpenGL,
  29. GXS.ApplicationFileIO,
  30. GXS.Scene,
  31. GXS.Texture,
  32. GXS.Material,
  33. GXS.Mesh,
  34. GXS.Octree,
  35. GXS.Silhouette,
  36. GXS.Context,
  37. GXS.Color,
  38. GXS.RenderContextInfo,
  39. GXS.State,
  40. GXS.ImageUtils,
  41. GXS.MeshUtils;
  42. type
  43. TgxMeshObjectList = class;
  44. TgxFaceGroups = class;
  45. TgxMeshAutoCentering = (macCenterX, macCenterY, macCenterZ, macUseBarycenter, macRestorePosition);
  46. TgxMeshAutoCenterings = set of TgxMeshAutoCentering;
  47. TgxMeshObjectMode = (momTriangles, momTriangleStrip, momFaceGroups);
  48. (* A base class for mesh objects.
  49. The class introduces a set of vertices and normals for the object but
  50. does no rendering of its own. *)
  51. TgxBaseMeshObject = class(TgxPersistentObject)
  52. private
  53. FName: string;
  54. FVertices: TgxAffineVectorList;
  55. FNormals: TgxAffineVectorList;
  56. FVisible: Boolean;
  57. protected
  58. procedure SetVertices(const val: TgxAffineVectorList);
  59. procedure SetNormals(const val: TgxAffineVectorList);
  60. procedure ContributeToBarycenter(var currentSum: TAffineVector; var nb: Integer); virtual;
  61. public
  62. constructor Create; override;
  63. destructor Destroy; override;
  64. procedure Assign(Source: TPersistent); override;
  65. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  66. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  67. // Clears all mesh object data, submeshes, facegroups, etc.
  68. procedure Clear; virtual;
  69. // Translates all the vertices by the given delta.
  70. procedure Translate(const delta: TAffineVector); virtual;
  71. (* Builds (smoothed) normals for the vertex list.
  72. If normalIndices is nil, the method assumes a bijection between
  73. vertices and normals sets, and when performed, Normals and Vertices
  74. list will have the same number of items (whatever previously was in
  75. the Normals list is ignored/removed).
  76. If normalIndices is defined, normals will be added to the list and
  77. their indices will be added to normalIndices. Already defined
  78. normals and indices are preserved.
  79. The only valid modes are currently momTriangles and momTriangleStrip
  80. (ie. momFaceGroups not supported). *)
  81. procedure BuildNormals(vertexIndices: TgxIntegerList; mode: TgxMeshObjectMode; normalIndices: TgxIntegerList = nil);
  82. (* Extracts all mesh triangles as a triangles list.
  83. The resulting list size is a multiple of 3, each group of 3 vertices
  84. making up and independant triangle.
  85. The returned list can be used independantly from the mesh object
  86. (all data is duplicated) and should be freed by caller.
  87. If texCoords is specified, per vertex texture coordinates will be
  88. placed there, when available. *)
  89. function ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil): TgxAffineVectorList; virtual;
  90. property Name: string read FName write FName;
  91. property Visible: Boolean read FVisible write FVisible;
  92. property Vertices: TgxAffineVectorList read FVertices write SetVertices;
  93. property normals: TgxAffineVectorList read FNormals write SetNormals;
  94. end;
  95. TgxSkeletonFrameList = class;
  96. TgxSkeletonFrameTransform = (sftRotation, sftQuaternion);
  97. (* Stores position and rotation for skeleton joints.
  98. If you directly alter some values, make sure to call FlushLocalMatrixList
  99. so that the local matrices will be recalculated (the call to Flush does
  100. not recalculate the matrices, but marks the current ones as dirty). *)
  101. TgxSkeletonFrame = class(TgxPersistentObject)
  102. private
  103. FOwner: TgxSkeletonFrameList;
  104. FName: string;
  105. FPosition: TgxAffineVectorList;
  106. FRotation: TgxAffineVectorList;
  107. FQuaternion: TgxQuaternionList;
  108. FLocalMatrixList: PMatrixArray;
  109. FTransformMode: TgxSkeletonFrameTransform;
  110. protected
  111. procedure SetPosition(const val: TgxAffineVectorList);
  112. procedure SetRotation(const val: TgxAffineVectorList);
  113. procedure SetQuaternion(const val: TgxQuaternionList);
  114. public
  115. constructor CreateOwned(aOwner: TgxSkeletonFrameList);
  116. constructor Create; override;
  117. destructor Destroy; override;
  118. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  119. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  120. property Owner: TgxSkeletonFrameList read FOwner;
  121. property Name: string read FName write FName;
  122. // Position values for the joints.
  123. property Position: TgxAffineVectorList read FPosition write SetPosition;
  124. // Rotation values for the joints.
  125. property Rotation: TgxAffineVectorList read FRotation write SetRotation;
  126. (* Quaternions are an alternative to Euler rotations to build the
  127. global matrices for the skeleton bones. *)
  128. property Quaternion: TgxQuaternionList read FQuaternion write SetQuaternion;
  129. (* TransformMode indicates whether to use Rotation or Quaternion to build
  130. the local transform matrices. *)
  131. property TransformMode: TgxSkeletonFrameTransform read FTransformMode write FTransformMode;
  132. (* Calculate or retrieves an array of local bone matrices.
  133. This array is calculated on the first call after creation, and the
  134. first call following a FlushLocalMatrixList. Subsequent calls return
  135. the same arrays. *)
  136. function LocalMatrixList: PMatrixArray;
  137. (* Flushes (frees) then LocalMatrixList data.
  138. Call this function to allow a recalculation of local matrices. *)
  139. procedure FlushLocalMatrixList;
  140. // As the name states; Convert Quaternions to Rotations or vice-versa.
  141. procedure ConvertQuaternionsToRotations(KeepQuaternions: Boolean = True);
  142. procedure ConvertRotationsToQuaternions(KeepRotations: Boolean = True);
  143. end;
  144. // A list of TgxSkeletonFrame objects.
  145. TgxSkeletonFrameList = class(TgxPersistentObjectList)
  146. private
  147. FOwner: TPersistent;
  148. protected
  149. function GetSkeletonFrame(Index: Integer): TgxSkeletonFrame;
  150. public
  151. constructor CreateOwned(aOwner: TPersistent);
  152. destructor Destroy; override;
  153. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  154. // As the name states; Convert Quaternions to Rotations or vice-versa.
  155. procedure ConvertQuaternionsToRotations(KeepQuaternions: Boolean = True; SetTransformMode: Boolean = True);
  156. procedure ConvertRotationsToQuaternions(KeepRotations: Boolean = True; SetTransformMode: Boolean = True);
  157. property Owner: TPersistent read FOwner;
  158. procedure Clear; override;
  159. property Items[Index: Integer]: TgxSkeletonFrame read GetSkeletonFrame; default;
  160. end;
  161. TgxSkeleton = class;
  162. TgxSkeletonBone = class;
  163. // A list of skeleton bones.
  164. TgxSkeletonBoneList = class(TgxPersistentObjectList)
  165. private
  166. FSkeleton: TgxSkeleton; // not persistent
  167. protected
  168. FGlobalMatrix: TMatrix4f;
  169. function GetSkeletonBone(Index: Integer): TgxSkeletonBone;
  170. procedure AfterObjectCreatedByReader(Sender: TObject); override;
  171. public
  172. constructor CreateOwned(aOwner: TgxSkeleton);
  173. constructor Create; override;
  174. destructor Destroy; override;
  175. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  176. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  177. property Skeleton: TgxSkeleton read FSkeleton;
  178. property Items[Index: Integer]: TgxSkeletonBone read GetSkeletonBone; default;
  179. // Returns a bone by its BoneID, nil if not found.
  180. function BoneByID(anID: Integer): TgxSkeletonBone; virtual;
  181. // Returns a bone by its Name, nil if not found.
  182. function BoneByName(const aName: string): TgxSkeletonBone; virtual;
  183. // Number of bones (including all children and self).
  184. function BoneCount: Integer;
  185. // Render skeleton wireframe
  186. procedure BuildList(var mrci: TgxRenderContextInfo); virtual; abstract;
  187. procedure PrepareGlobalMatrices; virtual;
  188. end;
  189. // This list store skeleton root bones exclusively.
  190. TgxSkeletonRootBoneList = class(TgxSkeletonBoneList)
  191. public
  192. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  193. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  194. // Render skeleton wireframe
  195. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  196. property GlobalMatrix: TMatrix4f read FGlobalMatrix write FGlobalMatrix;
  197. end;
  198. (* A skeleton bone or node and its children.
  199. This class is the base item of the bones hierarchy in a skeletal model.
  200. The joint values are stored in a TgxSkeletonFrame, but the calculated bone
  201. matrices are stored here. *)
  202. TgxSkeletonBone = class(TgxSkeletonBoneList)
  203. private
  204. FOwner: TgxSkeletonBoneList; // indirectly persistent
  205. FBoneID: Integer;
  206. FName: string;
  207. FColor: Cardinal;
  208. protected
  209. function GetSkeletonBone(Index: Integer): TgxSkeletonBone;
  210. procedure SetColor(const val: Cardinal);
  211. public
  212. constructor CreateOwned(aOwner: TgxSkeletonBoneList);
  213. constructor Create; override;
  214. destructor Destroy; override;
  215. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  216. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  217. // Render skeleton wireframe
  218. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  219. property Owner: TgxSkeletonBoneList read FOwner;
  220. property Name: string read FName write FName;
  221. property BoneID: Integer read FBoneID write FBoneID;
  222. property Color: Cardinal read FColor write SetColor;
  223. property Items[Index: Integer]: TgxSkeletonBone read GetSkeletonBone; default;
  224. // Returns a bone by its BoneID, nil if not found.
  225. function BoneByID(anID: Integer): TgxSkeletonBone; override;
  226. function BoneByName(const aName: string): TgxSkeletonBone; override;
  227. // Set the bone's matrix. Becareful using this.
  228. procedure SetGlobalMatrix(Matrix: TMatrix4f); // Ragdoll
  229. // Set the bone's GlobalMatrix. Used for Ragdoll.
  230. procedure SetGlobalMatrixForRagDoll(RagDollMatrix: TMatrix4f); // Ragdoll
  231. (* Calculates the global matrix for the bone and its sub-bone.
  232. Call this function directly only the RootBone. *)
  233. procedure PrepareGlobalMatrices; override;
  234. (* Global Matrix for the bone in the current frame.
  235. Global matrices must be prepared by invoking PrepareGlobalMatrices
  236. on the root bone. *)
  237. property GlobalMatrix: TMatrix4f read FGlobalMatrix;
  238. // Free all sub bones and reset BoneID and Name.
  239. procedure Clean; override;
  240. end;
  241. TgxSkeletonColliderList = class;
  242. (* A general class storing the base level info required for skeleton
  243. based collision methods. This class is meant to be inherited from
  244. to create skeleton driven Verlet Constraints, ODE Geoms, etc.
  245. Overriden classes should be named as TSCxxxxx. *)
  246. TgxSkeletonCollider = class(TgxPersistentObject)
  247. private
  248. FOwner: TgxSkeletonColliderList;
  249. FBone: TgxSkeletonBone;
  250. FBoneID: Integer;
  251. FLocalMatrix, FGlobalMatrix: TMatrix4f;
  252. FAutoUpdate: Boolean;
  253. protected
  254. procedure SetBone(const val: TgxSkeletonBone);
  255. procedure SetLocalMatrix(const val: TMatrix4f);
  256. public
  257. constructor Create; override;
  258. constructor CreateOwned(aOwner: TgxSkeletonColliderList);
  259. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  260. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  261. (* This method is used to align the colliders and their
  262. derived objects to their associated skeleton bone.
  263. Override to set up descendant class alignment properties. *)
  264. procedure AlignCollider; virtual;
  265. property Owner: TgxSkeletonColliderList read FOwner;
  266. // The bone that this collider associates with.
  267. property Bone: TgxSkeletonBone read FBone write SetBone;
  268. (* Offset and orientation of the collider in the associated
  269. bone's space. *)
  270. property LocalMatrix: TMatrix4f read FLocalMatrix write SetLocalMatrix;
  271. (* Global offset and orientation of the collider. This
  272. gets set in the AlignCollider method. *)
  273. property GlobalMatrix: TMatrix4f read FGlobalMatrix;
  274. property AutoUpdate: Boolean read FAutoUpdate write FAutoUpdate;
  275. end;
  276. // List class for storing TgxSkeletonCollider objects.
  277. TgxSkeletonColliderList = class(TgxPersistentObjectList)
  278. private
  279. FOwner: TPersistent;
  280. protected
  281. function GetSkeletonCollider(Index: Integer): TgxSkeletonCollider;
  282. public
  283. constructor CreateOwned(aOwner: TPersistent);
  284. destructor Destroy; override;
  285. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  286. procedure Clear; override;
  287. // Calls AlignCollider for each collider in the list.
  288. procedure AlignColliders;
  289. property Owner: TPersistent read FOwner;
  290. property Items[Index: Integer]: TgxSkeletonCollider read GetSkeletonCollider; default;
  291. end;
  292. TgxBaseMesh = class;
  293. // Small structure to store a weighted lerp for use in blending.
  294. TGXBlendedLerpInfo = record
  295. frameIndex1, frameIndex2: Integer;
  296. lerpFactor: Single;
  297. weight: Single;
  298. externalPositions: TgxAffineVectorList;
  299. externalRotations: TgxAffineVectorList;
  300. externalQuaternions: TgxQuaternionList;
  301. end;
  302. (* Main skeleton object.
  303. This class stores the bones hierarchy and animation frames.
  304. It is also responsible for maintaining the "CurrentFrame" and allowing
  305. various frame blending operations. *)
  306. TgxSkeleton = class(TgxPersistentObject)
  307. private
  308. FOwner: TgxBaseMesh;
  309. FRootBones: TgxSkeletonRootBoneList;
  310. FFrames: TgxSkeletonFrameList;
  311. FCurrentFrame: TgxSkeletonFrame; // not persistent
  312. FBonesByIDCache: TList;
  313. FColliders: TgxSkeletonColliderList;
  314. FRagDollEnabled: Boolean; // ragdoll
  315. FMorphInvisibleParts: Boolean;
  316. protected
  317. procedure SetRootBones(const val: TgxSkeletonRootBoneList);
  318. procedure SetFrames(const val: TgxSkeletonFrameList);
  319. function GetCurrentFrame: TgxSkeletonFrame;
  320. procedure SetCurrentFrame(val: TgxSkeletonFrame);
  321. procedure SetColliders(const val: TgxSkeletonColliderList);
  322. public
  323. constructor CreateOwned(aOwner: TgxBaseMesh);
  324. constructor Create; override;
  325. destructor Destroy; override;
  326. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  327. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  328. property Owner: TgxBaseMesh read FOwner;
  329. property RootBones: TgxSkeletonRootBoneList read FRootBones write SetRootBones;
  330. property Frames: TgxSkeletonFrameList read FFrames write SetFrames;
  331. property CurrentFrame: TgxSkeletonFrame read GetCurrentFrame write SetCurrentFrame;
  332. property Colliders: TgxSkeletonColliderList read FColliders write SetColliders;
  333. procedure FlushBoneByIDCache;
  334. function BoneByID(anID: Integer): TgxSkeletonBone;
  335. function BoneByName(const aName: string): TgxSkeletonBone;
  336. function BoneCount: Integer;
  337. procedure MorphTo(frameIndex: Integer); overload;
  338. procedure MorphTo(frame: TgxSkeletonFrame); overload;
  339. procedure Lerp(frameIndex1, frameIndex2: Integer; lerpFactor: Single);
  340. procedure BlendedLerps(const lerpInfos: array of TGXBlendedLerpInfo);
  341. (* Linearly removes the translation component between skeletal frames.
  342. This function will compute the translation of the first bone (index 0)
  343. and linearly subtract this translation in all frames between startFrame
  344. and endFrame. Its purpose is essentially to remove the 'slide' that
  345. exists in some animation formats (f.i. SMD). *)
  346. procedure MakeSkeletalTranslationStatic(startFrame, endFrame: Integer);
  347. (* Removes the absolute rotation component of the skeletal frames.
  348. Some formats will store frames with absolute rotation information,
  349. if this correct if the animation is the "main" animation.
  350. This function removes that absolute information, making the animation
  351. frames suitable for blending purposes. *)
  352. procedure MakeSkeletalRotationDelta(startFrame, endFrame: Integer);
  353. // Applies current frame to morph all mesh objects.
  354. procedure MorphMesh(normalize: Boolean);
  355. // Copy bone rotations from reference skeleton.
  356. procedure Synchronize(reference: TgxSkeleton);
  357. // Release bones and frames info.
  358. procedure Clear;
  359. // Backup and prepare the BoneMatrixInvertedMeshes to use with ragdolls
  360. procedure StartRagdoll; // ragdoll
  361. // Restore the BoneMatrixInvertedMeshes to stop the ragdoll
  362. procedure StopRagdoll; // ragdoll
  363. (* Turning this option off (by default) alows to increase FPS,
  364. but may break backwards-compatibility, because some may choose to
  365. attach other objects to invisible parts. *)
  366. property MorphInvisibleParts: Boolean read FMorphInvisibleParts write FMorphInvisibleParts;
  367. end;
  368. (* Rendering options per TgxMeshObject.
  369. moroGroupByMaterial : if set, the facegroups will be rendered by material
  370. in batchs, this will optimize rendering by reducing material switches, but
  371. also implies that facegroups will not be rendered in the order they are in
  372. the list. *)
  373. TgxMeshObjectRenderingOption = (moroGroupByMaterial);
  374. TgxMeshObjectRenderingOptions = set of TgxMeshObjectRenderingOption;
  375. TVBOBuffer = (vbVertices, vbNormals, vbColors, vbTexCoords, vbLightMapTexCoords, vbTexCoordsEx);
  376. TVBOBuffers = set of TVBOBuffer;
  377. (* Base mesh class.
  378. Introduces base methods and properties for mesh objects.
  379. Subclasses are named "TMOxxx". *)
  380. TgxMeshObject = class(TgxBaseMeshObject)
  381. private
  382. FOwner: TgxMeshObjectList;
  383. FExtentCacheRevision: Cardinal;
  384. FTexCoords: TgxAffineVectorList; // provision for 3D textures
  385. FLightMapTexCoords: TgxAffineVectorList; // reserved for 2D surface needs
  386. FColors: TgxVectorList;
  387. FFaceGroups: TgxFaceGroups;
  388. FMode: TgxMeshObjectMode;
  389. FRenderingOptions: TgxMeshObjectRenderingOptions;
  390. FArraysDeclared: Boolean; // not persistent
  391. FLightMapArrayEnabled: Boolean; // not persistent
  392. FLastLightMapIndex: Integer; // not persistent
  393. FTexCoordsEx: TList;
  394. FBinormalsTexCoordIndex: Integer;
  395. FTangentsTexCoordIndex: Integer;
  396. FLastXOpenGLTexMapping: Cardinal;
  397. FUseVBO: Boolean;
  398. FVerticesVBO: TgxVBOHandle;
  399. FNormalsVBO: TgxVBOHandle;
  400. FColorsVBO: TgxVBOHandle;
  401. FTexCoordsVBO: array of TgxVBOHandle;
  402. FLightmapTexCoordsVBO: TgxVBOHandle;
  403. FValidBuffers: TVBOBuffers;
  404. FExtentCache: TAABB;
  405. procedure SetUseVBO(const Value: Boolean);
  406. procedure SetValidBuffers(Value: TVBOBuffers);
  407. protected
  408. procedure SetTexCoords(const val: TgxAffineVectorList);
  409. procedure SetLightmapTexCoords(const val: TgxAffineVectorList);
  410. procedure SetColors(const val: TgxVectorList);
  411. procedure BufferArrays;
  412. procedure DeclareArraysToOpenGL(var mrci: TgxRenderContextInfo; evenIfAlreadyDeclared: Boolean = False);
  413. procedure DisableOpenGLArrays(var mrci: TgxRenderContextInfo);
  414. procedure EnableLightMapArray(var mrci: TgxRenderContextInfo);
  415. procedure DisableLightMapArray(var mrci: TgxRenderContextInfo);
  416. procedure SetTexCoordsEx(Index: Integer; const val: TgxVectorList);
  417. function GetTexCoordsEx(Index: Integer): TgxVectorList;
  418. procedure SetBinormals(const val: TgxVectorList);
  419. function GetBinormals: TgxVectorList;
  420. procedure SetBinormalsTexCoordIndex(const val: Integer);
  421. procedure SetTangents(const val: TgxVectorList);
  422. function GetTangents: TgxVectorList;
  423. procedure SetTangentsTexCoordIndex(const val: Integer);
  424. property ValidBuffers: TVBOBuffers read FValidBuffers write SetValidBuffers;
  425. public
  426. // Creates, assigns Owner and adds to list.
  427. constructor CreateOwned(aOwner: TgxMeshObjectList);
  428. constructor Create; override;
  429. destructor Destroy; override;
  430. procedure Assign(Source: TPersistent); override;
  431. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  432. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  433. procedure Clear; override;
  434. function ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil): TgxAffineVectorList;
  435. override;
  436. // Returns number of triangles in the mesh object.
  437. function TriangleCount: Integer; virtual;
  438. procedure PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  439. procedure DropMaterialLibraryCache;
  440. (* Prepare the texture and materials before rendering.
  441. Invoked once, before building the list and NOT while building the list. *)
  442. procedure PrepareBuildList(var mrci: TgxRenderContextInfo); virtual;
  443. // Similar to regular scene object's BuildList method
  444. procedure BuildList(var mrci: TgxRenderContextInfo); virtual;
  445. // The extents of the object (min and max coordinates)
  446. procedure GetExtents(out min, max: TAffineVector); overload; virtual;
  447. procedure GetExtents(out aabb: TAABB); overload; virtual;
  448. // Barycenter from vertices data
  449. function GetBarycenter: TVector4f;
  450. // Precalculate whatever is needed for rendering, called once
  451. procedure Prepare; virtual;
  452. function PointInObject(const aPoint: TAffineVector): Boolean; virtual;
  453. // Returns the triangle data for a given triangle
  454. procedure GetTriangleData(tri: Integer; list: TgxAffineVectorList; var v0, v1, v2: TAffineVector); overload;
  455. procedure GetTriangleData(tri: Integer; list: TgxVectorList; var v0, v1, v2: TVector4f); overload;
  456. // Sets the triangle data of a given triangle
  457. procedure SetTriangleData(tri: Integer; list: TgxAffineVectorList; const v0, v1, v2: TAffineVector); overload;
  458. procedure SetTriangleData(tri: Integer; list: TgxVectorList; const v0, v1, v2: TVector4f); overload;
  459. (* Build the tangent space from the mesh object's vertex, normal
  460. and texcoord data, filling the binormals and tangents where
  461. specified. *)
  462. procedure BuildTangentSpace(buildBinormals: Boolean = True; buildTangents: Boolean = True);
  463. property Owner: TgxMeshObjectList read FOwner;
  464. property mode: TgxMeshObjectMode read FMode write FMode;
  465. property texCoords: TgxAffineVectorList read FTexCoords write SetTexCoords;
  466. property LightMapTexCoords: TgxAffineVectorList read FLightMapTexCoords write SetLightmapTexCoords;
  467. property Colors: TgxVectorList read FColors write SetColors;
  468. property FaceGroups: TgxFaceGroups read FFaceGroups;
  469. property RenderingOptions: TgxMeshObjectRenderingOptions read FRenderingOptions write FRenderingOptions;
  470. // If set, rendering will use VBO's instead of vertex arrays.
  471. property UseVBO: Boolean read FUseVBO write SetUseVBO;
  472. (* The TexCoords Extension is a list of vector lists that are used
  473. to extend the vertex data applied during rendering.
  474. The lists are applied to the GL_TEXTURE0_ARB + index texture
  475. environment. This means that if TexCoordsEx 0 or 1 have data it
  476. will override the TexCoords or LightMapTexCoords repectively.
  477. Lists are created on demand, meaning that if you request
  478. TexCoordsEx[4] it will create the list up to and including 4.
  479. The extensions are only applied to the texture environment if
  480. they contain data. *)
  481. property TexCoordsEx[index: Integer]: TgxVectorList read GetTexCoordsEx write SetTexCoordsEx;
  482. (* A TexCoordsEx list wrapper for binormals usage,
  483. returns TexCoordsEx[BinormalsTexCoordIndex]. *)
  484. property Binormals: TgxVectorList read GetBinormals write SetBinormals;
  485. (* A TexCoordsEx list wrapper for tangents usage,
  486. returns TexCoordsEx[BinormalsTexCoordIndex]. *)
  487. property Tangents: TgxVectorList read GetTangents write SetTangents;
  488. // Specify the texcoord extension index for binormals (default = 2)
  489. property BinormalsTexCoordIndex: Integer read FBinormalsTexCoordIndex write SetBinormalsTexCoordIndex;
  490. // Specify the texcoord extension index for tangents (default = 3)
  491. property TangentsTexCoordIndex: Integer read FTangentsTexCoordIndex write SetTangentsTexCoordIndex;
  492. end;
  493. // A list of TgxMeshObject objects.
  494. TgxMeshObjectList = class(TgxPersistentObjectList)
  495. private
  496. FOwner: TgxBaseMesh;
  497. // Resturns True if all its MeshObjects use VBOs.
  498. function GetUseVBO: Boolean;
  499. procedure SetUseVBO(const Value: Boolean);
  500. protected
  501. function GetMeshObject(Index: Integer): TgxMeshObject;
  502. public
  503. constructor CreateOwned(aOwner: TgxBaseMesh);
  504. destructor Destroy; override;
  505. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  506. procedure PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  507. procedure DropMaterialLibraryCache;
  508. (* Prepare the texture and materials before rendering.
  509. Invoked once, before building the list and NOT while building the list. *)
  510. procedure PrepareBuildList(var mrci: TgxRenderContextInfo); virtual;
  511. // Similar to regular scene object's BuildList method
  512. procedure BuildList(var mrci: TgxRenderContextInfo); virtual;
  513. procedure MorphTo(morphTargetIndex: Integer);
  514. procedure Lerp(morphTargetIndex1, morphTargetIndex2: Integer; lerpFactor: Single);
  515. function MorphTargetCount: Integer;
  516. procedure GetExtents(out min, max: TAffineVector);
  517. procedure Translate(const delta: TAffineVector);
  518. function ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil): TgxAffineVectorList;
  519. // Returns number of triangles in the meshes of the list.
  520. function TriangleCount: Integer;
  521. (* Build the tangent space from the mesh object's vertex, normal
  522. and texcoord data, filling the binormals and tangents where
  523. specified. *)
  524. procedure BuildTangentSpace(buildBinormals: Boolean = True; buildTangents: Boolean = True);
  525. (* If set, rendering will use VBO's instead of vertex arrays.
  526. Resturns True if all its MeshObjects use VBOs. *)
  527. property UseVBO: Boolean read GetUseVBO write SetUseVBO;
  528. // Precalculate whatever is needed for rendering, called once
  529. procedure Prepare; virtual;
  530. function FindMeshByName(MeshName: string): TgxMeshObject;
  531. property Owner: TgxBaseMesh read FOwner;
  532. procedure Clear; override;
  533. property Items[Index: Integer]: TgxMeshObject read GetMeshObject; default;
  534. end;
  535. TgxMeshObjectListClass = class of TgxMeshObjectList;
  536. TgxMeshMorphTargetList = class;
  537. // A morph target, stores alternate lists of vertices and normals.
  538. TgxMeshMorphTarget = class(TgxBaseMeshObject)
  539. private
  540. FOwner: TgxMeshMorphTargetList;
  541. public
  542. constructor CreateOwned(aOwner: TgxMeshMorphTargetList);
  543. destructor Destroy; override;
  544. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  545. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  546. property Owner: TgxMeshMorphTargetList read FOwner;
  547. end;
  548. // A list of TgxMeshMorphTarget objects.
  549. TgxMeshMorphTargetList = class(TgxPersistentObjectList)
  550. private
  551. FOwner: TPersistent;
  552. protected
  553. function GetMeshMorphTarget(Index: Integer): TgxMeshMorphTarget;
  554. public
  555. constructor CreateOwned(aOwner: TPersistent);
  556. destructor Destroy; override;
  557. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  558. procedure Translate(const delta: TAffineVector);
  559. property Owner: TPersistent read FOwner;
  560. procedure Clear; override;
  561. property Items[Index: Integer]: TgxMeshMorphTarget read GetMeshMorphTarget; default;
  562. end;
  563. (* Mesh object with support for morph targets.
  564. The morph targets allow to change vertices and normals according to pre-
  565. existing "morph targets". *)
  566. TgxMorphableMeshObject = class(TgxMeshObject)
  567. private
  568. FMorphTargets: TgxMeshMorphTargetList;
  569. public
  570. constructor Create; override;
  571. destructor Destroy; override;
  572. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  573. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  574. procedure Clear; override;
  575. procedure Translate(const delta: TAffineVector); override;
  576. procedure MorphTo(morphTargetIndex: Integer); virtual;
  577. procedure Lerp(morphTargetIndex1, morphTargetIndex2: Integer; lerpFactor: Single); virtual;
  578. property MorphTargets: TgxMeshMorphTargetList read FMorphTargets;
  579. end;
  580. TgxVertexBoneWeight = packed record
  581. BoneID: Integer;
  582. weight: Single;
  583. end;
  584. TgxVertexBoneWeightArray = array [0 .. MaxInt div (2 * SizeOf(TgxVertexBoneWeight))] of TgxVertexBoneWeight;
  585. PgxVertexBoneWeightArray = ^TgxVertexBoneWeightArray;
  586. TgxVerticesBoneWeights = array [0 .. MaxInt div (2 * SizeOf(PgxVertexBoneWeightArray))] of PgxVertexBoneWeightArray;
  587. PgxVerticesBoneWeights = ^TgxVerticesBoneWeights;
  588. TgxVertexBoneWeightDynArray = array of TgxVertexBoneWeight;
  589. (* A mesh object with vertice bone attachments.
  590. The class adds per vertex bone weights to the standard morphable mesh.
  591. The TgxVertexBoneWeight structures are accessed via VerticesBonesWeights,
  592. they must be initialized by adjusting the BonesPerVertex and
  593. VerticeBoneWeightCount properties, you can also add vertex by vertex
  594. by using the AddWeightedBone method.
  595. When BonesPerVertex is 1, the weight is ignored (set to 1.0). *)
  596. TgxSkeletonMeshObject = class(TgxMorphableMeshObject)
  597. private
  598. FVerticesBonesWeights: PgxVerticesBoneWeights;
  599. FVerticeBoneWeightCount, FVerticeBoneWeightCapacity: Integer;
  600. FBonesPerVertex: Integer;
  601. FLastVerticeBoneWeightCount, FLastBonesPerVertex: Integer; // not persistent
  602. FBoneMatrixInvertedMeshes: TList; // not persistent
  603. FBackupInvertedMeshes: TList; // ragdoll
  604. procedure BackupBoneMatrixInvertedMeshes; // ragdoll
  605. procedure RestoreBoneMatrixInvertedMeshes; // ragdoll
  606. protected
  607. procedure SetVerticeBoneWeightCount(const val: Integer);
  608. procedure SetVerticeBoneWeightCapacity(const val: Integer);
  609. procedure SetBonesPerVertex(const val: Integer);
  610. procedure ResizeVerticesBonesWeights;
  611. public
  612. constructor Create; override;
  613. destructor Destroy; override;
  614. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  615. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  616. procedure Clear; override;
  617. property VerticesBonesWeights: PgxVerticesBoneWeights read FVerticesBonesWeights;
  618. property VerticeBoneWeightCount: Integer read FVerticeBoneWeightCount write SetVerticeBoneWeightCount;
  619. property VerticeBoneWeightCapacity: Integer read FVerticeBoneWeightCapacity write SetVerticeBoneWeightCapacity;
  620. property BonesPerVertex: Integer read FBonesPerVertex write SetBonesPerVertex;
  621. function FindOrAdd(BoneID: Integer; const vertex, normal: TAffineVector): Integer; overload;
  622. function FindOrAdd(const boneIDs: TgxVertexBoneWeightDynArray; const vertex, normal: TAffineVector): Integer; overload;
  623. procedure AddWeightedBone(aBoneID: Integer; aWeight: Single);
  624. procedure AddWeightedBones(const boneIDs: TgxVertexBoneWeightDynArray);
  625. procedure PrepareBoneMatrixInvertedMeshes;
  626. procedure ApplyCurrentSkeletonFrame(normalize: Boolean);
  627. end;
  628. (* Describes a face group of a TgxMeshObject.
  629. Face groups should be understood as "a way to use mesh data to render
  630. a part or the whole mesh object".
  631. Subclasses implement the actual behaviours, and should have at least
  632. one "Add" method, taking in parameters all that is required to describe
  633. a single base facegroup element. *)
  634. TgxFaceGroup = class(TgxPersistentObject)
  635. private
  636. FOwner: TgxFaceGroups;
  637. FMaterialName: string;
  638. FMaterialCache: TgxLibMaterial;
  639. FLightMapIndex: Integer;
  640. FRenderGroupID: Integer;
  641. // NOT Persistent, internal use only (rendering options)
  642. protected
  643. procedure AttachLightmap(lightMap: TgxTexture; var mrci: TgxRenderContextInfo);
  644. procedure AttachOrDetachLightmap(var mrci: TgxRenderContextInfo);
  645. public
  646. constructor CreateOwned(aOwner: TgxFaceGroups); virtual;
  647. destructor Destroy; override;
  648. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  649. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  650. procedure PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  651. procedure DropMaterialLibraryCache;
  652. procedure BuildList(var mrci: TgxRenderContextInfo); virtual; abstract;
  653. (* Add to the list the triangles corresponding to the facegroup.
  654. This function is used by TgxMeshObjects ExtractTriangles to retrieve
  655. all the triangles in a mesh. *)
  656. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  657. aNormals: TgxAffineVectorList = nil); virtual;
  658. // Returns number of triangles in the facegroup.
  659. function TriangleCount: Integer; virtual; abstract;
  660. (* Reverses the rendering order of faces.
  661. Default implementation does nothing *)
  662. procedure Reverse; virtual;
  663. // Precalculate whatever is needed for rendering, called once
  664. procedure Prepare; virtual;
  665. property Owner: TgxFaceGroups read FOwner write FOwner;
  666. property MaterialName: string read FMaterialName write FMaterialName;
  667. property MaterialCache: TgxLibMaterial read FMaterialCache;
  668. // Index of lightmap in the lightmap library.
  669. property LightMapIndex: Integer read FLightMapIndex write FLightMapIndex;
  670. end;
  671. (* Known descriptions for face group mesh modes.
  672. - fgmmTriangles : issue all vertices with GL_TRIANGLES.
  673. - fgmmTriangleStrip : issue all vertices with GL_TRIANGLE_STRIP.
  674. - fgmmFlatTriangles : same as fgmmTriangles, but take advantage of having
  675. the same normal for all vertices of a triangle.
  676. - fgmmTriangleFan : issue all vertices with GL_TRIANGLE_FAN.
  677. - fgmmQuads : issue all vertices with GL_QUADS. *)
  678. TgxFaceGroupMeshMode = (fgmmTriangles, fgmmTriangleStrip, fgmmFlatTriangles, fgmmTriangleFan, fgmmQuads);
  679. (* A face group based on an indexlist.
  680. The index list refers to items in the mesh object (vertices, normals, etc.),
  681. that are all considered in sync, the render is obtained issueing the items
  682. in the order given by the vertices. *)
  683. TgxFGVertexIndexList = class(TgxFaceGroup)
  684. private
  685. FVertexIndices: TgxIntegerList;
  686. FIndexVBO: TgxVBOElementArrayHandle;
  687. FMode: TgxFaceGroupMeshMode;
  688. procedure SetupVBO;
  689. procedure InvalidateVBO;
  690. protected
  691. procedure SetVertexIndices(const val: TgxIntegerList);
  692. procedure AddToList(Source, destination: TgxAffineVectorList; indices: TgxIntegerList);
  693. public
  694. constructor Create; override;
  695. destructor Destroy; override;
  696. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  697. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  698. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  699. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  700. aNormals: TgxAffineVectorList = nil); override;
  701. function TriangleCount: Integer; override;
  702. procedure Reverse; override;
  703. procedure Add(idx: Integer);
  704. procedure GetExtents(var min, max: TAffineVector);
  705. // If mode is strip or fan, convert the indices to triangle list indices.
  706. procedure ConvertToList;
  707. // Return the normal from the 1st three points in the facegroup
  708. function GetNormal: TAffineVector;
  709. property mode: TgxFaceGroupMeshMode read FMode write FMode;
  710. property vertexIndices: TgxIntegerList read FVertexIndices write SetVertexIndices;
  711. end;
  712. (* Adds normals and texcoords indices.
  713. Allows very compact description of a mesh. The Normals ad TexCoords
  714. indices are optionnal, if missing (empty), VertexIndices will be used. *)
  715. TFGVertexNormalTexIndexList = class(TgxFGVertexIndexList)
  716. private
  717. FNormalIndices: TgxIntegerList;
  718. FTexCoordIndices: TgxIntegerList;
  719. protected
  720. procedure SetNormalIndices(const val: TgxIntegerList);
  721. procedure SetTexCoordIndices(const val: TgxIntegerList);
  722. public
  723. constructor Create; override;
  724. destructor Destroy; override;
  725. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  726. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  727. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  728. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  729. aNormals: TgxAffineVectorList = nil); override;
  730. procedure Add(vertexIdx, normalIdx, texCoordIdx: Integer);
  731. property normalIndices: TgxIntegerList read FNormalIndices write SetNormalIndices;
  732. property TexCoordIndices: TgxIntegerList read FTexCoordIndices write SetTexCoordIndices;
  733. end;
  734. (* Adds per index texture coordinates to its ancestor.
  735. Per index texture coordinates allows having different texture coordinates
  736. per triangle, depending on the face it is used in. *)
  737. TgxFGIndexTexCoordList = class(TgxFGVertexIndexList)
  738. private
  739. FTexCoords: TgxAffineVectorList;
  740. protected
  741. procedure SetTexCoords(const val: TgxAffineVectorList);
  742. public
  743. constructor Create; override;
  744. destructor Destroy; override;
  745. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  746. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  747. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  748. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  749. aNormals: TgxAffineVectorList = nil); override;
  750. procedure Add(idx: Integer; const texCoord: TAffineVector); overload;
  751. procedure Add(idx: Integer; const s, t: Single); overload;
  752. property texCoords: TgxAffineVectorList read FTexCoords write SetTexCoords;
  753. end;
  754. // A list of TgxFaceGroup objects.
  755. TgxFaceGroups = class(TgxPersistentObjectList)
  756. private
  757. FOwner: TgxMeshObject;
  758. protected
  759. function GetFaceGroup(Index: Integer): TgxFaceGroup;
  760. public
  761. constructor CreateOwned(aOwner: TgxMeshObject);
  762. destructor Destroy; override;
  763. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  764. procedure PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  765. procedure DropMaterialLibraryCache;
  766. property Owner: TgxMeshObject read FOwner;
  767. procedure Clear; override;
  768. property Items[Index: Integer]: TgxFaceGroup read GetFaceGroup; default;
  769. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil; aNormals: TgxAffineVectorList = nil);
  770. // Material Library of the owner TgxBaseMesh.
  771. function MaterialLibrary: TgxMaterialLibrary;
  772. (* Sort faces by material.
  773. Those without material first in list, followed by opaque materials,
  774. then transparent materials. *)
  775. procedure SortByMaterial;
  776. end;
  777. (* Determines how normals orientation is defined in a mesh.
  778. - mnoDefault : uses default orientation
  779. - mnoInvert : inverse of default orientation
  780. - mnoAutoSolid : autocalculate to make the mesh globally solid
  781. - mnoAutoHollow : autocalculate to make the mesh globally hollow *)
  782. TgxMeshNormalsOrientation = (mnoDefault, mnoInvert); // , mnoAutoSolid, mnoAutoHollow);
  783. (* Abstract base class for different vector file Formatx.
  784. The actual implementation for these files (3DS, DXF..) must be done
  785. seperately. The concept for TgxVectorFile is very similar to TGraphic
  786. (see Delphi Help). *)
  787. TgxVectorFile = class(TgxDataFile)
  788. private
  789. FNormalsOrientation: TgxMeshNormalsOrientation;
  790. protected
  791. procedure SetNormalsOrientation(const val: TgxMeshNormalsOrientation); virtual;
  792. public
  793. constructor Create(aOwner: TPersistent); override;
  794. function Owner: TgxBaseMesh;
  795. property NormalsOrientation: TgxMeshNormalsOrientation read FNormalsOrientation write SetNormalsOrientation;
  796. end;
  797. TgxVectorFileClass = class of TgxVectorFile;
  798. (* GLSM ( GXScene Mesh) vector file.
  799. This corresponds to the 'native' Scene format, and object persistence
  800. stream, which should be the 'fastest' of all formats to load, and supports
  801. all of GXScene features. *)
  802. TgxVectorFileGLSM = class(TgxVectorFile)
  803. public
  804. class function Capabilities: TDataFileCapabilities; override;
  805. procedure LoadFromStream(aStream: TStream); override;
  806. procedure SaveToStream(aStream: TStream); override;
  807. end;
  808. // Base class for mesh objects.
  809. TgxBaseMesh = class(TgxSceneObject)
  810. private
  811. FNormalsOrientation: TgxMeshNormalsOrientation;
  812. FMaterialLibrary: TgxMaterialLibrary;
  813. FLightmapLibrary: TgxMaterialLibrary;
  814. FAxisAlignedDimensionsCache: TVector4f;
  815. FBaryCenterOffsetChanged: Boolean;
  816. FBaryCenterOffset: TVector4f;
  817. FUseMeshMaterials: Boolean;
  818. FOverlaySkeleton: Boolean;
  819. FIgnoreMissingTextures: Boolean;
  820. FAutoCentering: TgxMeshAutoCenterings;
  821. FAutoScaling: TgxCoordinates;
  822. FMaterialLibraryCachesPrepared: Boolean;
  823. FConnectivity: TObject;
  824. FLastLoadedFilename: string;
  825. protected
  826. FMeshObjects: TgxMeshObjectList; // a list of mesh objects
  827. FSkeleton: TgxSkeleton; // skeleton data & frames
  828. procedure SetUseMeshMaterials(const val: Boolean);
  829. procedure SetMaterialLibrary(const val: TgxMaterialLibrary);
  830. procedure SetLightmapLibrary(const val: TgxMaterialLibrary);
  831. procedure SetNormalsOrientation(const val: TgxMeshNormalsOrientation);
  832. procedure SetOverlaySkeleton(const val: Boolean);
  833. procedure SetAutoScaling(const Value: TgxCoordinates);
  834. procedure DestroyHandle; override;
  835. (* Invoked after creating a TgxVectorFile and before loading.
  836. Triggered by LoadFromFile/Stream and AddDataFromFile/Stream.
  837. Allows to adjust/transfer subclass-specific features. *)
  838. procedure PrepareVectorFile(aFile: TgxVectorFile); virtual;
  839. (* Invoked after a mesh has been loaded/added.
  840. Triggered by LoadFromFile/Stream and AddDataFromFile/Stream.
  841. Allows to adjust/transfer subclass-specific features. *)
  842. procedure PrepareMesh; virtual;
  843. (* Recursively propagated to mesh object and facegroups.
  844. Notifies that they all can establish their material library caches. *)
  845. procedure PrepareMaterialLibraryCache;
  846. (* Recursively propagated to mesh object and facegroups.
  847. Notifies that they all should forget their material library caches. *)
  848. procedure DropMaterialLibraryCache;
  849. (* Prepare the texture and materials before rendering.
  850. Invoked once, before building the list and NOT while building the list,
  851. MaterialLibraryCache can be assumed to having been prepared if materials
  852. are active. Default behaviour is to prepare build lists for the
  853. meshobjects. *)
  854. procedure PrepareBuildList(var mrci: TgxRenderContextInfo); virtual;
  855. public
  856. constructor Create(aOwner: TComponent); override;
  857. destructor Destroy; override;
  858. procedure Assign(Source: TPersistent); override;
  859. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  860. function AxisAlignedDimensionsUnscaled: TVector4f; override;
  861. function BarycenterOffset: TVector4f;
  862. function BarycenterPosition: TVector4f;
  863. function BarycenterAbsolutePosition: TVector4f; override;
  864. procedure BuildList(var rci: TgxRenderContextInfo); override;
  865. procedure DoRender(var rci: TgxRenderContextInfo; renderSelf, renderChildren: Boolean); override;
  866. procedure StructureChanged; override;
  867. (* Notifies that geometry data changed, but no re-preparation is needed.
  868. Using this method will usually be faster, but may result in incorrect
  869. rendering, reduced performance and/or invalid bounding box data
  870. (ie. invalid collision detection). Use with caution. *)
  871. procedure StructureChangedNoPrepare;
  872. // BEWARE! Utterly inefficient implementation!
  873. function RayCastIntersect(const rayStart, rayVector: TVector4f; intersectPoint: PVector4f = nil; intersectNormal: PVector4f = nil)
  874. : Boolean; override;
  875. function GenerateSilhouette(const SilhouetteParameters: TgxSilhouetteParameters): TgxSilhouette; override;
  876. (* This method allows fast shadow volumes for GLActors.
  877. If your actor/mesh doesn't change, you don't need to call this.
  878. It basically caches the connectivity data. *)
  879. procedure BuildSilhouetteConnectivityData;
  880. property MeshObjects: TgxMeshObjectList read FMeshObjects;
  881. property Skeleton: TgxSkeleton read FSkeleton;
  882. // Computes the extents of the mesh.
  883. procedure GetExtents(out min, max: TAffineVector);
  884. // Computes the barycenter of the mesh.
  885. function GetBarycenter: TAffineVector;
  886. (* Invoked after a mesh has been loaded.
  887. Should auto-center according to the AutoCentering property. *)
  888. procedure PerformAutoCentering; virtual;
  889. (* Invoked after a mesh has been loaded.
  890. Should auto-scale the vertices of the meshobjects to AutoScaling the property. *)
  891. procedure PerformAutoScaling; virtual;
  892. (* Loads a vector file.
  893. A vector files (for instance a ".3DS") stores the definition of
  894. a mesh as well as materials property.
  895. Loading a file replaces the current one (if any). *)
  896. procedure LoadFromFile(const filename: string); virtual;
  897. (* Loads a vector file from a stream.
  898. See LoadFromFile.
  899. The filename attribute is required to identify the type data you're
  900. streaming (3DS, OBJ, etc.) *)
  901. procedure LoadFromStream(const filename: string; aStream: TStream); virtual;
  902. (* Saves to a vector file.
  903. Note that only some of the vector files formats can be written. *)
  904. procedure SaveToFile(const filename: string); virtual;
  905. (* Saves to a vector file in a stream.
  906. Note that only some of the vector files formats can be written. *)
  907. procedure SaveToStream(const filename: string; aStream: TStream); virtual;
  908. (* Loads additionnal data from a file.
  909. Additionnal data could be more animation frames or morph target.
  910. The VectorFile importer must be able to handle addition of data
  911. flawlessly. *)
  912. procedure AddDataFromFile(const filename: string); virtual;
  913. // Loads additionnal data from stream. See AddDataFromFile.
  914. procedure AddDataFromStream(const filename: string; aStream: TStream); virtual;
  915. (* Returns the filename of the last loaded file, or a blank string if not
  916. file was loaded (or if the mesh was dinamically built). This does not
  917. take into account the data added to the mesh (through AddDataFromFile)
  918. or saved files. *)
  919. function LastLoadedFilename: string;
  920. (* Determines if a mesh should be centered and how.
  921. AutoCentering is performed only after loading a mesh, it has
  922. no effect on already loaded mesh data or when adding from a file/stream.
  923. If you want to alter mesh data, use direct manipulation methods
  924. (on the TgxMeshObjects). *)
  925. property AutoCentering: TgxMeshAutoCenterings read FAutoCentering write FAutoCentering default [];
  926. (* Scales vertices to a AutoScaling.
  927. AutoScaling is performed only after loading a mesh, it has
  928. no effect on already loaded mesh data or when adding from a file/stream.
  929. If you want to alter mesh data, use direct manipulation methods
  930. (on the TgxMeshObjects). *)
  931. property AutoScaling: TgxCoordinates read FAutoScaling write FAutoScaling;
  932. (* Material library where mesh materials will be stored/retrieved.
  933. If this property is not defined or if UseMeshMaterials is false,
  934. only the FreeForm's material will be used (and the mesh's materials
  935. will be ignored. *)
  936. property MaterialLibrary: TgxMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  937. (* Defines wether materials declared in the vector file mesh are used.
  938. You must also define the MaterialLibrary property. *)
  939. property UseMeshMaterials: Boolean read FUseMeshMaterials write SetUseMeshMaterials default True;
  940. (* LightMap library where lightmaps will be stored/retrieved.
  941. If this property is not defined, lightmaps won't be used.
  942. Lightmaps currently *always* use the second texture unit (unit 1),
  943. and may interfere with multi-texture materials. *)
  944. property LightmapLibrary: TgxMaterialLibrary read FLightmapLibrary write SetLightmapLibrary;
  945. (* If True, exceptions about missing textures will be ignored.
  946. Implementation is up to the file loader class (ie. this property
  947. may be ignored by some loaders) *)
  948. property IgnoreMissingTextures: Boolean read FIgnoreMissingTextures write FIgnoreMissingTextures default False;
  949. // Normals orientation for owned mesh.
  950. property NormalsOrientation: TgxMeshNormalsOrientation read FNormalsOrientation write SetNormalsOrientation
  951. default mnoDefault;
  952. // Request rendering of skeleton bones over the mesh.
  953. property OverlaySkeleton: Boolean read FOverlaySkeleton write SetOverlaySkeleton default False;
  954. end;
  955. (* Container objects for a vector file mesh.
  956. FreeForms allows loading and rendering vector files (like 3DStudio
  957. ".3DS" file) in GLScene. Meshes can be loaded with the LoadFromFile
  958. method.
  959. A FreeForm may contain more than one mesh, but they will all be handled
  960. as a single object in a scene. *)
  961. TgxFreeForm = class(TgxBaseMesh)
  962. private
  963. FOctree: TgxOctree;
  964. protected
  965. function GetOctree: TgxOctree;
  966. public
  967. constructor Create(aOwner: TComponent); override;
  968. destructor Destroy; override;
  969. function OctreeRayCastIntersect(const rayStart, rayVector: TVector4f; intersectPoint: PVector4f = nil;
  970. intersectNormal: PVector4f = nil): Boolean;
  971. function OctreeSphereSweepIntersect(const rayStart, rayVector: TVector4f; const velocity, radius: Single;
  972. intersectPoint: PVector4f = nil; intersectNormal: PVector4f = nil): Boolean;
  973. function OctreeTriangleIntersect(const v1, v2, v3: TAffineVector): Boolean;
  974. (* Returns true if Point is inside the free form - this will only work
  975. properly on closed meshes. Requires that Octree has been prepared. *)
  976. function OctreePointInMesh(const Point: TVector4f): Boolean;
  977. function OctreeAABBIntersect(const aabb: TAABB; objMatrix, invObjMatrix: TMatrix4f;
  978. triangles: TgxAffineVectorList = nil): Boolean;
  979. // TODO: function OctreeSphereIntersect
  980. (* Octree support *experimental*.
  981. Use only if you understand what you're doing! *)
  982. property Octree: TgxOctree read GetOctree;
  983. procedure BuildOctree(TreeDepth: Integer = 3);
  984. published
  985. property AutoCentering;
  986. property AutoScaling;
  987. property MaterialLibrary;
  988. property LightmapLibrary;
  989. property UseMeshMaterials;
  990. property NormalsOrientation;
  991. end;
  992. (* Miscellanious actor options.
  993. aoSkeletonNormalizeNormals : if set the normals of a skeleton-animated
  994. mesh will be normalized, this is not required if no normals-based texture
  995. coordinates generation occurs, and thus may be unset to improve performance. *)
  996. TgxActorOption = (aoSkeletonNormalizeNormals);
  997. TgxActorOptions = set of TgxActorOption;
  998. const
  999. cDefaultActorOptions = [aoSkeletonNormalizeNormals];
  1000. type
  1001. TgxActor = class;
  1002. TgxActorAnimationReference = (aarMorph, aarSkeleton, aarNone);
  1003. (* An actor animation sequence.
  1004. An animation sequence is a named set of contiguous frames that can be used
  1005. for animating an actor. The referred frames can be either morph or skeletal
  1006. frames (choose which via the Reference property).
  1007. An animation can be directly "played" by the actor by selecting it with
  1008. SwitchAnimation, and can also be "blended" via a TgxAnimationControler. *)
  1009. TgxActorAnimation = class(TCollectionItem)
  1010. private
  1011. FName: string;
  1012. FStartFrame: Integer;
  1013. FEndFrame: Integer;
  1014. FReference: TgxActorAnimationReference;
  1015. protected
  1016. function GetDisplayName: string; override;
  1017. function FrameCount: Integer;
  1018. procedure SetStartFrame(const val: Integer);
  1019. procedure SetEndFrame(const val: Integer);
  1020. procedure SetReference(val: TgxActorAnimationReference);
  1021. procedure SetAsString(const val: string);
  1022. function GetAsString: string;
  1023. public
  1024. constructor Create(Collection: TCollection); override;
  1025. destructor Destroy; override;
  1026. procedure Assign(Source: TPersistent); override;
  1027. property AsString: string read GetAsString write SetAsString;
  1028. function OwnerActor: TgxActor;
  1029. (* Linearly removes the translation component between skeletal frames.
  1030. This function will compute the translation of the first bone (index 0)
  1031. and linearly subtract this translation in all frames between startFrame
  1032. and endFrame. Its purpose is essentially to remove the 'slide' that
  1033. exists in some animation formats (f.i. SMD). *)
  1034. procedure MakeSkeletalTranslationStatic;
  1035. (* Removes the absolute rotation component of the skeletal frames.
  1036. Some formats will store frames with absolute rotation information,
  1037. if this correct if the animation is the "main" animation.
  1038. This function removes that absolute information, making the animation
  1039. frames suitable for blending purposes. *)
  1040. procedure MakeSkeletalRotationDelta;
  1041. published
  1042. property Name: string read FName write FName;
  1043. // Index of the initial frame of the animation.
  1044. property startFrame: Integer read FStartFrame write SetStartFrame;
  1045. // Index of the final frame of the animation.
  1046. property endFrame: Integer read FEndFrame write SetEndFrame;
  1047. // Indicates if this is a skeletal or a morph-based animation.
  1048. property reference: TgxActorAnimationReference read FReference write SetReference default aarMorph;
  1049. end;
  1050. TgxActorAnimationName = string;
  1051. // Collection of actor animations sequences.
  1052. TgxActorAnimations = class(TCollection)
  1053. private
  1054. FOwner: TgxActor;
  1055. protected
  1056. function GetOwner: TPersistent; override;
  1057. procedure SetItems(Index: Integer; const val: TgxActorAnimation);
  1058. function GetItems(Index: Integer): TgxActorAnimation;
  1059. public
  1060. constructor Create(aOwner: TgxActor);
  1061. function Add: TgxActorAnimation;
  1062. function FindItemID(ID: Integer): TgxActorAnimation;
  1063. function FindName(const aName: string): TgxActorAnimation;
  1064. function FindFrame(aFrame: Integer; aReference: TgxActorAnimationReference): TgxActorAnimation;
  1065. procedure SetToStrings(aStrings: TStrings);
  1066. procedure SaveToStream(aStream: TStream);
  1067. procedure LoadFromStream(aStream: TStream);
  1068. procedure SaveToFile(const filename: string);
  1069. procedure LoadFromFile(const filename: string);
  1070. property Items[index: Integer]: TgxActorAnimation read GetItems write SetItems; default;
  1071. function Last: TgxActorAnimation;
  1072. end;
  1073. // Base class for skeletal animation control.
  1074. TgxBaseAnimationControler = class(TComponent)
  1075. private
  1076. FEnabled: Boolean;
  1077. FActor: TgxActor;
  1078. protected
  1079. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1080. procedure SetEnabled(const val: Boolean);
  1081. procedure SetActor(const val: TgxActor);
  1082. procedure DoChange; virtual;
  1083. function Apply(var lerpInfo: TGXBlendedLerpInfo): Boolean; virtual;
  1084. public
  1085. constructor Create(aOwner: TComponent); override;
  1086. destructor Destroy; override;
  1087. published
  1088. property Enabled: Boolean read FEnabled write SetEnabled default True;
  1089. property Actor: TgxActor read FActor write SetActor;
  1090. end;
  1091. (* Controls the blending of an additionnal skeletal animation into an actor.
  1092. The animation controler allows animating an actor with several animations
  1093. at a time, for instance, you could use a "run" animation as base animation
  1094. (in TgxActor), blend an animation that makes the arms move differently
  1095. depending on what the actor is carrying, along with an animation that will
  1096. make the head turn toward a target. *)
  1097. TgxAnimationControler = class(TgxBaseAnimationControler)
  1098. private
  1099. FAnimationName: TgxActorAnimationName;
  1100. FRatio: Single;
  1101. protected
  1102. procedure SetAnimationName(const val: TgxActorAnimationName);
  1103. procedure SetRatio(const val: Single);
  1104. procedure DoChange; override;
  1105. function Apply(var lerpInfo: TGXBlendedLerpInfo): Boolean; override;
  1106. published
  1107. property AnimationName: string read FAnimationName write SetAnimationName;
  1108. property Ratio: Single read FRatio write SetRatio;
  1109. end;
  1110. (* Actor frame-interpolation mode.
  1111. - afpNone : no interpolation, display CurrentFrame only
  1112. - afpLinear : perform linear interpolation between current and next frame *)
  1113. TgxActorFrameInterpolation = (afpNone, afpLinear);
  1114. (* Defines how an actor plays between its StartFrame and EndFrame.
  1115. aamNone : no animation is performed
  1116. aamPlayOnce : play from current frame to EndFrame, once end frame has
  1117. been reached, switches to aamNone
  1118. aamLoop : play from current frame to EndFrame, once end frame has
  1119. been reached, sets CurrentFrame to StartFrame
  1120. aamBounceForward : play from current frame to EndFrame, once end frame
  1121. has been reached, switches to aamBounceBackward
  1122. aamBounceBackward : play from current frame to StartFrame, once start
  1123. frame has been reached, switches to aamBounceForward
  1124. aamExternal : Allows for external animation control *)
  1125. TgxActorAnimationMode = (aamNone, aamPlayOnce, aamLoop, aamBounceForward, aamBounceBackward, aamLoopBackward, aamExternal);
  1126. (* Mesh class specialized in animated meshes.
  1127. The TgxActor provides a quick interface to animated meshes based on morph
  1128. or skeleton frames, it is capable of performing frame interpolation and
  1129. animation blending (via TgxAnimationControler components). *)
  1130. TgxActor = class(TgxBaseMesh)
  1131. private
  1132. FStartFrame, FEndFrame: Integer;
  1133. FReference: TgxActorAnimationReference;
  1134. FCurrentFrame: Integer;
  1135. FCurrentFrameDelta: Single;
  1136. FFrameInterpolation: TgxActorFrameInterpolation;
  1137. FInterval: Integer;
  1138. FAnimationMode: TgxActorAnimationMode;
  1139. FOnFrameChanged: TNotifyEvent;
  1140. FOnEndFrameReached, FOnStartFrameReached: TNotifyEvent;
  1141. FAnimations: TgxActorAnimations;
  1142. FTargetSmoothAnimation: TgxActorAnimation;
  1143. FControlers: TList;
  1144. FOptions: TgxActorOptions;
  1145. protected
  1146. procedure SetCurrentFrame(val: Integer);
  1147. procedure SetStartFrame(val: Integer);
  1148. procedure SetEndFrame(val: Integer);
  1149. procedure SetReference(val: TgxActorAnimationReference);
  1150. procedure SetAnimations(const val: TgxActorAnimations);
  1151. function StoreAnimations: Boolean;
  1152. procedure SetOptions(const val: TgxActorOptions);
  1153. procedure PrepareMesh; override;
  1154. procedure PrepareBuildList(var mrci: TgxRenderContextInfo); override;
  1155. procedure DoAnimate; virtual;
  1156. procedure RegisterControler(aControler: TgxBaseAnimationControler);
  1157. procedure UnRegisterControler(aControler: TgxBaseAnimationControler);
  1158. public
  1159. constructor Create(aOwner: TComponent); override;
  1160. destructor Destroy; override;
  1161. procedure Assign(Source: TPersistent); override;
  1162. procedure BuildList(var rci: TgxRenderContextInfo); override;
  1163. procedure DoProgress(const progressTime: TgxProgressTimes); override;
  1164. procedure LoadFromStream(const filename: string; aStream: TStream); override;
  1165. procedure SwitchToAnimation(anAnimation: TgxActorAnimation; smooth: Boolean = False); overload;
  1166. procedure SwitchToAnimation(const AnimationName: string; smooth: Boolean = False); overload;
  1167. procedure SwitchToAnimation(animationIndex: Integer; smooth: Boolean = False); overload;
  1168. function CurrentAnimation: string;
  1169. (* Synchronize self animation with an other actor.
  1170. Copies Start/Current/End Frame values, CurrentFrameDelta,
  1171. AnimationMode and FrameInterpolation. *)
  1172. procedure Synchronize(referenceActor: TgxActor);
  1173. (* Provides a direct access to FCurrentFrame without any checks.
  1174. Used in TgxActorProxy. *)
  1175. procedure SetCurrentFrameDirect(const Value: Integer);
  1176. function NextFrameIndex: Integer;
  1177. procedure NextFrame(nbSteps: Integer = 1);
  1178. procedure PrevFrame(nbSteps: Integer = 1);
  1179. function FrameCount: Integer;
  1180. (* Indicates whether the actor is currently swithing animations (with
  1181. smooth interpolation). *)
  1182. function isSwitchingAnimation: Boolean;
  1183. published
  1184. property startFrame: Integer read FStartFrame write SetStartFrame default 0;
  1185. property endFrame: Integer read FEndFrame write SetEndFrame default 0;
  1186. (* Reference Frame Animation mode.
  1187. Allows specifying if the model is primarily morph or skeleton based. *)
  1188. property reference: TgxActorAnimationReference read FReference write FReference default aarMorph;
  1189. // Current animation frame.
  1190. property CurrentFrame: Integer read FCurrentFrame write SetCurrentFrame default 0;
  1191. // Value in the [0; 1] range expressing the delta to the next frame.
  1192. property CurrentFrameDelta: Single read FCurrentFrameDelta write FCurrentFrameDelta;
  1193. // Frame interpolation mode (afpNone/afpLinear).
  1194. property FrameInterpolation: TgxActorFrameInterpolation read FFrameInterpolation write FFrameInterpolation default afpLinear;
  1195. // See TgxActorAnimationMode.
  1196. property AnimationMode: TgxActorAnimationMode read FAnimationMode write FAnimationMode default aamNone;
  1197. // Interval between frames, in milliseconds.
  1198. property Interval: Integer read FInterval write FInterval;
  1199. // Actor and animation miscellanious options.
  1200. property Options: TgxActorOptions read FOptions write SetOptions default cDefaultActorOptions;
  1201. // Triggered after each CurrentFrame change.
  1202. property OnFrameChanged: TNotifyEvent read FOnFrameChanged write FOnFrameChanged;
  1203. // Triggered after EndFrame has been reached by progression or "nextframe"
  1204. property OnEndFrameReached: TNotifyEvent read FOnEndFrameReached write FOnEndFrameReached;
  1205. // Triggered after StartFrame has been reached by progression or "nextframe"
  1206. property OnStartFrameReached: TNotifyEvent read FOnStartFrameReached write FOnStartFrameReached;
  1207. // Collection of animations sequences.
  1208. property Animations: TgxActorAnimations read FAnimations write SetAnimations stored StoreAnimations;
  1209. property AutoCentering;
  1210. property MaterialLibrary;
  1211. property LightmapLibrary;
  1212. property UseMeshMaterials;
  1213. property NormalsOrientation;
  1214. property OverlaySkeleton;
  1215. end;
  1216. TgxVectorFileFormat = class
  1217. public
  1218. VectorFileClass: TgxVectorFileClass;
  1219. Extension: string;
  1220. Description: string;
  1221. DescResID: Integer;
  1222. end;
  1223. // Stores registered vector file Formatx.
  1224. TgxVectorFileFormatsList = class(TgxPersistentObjectList)
  1225. public
  1226. destructor Destroy; override;
  1227. procedure Add(const Ext, Desc: string; DescID: Integer; AClass: TgxVectorFileClass);
  1228. function FindExt(Ext: string): TgxVectorFileClass;
  1229. function FindFromFileName(const filename: string): TgxVectorFileClass;
  1230. procedure Remove(AClass: TgxVectorFileClass);
  1231. procedure BuildFilterStrings(VectorFileClass: TgxVectorFileClass; out descriptions, filters: string;
  1232. formatsThatCanBeOpened: Boolean = True; formatsThatCanBeSaved: Boolean = False);
  1233. function FindExtByIndex(Index: Integer; formatsThatCanBeOpened: Boolean = True;
  1234. formatsThatCanBeSaved: Boolean = False): string;
  1235. end;
  1236. EgxInvalidVectorFile = class(Exception);
  1237. // Read access to the list of registered vector file formats
  1238. function GetVectorFileFormats: TgxVectorFileFormatsList;
  1239. // A file extension filter suitable for dialog's 'Filter' property
  1240. function VectorFileFormatsFilter: string;
  1241. // A file extension filter suitable for a savedialog's 'Filter' property
  1242. function VectorFileFormatsSaveFilter: string;
  1243. (* Returns an extension by its index in the vector files dialogs filter.
  1244. Use VectorFileFormatsFilter to obtain the filter. *)
  1245. function VectorFileFormatExtensionByIndex(Index: Integer): string;
  1246. procedure RegisterVectorFileFormat(const aExtension, aDescription: string; AClass: TgxVectorFileClass);
  1247. procedure UnregisterVectorFileClass(AClass: TgxVectorFileClass);
  1248. var
  1249. vVectorFileObjectsAllocateMaterials: Boolean = True;
  1250. // Flag to avoid loading materials (useful for IDE Extentions or scene editors)
  1251. vVectorFileObjectsEnableVBOByDefault: Boolean = True;
  1252. implementation //--------------------------------------------------------------
  1253. uses
  1254. GXS.BaseMeshSilhouette;
  1255. var
  1256. vVectorFileFormats: TgxVectorFileFormatsList;
  1257. vNextRenderGroupID: Integer = 1;
  1258. const
  1259. cAAFHeader: AnsiString = 'AAF';
  1260. function GetVectorFileFormats: TgxVectorFileFormatsList;
  1261. begin
  1262. if not Assigned(vVectorFileFormats) then
  1263. vVectorFileFormats := TgxVectorFileFormatsList.Create;
  1264. Result := vVectorFileFormats;
  1265. end;
  1266. function VectorFileFormatsFilter: string;
  1267. var
  1268. f: string;
  1269. begin
  1270. GetVectorFileFormats.BuildFilterStrings(TgxVectorFile, Result, f);
  1271. end;
  1272. function VectorFileFormatsSaveFilter: string;
  1273. var
  1274. f: string;
  1275. begin
  1276. GetVectorFileFormats.BuildFilterStrings(TgxVectorFile, Result, f, False, True);
  1277. end;
  1278. procedure RegisterVectorFileFormat(const aExtension, aDescription: string; AClass: TgxVectorFileClass);
  1279. begin
  1280. RegisterClass(AClass);
  1281. GetVectorFileFormats.Add(aExtension, aDescription, 0, AClass);
  1282. end;
  1283. procedure UnregisterVectorFileClass(AClass: TgxVectorFileClass);
  1284. begin
  1285. if Assigned(vVectorFileFormats) then
  1286. vVectorFileFormats.Remove(AClass);
  1287. end;
  1288. function VectorFileFormatExtensionByIndex(Index: Integer): string;
  1289. begin
  1290. Result := GetVectorFileFormats.FindExtByIndex(index);
  1291. end;
  1292. destructor TgxVectorFileFormatsList.Destroy;
  1293. begin
  1294. Clean;
  1295. inherited;
  1296. end;
  1297. procedure TgxVectorFileFormatsList.Add(const Ext, Desc: string; DescID: Integer; AClass: TgxVectorFileClass);
  1298. var
  1299. newRec: TgxVectorFileFormat;
  1300. begin
  1301. newRec := TgxVectorFileFormat.Create;
  1302. with newRec do
  1303. begin
  1304. Extension := AnsiLowerCase(Ext);
  1305. VectorFileClass := AClass;
  1306. Description := Desc;
  1307. DescResID := DescID;
  1308. end;
  1309. inherited Add(newRec);
  1310. end;
  1311. function TgxVectorFileFormatsList.FindExt(Ext: string): TgxVectorFileClass;
  1312. var
  1313. i: Integer;
  1314. begin
  1315. Ext := AnsiLowerCase(Ext);
  1316. for i := Count - 1 downto 0 do
  1317. with TgxVectorFileFormat(Items[i]) do
  1318. begin
  1319. if Extension = Ext then
  1320. begin
  1321. Result := VectorFileClass;
  1322. Exit;
  1323. end;
  1324. end;
  1325. Result := nil;
  1326. end;
  1327. function TgxVectorFileFormatsList.FindFromFileName(const filename: string): TgxVectorFileClass;
  1328. var
  1329. Ext: string;
  1330. begin
  1331. Ext := ExtractFileExt(filename);
  1332. System.Delete(Ext, 1, 1);
  1333. Result := FindExt(Ext);
  1334. if not Assigned(Result) then
  1335. raise EgxInvalidVectorFile.CreateFmt(strUnknownExtension, [Ext, 'GLFile' + UpperCase(Ext)]);
  1336. end;
  1337. procedure TgxVectorFileFormatsList.Remove(AClass: TgxVectorFileClass);
  1338. var
  1339. i: Integer;
  1340. begin
  1341. for i := Count - 1 downto 0 do
  1342. begin
  1343. if TgxVectorFileFormat(Items[i]).VectorFileClass.InheritsFrom(AClass) then
  1344. DeleteAndFree(i);
  1345. end;
  1346. end;
  1347. procedure TgxVectorFileFormatsList.BuildFilterStrings(VectorFileClass: TgxVectorFileClass; out descriptions, filters: string;
  1348. formatsThatCanBeOpened: Boolean = True; formatsThatCanBeSaved: Boolean = False);
  1349. var
  1350. k, i: Integer;
  1351. p: TgxVectorFileFormat;
  1352. begin
  1353. descriptions := '';
  1354. filters := '';
  1355. k := 0;
  1356. for i := 0 to Count - 1 do
  1357. begin
  1358. p := TgxVectorFileFormat(Items[i]);
  1359. if p.VectorFileClass.InheritsFrom(VectorFileClass) and (p.Extension <> '') and
  1360. ((formatsThatCanBeOpened and (dfcRead in p.VectorFileClass.Capabilities)) or
  1361. (formatsThatCanBeSaved and (dfcWrite in p.VectorFileClass.Capabilities))) then
  1362. begin
  1363. with p do
  1364. begin
  1365. if k <> 0 then
  1366. begin
  1367. descriptions := descriptions + '|';
  1368. filters := filters + ';';
  1369. end;
  1370. if (Description = '') and (DescResID <> 0) then
  1371. Description := LoadStr(DescResID);
  1372. FmtStr(descriptions, '%s%s (*.%s)|*.%2:s', [descriptions, Description, Extension]);
  1373. filters := filters + '*.' + Extension;
  1374. Inc(k);
  1375. end;
  1376. end;
  1377. end;
  1378. if (k > 1) and (not formatsThatCanBeSaved) then
  1379. FmtStr(descriptions, '%s (%s)|%1:s|%s', [sAllFilter, filters, descriptions]);
  1380. end;
  1381. function TgxVectorFileFormatsList.FindExtByIndex(Index: Integer; formatsThatCanBeOpened: Boolean = True;
  1382. formatsThatCanBeSaved: Boolean = False): string;
  1383. var
  1384. i: Integer;
  1385. p: TgxVectorFileFormat;
  1386. begin
  1387. Result := '';
  1388. if index > 0 then
  1389. begin
  1390. for i := 0 to Count - 1 do
  1391. begin
  1392. p := TgxVectorFileFormat(Items[i]);
  1393. if (formatsThatCanBeOpened and (dfcRead in p.VectorFileClass.Capabilities)) or
  1394. (formatsThatCanBeSaved and (dfcWrite in p.VectorFileClass.Capabilities)) then
  1395. begin
  1396. if index = 1 then
  1397. begin
  1398. Result := p.Extension;
  1399. Break;
  1400. end
  1401. else
  1402. Dec(index);
  1403. end;
  1404. end;
  1405. end;
  1406. end;
  1407. // ------------------
  1408. // ------------------ TgxBaseMeshObject ------------------
  1409. // ------------------
  1410. constructor TgxBaseMeshObject.Create;
  1411. begin
  1412. FVertices := TgxAffineVectorList.Create;
  1413. FNormals := TgxAffineVectorList.Create;
  1414. FVisible := True;
  1415. inherited Create;
  1416. end;
  1417. destructor TgxBaseMeshObject.Destroy;
  1418. begin
  1419. FNormals.Free;
  1420. FVertices.Free;
  1421. inherited;
  1422. end;
  1423. procedure TgxBaseMeshObject.Assign(Source: TPersistent);
  1424. begin
  1425. if Source is TgxBaseMeshObject then
  1426. begin
  1427. FName := TgxBaseMeshObject(Source).Name;
  1428. FVertices.Assign(TgxBaseMeshObject(Source).FVertices);
  1429. FNormals.Assign(TgxBaseMeshObject(Source).FNormals);
  1430. end
  1431. else
  1432. inherited; // Die!
  1433. end;
  1434. procedure TgxBaseMeshObject.WriteToFiler(writer: TgxVirtualWriter);
  1435. begin
  1436. inherited WriteToFiler(writer);
  1437. with writer do
  1438. begin
  1439. WriteInteger(1); // Archive Version 1, added FVisible
  1440. WriteString(FName);
  1441. FVertices.WriteToFiler(writer);
  1442. FNormals.WriteToFiler(writer);
  1443. WriteBoolean(FVisible);
  1444. end;
  1445. end;
  1446. procedure TgxBaseMeshObject.ReadFromFiler(reader: TgxVirtualReader);
  1447. var
  1448. archiveVersion: Integer;
  1449. begin
  1450. inherited ReadFromFiler(reader);
  1451. archiveVersion := reader.ReadInteger;
  1452. if archiveVersion in [0 .. 1] then
  1453. with reader do
  1454. begin
  1455. FName := ReadString;
  1456. FVertices.ReadFromFiler(reader);
  1457. FNormals.ReadFromFiler(reader);
  1458. if archiveVersion >= 1 then
  1459. FVisible := ReadBoolean
  1460. else
  1461. FVisible := True;
  1462. end
  1463. else
  1464. RaiseFilerException(archiveVersion);
  1465. end;
  1466. procedure TgxBaseMeshObject.Clear;
  1467. begin
  1468. FNormals.Clear;
  1469. FVertices.Clear;
  1470. end;
  1471. procedure TgxBaseMeshObject.ContributeToBarycenter(var currentSum: TAffineVector; var nb: Integer);
  1472. begin
  1473. AddVector(currentSum, FVertices.Sum);
  1474. nb := nb + FVertices.Count;
  1475. end;
  1476. procedure TgxBaseMeshObject.Translate(const delta: TAffineVector);
  1477. begin
  1478. FVertices.Translate(delta);
  1479. end;
  1480. procedure TgxBaseMeshObject.BuildNormals(vertexIndices: TgxIntegerList; mode: TgxMeshObjectMode;
  1481. normalIndices: TgxIntegerList = nil);
  1482. var
  1483. i, base: Integer;
  1484. n: TAffineVector;
  1485. newNormals: TgxIntegerList;
  1486. function TranslateNewNormal(vertexIndex: Integer; const delta: TAffineVector): Integer;
  1487. var
  1488. pv: PAffineVector;
  1489. begin
  1490. Result := newNormals[vertexIndex];
  1491. if Result < base then
  1492. begin
  1493. Result := normals.Add(NullVector);
  1494. newNormals[vertexIndex] := Result;
  1495. end;
  1496. pv := @normals.list[Result];
  1497. AddVector(pv^, delta);
  1498. end;
  1499. begin
  1500. if not Assigned(normalIndices) then
  1501. begin
  1502. // build bijection
  1503. normals.Clear;
  1504. normals.Count := Vertices.Count;
  1505. case mode of
  1506. momTriangles:
  1507. begin
  1508. i := 0;
  1509. while i <= vertexIndices.Count - 3 do
  1510. with normals do
  1511. begin
  1512. with Vertices do
  1513. begin
  1514. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 1]], Items[vertexIndices[i + 2]], n);
  1515. end;
  1516. with normals do
  1517. begin
  1518. TranslateItem(vertexIndices[i + 0], n);
  1519. TranslateItem(vertexIndices[i + 1], n);
  1520. TranslateItem(vertexIndices[i + 2], n);
  1521. end;
  1522. Inc(i, 3);
  1523. end;
  1524. end;
  1525. momTriangleStrip:
  1526. begin
  1527. i := 0;
  1528. while i <= vertexIndices.Count - 3 do
  1529. with normals do
  1530. begin
  1531. with Vertices do
  1532. begin
  1533. if (i and 1) = 0 then
  1534. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 1]], Items[vertexIndices[i + 2]], n)
  1535. else
  1536. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 2]], Items[vertexIndices[i + 1]], n);
  1537. end;
  1538. with normals do
  1539. begin
  1540. TranslateItem(vertexIndices[i + 0], n);
  1541. TranslateItem(vertexIndices[i + 1], n);
  1542. TranslateItem(vertexIndices[i + 2], n);
  1543. end;
  1544. Inc(i, 1);
  1545. end;
  1546. end;
  1547. else
  1548. Assert(False);
  1549. end;
  1550. normals.normalize;
  1551. end
  1552. else
  1553. begin
  1554. // add new normals
  1555. base := normals.Count;
  1556. newNormals := TgxIntegerList.Create;
  1557. newNormals.AddSerie(-1, 0, Vertices.Count);
  1558. case mode of
  1559. momTriangles:
  1560. begin
  1561. i := 0;
  1562. while i <= vertexIndices.Count - 3 do
  1563. begin
  1564. with Vertices do
  1565. begin
  1566. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 1]], Items[vertexIndices[i + 2]], n);
  1567. end;
  1568. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 0], n));
  1569. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 1], n));
  1570. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 2], n));
  1571. Inc(i, 3);
  1572. end;
  1573. end;
  1574. momTriangleStrip:
  1575. begin
  1576. i := 0;
  1577. while i <= vertexIndices.Count - 3 do
  1578. begin
  1579. with Vertices do
  1580. begin
  1581. if (i and 1) = 0 then
  1582. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 1]], Items[vertexIndices[i + 2]], n)
  1583. else
  1584. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 2]], Items[vertexIndices[i + 1]], n);
  1585. end;
  1586. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 0], n));
  1587. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 1], n));
  1588. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 2], n));
  1589. Inc(i, 1);
  1590. end;
  1591. end;
  1592. else
  1593. Assert(False);
  1594. end;
  1595. for i := base to normals.Count - 1 do
  1596. NormalizeVector(normals.list^[i]);
  1597. newNormals.Free;
  1598. end;
  1599. end;
  1600. function TgxBaseMeshObject.ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil)
  1601. : TgxAffineVectorList;
  1602. begin
  1603. Result := TgxAffineVectorList.Create;
  1604. if (Vertices.Count mod 3) = 0 then
  1605. begin
  1606. Result.Assign(Vertices);
  1607. if Assigned(normals) then
  1608. normals.Assign(Self.normals);
  1609. end;
  1610. end;
  1611. procedure TgxBaseMeshObject.SetVertices(const val: TgxAffineVectorList);
  1612. begin
  1613. FVertices.Assign(val);
  1614. end;
  1615. procedure TgxBaseMeshObject.SetNormals(const val: TgxAffineVectorList);
  1616. begin
  1617. FNormals.Assign(val);
  1618. end;
  1619. // ------------------
  1620. // ------------------ TgxSkeletonFrame ------------------
  1621. // ------------------
  1622. constructor TgxSkeletonFrame.CreateOwned(aOwner: TgxSkeletonFrameList);
  1623. begin
  1624. FOwner := aOwner;
  1625. aOwner.Add(Self);
  1626. Create;
  1627. end;
  1628. constructor TgxSkeletonFrame.Create;
  1629. begin
  1630. inherited Create;
  1631. FPosition := TgxAffineVectorList.Create;
  1632. FRotation := TgxAffineVectorList.Create;
  1633. FQuaternion := TgxQuaternionList.Create;
  1634. FTransformMode := sftRotation;
  1635. end;
  1636. destructor TgxSkeletonFrame.Destroy;
  1637. begin
  1638. FlushLocalMatrixList;
  1639. FRotation.Free;
  1640. FPosition.Free;
  1641. FQuaternion.Free;
  1642. inherited Destroy;
  1643. end;
  1644. procedure TgxSkeletonFrame.WriteToFiler(writer: TgxVirtualWriter);
  1645. begin
  1646. inherited WriteToFiler(writer);
  1647. with writer do
  1648. begin
  1649. WriteInteger(1); // Archive Version 1
  1650. WriteString(FName);
  1651. FPosition.WriteToFiler(writer);
  1652. FRotation.WriteToFiler(writer);
  1653. FQuaternion.WriteToFiler(writer);
  1654. WriteInteger(Integer(FTransformMode));
  1655. end;
  1656. end;
  1657. procedure TgxSkeletonFrame.ReadFromFiler(reader: TgxVirtualReader);
  1658. var
  1659. archiveVersion: Integer;
  1660. begin
  1661. inherited ReadFromFiler(reader);
  1662. archiveVersion := reader.ReadInteger;
  1663. if (archiveVersion = 0) or (archiveVersion = 1) then
  1664. with reader do
  1665. begin
  1666. FName := ReadString;
  1667. FPosition.ReadFromFiler(reader);
  1668. FRotation.ReadFromFiler(reader);
  1669. if (archiveVersion = 1) then
  1670. begin
  1671. FQuaternion.ReadFromFiler(reader);
  1672. FTransformMode := TgxSkeletonFrameTransform(ReadInteger);
  1673. end;
  1674. end
  1675. else
  1676. RaiseFilerException(archiveVersion);
  1677. FlushLocalMatrixList;
  1678. end;
  1679. procedure TgxSkeletonFrame.SetPosition(const val: TgxAffineVectorList);
  1680. begin
  1681. FPosition.Assign(val);
  1682. end;
  1683. procedure TgxSkeletonFrame.SetRotation(const val: TgxAffineVectorList);
  1684. begin
  1685. FRotation.Assign(val);
  1686. end;
  1687. procedure TgxSkeletonFrame.SetQuaternion(const val: TgxQuaternionList);
  1688. begin
  1689. FQuaternion.Assign(val);
  1690. end;
  1691. function TgxSkeletonFrame.LocalMatrixList: PMatrixArray;
  1692. var
  1693. i: Integer;
  1694. s, c: Single;
  1695. mat, rmat: TMatrix4f;
  1696. quat: TQuaternion;
  1697. begin
  1698. if not Assigned(FLocalMatrixList) then
  1699. begin
  1700. case FTransformMode of
  1701. sftRotation:
  1702. begin
  1703. FLocalMatrixList := AllocMem(SizeOf(TMatrix4f) * Rotation.Count);
  1704. for i := 0 to Rotation.Count - 1 do
  1705. begin
  1706. if Rotation[i].X <> 0 then
  1707. begin
  1708. SinCosine(Rotation[i].X, s, c);
  1709. mat := CreateRotationMatrixX(s, c);
  1710. end
  1711. else
  1712. mat := IdentityHmgMatrix;
  1713. if Rotation[i].Y <> 0 then
  1714. begin
  1715. SinCosine(Rotation[i].Y, s, c);
  1716. rmat := CreateRotationMatrixY(s, c);
  1717. mat := MatrixMultiply(mat, rmat);
  1718. end;
  1719. if Rotation[i].Z <> 0 then
  1720. begin
  1721. SinCosine(Rotation[i].Z, s, c);
  1722. rmat := CreateRotationMatrixZ(s, c);
  1723. mat := MatrixMultiply(mat, rmat);
  1724. end;
  1725. mat.W.X := Position[i].X;
  1726. mat.W.Y := Position[i].Y;
  1727. mat.W.Z := Position[i].Z;
  1728. FLocalMatrixList^[i] := mat;
  1729. end;
  1730. end;
  1731. sftQuaternion:
  1732. begin
  1733. FLocalMatrixList := AllocMem(SizeOf(TMatrix4f) * Quaternion.Count);
  1734. for i := 0 to Quaternion.Count - 1 do
  1735. begin
  1736. quat := Quaternion[i];
  1737. mat := QuaternionToMatrix(quat);
  1738. mat.W.X := Position[i].X;
  1739. mat.W.Y := Position[i].Y;
  1740. mat.W.Z := Position[i].Z;
  1741. mat.W.W := 1;
  1742. FLocalMatrixList^[i] := mat;
  1743. end;
  1744. end;
  1745. end;
  1746. end;
  1747. Result := FLocalMatrixList;
  1748. end;
  1749. procedure TgxSkeletonFrame.FlushLocalMatrixList;
  1750. begin
  1751. if Assigned(FLocalMatrixList) then
  1752. begin
  1753. FreeMem(FLocalMatrixList);
  1754. FLocalMatrixList := nil;
  1755. end;
  1756. end;
  1757. procedure TgxSkeletonFrame.ConvertQuaternionsToRotations(KeepQuaternions: Boolean = True);
  1758. var
  1759. i: Integer;
  1760. t: TTransformations;
  1761. m: TMatrix4f;
  1762. begin
  1763. Rotation.Clear;
  1764. for i := 0 to Quaternion.Count - 1 do
  1765. begin
  1766. m := QuaternionToMatrix(Quaternion[i]);
  1767. if MatrixDecompose(m, t) then
  1768. Rotation.Add(t[ttRotateX], t[ttRotateY], t[ttRotateZ])
  1769. else
  1770. Rotation.Add(NullVector);
  1771. end;
  1772. if not KeepQuaternions then
  1773. Quaternion.Clear;
  1774. end;
  1775. procedure TgxSkeletonFrame.ConvertRotationsToQuaternions(KeepRotations: Boolean = True);
  1776. var
  1777. i: Integer;
  1778. mat, rmat: TMatrix4f;
  1779. s, c: Single;
  1780. begin
  1781. Quaternion.Clear;
  1782. for i := 0 to Rotation.Count - 1 do
  1783. begin
  1784. mat := IdentityHmgMatrix;
  1785. SinCosine(Rotation[i].X, s, c);
  1786. rmat := CreateRotationMatrixX(s, c);
  1787. mat := MatrixMultiply(mat, rmat);
  1788. SinCosine(Rotation[i].Y, s, c);
  1789. rmat := CreateRotationMatrixY(s, c);
  1790. mat := MatrixMultiply(mat, rmat);
  1791. SinCosine(Rotation[i].Z, s, c);
  1792. rmat := CreateRotationMatrixZ(s, c);
  1793. mat := MatrixMultiply(mat, rmat);
  1794. Quaternion.Add(QuaternionFromMatrix(mat));
  1795. end;
  1796. if not KeepRotations then
  1797. Rotation.Clear;
  1798. end;
  1799. // ------------------
  1800. // ------------------ TgxSkeletonFrameList ------------------
  1801. // ------------------
  1802. constructor TgxSkeletonFrameList.CreateOwned(aOwner: TPersistent);
  1803. begin
  1804. FOwner := aOwner;
  1805. Create;
  1806. end;
  1807. destructor TgxSkeletonFrameList.Destroy;
  1808. begin
  1809. Clear;
  1810. inherited;
  1811. end;
  1812. procedure TgxSkeletonFrameList.ReadFromFiler(reader: TgxVirtualReader);
  1813. var
  1814. i: Integer;
  1815. begin
  1816. inherited;
  1817. for i := 0 to Count - 1 do
  1818. Items[i].FOwner := Self;
  1819. end;
  1820. procedure TgxSkeletonFrameList.Clear;
  1821. var
  1822. i: Integer;
  1823. begin
  1824. for i := 0 to Count - 1 do
  1825. with Items[i] do
  1826. begin
  1827. FOwner := nil;
  1828. Free;
  1829. end;
  1830. inherited;
  1831. end;
  1832. function TgxSkeletonFrameList.GetSkeletonFrame(Index: Integer): TgxSkeletonFrame;
  1833. begin
  1834. Result := TgxSkeletonFrame(list^[Index]);
  1835. end;
  1836. procedure TgxSkeletonFrameList.ConvertQuaternionsToRotations(KeepQuaternions: Boolean = True; SetTransformMode: Boolean = True);
  1837. var
  1838. i: Integer;
  1839. begin
  1840. for i := 0 to Count - 1 do
  1841. begin
  1842. Items[i].ConvertQuaternionsToRotations(KeepQuaternions);
  1843. if SetTransformMode then
  1844. Items[i].TransformMode := sftRotation;
  1845. end;
  1846. end;
  1847. procedure TgxSkeletonFrameList.ConvertRotationsToQuaternions(KeepRotations: Boolean = True; SetTransformMode: Boolean = True);
  1848. var
  1849. i: Integer;
  1850. begin
  1851. for i := 0 to Count - 1 do
  1852. begin
  1853. Items[i].ConvertRotationsToQuaternions(KeepRotations);
  1854. if SetTransformMode then
  1855. Items[i].TransformMode := sftQuaternion;
  1856. end;
  1857. end;
  1858. // ------------------
  1859. // ------------------ TgxSkeletonBoneList ------------------
  1860. // ------------------
  1861. constructor TgxSkeletonBoneList.CreateOwned(aOwner: TgxSkeleton);
  1862. begin
  1863. FSkeleton := aOwner;
  1864. Create;
  1865. end;
  1866. constructor TgxSkeletonBoneList.Create;
  1867. begin
  1868. inherited;
  1869. FGlobalMatrix := IdentityHmgMatrix;
  1870. end;
  1871. destructor TgxSkeletonBoneList.Destroy;
  1872. begin
  1873. Clean;
  1874. inherited;
  1875. end;
  1876. procedure TgxSkeletonBoneList.WriteToFiler(writer: TgxVirtualWriter);
  1877. begin
  1878. inherited WriteToFiler(writer);
  1879. with writer do
  1880. begin
  1881. WriteInteger(0); // Archive Version 0
  1882. // nothing, yet
  1883. end;
  1884. end;
  1885. procedure TgxSkeletonBoneList.ReadFromFiler(reader: TgxVirtualReader);
  1886. var
  1887. archiveVersion, i: Integer;
  1888. begin
  1889. inherited ReadFromFiler(reader);
  1890. archiveVersion := reader.ReadInteger;
  1891. if archiveVersion = 0 then
  1892. with reader do
  1893. begin
  1894. // nothing, yet
  1895. end
  1896. else
  1897. RaiseFilerException(archiveVersion);
  1898. for i := 0 to Count - 1 do
  1899. Items[i].FOwner := Self;
  1900. end;
  1901. procedure TgxSkeletonBoneList.AfterObjectCreatedByReader(Sender: TObject);
  1902. begin
  1903. with (Sender as TgxSkeletonBone) do
  1904. begin
  1905. FOwner := Self;
  1906. FSkeleton := Self.Skeleton;
  1907. end;
  1908. end;
  1909. function TgxSkeletonBoneList.GetSkeletonBone(Index: Integer): TgxSkeletonBone;
  1910. begin
  1911. Result := TgxSkeletonBone(list^[Index]);
  1912. end;
  1913. function TgxSkeletonBoneList.BoneByID(anID: Integer): TgxSkeletonBone;
  1914. var
  1915. i: Integer;
  1916. begin
  1917. Result := nil;
  1918. for i := 0 to Count - 1 do
  1919. begin
  1920. Result := Items[i].BoneByID(anID);
  1921. if Assigned(Result) then
  1922. Break;
  1923. end;
  1924. end;
  1925. function TgxSkeletonBoneList.BoneByName(const aName: string): TgxSkeletonBone;
  1926. var
  1927. i: Integer;
  1928. begin
  1929. Result := nil;
  1930. for i := 0 to Count - 1 do
  1931. begin
  1932. Result := Items[i].BoneByName(aName);
  1933. if Assigned(Result) then
  1934. Break;
  1935. end;
  1936. end;
  1937. function TgxSkeletonBoneList.BoneCount: Integer;
  1938. var
  1939. i: Integer;
  1940. begin
  1941. Result := 1;
  1942. for i := 0 to Count - 1 do
  1943. Inc(Result, Items[i].BoneCount);
  1944. end;
  1945. procedure TgxSkeletonBoneList.PrepareGlobalMatrices;
  1946. var
  1947. i: Integer;
  1948. begin
  1949. for i := 0 to Count - 1 do
  1950. Items[i].PrepareGlobalMatrices;
  1951. end;
  1952. // ------------------
  1953. // ------------------ TgxSkeletonRootBoneList ------------------
  1954. // ------------------
  1955. procedure TgxSkeletonRootBoneList.WriteToFiler(writer: TgxVirtualWriter);
  1956. begin
  1957. inherited WriteToFiler(writer);
  1958. with writer do
  1959. begin
  1960. WriteInteger(0); // Archive Version 0
  1961. // nothing, yet
  1962. end;
  1963. end;
  1964. procedure TgxSkeletonRootBoneList.ReadFromFiler(reader: TgxVirtualReader);
  1965. var
  1966. archiveVersion, i: Integer;
  1967. begin
  1968. inherited ReadFromFiler(reader);
  1969. archiveVersion := reader.ReadInteger;
  1970. if archiveVersion = 0 then
  1971. with reader do
  1972. begin
  1973. // nothing, yet
  1974. end
  1975. else
  1976. RaiseFilerException(archiveVersion);
  1977. for i := 0 to Count - 1 do
  1978. Items[i].FOwner := Self;
  1979. end;
  1980. procedure TgxSkeletonRootBoneList.BuildList(var mrci: TgxRenderContextInfo);
  1981. var
  1982. i: Integer;
  1983. begin
  1984. // root node setups and restore OpenGL stuff
  1985. mrci.gxStates.Disable(stColorMaterial);
  1986. mrci.gxStates.Disable(stLighting);
  1987. glColor3f(1, 1, 1);
  1988. // render root-bones
  1989. for i := 0 to Count - 1 do
  1990. Items[i].BuildList(mrci);
  1991. end;
  1992. // ------------------
  1993. // ------------------ TgxSkeletonBone ------------------
  1994. // ------------------
  1995. constructor TgxSkeletonBone.CreateOwned(aOwner: TgxSkeletonBoneList);
  1996. begin
  1997. FOwner := aOwner;
  1998. aOwner.Add(Self);
  1999. FSkeleton := aOwner.Skeleton;
  2000. Create;
  2001. end;
  2002. constructor TgxSkeletonBone.Create;
  2003. begin
  2004. FColor := $FFFFFFFF; // opaque white
  2005. inherited;
  2006. end;
  2007. destructor TgxSkeletonBone.Destroy;
  2008. begin
  2009. if Assigned(Owner) then
  2010. Owner.Remove(Self);
  2011. inherited Destroy;
  2012. end;
  2013. procedure TgxSkeletonBone.WriteToFiler(writer: TgxVirtualWriter);
  2014. begin
  2015. inherited WriteToFiler(writer);
  2016. with writer do
  2017. begin
  2018. WriteInteger(0); // Archive Version 0
  2019. WriteString(FName);
  2020. WriteInteger(FBoneID);
  2021. WriteInteger(Integer(FColor));
  2022. end;
  2023. end;
  2024. procedure TgxSkeletonBone.ReadFromFiler(reader: TgxVirtualReader);
  2025. var
  2026. archiveVersion, i: Integer;
  2027. begin
  2028. inherited ReadFromFiler(reader);
  2029. archiveVersion := reader.ReadInteger;
  2030. if archiveVersion = 0 then
  2031. with reader do
  2032. begin
  2033. FName := ReadString;
  2034. FBoneID := ReadInteger;
  2035. FColor := Cardinal(ReadInteger);
  2036. end
  2037. else
  2038. RaiseFilerException(archiveVersion);
  2039. for i := 0 to Count - 1 do
  2040. Items[i].FOwner := Self;
  2041. end;
  2042. procedure TgxSkeletonBone.BuildList(var mrci: TgxRenderContextInfo);
  2043. procedure IssueColor(Color: Cardinal);
  2044. begin
  2045. glColor4f(GetRValue(Color) / 255, GetGValue(Color) / 255, GetBValue(Color) / 255, ((Color shr 24) and 255) / 255);
  2046. end;
  2047. var
  2048. i: Integer;
  2049. begin
  2050. // point for self
  2051. mrci.gxStates.PointSize := 5;
  2052. glBegin(GL_POINTS);
  2053. IssueColor(Color);
  2054. glVertex3fv(@GlobalMatrix.W.X);
  2055. glEnd;
  2056. // parent-self bone line
  2057. if Owner is TgxSkeletonBone then
  2058. begin
  2059. glBegin(GL_LINES);
  2060. glVertex3fv(@TgxSkeletonBone(Owner).GlobalMatrix.W.X);
  2061. glVertex3fv(@GlobalMatrix.W.X);
  2062. glEnd;
  2063. end;
  2064. // render sub-bones
  2065. for i := 0 to Count - 1 do
  2066. Items[i].BuildList(mrci);
  2067. end;
  2068. function TgxSkeletonBone.GetSkeletonBone(Index: Integer): TgxSkeletonBone;
  2069. begin
  2070. Result := TgxSkeletonBone(list^[Index]);
  2071. end;
  2072. procedure TgxSkeletonBone.SetColor(const val: Cardinal);
  2073. begin
  2074. FColor := val;
  2075. end;
  2076. function TgxSkeletonBone.BoneByID(anID: Integer): TgxSkeletonBone;
  2077. begin
  2078. if BoneID = anID then
  2079. Result := Self
  2080. else
  2081. Result := inherited BoneByID(anID);
  2082. end;
  2083. function TgxSkeletonBone.BoneByName(const aName: string): TgxSkeletonBone;
  2084. begin
  2085. if Name = aName then
  2086. Result := Self
  2087. else
  2088. Result := inherited BoneByName(aName);
  2089. end;
  2090. procedure TgxSkeletonBone.Clean;
  2091. begin
  2092. BoneID := 0;
  2093. Name := '';
  2094. inherited;
  2095. end;
  2096. procedure TgxSkeletonBone.PrepareGlobalMatrices;
  2097. begin
  2098. if (Skeleton.FRagDollEnabled) then
  2099. Exit; // ragdoll
  2100. FGlobalMatrix := MatrixMultiply(Skeleton.CurrentFrame.LocalMatrixList^[BoneID], TgxSkeletonBoneList(Owner).FGlobalMatrix);
  2101. inherited;
  2102. end;
  2103. procedure TgxSkeletonBone.SetGlobalMatrix(Matrix: TMatrix4f); // ragdoll
  2104. begin
  2105. FGlobalMatrix := Matrix;
  2106. end;
  2107. procedure TgxSkeletonBone.SetGlobalMatrixForRagDoll(RagDollMatrix: TMatrix4f);
  2108. // ragdoll
  2109. begin
  2110. FGlobalMatrix := MatrixMultiply(RagDollMatrix, Skeleton.Owner.InvAbsoluteMatrix);
  2111. inherited;
  2112. end;
  2113. // ------------------
  2114. // ------------------ TgxSkeletonCollider ------------------
  2115. // ------------------
  2116. constructor TgxSkeletonCollider.Create;
  2117. begin
  2118. inherited;
  2119. FLocalMatrix := IdentityHmgMatrix;
  2120. FGlobalMatrix := IdentityHmgMatrix;
  2121. FAutoUpdate := True;
  2122. end;
  2123. constructor TgxSkeletonCollider.CreateOwned(aOwner: TgxSkeletonColliderList);
  2124. begin
  2125. Create;
  2126. FOwner := aOwner;
  2127. if Assigned(FOwner) then
  2128. FOwner.Add(Self);
  2129. end;
  2130. procedure TgxSkeletonCollider.WriteToFiler(writer: TgxVirtualWriter);
  2131. begin
  2132. inherited WriteToFiler(writer);
  2133. with writer do
  2134. begin
  2135. WriteInteger(0); // Archive Version 0
  2136. if Assigned(FBone) then
  2137. WriteInteger(FBone.BoneID)
  2138. else
  2139. WriteInteger(-1);
  2140. Write(FLocalMatrix, SizeOf(TMatrix4f));
  2141. end;
  2142. end;
  2143. procedure TgxSkeletonCollider.ReadFromFiler(reader: TgxVirtualReader);
  2144. var
  2145. archiveVersion: Integer;
  2146. begin
  2147. inherited ReadFromFiler(reader);
  2148. archiveVersion := reader.ReadInteger;
  2149. if archiveVersion = 0 then
  2150. with reader do
  2151. begin
  2152. FBoneID := ReadInteger;
  2153. Read(FLocalMatrix, SizeOf(TMatrix4f));
  2154. end
  2155. else
  2156. RaiseFilerException(archiveVersion);
  2157. end;
  2158. procedure TgxSkeletonCollider.AlignCollider;
  2159. var
  2160. mat: TMatrix4f;
  2161. begin
  2162. if Assigned(FBone) then
  2163. begin
  2164. if Owner.Owner is TgxSkeleton then
  2165. if TgxSkeleton(Owner.Owner).Owner is TgxBaseSceneObject then
  2166. mat := MatrixMultiply(FBone.GlobalMatrix, TgxBaseSceneObject(TgxSkeleton(Owner.Owner).Owner).AbsoluteMatrix)
  2167. else
  2168. mat := FBone.GlobalMatrix;
  2169. MatrixMultiply(FLocalMatrix, mat, FGlobalMatrix);
  2170. end
  2171. else
  2172. FGlobalMatrix := FLocalMatrix;
  2173. end;
  2174. procedure TgxSkeletonCollider.SetBone(const val: TgxSkeletonBone);
  2175. begin
  2176. if val <> FBone then
  2177. FBone := val;
  2178. end;
  2179. procedure TgxSkeletonCollider.SetLocalMatrix(const val: TMatrix4f);
  2180. begin
  2181. FLocalMatrix := val;
  2182. end;
  2183. // ------------------
  2184. // ------------------ TgxSkeletonColliderList ------------------
  2185. // ------------------
  2186. constructor TgxSkeletonColliderList.CreateOwned(aOwner: TPersistent);
  2187. begin
  2188. Create;
  2189. FOwner := aOwner;
  2190. end;
  2191. destructor TgxSkeletonColliderList.Destroy;
  2192. begin
  2193. Clear;
  2194. inherited;
  2195. end;
  2196. function TgxSkeletonColliderList.GetSkeletonCollider(Index: Integer): TgxSkeletonCollider;
  2197. begin
  2198. Result := TgxSkeletonCollider(inherited Get(index));
  2199. end;
  2200. procedure TgxSkeletonColliderList.ReadFromFiler(reader: TgxVirtualReader);
  2201. var
  2202. i: Integer;
  2203. begin
  2204. inherited;
  2205. for i := 0 to Count - 1 do
  2206. begin
  2207. Items[i].FOwner := Self;
  2208. if (Owner is TgxSkeleton) and (Items[i].FBoneID <> -1) then
  2209. Items[i].Bone := TgxSkeleton(Owner).BoneByID(Items[i].FBoneID);
  2210. end;
  2211. end;
  2212. procedure TgxSkeletonColliderList.Clear;
  2213. var
  2214. i: Integer;
  2215. begin
  2216. for i := 0 to Count - 1 do
  2217. begin
  2218. Items[i].FOwner := nil;
  2219. Items[i].Free;
  2220. end;
  2221. inherited;
  2222. end;
  2223. procedure TgxSkeletonColliderList.AlignColliders;
  2224. var
  2225. i: Integer;
  2226. begin
  2227. for i := 0 to Count - 1 do
  2228. if Items[i].AutoUpdate then
  2229. Items[i].AlignCollider;
  2230. end;
  2231. // ------------------
  2232. // ------------------ TgxSkeleton ------------------
  2233. // ------------------
  2234. constructor TgxSkeleton.CreateOwned(aOwner: TgxBaseMesh);
  2235. begin
  2236. FOwner := aOwner;
  2237. Create;
  2238. end;
  2239. constructor TgxSkeleton.Create;
  2240. begin
  2241. inherited Create;
  2242. FRootBones := TgxSkeletonRootBoneList.CreateOwned(Self);
  2243. FFrames := TgxSkeletonFrameList.CreateOwned(Self);
  2244. FColliders := TgxSkeletonColliderList.CreateOwned(Self);
  2245. end;
  2246. destructor TgxSkeleton.Destroy;
  2247. begin
  2248. FlushBoneByIDCache;
  2249. FCurrentFrame.Free;
  2250. FFrames.Free;
  2251. FRootBones.Free;
  2252. FColliders.Free;
  2253. inherited Destroy;
  2254. end;
  2255. procedure TgxSkeleton.WriteToFiler(writer: TgxVirtualWriter);
  2256. begin
  2257. inherited WriteToFiler(writer);
  2258. with writer do
  2259. begin
  2260. if FColliders.Count > 0 then
  2261. WriteInteger(1) // Archive Version 1 : with colliders
  2262. else
  2263. WriteInteger(0); // Archive Version 0
  2264. FRootBones.WriteToFiler(writer);
  2265. FFrames.WriteToFiler(writer);
  2266. if FColliders.Count > 0 then
  2267. FColliders.WriteToFiler(writer);
  2268. end;
  2269. end;
  2270. procedure TgxSkeleton.ReadFromFiler(reader: TgxVirtualReader);
  2271. var
  2272. archiveVersion: Integer;
  2273. begin
  2274. inherited ReadFromFiler(reader);
  2275. archiveVersion := reader.ReadInteger;
  2276. if (archiveVersion = 0) or (archiveVersion = 1) then
  2277. with reader do
  2278. begin
  2279. FRootBones.ReadFromFiler(reader);
  2280. FFrames.ReadFromFiler(reader);
  2281. if (archiveVersion = 1) then
  2282. FColliders.ReadFromFiler(reader);
  2283. end
  2284. else
  2285. RaiseFilerException(archiveVersion);
  2286. end;
  2287. procedure TgxSkeleton.SetRootBones(const val: TgxSkeletonRootBoneList);
  2288. begin
  2289. FRootBones.Assign(val);
  2290. end;
  2291. procedure TgxSkeleton.SetFrames(const val: TgxSkeletonFrameList);
  2292. begin
  2293. FFrames.Assign(val);
  2294. end;
  2295. function TgxSkeleton.GetCurrentFrame: TgxSkeletonFrame;
  2296. begin
  2297. if not Assigned(FCurrentFrame) then
  2298. FCurrentFrame := TgxSkeletonFrame(FFrames.Items[0].CreateClone);
  2299. Result := FCurrentFrame;
  2300. end;
  2301. procedure TgxSkeleton.SetCurrentFrame(val: TgxSkeletonFrame);
  2302. begin
  2303. if Assigned(FCurrentFrame) then
  2304. FCurrentFrame.Free;
  2305. FCurrentFrame := TgxSkeletonFrame(val.CreateClone);
  2306. end;
  2307. procedure TgxSkeleton.SetColliders(const val: TgxSkeletonColliderList);
  2308. begin
  2309. FColliders.Assign(val);
  2310. end;
  2311. procedure TgxSkeleton.FlushBoneByIDCache;
  2312. begin
  2313. FBonesByIDCache.Free;
  2314. FBonesByIDCache := nil;
  2315. end;
  2316. function TgxSkeleton.BoneByID(anID: Integer): TgxSkeletonBone;
  2317. procedure CollectBones(Bone: TgxSkeletonBone);
  2318. var
  2319. i: Integer;
  2320. begin
  2321. if Bone.BoneID >= FBonesByIDCache.Count then
  2322. FBonesByIDCache.Count := Bone.BoneID + 1;
  2323. FBonesByIDCache[Bone.BoneID] := Bone;
  2324. for i := 0 to Bone.Count - 1 do
  2325. CollectBones(Bone[i]);
  2326. end;
  2327. var
  2328. i: Integer;
  2329. begin
  2330. if not Assigned(FBonesByIDCache) then
  2331. begin
  2332. FBonesByIDCache := TList.Create;
  2333. for i := 0 to RootBones.Count - 1 do
  2334. CollectBones(RootBones[i]);
  2335. end;
  2336. Result := TgxSkeletonBone(FBonesByIDCache[anID])
  2337. end;
  2338. function TgxSkeleton.BoneByName(const aName: string): TgxSkeletonBone;
  2339. begin
  2340. Result := RootBones.BoneByName(aName);
  2341. end;
  2342. function TgxSkeleton.BoneCount: Integer;
  2343. begin
  2344. Result := RootBones.BoneCount;
  2345. end;
  2346. procedure TgxSkeleton.MorphTo(frameIndex: Integer);
  2347. begin
  2348. CurrentFrame := Frames[frameIndex];
  2349. end;
  2350. procedure TgxSkeleton.MorphTo(frame: TgxSkeletonFrame);
  2351. begin
  2352. CurrentFrame := frame;
  2353. end;
  2354. procedure TgxSkeleton.Lerp(frameIndex1, frameIndex2: Integer; lerpFactor: Single);
  2355. begin
  2356. if Assigned(FCurrentFrame) then
  2357. FCurrentFrame.Free;
  2358. FCurrentFrame := TgxSkeletonFrame.Create;
  2359. FCurrentFrame.TransformMode := Frames[frameIndex1].TransformMode;
  2360. with FCurrentFrame do
  2361. begin
  2362. Position.Lerp(Frames[frameIndex1].Position, Frames[frameIndex2].Position, lerpFactor);
  2363. case TransformMode of
  2364. sftRotation:
  2365. Rotation.AngleLerp(Frames[frameIndex1].Rotation, Frames[frameIndex2].Rotation, lerpFactor);
  2366. sftQuaternion:
  2367. Quaternion.Lerp(Frames[frameIndex1].Quaternion, Frames[frameIndex2].Quaternion, lerpFactor);
  2368. end;
  2369. end;
  2370. end;
  2371. procedure TgxSkeleton.BlendedLerps(const lerpInfos: array of TGXBlendedLerpInfo);
  2372. var
  2373. i, n: Integer;
  2374. blendPositions: TgxAffineVectorList;
  2375. blendRotations: TgxAffineVectorList;
  2376. blendQuaternions: TgxQuaternionList;
  2377. begin
  2378. n := High(lerpInfos) - Low(lerpInfos) + 1;
  2379. Assert(n >= 1);
  2380. i := Low(lerpInfos);
  2381. if n = 1 then
  2382. begin
  2383. // use fast lerp (no blend)
  2384. with lerpInfos[i] do
  2385. Lerp(frameIndex1, frameIndex2, lerpFactor);
  2386. end
  2387. else
  2388. begin
  2389. if Assigned(FCurrentFrame) then
  2390. FCurrentFrame.Free;
  2391. FCurrentFrame := TgxSkeletonFrame.Create;
  2392. FCurrentFrame.TransformMode := Frames[lerpInfos[i].frameIndex1].TransformMode;
  2393. with FCurrentFrame do
  2394. begin
  2395. blendPositions := TgxAffineVectorList.Create;
  2396. // lerp first item separately
  2397. Position.Lerp(Frames[lerpInfos[i].frameIndex1].Position, Frames[lerpInfos[i].frameIndex2].Position,
  2398. lerpInfos[i].lerpFactor);
  2399. if lerpInfos[i].weight <> 1 then
  2400. Position.Scale(lerpInfos[i].weight);
  2401. Inc(i);
  2402. // combine the other items
  2403. while i <= High(lerpInfos) do
  2404. begin
  2405. if not Assigned(lerpInfos[i].externalPositions) then
  2406. begin
  2407. blendPositions.Lerp(Frames[lerpInfos[i].frameIndex1].Position, Frames[lerpInfos[i].frameIndex2].Position,
  2408. lerpInfos[i].lerpFactor);
  2409. Position.AngleCombine(blendPositions, 1);
  2410. end
  2411. else
  2412. Position.Combine(lerpInfos[i].externalPositions, 1);
  2413. Inc(i);
  2414. end;
  2415. blendPositions.Free;
  2416. i := Low(lerpInfos);
  2417. case TransformMode of
  2418. sftRotation:
  2419. begin
  2420. blendRotations := TgxAffineVectorList.Create;
  2421. // lerp first item separately
  2422. Rotation.AngleLerp(Frames[lerpInfos[i].frameIndex1].Rotation, Frames[lerpInfos[i].frameIndex2].Rotation,
  2423. lerpInfos[i].lerpFactor);
  2424. Inc(i);
  2425. // combine the other items
  2426. while i <= High(lerpInfos) do
  2427. begin
  2428. if not Assigned(lerpInfos[i].externalRotations) then
  2429. begin
  2430. blendRotations.AngleLerp(Frames[lerpInfos[i].frameIndex1].Rotation, Frames[lerpInfos[i].frameIndex2].Rotation,
  2431. lerpInfos[i].lerpFactor);
  2432. Rotation.AngleCombine(blendRotations, 1);
  2433. end
  2434. else
  2435. Rotation.AngleCombine(lerpInfos[i].externalRotations, 1);
  2436. Inc(i);
  2437. end;
  2438. blendRotations.Free;
  2439. end;
  2440. sftQuaternion:
  2441. begin
  2442. blendQuaternions := TgxQuaternionList.Create;
  2443. // Initial frame lerp
  2444. Quaternion.Lerp(Frames[lerpInfos[i].frameIndex1].Quaternion, Frames[lerpInfos[i].frameIndex2].Quaternion,
  2445. lerpInfos[i].lerpFactor);
  2446. Inc(i);
  2447. // Combine the lerped frames together
  2448. while i <= High(lerpInfos) do
  2449. begin
  2450. if not Assigned(lerpInfos[i].externalQuaternions) then
  2451. begin
  2452. blendQuaternions.Lerp(Frames[lerpInfos[i].frameIndex1].Quaternion, Frames[lerpInfos[i].frameIndex2].Quaternion,
  2453. lerpInfos[i].lerpFactor);
  2454. Quaternion.Combine(blendQuaternions, 1);
  2455. end
  2456. else
  2457. Quaternion.Combine(lerpInfos[i].externalQuaternions, 1);
  2458. Inc(i);
  2459. end;
  2460. blendQuaternions.Free;
  2461. end;
  2462. end;
  2463. end;
  2464. end;
  2465. end;
  2466. procedure TgxSkeleton.MakeSkeletalTranslationStatic(startFrame, endFrame: Integer);
  2467. var
  2468. delta: TAffineVector;
  2469. i: Integer;
  2470. f: Single;
  2471. begin
  2472. if endFrame <= startFrame then
  2473. Exit;
  2474. delta := VectorSubtract(Frames[endFrame].Position[0], Frames[startFrame].Position[0]);
  2475. f := -1 / (endFrame - startFrame);
  2476. for i := startFrame to endFrame do
  2477. Frames[i].Position[0] := VectorCombine(Frames[i].Position[0], delta, 1, (i - startFrame) * f);
  2478. end;
  2479. procedure TgxSkeleton.MakeSkeletalRotationDelta(startFrame, endFrame: Integer);
  2480. var
  2481. i, j: Integer;
  2482. v: TAffineVector;
  2483. begin
  2484. if endFrame <= startFrame then
  2485. Exit;
  2486. for i := startFrame to endFrame do
  2487. begin
  2488. for j := 0 to Frames[i].Position.Count - 1 do
  2489. begin
  2490. Frames[i].Position[j] := NullVector;
  2491. v := VectorSubtract(Frames[i].Rotation[j], Frames[0].Rotation[j]);
  2492. if VectorNorm(v) < 1E-6 then
  2493. Frames[i].Rotation[j] := NullVector
  2494. else
  2495. Frames[i].Rotation[j] := v;
  2496. end;
  2497. end;
  2498. end;
  2499. procedure TgxSkeleton.MorphMesh(normalize: Boolean);
  2500. var
  2501. i: Integer;
  2502. Mesh: TgxBaseMeshObject;
  2503. begin
  2504. if Owner.MeshObjects.Count > 0 then
  2505. begin
  2506. RootBones.PrepareGlobalMatrices;
  2507. if Colliders.Count > 0 then
  2508. Colliders.AlignColliders;
  2509. if FMorphInvisibleParts then
  2510. for i := 0 to Owner.MeshObjects.Count - 1 do
  2511. begin
  2512. Mesh := Owner.MeshObjects.Items[i];
  2513. if (Mesh is TgxSkeletonMeshObject) then
  2514. TgxSkeletonMeshObject(Mesh).ApplyCurrentSkeletonFrame(normalize);
  2515. end
  2516. else
  2517. for i := 0 to Owner.MeshObjects.Count - 1 do
  2518. begin
  2519. Mesh := Owner.MeshObjects.Items[i];
  2520. if (Mesh is TgxSkeletonMeshObject) and Mesh.Visible then
  2521. TgxSkeletonMeshObject(Mesh).ApplyCurrentSkeletonFrame(normalize);
  2522. end
  2523. end;
  2524. end;
  2525. procedure TgxSkeleton.Synchronize(reference: TgxSkeleton);
  2526. begin
  2527. CurrentFrame.Assign(reference.CurrentFrame);
  2528. MorphMesh(True);
  2529. end;
  2530. procedure TgxSkeleton.Clear;
  2531. begin
  2532. FlushBoneByIDCache;
  2533. RootBones.Clean;
  2534. Frames.Clear;
  2535. FCurrentFrame.Free;
  2536. FCurrentFrame := nil;
  2537. FColliders.Clear;
  2538. end;
  2539. procedure TgxSkeleton.StartRagdoll; // ragdoll
  2540. var
  2541. i: Integer;
  2542. Mesh: TgxBaseMeshObject;
  2543. begin
  2544. if FRagDollEnabled then
  2545. Exit
  2546. else
  2547. FRagDollEnabled := True;
  2548. if Owner.MeshObjects.Count > 0 then
  2549. begin
  2550. for i := 0 to Owner.MeshObjects.Count - 1 do
  2551. begin
  2552. Mesh := Owner.MeshObjects.Items[i];
  2553. if Mesh is TgxSkeletonMeshObject then
  2554. begin
  2555. TgxSkeletonMeshObject(Mesh).BackupBoneMatrixInvertedMeshes;
  2556. TgxSkeletonMeshObject(Mesh).PrepareBoneMatrixInvertedMeshes;
  2557. end;
  2558. end;
  2559. end;
  2560. end;
  2561. procedure TgxSkeleton.StopRagdoll; // ragdoll
  2562. var
  2563. i: Integer;
  2564. Mesh: TgxBaseMeshObject;
  2565. begin
  2566. FRagDollEnabled := False;
  2567. if Owner.MeshObjects.Count > 0 then
  2568. begin
  2569. for i := 0 to Owner.MeshObjects.Count - 1 do
  2570. begin
  2571. Mesh := Owner.MeshObjects.Items[i];
  2572. if Mesh is TgxSkeletonMeshObject then
  2573. TgxSkeletonMeshObject(Mesh).RestoreBoneMatrixInvertedMeshes;
  2574. end;
  2575. end;
  2576. end;
  2577. // ------------------
  2578. // ------------------ TgxMeshObject ------------------
  2579. // ------------------
  2580. constructor TgxMeshObject.CreateOwned(aOwner: TgxMeshObjectList);
  2581. begin
  2582. FOwner := aOwner;
  2583. Create;
  2584. if Assigned(FOwner) then
  2585. FOwner.Add(Self);
  2586. end;
  2587. constructor TgxMeshObject.Create;
  2588. begin
  2589. FMode := momTriangles;
  2590. FTexCoords := TgxAffineVectorList.Create;
  2591. FLightMapTexCoords := TgxAffineVectorList.Create;
  2592. FColors := TgxVectorList.Create;
  2593. FFaceGroups := TgxFaceGroups.CreateOwned(Self);
  2594. FTexCoordsEx := TList.Create;
  2595. FTangentsTexCoordIndex := 1;
  2596. FBinormalsTexCoordIndex := 2;
  2597. FUseVBO := vVectorFileObjectsEnableVBOByDefault;
  2598. inherited;
  2599. end;
  2600. destructor TgxMeshObject.Destroy;
  2601. var
  2602. i: Integer;
  2603. begin
  2604. FVerticesVBO.Free;
  2605. FNormalsVBO.Free;
  2606. FColorsVBO.Free;
  2607. for i := 0 to high(FTexCoordsVBO) do
  2608. FTexCoordsVBO[i].Free;
  2609. FLightmapTexCoordsVBO.Free;
  2610. FFaceGroups.Free;
  2611. FColors.Free;
  2612. FTexCoords.Free;
  2613. FLightMapTexCoords.Free;
  2614. for i := 0 to FTexCoordsEx.Count - 1 do
  2615. TgxVectorList(FTexCoordsEx[i]).Free;
  2616. FTexCoordsEx.Free;
  2617. if Assigned(FOwner) then
  2618. FOwner.Remove(Self);
  2619. inherited;
  2620. end;
  2621. procedure TgxMeshObject.Assign(Source: TPersistent);
  2622. var
  2623. i: Integer;
  2624. begin
  2625. inherited Assign(Source);
  2626. if Source is TgxMeshObject then
  2627. begin
  2628. FTexCoords.Assign(TgxMeshObject(Source).FTexCoords);
  2629. FLightMapTexCoords.Assign(TgxMeshObject(Source).FLightMapTexCoords);
  2630. FColors.Assign(TgxMeshObject(Source).FColors);
  2631. FFaceGroups.Assign(TgxMeshObject(Source).FFaceGroups);
  2632. FMode := TgxMeshObject(Source).FMode;
  2633. FRenderingOptions := TgxMeshObject(Source).FRenderingOptions;
  2634. FBinormalsTexCoordIndex := TgxMeshObject(Source).FBinormalsTexCoordIndex;
  2635. FTangentsTexCoordIndex := TgxMeshObject(Source).FTangentsTexCoordIndex;
  2636. // Clear FTexCoordsEx.
  2637. for i := 0 to FTexCoordsEx.Count - 1 do
  2638. TgxVectorList(FTexCoordsEx[i]).Free;
  2639. FTexCoordsEx.Count := TgxMeshObject(Source).FTexCoordsEx.Count;
  2640. // Fill FTexCoordsEx.
  2641. for i := 0 to FTexCoordsEx.Count - 1 do
  2642. begin
  2643. FTexCoordsEx[i] := TgxVectorList.Create;
  2644. TgxVectorList(FTexCoordsEx[i]).Assign(TgxMeshObject(Source).FTexCoordsEx[i]);
  2645. end;
  2646. end;
  2647. end;
  2648. procedure TgxMeshObject.WriteToFiler(writer: TgxVirtualWriter);
  2649. var
  2650. i: Integer;
  2651. begin
  2652. inherited WriteToFiler(writer);
  2653. with writer do
  2654. begin
  2655. WriteInteger(3); // Archive Version 3
  2656. FTexCoords.WriteToFiler(writer);
  2657. FLightMapTexCoords.WriteToFiler(writer);
  2658. FColors.WriteToFiler(writer);
  2659. FFaceGroups.WriteToFiler(writer);
  2660. WriteInteger(Integer(FMode));
  2661. WriteInteger(SizeOf(FRenderingOptions));
  2662. Write(FRenderingOptions, SizeOf(FRenderingOptions));
  2663. WriteInteger(FTexCoordsEx.Count);
  2664. for i := 0 to FTexCoordsEx.Count - 1 do
  2665. TexCoordsEx[i].WriteToFiler(writer);
  2666. WriteInteger(BinormalsTexCoordIndex);
  2667. WriteInteger(TangentsTexCoordIndex);
  2668. end;
  2669. end;
  2670. procedure TgxMeshObject.ReadFromFiler(reader: TgxVirtualReader);
  2671. var
  2672. i, Count, archiveVersion: Integer;
  2673. lOldLightMapTexCoords: TgxTexPointList;
  2674. tc: TTexPoint;
  2675. size, ro: Integer;
  2676. begin
  2677. inherited ReadFromFiler(reader);
  2678. archiveVersion := reader.ReadInteger;
  2679. if archiveVersion in [0 .. 3] then
  2680. with reader do
  2681. begin
  2682. FTexCoords.ReadFromFiler(reader);
  2683. if archiveVersion = 0 then
  2684. begin
  2685. // FLightMapTexCoords did not exist back than.
  2686. FLightMapTexCoords.Clear;
  2687. end
  2688. else if (archiveVersion = 1) or (archiveVersion = 2) then
  2689. begin
  2690. lOldLightMapTexCoords := TgxTexPointList.CreateFromFiler(reader);
  2691. for i := 0 to lOldLightMapTexCoords.Count - 1 do
  2692. begin
  2693. tc := lOldLightMapTexCoords[i];
  2694. FLightMapTexCoords.Add(tc.s, tc.t);
  2695. end;
  2696. lOldLightMapTexCoords.Free;
  2697. end
  2698. else
  2699. begin
  2700. // Load FLightMapTexCoords the normal way.
  2701. FLightMapTexCoords.ReadFromFiler(reader);
  2702. end;
  2703. FColors.ReadFromFiler(reader);
  2704. FFaceGroups.ReadFromFiler(reader);
  2705. FMode := TgxMeshObjectMode(ReadInteger);
  2706. size := ReadInteger;
  2707. ro := 0;
  2708. Read(ro, size);
  2709. FRenderingOptions := TgxMeshObjectRenderingOptions(Byte(ro));
  2710. if archiveVersion >= 2 then
  2711. begin
  2712. Count := ReadInteger;
  2713. for i := 0 to Count - 1 do
  2714. TexCoordsEx[i].ReadFromFiler(reader);
  2715. BinormalsTexCoordIndex := ReadInteger;
  2716. TangentsTexCoordIndex := ReadInteger;
  2717. end;
  2718. end
  2719. else
  2720. RaiseFilerException(archiveVersion);
  2721. end;
  2722. procedure TgxMeshObject.Clear;
  2723. var
  2724. i: Integer;
  2725. begin
  2726. inherited;
  2727. FFaceGroups.Clear;
  2728. FColors.Clear;
  2729. FTexCoords.Clear;
  2730. FLightMapTexCoords.Clear;
  2731. for i := 0 to FTexCoordsEx.Count - 1 do
  2732. TexCoordsEx[i].Clear;
  2733. end;
  2734. function TgxMeshObject.ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil)
  2735. : TgxAffineVectorList;
  2736. begin
  2737. case mode of
  2738. momTriangles:
  2739. begin
  2740. Result := inherited ExtractTriangles;
  2741. if Assigned(texCoords) then
  2742. texCoords.Assign(Self.texCoords);
  2743. if Assigned(normals) then
  2744. normals.Assign(Self.normals);
  2745. end;
  2746. momTriangleStrip:
  2747. begin
  2748. Result := TgxAffineVectorList.Create;
  2749. ConvertStripToList(Vertices, Result);
  2750. if Assigned(texCoords) then
  2751. ConvertStripToList(Self.texCoords, texCoords);
  2752. if Assigned(normals) then
  2753. ConvertStripToList(Self.normals, normals);
  2754. end;
  2755. momFaceGroups:
  2756. begin
  2757. Result := TgxAffineVectorList.Create;
  2758. FaceGroups.AddToTriangles(Result, texCoords, normals);
  2759. end;
  2760. else
  2761. Result := nil;
  2762. Assert(False);
  2763. end;
  2764. end;
  2765. function TgxMeshObject.TriangleCount: Integer;
  2766. var
  2767. i: Integer;
  2768. begin
  2769. case mode of
  2770. momTriangles:
  2771. Result := (Vertices.Count div 3);
  2772. momTriangleStrip:
  2773. begin
  2774. Result := Vertices.Count - 2;
  2775. if Result < 0 then
  2776. Result := 0;
  2777. end;
  2778. momFaceGroups:
  2779. begin
  2780. Result := 0;
  2781. for i := 0 to FaceGroups.Count - 1 do
  2782. Result := Result + FaceGroups[i].TriangleCount;
  2783. end;
  2784. else
  2785. Result := 0;
  2786. Assert(False);
  2787. end;
  2788. end;
  2789. procedure TgxMeshObject.PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  2790. begin
  2791. FaceGroups.PrepareMaterialLibraryCache(matLib);
  2792. end;
  2793. procedure TgxMeshObject.DropMaterialLibraryCache;
  2794. begin
  2795. FaceGroups.DropMaterialLibraryCache;
  2796. end;
  2797. procedure TgxMeshObject.GetExtents(out min, max: TAffineVector);
  2798. begin
  2799. if FVertices.Revision <> FExtentCacheRevision then
  2800. begin
  2801. FVertices.GetExtents(FExtentCache.min, FExtentCache.max);
  2802. FExtentCacheRevision := FVertices.Revision;
  2803. end;
  2804. min := FExtentCache.min;
  2805. max := FExtentCache.max;
  2806. end;
  2807. procedure TgxMeshObject.GetExtents(out aabb: TAABB);
  2808. begin
  2809. if FVertices.Revision <> FExtentCacheRevision then
  2810. begin
  2811. FVertices.GetExtents(FExtentCache.min, FExtentCache.max);
  2812. FExtentCacheRevision := FVertices.Revision;
  2813. end;
  2814. aabb := FExtentCache;
  2815. end;
  2816. function TgxMeshObject.GetBarycenter: TVector4f;
  2817. var
  2818. dMin, dMax: TAffineVector;
  2819. begin
  2820. GetExtents(dMin, dMax);
  2821. Result.X := (dMin.X + dMax.X) / 2;
  2822. Result.Y := (dMin.Y + dMax.Y) / 2;
  2823. Result.Z := (dMin.Z + dMax.Z) / 2;
  2824. Result.W := 0;
  2825. end;
  2826. procedure TgxMeshObject.Prepare;
  2827. var
  2828. i: Integer;
  2829. begin
  2830. ValidBuffers := [];
  2831. for i := 0 to FaceGroups.Count - 1 do
  2832. FaceGroups[i].Prepare;
  2833. end;
  2834. function TgxMeshObject.PointInObject(const aPoint: TAffineVector): Boolean;
  2835. var
  2836. min, max: TAffineVector;
  2837. begin
  2838. GetExtents(min, max);
  2839. Result := (aPoint.X >= min.X) and (aPoint.Y >= min.Y) and (aPoint.Z >= min.Z) and (aPoint.X <= max.X) and (aPoint.Y <= max.Y)
  2840. and (aPoint.Z <= max.Z);
  2841. end;
  2842. procedure TgxMeshObject.SetTexCoords(const val: TgxAffineVectorList);
  2843. begin
  2844. FTexCoords.Assign(val);
  2845. end;
  2846. procedure TgxMeshObject.SetLightmapTexCoords(const val: TgxAffineVectorList);
  2847. begin
  2848. FLightMapTexCoords.Assign(val);
  2849. end;
  2850. procedure TgxMeshObject.SetColors(const val: TgxVectorList);
  2851. begin
  2852. FColors.Assign(val);
  2853. end;
  2854. procedure TgxMeshObject.SetTexCoordsEx(Index: Integer; const val: TgxVectorList);
  2855. begin
  2856. TexCoordsEx[index].Assign(val);
  2857. end;
  2858. function TgxMeshObject.GetTexCoordsEx(Index: Integer): TgxVectorList;
  2859. var
  2860. i: Integer;
  2861. begin
  2862. if index > FTexCoordsEx.Count - 1 then
  2863. for i := FTexCoordsEx.Count - 1 to index do
  2864. FTexCoordsEx.Add(TgxVectorList.Create);
  2865. Result := TgxVectorList(FTexCoordsEx[index]);
  2866. end;
  2867. procedure TgxMeshObject.SetBinormals(const val: TgxVectorList);
  2868. begin
  2869. Binormals.Assign(val);
  2870. end;
  2871. function TgxMeshObject.GetBinormals: TgxVectorList;
  2872. begin
  2873. Result := TexCoordsEx[BinormalsTexCoordIndex];
  2874. end;
  2875. procedure TgxMeshObject.SetBinormalsTexCoordIndex(const val: Integer);
  2876. begin
  2877. Assert(val >= 0);
  2878. if val <> FBinormalsTexCoordIndex then
  2879. begin
  2880. FBinormalsTexCoordIndex := val;
  2881. end;
  2882. end;
  2883. procedure TgxMeshObject.SetTangents(const val: TgxVectorList);
  2884. begin
  2885. Tangents.Assign(val);
  2886. end;
  2887. function TgxMeshObject.GetTangents: TgxVectorList;
  2888. begin
  2889. Result := TexCoordsEx[TangentsTexCoordIndex];
  2890. end;
  2891. procedure TgxMeshObject.SetTangentsTexCoordIndex(const val: Integer);
  2892. begin
  2893. Assert(val >= 0);
  2894. if val <> FTangentsTexCoordIndex then
  2895. begin
  2896. FTangentsTexCoordIndex := val;
  2897. end;
  2898. end;
  2899. procedure TgxMeshObject.GetTriangleData(tri: Integer; list: TgxAffineVectorList; var v0, v1, v2: TAffineVector);
  2900. var
  2901. i, LastCount, Count: Integer;
  2902. fg: TgxFGVertexIndexList;
  2903. begin
  2904. case mode of
  2905. momTriangles:
  2906. begin
  2907. v0 := list[3 * tri];
  2908. v1 := list[3 * tri + 1];
  2909. v2 := list[3 * tri + 2];
  2910. end;
  2911. momTriangleStrip:
  2912. begin
  2913. v0 := list[tri];
  2914. v1 := list[tri + 1];
  2915. v2 := list[tri + 2];
  2916. end;
  2917. momFaceGroups:
  2918. begin
  2919. Count := 0;
  2920. for i := 0 to FaceGroups.Count - 1 do
  2921. begin
  2922. LastCount := Count;
  2923. fg := TgxFGVertexIndexList(FaceGroups[i]);
  2924. Count := Count + fg.TriangleCount;
  2925. if Count > tri then
  2926. begin
  2927. Count := tri - LastCount;
  2928. case fg.mode of
  2929. fgmmTriangles, fgmmFlatTriangles:
  2930. begin
  2931. v0 := list[fg.vertexIndices[3 * Count]];
  2932. v1 := list[fg.vertexIndices[3 * Count + 1]];
  2933. v2 := list[fg.vertexIndices[3 * Count + 2]];
  2934. end;
  2935. fgmmTriangleStrip:
  2936. begin
  2937. v0 := list[fg.vertexIndices[Count]];
  2938. v1 := list[fg.vertexIndices[Count + 1]];
  2939. v2 := list[fg.vertexIndices[Count + 2]];
  2940. end;
  2941. fgmmTriangleFan:
  2942. begin
  2943. v0 := list[fg.vertexIndices[0]];
  2944. v1 := list[fg.vertexIndices[Count + 1]];
  2945. v2 := list[fg.vertexIndices[Count + 2]];
  2946. end;
  2947. fgmmQuads:
  2948. begin
  2949. if Count mod 2 = 0 then
  2950. begin
  2951. v0 := list[fg.vertexIndices[4 * (Count div 2)]];
  2952. v1 := list[fg.vertexIndices[4 * (Count div 2) + 1]];
  2953. v2 := list[fg.vertexIndices[4 * (Count div 2) + 2]];
  2954. end
  2955. else
  2956. begin
  2957. v0 := list[fg.vertexIndices[4 * (Count div 2)]];
  2958. v1 := list[fg.vertexIndices[4 * (Count div 2) + 2]];
  2959. v2 := list[fg.vertexIndices[4 * (Count div 2) + 3]];
  2960. end;
  2961. end;
  2962. else
  2963. Assert(False);
  2964. end;
  2965. Break;
  2966. end;
  2967. end;
  2968. end;
  2969. else
  2970. Assert(False);
  2971. end;
  2972. end;
  2973. procedure TgxMeshObject.GetTriangleData(tri: Integer; list: TgxVectorList; var v0, v1, v2: TVector4f);
  2974. var
  2975. i, LastCount, Count: Integer;
  2976. fg: TgxFGVertexIndexList;
  2977. begin
  2978. case mode of
  2979. momTriangles:
  2980. begin
  2981. v0 := list[3 * tri];
  2982. v1 := list[3 * tri + 1];
  2983. v2 := list[3 * tri + 2];
  2984. end;
  2985. momTriangleStrip:
  2986. begin
  2987. v0 := list[tri];
  2988. v1 := list[tri + 1];
  2989. v2 := list[tri + 2];
  2990. end;
  2991. momFaceGroups:
  2992. begin
  2993. Count := 0;
  2994. for i := 0 to FaceGroups.Count - 1 do
  2995. begin
  2996. LastCount := Count;
  2997. fg := TgxFGVertexIndexList(FaceGroups[i]);
  2998. Count := Count + fg.TriangleCount;
  2999. if Count > tri then
  3000. begin
  3001. Count := tri - LastCount;
  3002. case fg.mode of
  3003. fgmmTriangles, fgmmFlatTriangles:
  3004. begin
  3005. v0 := list[fg.vertexIndices[3 * Count]];
  3006. v1 := list[fg.vertexIndices[3 * Count + 1]];
  3007. v2 := list[fg.vertexIndices[3 * Count + 2]];
  3008. end;
  3009. fgmmTriangleStrip:
  3010. begin
  3011. v0 := list[fg.vertexIndices[Count]];
  3012. v1 := list[fg.vertexIndices[Count + 1]];
  3013. v2 := list[fg.vertexIndices[Count + 2]];
  3014. end;
  3015. fgmmTriangleFan:
  3016. begin
  3017. v0 := list[fg.vertexIndices[0]];
  3018. v1 := list[fg.vertexIndices[Count + 1]];
  3019. v2 := list[fg.vertexIndices[Count + 2]];
  3020. end;
  3021. fgmmQuads:
  3022. begin
  3023. if Count mod 2 = 0 then
  3024. begin
  3025. v0 := list[fg.vertexIndices[4 * (Count div 2)]];
  3026. v1 := list[fg.vertexIndices[4 * (Count div 2) + 1]];
  3027. v2 := list[fg.vertexIndices[4 * (Count div 2) + 2]];
  3028. end
  3029. else
  3030. begin
  3031. v0 := list[fg.vertexIndices[4 * (Count div 2)]];
  3032. v1 := list[fg.vertexIndices[4 * (Count div 2) + 2]];
  3033. v2 := list[fg.vertexIndices[4 * (Count div 2) + 3]];
  3034. end;
  3035. end;
  3036. else
  3037. Assert(False);
  3038. end;
  3039. Break;
  3040. end;
  3041. end;
  3042. end;
  3043. else
  3044. Assert(False);
  3045. end;
  3046. end;
  3047. procedure TgxMeshObject.SetTriangleData(tri: Integer; list: TgxAffineVectorList; const v0, v1, v2: TAffineVector);
  3048. var
  3049. i, LastCount, Count: Integer;
  3050. fg: TgxFGVertexIndexList;
  3051. begin
  3052. case mode of
  3053. momTriangles:
  3054. begin
  3055. list[3 * tri] := v0;
  3056. list[3 * tri + 1] := v1;
  3057. list[3 * tri + 2] := v2;
  3058. end;
  3059. momTriangleStrip:
  3060. begin
  3061. list[tri] := v0;
  3062. list[tri + 1] := v1;
  3063. list[tri + 2] := v2;
  3064. end;
  3065. momFaceGroups:
  3066. begin
  3067. Count := 0;
  3068. for i := 0 to FaceGroups.Count - 1 do
  3069. begin
  3070. LastCount := Count;
  3071. fg := TgxFGVertexIndexList(FaceGroups[i]);
  3072. Count := Count + fg.TriangleCount;
  3073. if Count > tri then
  3074. begin
  3075. Count := tri - LastCount;
  3076. case fg.mode of
  3077. fgmmTriangles, fgmmFlatTriangles:
  3078. begin
  3079. list[fg.vertexIndices[3 * Count]] := v0;
  3080. list[fg.vertexIndices[3 * Count + 1]] := v1;
  3081. list[fg.vertexIndices[3 * Count + 2]] := v2;
  3082. end;
  3083. fgmmTriangleStrip:
  3084. begin
  3085. list[fg.vertexIndices[Count]] := v0;
  3086. list[fg.vertexIndices[Count + 1]] := v1;
  3087. list[fg.vertexIndices[Count + 2]] := v2;
  3088. end;
  3089. fgmmTriangleFan:
  3090. begin
  3091. list[fg.vertexIndices[0]] := v0;
  3092. list[fg.vertexIndices[Count + 1]] := v1;
  3093. list[fg.vertexIndices[Count + 2]] := v2;
  3094. end;
  3095. fgmmQuads:
  3096. begin
  3097. if Count mod 2 = 0 then
  3098. begin
  3099. list[fg.vertexIndices[4 * (Count div 2)]] := v0;
  3100. list[fg.vertexIndices[4 * (Count div 2) + 1]] := v1;
  3101. list[fg.vertexIndices[4 * (Count div 2) + 2]] := v2;
  3102. end
  3103. else
  3104. begin
  3105. list[fg.vertexIndices[4 * (Count div 2)]] := v0;
  3106. list[fg.vertexIndices[4 * (Count div 2) + 2]] := v1;
  3107. list[fg.vertexIndices[4 * (Count div 2) + 3]] := v2;
  3108. end;
  3109. end;
  3110. else
  3111. Assert(False);
  3112. end;
  3113. Break;
  3114. end;
  3115. end;
  3116. end;
  3117. else
  3118. Assert(False);
  3119. end;
  3120. end;
  3121. procedure TgxMeshObject.SetTriangleData(tri: Integer; list: TgxVectorList; const v0, v1, v2: TVector4f);
  3122. var
  3123. i, LastCount, Count: Integer;
  3124. fg: TgxFGVertexIndexList;
  3125. begin
  3126. case mode of
  3127. momTriangles:
  3128. begin
  3129. list[3 * tri] := v0;
  3130. list[3 * tri + 1] := v1;
  3131. list[3 * tri + 2] := v2;
  3132. end;
  3133. momTriangleStrip:
  3134. begin
  3135. list[tri] := v0;
  3136. list[tri + 1] := v1;
  3137. list[tri + 2] := v2;
  3138. end;
  3139. momFaceGroups:
  3140. begin
  3141. Count := 0;
  3142. for i := 0 to FaceGroups.Count - 1 do
  3143. begin
  3144. LastCount := Count;
  3145. fg := TgxFGVertexIndexList(FaceGroups[i]);
  3146. Count := Count + fg.TriangleCount;
  3147. if Count > tri then
  3148. begin
  3149. Count := tri - LastCount;
  3150. case fg.mode of
  3151. fgmmTriangles, fgmmFlatTriangles:
  3152. begin
  3153. list[fg.vertexIndices[3 * Count]] := v0;
  3154. list[fg.vertexIndices[3 * Count + 1]] := v1;
  3155. list[fg.vertexIndices[3 * Count + 2]] := v2;
  3156. end;
  3157. fgmmTriangleStrip:
  3158. begin
  3159. list[fg.vertexIndices[Count]] := v0;
  3160. list[fg.vertexIndices[Count + 1]] := v1;
  3161. list[fg.vertexIndices[Count + 2]] := v2;
  3162. end;
  3163. fgmmTriangleFan:
  3164. begin
  3165. list[fg.vertexIndices[0]] := v0;
  3166. list[fg.vertexIndices[Count + 1]] := v1;
  3167. list[fg.vertexIndices[Count + 2]] := v2;
  3168. end;
  3169. fgmmQuads:
  3170. begin
  3171. if Count mod 2 = 0 then
  3172. begin
  3173. list[fg.vertexIndices[4 * (Count div 2)]] := v0;
  3174. list[fg.vertexIndices[4 * (Count div 2) + 1]] := v1;
  3175. list[fg.vertexIndices[4 * (Count div 2) + 2]] := v2;
  3176. end
  3177. else
  3178. begin
  3179. list[fg.vertexIndices[4 * (Count div 2)]] := v0;
  3180. list[fg.vertexIndices[4 * (Count div 2) + 2]] := v1;
  3181. list[fg.vertexIndices[4 * (Count div 2) + 3]] := v2;
  3182. end;
  3183. end;
  3184. else
  3185. Assert(False);
  3186. end;
  3187. Break;
  3188. end;
  3189. end;
  3190. end;
  3191. else
  3192. Assert(False);
  3193. end;
  3194. end;
  3195. procedure TgxMeshObject.SetUseVBO(const Value: Boolean);
  3196. var
  3197. i: Integer;
  3198. begin
  3199. if Value = FUseVBO then
  3200. Exit;
  3201. if FUseVBO then
  3202. begin
  3203. FreeAndNil(FVerticesVBO);
  3204. FreeAndNil(FNormalsVBO);
  3205. FreeAndNil(FColorsVBO);
  3206. for i := 0 to high(FTexCoordsVBO) do
  3207. FreeAndNil(FTexCoordsVBO[i]);
  3208. FreeAndNil(FLightmapTexCoordsVBO);
  3209. end;
  3210. FValidBuffers := [];
  3211. FUseVBO := Value;
  3212. end;
  3213. procedure TgxMeshObject.SetValidBuffers(Value: TVBOBuffers);
  3214. var
  3215. i: Integer;
  3216. begin
  3217. if FValidBuffers <> Value then
  3218. begin
  3219. FValidBuffers := Value;
  3220. if Assigned(FVerticesVBO) then
  3221. FVerticesVBO.NotifyChangesOfData;
  3222. if Assigned(FNormalsVBO) then
  3223. FNormalsVBO.NotifyChangesOfData;
  3224. if Assigned(FColorsVBO) then
  3225. FColorsVBO.NotifyChangesOfData;
  3226. for i := 0 to high(FTexCoordsVBO) do
  3227. if Assigned(FTexCoordsVBO[i]) then
  3228. FTexCoordsVBO[i].NotifyChangesOfData;
  3229. if Assigned(FLightmapTexCoordsVBO) then
  3230. FLightmapTexCoordsVBO.NotifyChangesOfData;
  3231. end;
  3232. end;
  3233. procedure TgxMeshObject.BuildTangentSpace(buildBinormals: Boolean = True; buildTangents: Boolean = True);
  3234. var
  3235. i, j: Integer;
  3236. v, n, t: array [0 .. 2] of TAffineVector;
  3237. tangent, binormal: array [0 .. 2] of TVector4f;
  3238. vt, tt: TAffineVector;
  3239. interp, dot: Single;
  3240. procedure SortVertexData(sortidx: Integer);
  3241. begin
  3242. if t[0].v[sortidx] < t[1].v[sortidx] then
  3243. begin
  3244. vt := v[0];
  3245. tt := t[0];
  3246. v[0] := v[1];
  3247. t[0] := t[1];
  3248. v[1] := vt;
  3249. t[1] := tt;
  3250. end;
  3251. if t[0].v[sortidx] < t[2].v[sortidx] then
  3252. begin
  3253. vt := v[0];
  3254. tt := t[0];
  3255. v[0] := v[2];
  3256. t[0] := t[2];
  3257. v[2] := vt;
  3258. t[2] := tt;
  3259. end;
  3260. if t[1].v[sortidx] < t[2].v[sortidx] then
  3261. begin
  3262. vt := v[1];
  3263. tt := t[1];
  3264. v[1] := v[2];
  3265. t[1] := t[2];
  3266. v[2] := vt;
  3267. t[2] := tt;
  3268. end;
  3269. end;
  3270. begin
  3271. Tangents.Clear;
  3272. Binormals.Clear;
  3273. if buildTangents then
  3274. Tangents.Count := Vertices.Count;
  3275. if buildBinormals then
  3276. Binormals.Count := Vertices.Count;
  3277. for i := 0 to TriangleCount - 1 do
  3278. begin
  3279. // Get triangle data
  3280. GetTriangleData(i, Vertices, v[0], v[1], v[2]);
  3281. GetTriangleData(i, normals, n[0], n[1], n[2]);
  3282. GetTriangleData(i, texCoords, t[0], t[1], t[2]);
  3283. for j := 0 to 2 do
  3284. begin
  3285. // Compute tangent
  3286. if buildTangents then
  3287. begin
  3288. SortVertexData(1);
  3289. if (t[2].Y - t[0].Y) = 0 then
  3290. interp := 1
  3291. else
  3292. interp := (t[1].Y - t[0].Y) / (t[2].Y - t[0].Y);
  3293. vt := VectorLerp(v[0], v[2], interp);
  3294. interp := t[0].X + (t[2].X - t[0].X) * interp;
  3295. vt := VectorSubtract(vt, v[1]);
  3296. if t[1].X < interp then
  3297. vt := VectorNegate(vt);
  3298. dot := VectorDotProduct(vt, n[j]);
  3299. vt.X := vt.X - n[j].X * dot;
  3300. vt.Y := vt.Y - n[j].Y * dot;
  3301. vt.Z := vt.Z - n[j].Z * dot;
  3302. tangent[j] := VectorMake(VectorNormalize(vt), 0);
  3303. end;
  3304. // Compute Bi-Normal
  3305. if buildBinormals then
  3306. begin
  3307. SortVertexData(0);
  3308. if (t[2].X - t[0].X) = 0 then
  3309. interp := 1
  3310. else
  3311. interp := (t[1].X - t[0].X) / (t[2].X - t[0].X);
  3312. vt := VectorLerp(v[0], v[2], interp);
  3313. interp := t[0].Y + (t[2].Y - t[0].Y) * interp;
  3314. vt := VectorSubtract(vt, v[1]);
  3315. if t[1].Y < interp then
  3316. vt := VectorNegate(vt);
  3317. dot := VectorDotProduct(vt, n[j]);
  3318. vt.X := vt.X - n[j].X * dot;
  3319. vt.Y := vt.Y - n[j].Y * dot;
  3320. vt.Z := vt.Z - n[j].Z * dot;
  3321. binormal[j] := VectorMake(VectorNormalize(vt), 0);
  3322. end;
  3323. end;
  3324. if buildTangents then
  3325. SetTriangleData(i, Tangents, tangent[0], tangent[1], tangent[2]);
  3326. if buildBinormals then
  3327. SetTriangleData(i, Binormals, binormal[0], binormal[1], binormal[2]);
  3328. end;
  3329. end;
  3330. procedure TgxMeshObject.DeclareArraysToOpenGL(var mrci: TgxRenderContextInfo; evenIfAlreadyDeclared: Boolean = False);
  3331. var
  3332. i: Integer;
  3333. currentMapping: Cardinal;
  3334. lists: array [0 .. 4] of pointer;
  3335. tlists: array of pointer;
  3336. begin
  3337. if evenIfAlreadyDeclared or (not FArraysDeclared) then
  3338. begin
  3339. FillChar(lists, SizeOf(lists), 0);
  3340. SetLength(tlists, FTexCoordsEx.Count);
  3341. // workaround for ATI bug, disable element VBO if
  3342. // inside a display list
  3343. FUseVBO := FUseVBO and not mrci.gxStates.InsideList;
  3344. /// and GL_ARB_vertex_buffer_object
  3345. if not FUseVBO then
  3346. begin
  3347. lists[0] := Vertices.list;
  3348. lists[1] := normals.list;
  3349. lists[2] := Colors.list;
  3350. lists[3] := texCoords.list;
  3351. lists[4] := LightMapTexCoords.list;
  3352. for i := 0 to FTexCoordsEx.Count - 1 do
  3353. tlists[i] := TexCoordsEx[i].list;
  3354. end
  3355. else
  3356. begin
  3357. BufferArrays;
  3358. end;
  3359. if not mrci.ignoreMaterials then
  3360. begin
  3361. if normals.Count > 0 then
  3362. begin
  3363. if FUseVBO then
  3364. FNormalsVBO.Bind;
  3365. glEnableClientState(GL_NORMAL_ARRAY);
  3366. glNormalPointer(GL_FLOAT, 0, lists[1]);
  3367. end
  3368. else
  3369. glDisableClientState(GL_NORMAL_ARRAY);
  3370. if (Colors.Count > 0) and (not mrci.ignoreMaterials) then
  3371. begin
  3372. if FUseVBO then
  3373. FColorsVBO.Bind;
  3374. glEnableClientState(GL_COLOR_ARRAY);
  3375. glColorPointer(4, GL_FLOAT, 0, lists[2]);
  3376. end
  3377. else
  3378. glDisableClientState(GL_COLOR_ARRAY);
  3379. if texCoords.Count > 0 then
  3380. begin
  3381. if FUseVBO then
  3382. FTexCoordsVBO[0].Bind;
  3383. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  3384. glTexCoordPointer(2, GL_FLOAT, SizeOf(TAffineVector), lists[3]);
  3385. end
  3386. else
  3387. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3388. /// if GL_ARB_multitexture then
  3389. begin
  3390. if LightMapTexCoords.Count > 0 then
  3391. begin
  3392. if FUseVBO then
  3393. FLightmapTexCoordsVBO.Bind;
  3394. glClientActiveTexture(GL_TEXTURE1);
  3395. glTexCoordPointer(2, GL_FLOAT, SizeOf(TAffineVector), lists[4]);
  3396. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  3397. end;
  3398. for i := 0 to FTexCoordsEx.Count - 1 do
  3399. begin
  3400. if TexCoordsEx[i].Count > 0 then
  3401. begin
  3402. if FUseVBO then
  3403. FTexCoordsVBO[i].Bind;
  3404. glClientActiveTexture(GL_TEXTURE0 + i);
  3405. glTexCoordPointer(4, GL_FLOAT, SizeOf(TVector4f), tlists[i]);
  3406. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  3407. end;
  3408. end;
  3409. glClientActiveTexture(GL_TEXTURE0);
  3410. end;
  3411. end
  3412. else
  3413. begin
  3414. glDisableClientState(GL_NORMAL_ARRAY);
  3415. glDisableClientState(GL_COLOR_ARRAY);
  3416. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3417. end;
  3418. if Vertices.Count > 0 then
  3419. begin
  3420. if FUseVBO then
  3421. FVerticesVBO.Bind;
  3422. glEnableClientState(GL_VERTEX_ARRAY);
  3423. glVertexPointer(3, GL_FLOAT, 0, lists[0]);
  3424. end
  3425. else
  3426. glDisableClientState(GL_VERTEX_ARRAY);
  3427. if (LightMapTexCoords.Count = 0) and not FUseVBO then
  3428. /// and GL_EXT_compiled_vertex_array
  3429. glLockArraysEXT(0, Vertices.Count);
  3430. FLastLightMapIndex := -1;
  3431. FArraysDeclared := True;
  3432. FLightMapArrayEnabled := False;
  3433. if mrci.drawState <> dsPicking then
  3434. FLastXOpenGLTexMapping := xglGetBitWiseMapping;
  3435. end
  3436. else
  3437. begin
  3438. if not mrci.ignoreMaterials and not(mrci.drawState = dsPicking) then
  3439. if texCoords.Count > 0 then
  3440. begin
  3441. currentMapping := xglGetBitWiseMapping;
  3442. if FLastXOpenGLTexMapping <> currentMapping then
  3443. begin
  3444. xglEnableClientState(GL_TEXTURE_COORD_ARRAY);
  3445. xglTexCoordPointer(2, GL_FLOAT, SizeOf(TAffineVector), texCoords.list);
  3446. FLastXOpenGLTexMapping := currentMapping;
  3447. end;
  3448. end;
  3449. end;
  3450. end;
  3451. procedure TgxMeshObject.DisableOpenGLArrays(var mrci: TgxRenderContextInfo);
  3452. var
  3453. i: Integer;
  3454. begin
  3455. if FArraysDeclared then
  3456. begin
  3457. DisableLightMapArray(mrci);
  3458. if (LightMapTexCoords.Count = 0) and not FUseVBO then
  3459. /// and GL_EXT_compiled_vertex_array
  3460. glUnlockArraysEXT;
  3461. if Vertices.Count > 0 then
  3462. glDisableClientState(GL_VERTEX_ARRAY);
  3463. if not mrci.ignoreMaterials then
  3464. begin
  3465. if normals.Count > 0 then
  3466. glDisableClientState(GL_NORMAL_ARRAY);
  3467. if (Colors.Count > 0) and (not mrci.ignoreMaterials) then
  3468. glDisableClientState(GL_COLOR_ARRAY);
  3469. if texCoords.Count > 0 then
  3470. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3471. /// if GL_ARB_multitexture then
  3472. begin
  3473. if LightMapTexCoords.Count > 0 then
  3474. begin
  3475. glClientActiveTexture(GL_TEXTURE1);
  3476. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3477. end;
  3478. for i := 0 to FTexCoordsEx.Count - 1 do
  3479. begin
  3480. if TexCoordsEx[i].Count > 0 then
  3481. begin
  3482. glClientActiveTexture(GL_TEXTURE0 + i);
  3483. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3484. end;
  3485. end;
  3486. glClientActiveTexture(GL_TEXTURE0);
  3487. end;
  3488. end;
  3489. if FUseVBO then
  3490. begin
  3491. if Vertices.Count > 0 then
  3492. FVerticesVBO.UnBind;
  3493. if normals.Count > 0 then
  3494. FNormalsVBO.UnBind;
  3495. if Colors.Count > 0 then
  3496. FColorsVBO.UnBind;
  3497. if texCoords.Count > 0 then
  3498. FTexCoordsVBO[0].UnBind;
  3499. if LightMapTexCoords.Count > 0 then
  3500. FLightmapTexCoordsVBO.UnBind;
  3501. if FTexCoordsEx.Count > 0 then
  3502. begin
  3503. for i := 0 to FTexCoordsEx.Count - 1 do
  3504. begin
  3505. if TexCoordsEx[i].Count > 0 then
  3506. FTexCoordsVBO[i].UnBind;
  3507. end;
  3508. end;
  3509. end;
  3510. FArraysDeclared := False;
  3511. end;
  3512. end;
  3513. procedure TgxMeshObject.EnableLightMapArray(var mrci: TgxRenderContextInfo);
  3514. begin
  3515. if (not mrci.ignoreMaterials) then
  3516. /// and GL_ARB_multitexture
  3517. begin
  3518. Assert(FArraysDeclared);
  3519. if not FLightMapArrayEnabled then
  3520. begin
  3521. mrci.gxStates.ActiveTexture := 1;
  3522. mrci.gxStates.ActiveTextureEnabled[ttTexture2D] := True;
  3523. mrci.gxStates.ActiveTexture := 0;
  3524. FLightMapArrayEnabled := True;
  3525. end;
  3526. end;
  3527. end;
  3528. procedure TgxMeshObject.DisableLightMapArray(var mrci: TgxRenderContextInfo);
  3529. begin
  3530. if FLightMapArrayEnabled then
  3531. /// and GL_ARB_multitexture
  3532. begin
  3533. mrci.gxStates.ActiveTexture := 1;
  3534. mrci.gxStates.ActiveTextureEnabled[ttTexture2D] := False;
  3535. mrci.gxStates.ActiveTexture := 0;
  3536. FLightMapArrayEnabled := False;
  3537. end;
  3538. end;
  3539. procedure TgxMeshObject.PrepareBuildList(var mrci: TgxRenderContextInfo);
  3540. var
  3541. i: Integer;
  3542. begin
  3543. if (mode = momFaceGroups) and Assigned(mrci.MaterialLibrary) then
  3544. begin
  3545. for i := 0 to FaceGroups.Count - 1 do
  3546. with TgxFaceGroup(FaceGroups.list^[i]) do
  3547. begin
  3548. if MaterialCache <> nil then
  3549. MaterialCache.PrepareBuildList;
  3550. end;
  3551. end;
  3552. end;
  3553. procedure TgxMeshObject.BufferArrays;
  3554. const
  3555. BufferUsage = GL_DYNAMIC_DRAW;
  3556. var
  3557. i: Integer;
  3558. begin
  3559. if Vertices.Count > 0 then
  3560. begin
  3561. if not Assigned(FVerticesVBO) then
  3562. FVerticesVBO := TgxVBOArrayBufferHandle.Create;
  3563. FVerticesVBO.AllocateHandle;
  3564. if FVerticesVBO.IsDataNeedUpdate then
  3565. begin
  3566. FVerticesVBO.BindBufferData(Vertices.list, SizeOf(TAffineVector) * Vertices.Count, BufferUsage);
  3567. FVerticesVBO.NotifyDataUpdated;
  3568. FVerticesVBO.UnBind;
  3569. end;
  3570. Include(FValidBuffers, vbVertices);
  3571. end;
  3572. if normals.Count > 0 then
  3573. begin
  3574. if not Assigned(FNormalsVBO) then
  3575. FNormalsVBO := TgxVBOArrayBufferHandle.Create;
  3576. FNormalsVBO.AllocateHandle;
  3577. if FNormalsVBO.IsDataNeedUpdate then
  3578. begin
  3579. FNormalsVBO.BindBufferData(normals.list, SizeOf(TAffineVector) * normals.Count, BufferUsage);
  3580. FNormalsVBO.NotifyDataUpdated;
  3581. FNormalsVBO.UnBind;
  3582. end;
  3583. Include(FValidBuffers, vbNormals);
  3584. end;
  3585. if Colors.Count > 0 then
  3586. begin
  3587. if not Assigned(FColorsVBO) then
  3588. FColorsVBO := TgxVBOArrayBufferHandle.Create;
  3589. FColorsVBO.AllocateHandle;
  3590. if FColorsVBO.IsDataNeedUpdate then
  3591. begin
  3592. FColorsVBO.BindBufferData(Colors.list, SizeOf(TVector4f) * Colors.Count, BufferUsage);
  3593. FColorsVBO.NotifyDataUpdated;
  3594. FColorsVBO.UnBind;
  3595. end;
  3596. Include(FValidBuffers, vbColors);
  3597. end;
  3598. if texCoords.Count > 0 then
  3599. begin
  3600. if Length(FTexCoordsVBO) < 1 then
  3601. SetLength(FTexCoordsVBO, 1);
  3602. if not Assigned(FTexCoordsVBO[0]) then
  3603. FTexCoordsVBO[0] := TgxVBOArrayBufferHandle.Create;
  3604. FTexCoordsVBO[0].AllocateHandle;
  3605. if FTexCoordsVBO[0].IsDataNeedUpdate then
  3606. begin
  3607. FTexCoordsVBO[0].BindBufferData(texCoords.list, SizeOf(TAffineVector) * texCoords.Count, BufferUsage);
  3608. FTexCoordsVBO[0].NotifyDataUpdated;
  3609. FTexCoordsVBO[0].UnBind;
  3610. end;
  3611. Include(FValidBuffers, vbTexCoords);
  3612. end;
  3613. if LightMapTexCoords.Count > 0 then
  3614. begin
  3615. if not Assigned(FLightmapTexCoordsVBO) then
  3616. FLightmapTexCoordsVBO := TgxVBOArrayBufferHandle.Create;
  3617. FLightmapTexCoordsVBO.AllocateHandle;
  3618. FLightmapTexCoordsVBO.BindBufferData(LightMapTexCoords.list, SizeOf(TAffineVector) * LightMapTexCoords.Count, BufferUsage);
  3619. FLightmapTexCoordsVBO.NotifyDataUpdated;
  3620. FLightmapTexCoordsVBO.UnBind;
  3621. Include(FValidBuffers, vbLightMapTexCoords);
  3622. end;
  3623. if FTexCoordsEx.Count > 0 then
  3624. begin
  3625. if Length(FTexCoordsVBO) < FTexCoordsEx.Count then
  3626. SetLength(FTexCoordsVBO, FTexCoordsEx.Count);
  3627. for i := 0 to FTexCoordsEx.Count - 1 do
  3628. begin
  3629. if TexCoordsEx[i].Count <= 0 then
  3630. continue;
  3631. if not Assigned(FTexCoordsVBO[i]) then
  3632. FTexCoordsVBO[i] := TgxVBOArrayBufferHandle.Create;
  3633. FTexCoordsVBO[i].AllocateHandle;
  3634. if FTexCoordsVBO[i].IsDataNeedUpdate then
  3635. begin
  3636. FTexCoordsVBO[i].BindBufferData(TexCoordsEx[i].list, SizeOf(TVector4f) * TexCoordsEx[i].Count, BufferUsage);
  3637. FTexCoordsVBO[i].NotifyDataUpdated;
  3638. FTexCoordsVBO[i].UnBind;
  3639. end;
  3640. end;
  3641. Include(FValidBuffers, vbTexCoordsEx);
  3642. end;
  3643. /// CheckOpenGLError;
  3644. end;
  3645. procedure TgxMeshObject.BuildList(var mrci: TgxRenderContextInfo);
  3646. var
  3647. i, j, groupID, nbGroups: Integer;
  3648. gotNormals, gotTexCoords, gotColor: Boolean;
  3649. gotTexCoordsEx: array of Boolean;
  3650. libMat: TgxLibMaterial;
  3651. fg: TgxFaceGroup;
  3652. begin
  3653. // Make sure no VBO is bound and states enabled
  3654. FArraysDeclared := False;
  3655. FLastXOpenGLTexMapping := 0;
  3656. gotColor := (Vertices.Count = Colors.Count);
  3657. if gotColor then
  3658. begin
  3659. mrci.gxStates.Enable(stColorMaterial);
  3660. glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
  3661. mrci.gxStates.SetMaterialColors(cmFront, clrBlack, clrGray20, clrGray80, clrBlack, 0);
  3662. mrci.gxStates.SetMaterialColors(cmBack, clrBlack, clrGray20, clrGray80, clrBlack, 0);
  3663. end;
  3664. case mode of
  3665. momTriangles, momTriangleStrip:
  3666. if Vertices.Count > 0 then
  3667. begin
  3668. DeclareArraysToOpenGL(mrci);
  3669. gotNormals := (Vertices.Count = normals.Count);
  3670. gotTexCoords := (Vertices.Count = texCoords.Count);
  3671. SetLength(gotTexCoordsEx, FTexCoordsEx.Count);
  3672. for i := 0 to FTexCoordsEx.Count - 1 do
  3673. gotTexCoordsEx[i] := (TexCoordsEx[i].Count > 0);
  3674. /// and GL_ARB_multitexture;
  3675. if mode = momTriangles then
  3676. glBegin(GL_TRIANGLES)
  3677. else
  3678. glBegin(GL_TRIANGLE_STRIP);
  3679. for i := 0 to Vertices.Count - 1 do
  3680. begin
  3681. if gotNormals then
  3682. glNormal3fv(@normals.list[i]);
  3683. if gotColor then
  3684. glColor4fv(@Colors.list[i]);
  3685. if FTexCoordsEx.Count > 0 then
  3686. begin
  3687. if gotTexCoordsEx[0] then
  3688. glMultiTexCoord4fv(GL_TEXTURE0, @TexCoordsEx[0].list[i])
  3689. else if gotTexCoords then
  3690. glTexCoord2fv(@texCoords.list[i]);
  3691. for j := 1 to FTexCoordsEx.Count - 1 do
  3692. if gotTexCoordsEx[j] then
  3693. glMultiTexCoord4fv(GL_TEXTURE0 + j, @TexCoordsEx[j].list[i]);
  3694. end
  3695. else
  3696. begin
  3697. if gotTexCoords then
  3698. glTexCoord2fv(@texCoords.list[i]);
  3699. end;
  3700. glVertex3fv(@Vertices.list[i]);
  3701. end;
  3702. glEnd;
  3703. end;
  3704. momFaceGroups:
  3705. begin
  3706. if Assigned(mrci.MaterialLibrary) then
  3707. begin
  3708. if moroGroupByMaterial in RenderingOptions then
  3709. begin
  3710. // group-by-material rendering, reduces material switches,
  3711. // but alters rendering order
  3712. groupID := vNextRenderGroupID;
  3713. Inc(vNextRenderGroupID);
  3714. for i := 0 to FaceGroups.Count - 1 do
  3715. begin
  3716. if FaceGroups[i].FRenderGroupID <> groupID then
  3717. begin
  3718. libMat := FaceGroups[i].FMaterialCache;
  3719. if Assigned(libMat) then
  3720. libMat.Apply(mrci);
  3721. repeat
  3722. for j := i to FaceGroups.Count - 1 do
  3723. with FaceGroups[j] do
  3724. begin
  3725. if (FRenderGroupID <> groupID) and (FMaterialCache = libMat) then
  3726. begin
  3727. FRenderGroupID := groupID;
  3728. BuildList(mrci);
  3729. end;
  3730. end;
  3731. until (not Assigned(libMat)) or (not libMat.UnApply(mrci));
  3732. end;
  3733. end;
  3734. end
  3735. else
  3736. begin
  3737. // canonical rendering (regroups only contiguous facegroups)
  3738. i := 0;
  3739. nbGroups := FaceGroups.Count;
  3740. while i < nbGroups do
  3741. begin
  3742. libMat := FaceGroups[i].FMaterialCache;
  3743. if Assigned(libMat) then
  3744. begin
  3745. libMat.Apply(mrci);
  3746. repeat
  3747. j := i;
  3748. while j < nbGroups do
  3749. begin
  3750. fg := FaceGroups[j];
  3751. if fg.MaterialCache <> libMat then
  3752. Break;
  3753. fg.BuildList(mrci);
  3754. Inc(j);
  3755. end;
  3756. until not libMat.UnApply(mrci);
  3757. i := j;
  3758. end
  3759. else
  3760. begin
  3761. FaceGroups[i].BuildList(mrci);
  3762. Inc(i);
  3763. end;
  3764. end;
  3765. end;
  3766. // restore faceculling
  3767. if (stCullFace in mrci.gxStates.States) then
  3768. begin
  3769. if not mrci.bufferFaceCull then
  3770. mrci.gxStates.Disable(stCullFace);
  3771. end
  3772. else
  3773. begin
  3774. if mrci.bufferFaceCull then
  3775. mrci.gxStates.Enable(stCullFace);
  3776. end;
  3777. end
  3778. else
  3779. for i := 0 to FaceGroups.Count - 1 do
  3780. FaceGroups[i].BuildList(mrci);
  3781. end;
  3782. else
  3783. Assert(False);
  3784. end;
  3785. DisableOpenGLArrays(mrci);
  3786. end;
  3787. // ------------------
  3788. // ------------------ TgxMeshObjectList ------------------
  3789. // ------------------
  3790. constructor TgxMeshObjectList.CreateOwned(aOwner: TgxBaseMesh);
  3791. begin
  3792. FOwner := aOwner;
  3793. Create;
  3794. end;
  3795. destructor TgxMeshObjectList.Destroy;
  3796. begin
  3797. Clear;
  3798. inherited;
  3799. end;
  3800. procedure TgxMeshObjectList.ReadFromFiler(reader: TgxVirtualReader);
  3801. var
  3802. i: Integer;
  3803. Mesh: TgxMeshObject;
  3804. begin
  3805. inherited;
  3806. for i := 0 to Count - 1 do
  3807. begin
  3808. Mesh := Items[i];
  3809. Mesh.FOwner := Self;
  3810. if Mesh is TgxSkeletonMeshObject then
  3811. TgxSkeletonMeshObject(Mesh).PrepareBoneMatrixInvertedMeshes;
  3812. end;
  3813. end;
  3814. procedure TgxMeshObjectList.PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  3815. var
  3816. i: Integer;
  3817. begin
  3818. for i := 0 to Count - 1 do
  3819. TgxMeshObject(list^[i]).PrepareMaterialLibraryCache(matLib);
  3820. end;
  3821. procedure TgxMeshObjectList.DropMaterialLibraryCache;
  3822. var
  3823. i: Integer;
  3824. begin
  3825. for i := 0 to Count - 1 do
  3826. TgxMeshObject(list^[i]).DropMaterialLibraryCache;
  3827. end;
  3828. procedure TgxMeshObjectList.PrepareBuildList(var mrci: TgxRenderContextInfo);
  3829. var
  3830. i: Integer;
  3831. begin
  3832. for i := 0 to Count - 1 do
  3833. with Items[i] do
  3834. if Visible then
  3835. PrepareBuildList(mrci);
  3836. end;
  3837. procedure TgxMeshObjectList.BuildList(var mrci: TgxRenderContextInfo);
  3838. var
  3839. i: Integer;
  3840. begin
  3841. for i := 0 to Count - 1 do
  3842. with Items[i] do
  3843. if Visible then
  3844. BuildList(mrci);
  3845. end;
  3846. procedure TgxMeshObjectList.MorphTo(morphTargetIndex: Integer);
  3847. var
  3848. i: Integer;
  3849. begin
  3850. for i := 0 to Count - 1 do
  3851. if Items[i] is TgxMorphableMeshObject then
  3852. TgxMorphableMeshObject(Items[i]).MorphTo(morphTargetIndex);
  3853. end;
  3854. procedure TgxMeshObjectList.Lerp(morphTargetIndex1, morphTargetIndex2: Integer; lerpFactor: Single);
  3855. var
  3856. i: Integer;
  3857. begin
  3858. for i := 0 to Count - 1 do
  3859. if Items[i] is TgxMorphableMeshObject then
  3860. TgxMorphableMeshObject(Items[i]).Lerp(morphTargetIndex1, morphTargetIndex2, lerpFactor);
  3861. end;
  3862. function TgxMeshObjectList.MorphTargetCount: Integer;
  3863. var
  3864. i: Integer;
  3865. begin
  3866. Result := MaxInt;
  3867. for i := 0 to Count - 1 do
  3868. if Items[i] is TgxMorphableMeshObject then
  3869. with TgxMorphableMeshObject(Items[i]) do
  3870. if Result > MorphTargets.Count then
  3871. Result := MorphTargets.Count;
  3872. if Result = MaxInt then
  3873. Result := 0;
  3874. end;
  3875. procedure TgxMeshObjectList.Clear;
  3876. var
  3877. i: Integer;
  3878. begin
  3879. DropMaterialLibraryCache;
  3880. for i := 0 to Count - 1 do
  3881. with Items[i] do
  3882. begin
  3883. FOwner := nil;
  3884. Free;
  3885. end;
  3886. inherited;
  3887. end;
  3888. function TgxMeshObjectList.GetMeshObject(Index: Integer): TgxMeshObject;
  3889. begin
  3890. Result := TgxMeshObject(list^[Index]);
  3891. end;
  3892. procedure TgxMeshObjectList.GetExtents(out min, max: TAffineVector);
  3893. var
  3894. i, k: Integer;
  3895. lMin, lMax: TAffineVector;
  3896. const
  3897. cBigValue: Single = 1E30;
  3898. cSmallValue: Single = -1E30;
  3899. begin
  3900. SetVector(min, cBigValue, cBigValue, cBigValue);
  3901. SetVector(max, cSmallValue, cSmallValue, cSmallValue);
  3902. for i := 0 to Count - 1 do
  3903. begin
  3904. GetMeshObject(i).GetExtents(lMin, lMax);
  3905. for k := 0 to 2 do
  3906. begin
  3907. if lMin.v[k] < min.v[k] then
  3908. min.v[k] := lMin.v[k];
  3909. if lMax.v[k] > max.v[k] then
  3910. max.v[k] := lMax.v[k];
  3911. end;
  3912. end;
  3913. end;
  3914. procedure TgxMeshObjectList.Translate(const delta: TAffineVector);
  3915. var
  3916. i: Integer;
  3917. begin
  3918. for i := 0 to Count - 1 do
  3919. GetMeshObject(i).Translate(delta);
  3920. end;
  3921. function TgxMeshObjectList.ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil)
  3922. : TgxAffineVectorList;
  3923. var
  3924. i: Integer;
  3925. obj: TgxMeshObject;
  3926. objTris: TgxAffineVectorList;
  3927. objTexCoords: TgxAffineVectorList;
  3928. objNormals: TgxAffineVectorList;
  3929. begin
  3930. Result := TgxAffineVectorList.Create;
  3931. if Assigned(texCoords) then
  3932. objTexCoords := TgxAffineVectorList.Create
  3933. else
  3934. objTexCoords := nil;
  3935. if Assigned(normals) then
  3936. objNormals := TgxAffineVectorList.Create
  3937. else
  3938. objNormals := nil;
  3939. try
  3940. for i := 0 to Count - 1 do
  3941. begin
  3942. obj := GetMeshObject(i);
  3943. if not obj.Visible then
  3944. continue;
  3945. objTris := obj.ExtractTriangles(objTexCoords, objNormals);
  3946. try
  3947. Result.Add(objTris);
  3948. if Assigned(texCoords) then
  3949. begin
  3950. texCoords.Add(objTexCoords);
  3951. objTexCoords.Count := 0;
  3952. end;
  3953. if Assigned(normals) then
  3954. begin
  3955. normals.Add(objNormals);
  3956. objNormals.Count := 0;
  3957. end;
  3958. finally
  3959. objTris.Free;
  3960. end;
  3961. end;
  3962. finally
  3963. objTexCoords.Free;
  3964. objNormals.Free;
  3965. end;
  3966. end;
  3967. function TgxMeshObjectList.TriangleCount: Integer;
  3968. var
  3969. i: Integer;
  3970. begin
  3971. Result := 0;
  3972. for i := 0 to Count - 1 do
  3973. Result := Result + Items[i].TriangleCount;
  3974. end;
  3975. procedure TgxMeshObjectList.Prepare;
  3976. var
  3977. i: Integer;
  3978. begin
  3979. for i := 0 to Count - 1 do
  3980. Items[i].Prepare;
  3981. end;
  3982. function TgxMeshObjectList.FindMeshByName(MeshName: string): TgxMeshObject;
  3983. var
  3984. i: Integer;
  3985. begin
  3986. Result := nil;
  3987. for i := 0 to Count - 1 do
  3988. if Items[i].Name = MeshName then
  3989. begin
  3990. Result := Items[i];
  3991. Break;
  3992. end;
  3993. end;
  3994. procedure TgxMeshObjectList.BuildTangentSpace(buildBinormals, buildTangents: Boolean);
  3995. var
  3996. i: Integer;
  3997. begin
  3998. if Count <> 0 then
  3999. for i := 0 to Count - 1 do
  4000. GetMeshObject(i).BuildTangentSpace(buildBinormals, buildTangents);
  4001. end;
  4002. function TgxMeshObjectList.GetUseVBO: Boolean;
  4003. var
  4004. i: Integer;
  4005. begin
  4006. Result := True;
  4007. if Count <> 0 then
  4008. for i := 0 to Count - 1 do
  4009. Result := Result and GetMeshObject(i).FUseVBO;
  4010. end;
  4011. procedure TgxMeshObjectList.SetUseVBO(const Value: Boolean);
  4012. var
  4013. i: Integer;
  4014. begin
  4015. if Count <> 0 then
  4016. for i := 0 to Count - 1 do
  4017. GetMeshObject(i).SetUseVBO(Value);
  4018. end;
  4019. // ------------------
  4020. // ------------------ TgxMeshMorphTarget ------------------
  4021. // ------------------
  4022. constructor TgxMeshMorphTarget.CreateOwned(aOwner: TgxMeshMorphTargetList);
  4023. begin
  4024. FOwner := aOwner;
  4025. Create;
  4026. if Assigned(FOwner) then
  4027. FOwner.Add(Self);
  4028. end;
  4029. destructor TgxMeshMorphTarget.Destroy;
  4030. begin
  4031. if Assigned(FOwner) then
  4032. FOwner.Remove(Self);
  4033. inherited;
  4034. end;
  4035. procedure TgxMeshMorphTarget.WriteToFiler(writer: TgxVirtualWriter);
  4036. begin
  4037. inherited WriteToFiler(writer);
  4038. with writer do
  4039. begin
  4040. WriteInteger(0); // Archive Version 0
  4041. // nothing
  4042. end;
  4043. end;
  4044. procedure TgxMeshMorphTarget.ReadFromFiler(reader: TgxVirtualReader);
  4045. var
  4046. archiveVersion: Integer;
  4047. begin
  4048. inherited ReadFromFiler(reader);
  4049. archiveVersion := reader.ReadInteger;
  4050. if archiveVersion = 0 then
  4051. with reader do
  4052. begin
  4053. // nothing
  4054. end
  4055. else
  4056. RaiseFilerException(archiveVersion);
  4057. end;
  4058. // ------------------
  4059. // ------------------ TgxMeshMorphTargetList ------------------
  4060. // ------------------
  4061. constructor TgxMeshMorphTargetList.CreateOwned(aOwner: TPersistent);
  4062. begin
  4063. FOwner := aOwner;
  4064. Create;
  4065. end;
  4066. destructor TgxMeshMorphTargetList.Destroy;
  4067. begin
  4068. Clear;
  4069. inherited;
  4070. end;
  4071. procedure TgxMeshMorphTargetList.ReadFromFiler(reader: TgxVirtualReader);
  4072. var
  4073. i: Integer;
  4074. begin
  4075. inherited;
  4076. for i := 0 to Count - 1 do
  4077. Items[i].FOwner := Self;
  4078. end;
  4079. procedure TgxMeshMorphTargetList.Translate(const delta: TAffineVector);
  4080. var
  4081. i: Integer;
  4082. begin
  4083. for i := 0 to Count - 1 do
  4084. Items[i].Translate(delta);
  4085. end;
  4086. procedure TgxMeshMorphTargetList.Clear;
  4087. var
  4088. i: Integer;
  4089. begin
  4090. for i := 0 to Count - 1 do
  4091. with Items[i] do
  4092. begin
  4093. FOwner := nil;
  4094. Free;
  4095. end;
  4096. inherited;
  4097. end;
  4098. function TgxMeshMorphTargetList.GetMeshMorphTarget(Index: Integer): TgxMeshMorphTarget;
  4099. begin
  4100. Result := TgxMeshMorphTarget(list^[Index]);
  4101. end;
  4102. // ------------------
  4103. // ------------------ TgxMorphableMeshObject ------------------
  4104. // ------------------
  4105. constructor TgxMorphableMeshObject.Create;
  4106. begin
  4107. inherited;
  4108. FMorphTargets := TgxMeshMorphTargetList.CreateOwned(Self);
  4109. end;
  4110. destructor TgxMorphableMeshObject.Destroy;
  4111. begin
  4112. FMorphTargets.Free;
  4113. inherited;
  4114. end;
  4115. procedure TgxMorphableMeshObject.WriteToFiler(writer: TgxVirtualWriter);
  4116. begin
  4117. inherited WriteToFiler(writer);
  4118. with writer do
  4119. begin
  4120. WriteInteger(0); // Archive Version 0
  4121. FMorphTargets.WriteToFiler(writer);
  4122. end;
  4123. end;
  4124. procedure TgxMorphableMeshObject.ReadFromFiler(reader: TgxVirtualReader);
  4125. var
  4126. archiveVersion: Integer;
  4127. begin
  4128. inherited ReadFromFiler(reader);
  4129. archiveVersion := reader.ReadInteger;
  4130. if archiveVersion = 0 then
  4131. with reader do
  4132. begin
  4133. FMorphTargets.ReadFromFiler(reader);
  4134. end
  4135. else
  4136. RaiseFilerException(archiveVersion);
  4137. end;
  4138. procedure TgxMorphableMeshObject.Clear;
  4139. begin
  4140. inherited;
  4141. FMorphTargets.Clear;
  4142. end;
  4143. procedure TgxMorphableMeshObject.Translate(const delta: TAffineVector);
  4144. begin
  4145. inherited;
  4146. MorphTargets.Translate(delta);
  4147. ValidBuffers := ValidBuffers - [vbVertices];
  4148. end;
  4149. procedure TgxMorphableMeshObject.MorphTo(morphTargetIndex: Integer);
  4150. begin
  4151. if (morphTargetIndex = 0) and (MorphTargets.Count = 0) then
  4152. Exit;
  4153. Assert(Cardinal(morphTargetIndex) < Cardinal(MorphTargets.Count));
  4154. with MorphTargets[morphTargetIndex] do
  4155. begin
  4156. if Vertices.Count > 0 then
  4157. begin
  4158. Self.Vertices.Assign(Vertices);
  4159. ValidBuffers := ValidBuffers - [vbVertices];
  4160. end;
  4161. if normals.Count > 0 then
  4162. begin
  4163. Self.normals.Assign(normals);
  4164. ValidBuffers := ValidBuffers - [vbNormals];
  4165. end;
  4166. end;
  4167. end;
  4168. procedure TgxMorphableMeshObject.Lerp(morphTargetIndex1, morphTargetIndex2: Integer; lerpFactor: Single);
  4169. var
  4170. mt1, mt2: TgxMeshMorphTarget;
  4171. begin
  4172. Assert((Cardinal(morphTargetIndex1) < Cardinal(MorphTargets.Count)) and
  4173. (Cardinal(morphTargetIndex2) < Cardinal(MorphTargets.Count)));
  4174. if lerpFactor = 0 then
  4175. MorphTo(morphTargetIndex1)
  4176. else if lerpFactor = 1 then
  4177. MorphTo(morphTargetIndex2)
  4178. else
  4179. begin
  4180. mt1 := MorphTargets[morphTargetIndex1];
  4181. mt2 := MorphTargets[morphTargetIndex2];
  4182. if mt1.Vertices.Count > 0 then
  4183. begin
  4184. Vertices.Lerp(mt1.Vertices, mt2.Vertices, lerpFactor);
  4185. ValidBuffers := ValidBuffers - [vbVertices];
  4186. end;
  4187. if mt1.normals.Count > 0 then
  4188. begin
  4189. normals.Lerp(mt1.normals, mt2.normals, lerpFactor);
  4190. normals.normalize;
  4191. ValidBuffers := ValidBuffers - [vbNormals];
  4192. end;
  4193. end;
  4194. end;
  4195. // ------------------
  4196. // ------------------ TgxSkeletonMeshObject ------------------
  4197. // ------------------
  4198. constructor TgxSkeletonMeshObject.Create;
  4199. begin
  4200. FBoneMatrixInvertedMeshes := TList.Create;
  4201. FBackupInvertedMeshes := TList.Create; // ragdoll
  4202. inherited Create;
  4203. end;
  4204. destructor TgxSkeletonMeshObject.Destroy;
  4205. begin
  4206. Clear;
  4207. FBoneMatrixInvertedMeshes.Free;
  4208. FBackupInvertedMeshes.Free;
  4209. inherited Destroy;
  4210. end;
  4211. procedure TgxSkeletonMeshObject.WriteToFiler(writer: TgxVirtualWriter);
  4212. var
  4213. i: Integer;
  4214. begin
  4215. inherited WriteToFiler(writer);
  4216. with writer do
  4217. begin
  4218. WriteInteger(0); // Archive Version 0
  4219. WriteInteger(FVerticeBoneWeightCount);
  4220. WriteInteger(FBonesPerVertex);
  4221. WriteInteger(FVerticeBoneWeightCapacity);
  4222. for i := 0 to FVerticeBoneWeightCount - 1 do
  4223. Write(FVerticesBonesWeights[i][0], FBonesPerVertex * SizeOf(TgxVertexBoneWeight));
  4224. end;
  4225. end;
  4226. procedure TgxSkeletonMeshObject.ReadFromFiler(reader: TgxVirtualReader);
  4227. var
  4228. archiveVersion, i: Integer;
  4229. begin
  4230. inherited ReadFromFiler(reader);
  4231. archiveVersion := reader.ReadInteger;
  4232. if archiveVersion = 0 then
  4233. with reader do
  4234. begin
  4235. FVerticeBoneWeightCount := ReadInteger;
  4236. FBonesPerVertex := ReadInteger;
  4237. FVerticeBoneWeightCapacity := ReadInteger;
  4238. ResizeVerticesBonesWeights;
  4239. for i := 0 to FVerticeBoneWeightCount - 1 do
  4240. Read(FVerticesBonesWeights[i][0], FBonesPerVertex * SizeOf(TgxVertexBoneWeight));
  4241. end
  4242. else
  4243. RaiseFilerException(archiveVersion);
  4244. end;
  4245. procedure TgxSkeletonMeshObject.Clear;
  4246. var
  4247. i: Integer;
  4248. begin
  4249. inherited;
  4250. FVerticeBoneWeightCount := 0;
  4251. FBonesPerVertex := 0;
  4252. ResizeVerticesBonesWeights;
  4253. for i := 0 to FBoneMatrixInvertedMeshes.Count - 1 do
  4254. TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]).Free;
  4255. FBoneMatrixInvertedMeshes.Clear;
  4256. end;
  4257. procedure TgxSkeletonMeshObject.SetVerticeBoneWeightCount(const val: Integer);
  4258. begin
  4259. if val <> FVerticeBoneWeightCount then
  4260. begin
  4261. FVerticeBoneWeightCount := val;
  4262. if FVerticeBoneWeightCount > FVerticeBoneWeightCapacity then
  4263. VerticeBoneWeightCapacity := FVerticeBoneWeightCount + 16;
  4264. FLastVerticeBoneWeightCount := FVerticeBoneWeightCount;
  4265. end;
  4266. end;
  4267. procedure TgxSkeletonMeshObject.SetVerticeBoneWeightCapacity(const val: Integer);
  4268. begin
  4269. if val <> FVerticeBoneWeightCapacity then
  4270. begin
  4271. FVerticeBoneWeightCapacity := val;
  4272. ResizeVerticesBonesWeights;
  4273. end;
  4274. end;
  4275. procedure TgxSkeletonMeshObject.SetBonesPerVertex(const val: Integer);
  4276. begin
  4277. if val <> FBonesPerVertex then
  4278. begin
  4279. FBonesPerVertex := val;
  4280. ResizeVerticesBonesWeights;
  4281. end;
  4282. end;
  4283. procedure TgxSkeletonMeshObject.ResizeVerticesBonesWeights;
  4284. var
  4285. n, m, i, j: Integer;
  4286. newArea: PgxVerticesBoneWeights;
  4287. begin
  4288. n := BonesPerVertex * VerticeBoneWeightCapacity;
  4289. if n = 0 then
  4290. begin
  4291. // release everything
  4292. if Assigned(FVerticesBonesWeights) then
  4293. begin
  4294. FreeMem(FVerticesBonesWeights[0]);
  4295. FreeMem(FVerticesBonesWeights);
  4296. FVerticesBonesWeights := nil;
  4297. end;
  4298. end
  4299. else
  4300. begin
  4301. // allocate new area
  4302. GetMem(newArea, VerticeBoneWeightCapacity * SizeOf(PgxVertexBoneWeightArray));
  4303. newArea[0] := AllocMem(n * SizeOf(TgxVertexBoneWeight));
  4304. for i := 1 to VerticeBoneWeightCapacity - 1 do
  4305. newArea[i] := PgxVertexBoneWeightArray(Cardinal(newArea[0]) + Cardinal(i * SizeOf(TgxVertexBoneWeight) * BonesPerVertex));
  4306. // transfer old data
  4307. if FLastVerticeBoneWeightCount < VerticeBoneWeightCount then
  4308. n := FLastVerticeBoneWeightCount
  4309. else
  4310. n := VerticeBoneWeightCount;
  4311. if FLastBonesPerVertex < BonesPerVertex then
  4312. m := FLastBonesPerVertex
  4313. else
  4314. m := BonesPerVertex;
  4315. for i := 0 to n - 1 do
  4316. for j := 0 to m - 1 do
  4317. newArea[i][j] := VerticesBonesWeights[i][j];
  4318. // release old area and switch to new
  4319. if Assigned(FVerticesBonesWeights) then
  4320. begin
  4321. FreeMem(FVerticesBonesWeights[0]);
  4322. FreeMem(FVerticesBonesWeights);
  4323. end;
  4324. FVerticesBonesWeights := newArea;
  4325. end;
  4326. FLastBonesPerVertex := FBonesPerVertex;
  4327. end;
  4328. procedure TgxSkeletonMeshObject.AddWeightedBone(aBoneID: Integer; aWeight: Single);
  4329. begin
  4330. if BonesPerVertex < 1 then
  4331. BonesPerVertex := 1;
  4332. VerticeBoneWeightCount := VerticeBoneWeightCount + 1;
  4333. with VerticesBonesWeights^[VerticeBoneWeightCount - 1]^[0] do
  4334. begin
  4335. BoneID := aBoneID;
  4336. weight := aWeight;
  4337. end;
  4338. end;
  4339. procedure TgxSkeletonMeshObject.AddWeightedBones(const boneIDs: TgxVertexBoneWeightDynArray);
  4340. var
  4341. i: Integer;
  4342. n: Integer;
  4343. begin
  4344. n := Length(boneIDs);
  4345. if BonesPerVertex < n then
  4346. BonesPerVertex := n;
  4347. VerticeBoneWeightCount := VerticeBoneWeightCount + 1;
  4348. for i := 0 to n - 1 do
  4349. begin
  4350. with VerticesBonesWeights^[VerticeBoneWeightCount - 1]^[i] do
  4351. begin
  4352. BoneID := boneIDs[i].BoneID;
  4353. weight := boneIDs[i].weight;
  4354. end;
  4355. end;
  4356. end;
  4357. function TgxSkeletonMeshObject.FindOrAdd(BoneID: Integer; const vertex, normal: TAffineVector): Integer;
  4358. var
  4359. i: Integer;
  4360. dynArray: TgxVertexBoneWeightDynArray;
  4361. begin
  4362. if BonesPerVertex > 1 then
  4363. begin
  4364. SetLength(dynArray, 1);
  4365. dynArray[0].BoneID := BoneID;
  4366. dynArray[0].weight := 1;
  4367. Result := FindOrAdd(dynArray, vertex, normal);
  4368. Exit;
  4369. end;
  4370. Result := -1;
  4371. for i := 0 to Vertices.Count - 1 do
  4372. if (VerticesBonesWeights^[i]^[0].BoneID = BoneID) and VectorEquals(Vertices.list^[i], vertex) and
  4373. VectorEquals(normals.list^[i], normal) then
  4374. begin
  4375. Result := i;
  4376. Break;
  4377. end;
  4378. if Result < 0 then
  4379. begin
  4380. AddWeightedBone(BoneID, 1);
  4381. Vertices.Add(vertex);
  4382. Result := normals.Add(normal);
  4383. end;
  4384. end;
  4385. function TgxSkeletonMeshObject.FindOrAdd(const boneIDs: TgxVertexBoneWeightDynArray; const vertex, normal: TAffineVector)
  4386. : Integer;
  4387. var
  4388. i, j: Integer;
  4389. bonesMatch: Boolean;
  4390. begin
  4391. Result := -1;
  4392. for i := 0 to Vertices.Count - 1 do
  4393. begin
  4394. bonesMatch := True;
  4395. for j := 0 to High(boneIDs) do
  4396. begin
  4397. if (boneIDs[j].BoneID <> VerticesBonesWeights^[i]^[j].BoneID) or (boneIDs[j].weight <> VerticesBonesWeights^[i]^[j].weight)
  4398. then
  4399. begin
  4400. bonesMatch := False;
  4401. Break;
  4402. end;
  4403. end;
  4404. if bonesMatch and VectorEquals(Vertices[i], vertex) and VectorEquals(normals[i], normal) then
  4405. begin
  4406. Result := i;
  4407. Break;
  4408. end;
  4409. end;
  4410. if Result < 0 then
  4411. begin
  4412. AddWeightedBones(boneIDs);
  4413. Vertices.Add(vertex);
  4414. Result := normals.Add(normal);
  4415. end;
  4416. end;
  4417. procedure TgxSkeletonMeshObject.PrepareBoneMatrixInvertedMeshes;
  4418. var
  4419. i, k, boneIndex: Integer;
  4420. invMesh: TgxBaseMeshObject;
  4421. invMat: TMatrix4f;
  4422. Bone: TgxSkeletonBone;
  4423. p: TVector4f;
  4424. begin
  4425. // cleanup existing stuff
  4426. for i := 0 to FBoneMatrixInvertedMeshes.Count - 1 do
  4427. TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]).Free;
  4428. FBoneMatrixInvertedMeshes.Clear;
  4429. // calculate
  4430. for k := 0 to BonesPerVertex - 1 do
  4431. begin
  4432. invMesh := TgxBaseMeshObject.Create;
  4433. FBoneMatrixInvertedMeshes.Add(invMesh);
  4434. invMesh.Vertices := Vertices;
  4435. invMesh.normals := normals;
  4436. for i := 0 to Vertices.Count - 1 do
  4437. begin
  4438. boneIndex := VerticesBonesWeights^[i]^[k].BoneID;
  4439. Bone := Owner.Owner.Skeleton.RootBones.BoneByID(boneIndex);
  4440. // transform point
  4441. MakePoint(p, Vertices[i]);
  4442. invMat := Bone.GlobalMatrix;
  4443. InvertMatrix(invMat);
  4444. p := VectorTransform(p, invMat);
  4445. invMesh.Vertices[i] := PAffineVector(@p)^;
  4446. // transform normal
  4447. SetVector(p, normals[i]);
  4448. invMat := Bone.GlobalMatrix;
  4449. invMat.W := NullHmgPoint;
  4450. InvertMatrix(invMat);
  4451. p := VectorTransform(p, invMat);
  4452. invMesh.normals[i] := PAffineVector(@p)^;
  4453. end;
  4454. end;
  4455. end;
  4456. procedure TgxSkeletonMeshObject.BackupBoneMatrixInvertedMeshes; // ragdoll
  4457. var
  4458. i: Integer;
  4459. bm: TgxBaseMeshObject;
  4460. begin
  4461. // cleanup existing stuff
  4462. for i := 0 to FBackupInvertedMeshes.Count - 1 do
  4463. TgxBaseMeshObject(FBackupInvertedMeshes[i]).Free;
  4464. FBackupInvertedMeshes.Clear;
  4465. // copy current stuff
  4466. for i := 0 to FBoneMatrixInvertedMeshes.Count - 1 do
  4467. begin
  4468. bm := TgxBaseMeshObject.Create;
  4469. bm.Assign(TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]));
  4470. FBackupInvertedMeshes.Add(bm);
  4471. TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]).Free;
  4472. end;
  4473. FBoneMatrixInvertedMeshes.Clear;
  4474. end;
  4475. procedure TgxSkeletonMeshObject.RestoreBoneMatrixInvertedMeshes; // ragdoll
  4476. var
  4477. i: Integer;
  4478. bm: TgxBaseMeshObject;
  4479. begin
  4480. // cleanup existing stuff
  4481. for i := 0 to FBoneMatrixInvertedMeshes.Count - 1 do
  4482. TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]).Free;
  4483. FBoneMatrixInvertedMeshes.Clear;
  4484. // restore the backup
  4485. for i := 0 to FBackupInvertedMeshes.Count - 1 do
  4486. begin
  4487. bm := TgxBaseMeshObject.Create;
  4488. bm.Assign(TgxBaseMeshObject(FBackupInvertedMeshes[i]));
  4489. FBoneMatrixInvertedMeshes.Add(bm);
  4490. TgxBaseMeshObject(FBackupInvertedMeshes[i]).Free;
  4491. end;
  4492. FBackupInvertedMeshes.Clear;
  4493. end;
  4494. procedure TgxSkeletonMeshObject.ApplyCurrentSkeletonFrame(normalize: Boolean);
  4495. var
  4496. i, j, BoneID: Integer;
  4497. refVertices, refNormals: TgxAffineVectorList;
  4498. n, nt: TVector4f;
  4499. Bone: TgxSkeletonBone;
  4500. Skeleton: TgxSkeleton;
  4501. tempvert, tempnorm: TAffineVector;
  4502. begin
  4503. with TgxBaseMeshObject(FBoneMatrixInvertedMeshes[0]) do
  4504. begin
  4505. refVertices := Vertices;
  4506. refNormals := normals;
  4507. end;
  4508. Skeleton := Owner.Owner.Skeleton;
  4509. n.W := 0;
  4510. if BonesPerVertex = 1 then
  4511. begin
  4512. // simple case, one bone per vertex
  4513. for i := 0 to refVertices.Count - 1 do
  4514. begin
  4515. BoneID := VerticesBonesWeights^[i]^[0].BoneID;
  4516. Bone := Skeleton.BoneByID(BoneID);
  4517. Vertices.list^[i] := VectorTransform(refVertices.list^[i], Bone.GlobalMatrix);
  4518. PAffineVector(@n)^ := refNormals.list^[i];
  4519. nt := VectorTransform(n, Bone.GlobalMatrix);
  4520. normals.list^[i] := PAffineVector(@nt)^;
  4521. end;
  4522. end
  4523. else
  4524. begin
  4525. // multiple bones per vertex
  4526. for i := 0 to refVertices.Count - 1 do
  4527. begin
  4528. Vertices.list^[i] := NullVector;
  4529. normals.list^[i] := NullVector;
  4530. for j := 0 to BonesPerVertex - 1 do
  4531. begin
  4532. with TgxBaseMeshObject(FBoneMatrixInvertedMeshes[j]) do
  4533. begin
  4534. refVertices := Vertices;
  4535. refNormals := normals;
  4536. end;
  4537. tempvert := NullVector;
  4538. tempnorm := NullVector;
  4539. if VerticesBonesWeights^[i]^[j].weight <> 0 then
  4540. begin
  4541. BoneID := VerticesBonesWeights^[i]^[j].BoneID;
  4542. Bone := Skeleton.BoneByID(BoneID);
  4543. CombineVector(tempvert, VectorTransform(refVertices.list^[i], Bone.GlobalMatrix),
  4544. VerticesBonesWeights^[i]^[j].weight);
  4545. PAffineVector(@n)^ := refNormals.list^[i];
  4546. n := VectorTransform(n, Bone.GlobalMatrix);
  4547. CombineVector(tempnorm, PAffineVector(@n)^, VerticesBonesWeights^[i]^[j].weight);
  4548. end;
  4549. AddVector(Vertices.list^[i], tempvert);
  4550. AddVector(normals.list^[i], tempnorm);
  4551. end;
  4552. end;
  4553. end;
  4554. if normalize then
  4555. normals.normalize;
  4556. end;
  4557. // ------------------
  4558. // ------------------ TgxFaceGroup ------------------
  4559. // ------------------
  4560. constructor TgxFaceGroup.CreateOwned(aOwner: TgxFaceGroups);
  4561. begin
  4562. FOwner := aOwner;
  4563. FLightMapIndex := -1;
  4564. Create;
  4565. if Assigned(FOwner) then
  4566. FOwner.Add(Self);
  4567. end;
  4568. destructor TgxFaceGroup.Destroy;
  4569. begin
  4570. if Assigned(FOwner) then
  4571. FOwner.Remove(Self);
  4572. inherited;
  4573. end;
  4574. procedure TgxFaceGroup.WriteToFiler(writer: TgxVirtualWriter);
  4575. begin
  4576. inherited WriteToFiler(writer);
  4577. with writer do
  4578. begin
  4579. if FLightMapIndex < 0 then
  4580. begin
  4581. WriteInteger(0); // Archive Version 0
  4582. WriteString(FMaterialName);
  4583. end
  4584. else
  4585. begin
  4586. WriteInteger(1); // Archive Version 1, added FLightMapIndex
  4587. WriteString(FMaterialName);
  4588. WriteInteger(FLightMapIndex);
  4589. end;
  4590. end;
  4591. end;
  4592. procedure TgxFaceGroup.ReadFromFiler(reader: TgxVirtualReader);
  4593. var
  4594. archiveVersion: Integer;
  4595. begin
  4596. inherited ReadFromFiler(reader);
  4597. archiveVersion := reader.ReadInteger;
  4598. if archiveVersion in [0 .. 1] then
  4599. with reader do
  4600. begin
  4601. FMaterialName := ReadString;
  4602. if archiveVersion >= 1 then
  4603. FLightMapIndex := ReadInteger
  4604. else
  4605. FLightMapIndex := -1;
  4606. end
  4607. else
  4608. RaiseFilerException(archiveVersion);
  4609. end;
  4610. procedure TgxFaceGroup.AttachLightmap(lightMap: TgxTexture; var mrci: TgxRenderContextInfo);
  4611. begin
  4612. /// if GL_ARB_multitexture then
  4613. with lightMap do
  4614. begin
  4615. Assert(Image.NativeTextureTarget = ttTexture2D);
  4616. mrci.gxStates.TextureBinding[1, ttTexture2D] := Handle;
  4617. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  4618. mrci.gxStates.ActiveTexture := 0;
  4619. end;
  4620. end;
  4621. procedure TgxFaceGroup.AttachOrDetachLightmap(var mrci: TgxRenderContextInfo);
  4622. var
  4623. libMat: TgxLibMaterial;
  4624. begin
  4625. /// if GL_ARB_multitexture then
  4626. if (not mrci.ignoreMaterials) and Assigned(mrci.LightmapLibrary) then
  4627. begin
  4628. if Owner.Owner.FLastLightMapIndex <> LightMapIndex then
  4629. begin
  4630. Owner.Owner.FLastLightMapIndex := LightMapIndex;
  4631. if LightMapIndex >= 0 then
  4632. begin
  4633. // attach and activate lightmap
  4634. Assert(LightMapIndex < TgxMaterialLibrary(mrci.LightmapLibrary).Materials.Count);
  4635. libMat := TgxMaterialLibrary(mrci.LightmapLibrary).Materials[LightMapIndex];
  4636. AttachLightmap(libMat.Material.Texture, mrci);
  4637. Owner.Owner.EnableLightMapArray(mrci);
  4638. end
  4639. else
  4640. begin
  4641. // desactivate lightmap
  4642. Owner.Owner.DisableLightMapArray(mrci);
  4643. end;
  4644. end;
  4645. end;
  4646. end;
  4647. procedure TgxFaceGroup.PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  4648. begin
  4649. if (FMaterialName <> '') and (matLib <> nil) then
  4650. FMaterialCache := matLib.Materials.GetLibMaterialByName(FMaterialName)
  4651. else
  4652. FMaterialCache := nil;
  4653. end;
  4654. procedure TgxFaceGroup.DropMaterialLibraryCache;
  4655. begin
  4656. FMaterialCache := nil;
  4657. end;
  4658. procedure TgxFaceGroup.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  4659. aNormals: TgxAffineVectorList = nil);
  4660. begin
  4661. // nothing
  4662. end;
  4663. procedure TgxFaceGroup.Reverse;
  4664. begin
  4665. // nothing
  4666. end;
  4667. procedure TgxFaceGroup.Prepare;
  4668. begin
  4669. // nothing
  4670. end;
  4671. // ------------------
  4672. // ------------------ TgxFGVertexIndexList ------------------
  4673. // ------------------
  4674. constructor TgxFGVertexIndexList.Create;
  4675. begin
  4676. inherited;
  4677. FVertexIndices := TgxIntegerList.Create;
  4678. FMode := fgmmTriangles;
  4679. end;
  4680. destructor TgxFGVertexIndexList.Destroy;
  4681. begin
  4682. FVertexIndices.Free;
  4683. FIndexVBO.Free;
  4684. inherited;
  4685. end;
  4686. procedure TgxFGVertexIndexList.WriteToFiler(writer: TgxVirtualWriter);
  4687. begin
  4688. inherited WriteToFiler(writer);
  4689. with writer do
  4690. begin
  4691. WriteInteger(0); // Archive Version 0
  4692. FVertexIndices.WriteToFiler(writer);
  4693. WriteInteger(Integer(FMode));
  4694. end;
  4695. end;
  4696. procedure TgxFGVertexIndexList.ReadFromFiler(reader: TgxVirtualReader);
  4697. var
  4698. archiveVersion: Integer;
  4699. begin
  4700. inherited ReadFromFiler(reader);
  4701. archiveVersion := reader.ReadInteger;
  4702. if archiveVersion = 0 then
  4703. with reader do
  4704. begin
  4705. FVertexIndices.ReadFromFiler(reader);
  4706. FMode := TgxFaceGroupMeshMode(ReadInteger);
  4707. InvalidateVBO;
  4708. end
  4709. else
  4710. RaiseFilerException(archiveVersion);
  4711. end;
  4712. procedure TgxFGVertexIndexList.SetupVBO;
  4713. const
  4714. BufferUsage = GL_STATIC_DRAW;
  4715. begin
  4716. if not Assigned(FIndexVBO) then
  4717. FIndexVBO := TgxVBOElementArrayHandle.Create;
  4718. FIndexVBO.AllocateHandle;
  4719. if FIndexVBO.IsDataNeedUpdate then
  4720. begin
  4721. FIndexVBO.BindBufferData(vertexIndices.list, SizeOf(Integer) * vertexIndices.Count, BufferUsage);
  4722. FIndexVBO.NotifyDataUpdated;
  4723. end;
  4724. end;
  4725. procedure TgxFGVertexIndexList.SetVertexIndices(const val: TgxIntegerList);
  4726. begin
  4727. FVertexIndices.Assign(val);
  4728. InvalidateVBO;
  4729. end;
  4730. procedure TgxFGVertexIndexList.BuildList(var mrci: TgxRenderContextInfo);
  4731. const
  4732. cFaceGroupMeshModeToOpenGL: array [TgxFaceGroupMeshMode] of Integer = (GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLES,
  4733. GL_TRIANGLE_FAN, GL_QUADS);
  4734. begin
  4735. if vertexIndices.Count = 0 then
  4736. Exit;
  4737. Owner.Owner.DeclareArraysToOpenGL(mrci, False);
  4738. AttachOrDetachLightmap(mrci);
  4739. if Owner.Owner.UseVBO then
  4740. begin
  4741. SetupVBO;
  4742. FIndexVBO.Bind;
  4743. glDrawElements(cFaceGroupMeshModeToOpenGL[mode], vertexIndices.Count, GL_UNSIGNED_INT, nil);
  4744. FIndexVBO.UnBind;
  4745. end
  4746. else
  4747. begin
  4748. glDrawElements(cFaceGroupMeshModeToOpenGL[mode], vertexIndices.Count, GL_UNSIGNED_INT, vertexIndices.list);
  4749. end;
  4750. end;
  4751. procedure TgxFGVertexIndexList.AddToList(Source, destination: TgxAffineVectorList; indices: TgxIntegerList);
  4752. var
  4753. i, n: Integer;
  4754. begin
  4755. if not Assigned(destination) then
  4756. Exit;
  4757. if indices.Count < 3 then
  4758. Exit;
  4759. case mode of
  4760. fgmmTriangles, fgmmFlatTriangles:
  4761. begin
  4762. n := (indices.Count div 3) * 3;
  4763. if Source.Count > 0 then
  4764. begin
  4765. destination.AdjustCapacityToAtLeast(destination.Count + n);
  4766. for i := 0 to n - 1 do
  4767. destination.Add(Source[indices.list^[i]]);
  4768. end
  4769. else
  4770. destination.AddNulls(destination.Count + n);
  4771. end;
  4772. fgmmTriangleStrip:
  4773. begin
  4774. if Source.Count > 0 then
  4775. ConvertStripToList(Source, indices, destination)
  4776. else
  4777. destination.AddNulls(destination.Count + (indices.Count - 2) * 3);
  4778. end;
  4779. fgmmTriangleFan:
  4780. begin
  4781. n := (indices.Count - 2) * 3;
  4782. if Source.Count > 0 then
  4783. begin
  4784. destination.AdjustCapacityToAtLeast(destination.Count + n);
  4785. for i := 2 to vertexIndices.Count - 1 do
  4786. begin
  4787. destination.Add(Source[indices.list^[0]], Source[indices.list^[i - 1]], Source[indices.list^[i]]);
  4788. end;
  4789. end
  4790. else
  4791. destination.AddNulls(destination.Count + n);
  4792. end;
  4793. fgmmQuads:
  4794. begin
  4795. n := indices.Count div 4;
  4796. if Source.Count > 0 then
  4797. begin
  4798. destination.AdjustCapacityToAtLeast(destination.Count + n * 6);
  4799. i := 0;
  4800. while n > 0 do
  4801. begin
  4802. destination.Add(Source[indices.list^[i]], Source[indices.list^[i + 1]], Source[indices.list^[i + 2]]);
  4803. destination.Add(Source[indices.list^[i]], Source[indices.list^[i + 2]], Source[indices.list^[i + 3]]);
  4804. Inc(i, 4);
  4805. Dec(n);
  4806. end;
  4807. end
  4808. else
  4809. destination.AddNulls(destination.Count + n * 6);
  4810. end;
  4811. else
  4812. Assert(False);
  4813. end;
  4814. end;
  4815. procedure TgxFGVertexIndexList.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  4816. aNormals: TgxAffineVectorList = nil);
  4817. var
  4818. mo: TgxMeshObject;
  4819. begin
  4820. mo := Owner.Owner;
  4821. AddToList(mo.Vertices, aList, vertexIndices);
  4822. AddToList(mo.texCoords, aTexCoords, vertexIndices);
  4823. AddToList(mo.normals, aNormals, vertexIndices);
  4824. InvalidateVBO;
  4825. end;
  4826. function TgxFGVertexIndexList.TriangleCount: Integer;
  4827. begin
  4828. case mode of
  4829. fgmmTriangles, fgmmFlatTriangles:
  4830. Result := vertexIndices.Count div 3;
  4831. fgmmTriangleFan, fgmmTriangleStrip:
  4832. begin
  4833. Result := vertexIndices.Count - 2;
  4834. if Result < 0 then
  4835. Result := 0;
  4836. end;
  4837. fgmmQuads:
  4838. Result := vertexIndices.Count div 2;
  4839. else
  4840. Result := 0;
  4841. Assert(False);
  4842. end;
  4843. end;
  4844. procedure TgxFGVertexIndexList.Reverse;
  4845. begin
  4846. vertexIndices.Reverse;
  4847. InvalidateVBO;
  4848. end;
  4849. procedure TgxFGVertexIndexList.Add(idx: Integer);
  4850. begin
  4851. FVertexIndices.Add(idx);
  4852. InvalidateVBO;
  4853. end;
  4854. procedure TgxFGVertexIndexList.GetExtents(var min, max: TAffineVector);
  4855. var
  4856. i, k: Integer;
  4857. f: Single;
  4858. ref: PFloatArray;
  4859. const
  4860. cBigValue: Single = 1E50;
  4861. cSmallValue: Single = -1E50;
  4862. begin
  4863. SetVector(min, cBigValue, cBigValue, cBigValue);
  4864. SetVector(max, cSmallValue, cSmallValue, cSmallValue);
  4865. for i := 0 to vertexIndices.Count - 1 do
  4866. begin
  4867. ref := Owner.Owner.Vertices.ItemAddress[vertexIndices[i]];
  4868. for k := 0 to 2 do
  4869. begin
  4870. f := ref^[k];
  4871. if f < min.v[k] then
  4872. min.v[k] := f;
  4873. if f > max.v[k] then
  4874. max.v[k] := f;
  4875. end;
  4876. end;
  4877. end;
  4878. procedure TgxFGVertexIndexList.ConvertToList;
  4879. var
  4880. i: Integer;
  4881. bufList: TgxIntegerList;
  4882. begin
  4883. if vertexIndices.Count >= 3 then
  4884. begin
  4885. case mode of
  4886. fgmmTriangleStrip:
  4887. begin
  4888. bufList := TgxIntegerList.Create;
  4889. try
  4890. ConvertStripToList(vertexIndices, bufList);
  4891. vertexIndices := bufList;
  4892. finally
  4893. bufList.Free;
  4894. end;
  4895. FMode := fgmmTriangles;
  4896. end;
  4897. fgmmTriangleFan:
  4898. begin
  4899. bufList := TgxIntegerList.Create;
  4900. try
  4901. for i := 0 to vertexIndices.Count - 3 do
  4902. bufList.Add(vertexIndices[0], vertexIndices[i], vertexIndices[i + 1]);
  4903. vertexIndices := bufList;
  4904. finally
  4905. bufList.Free;
  4906. end;
  4907. FMode := fgmmTriangles;
  4908. end;
  4909. end;
  4910. InvalidateVBO;
  4911. end;
  4912. end;
  4913. function TgxFGVertexIndexList.GetNormal: TAffineVector;
  4914. begin
  4915. if vertexIndices.Count < 3 then
  4916. Result := NullVector
  4917. else
  4918. with Owner.Owner.Vertices do
  4919. CalcPlaneNormal(Items[vertexIndices[0]], Items[vertexIndices[1]], Items[vertexIndices[2]], Result);
  4920. end;
  4921. procedure TgxFGVertexIndexList.InvalidateVBO;
  4922. begin
  4923. if Assigned(FIndexVBO) then
  4924. FIndexVBO.NotifyChangesOfData;
  4925. end;
  4926. // ------------------
  4927. // ------------------ TFGVertexNormalTexIndexList ------------------
  4928. // ------------------
  4929. constructor TFGVertexNormalTexIndexList.Create;
  4930. begin
  4931. inherited;
  4932. FNormalIndices := TgxIntegerList.Create;
  4933. FTexCoordIndices := TgxIntegerList.Create;
  4934. end;
  4935. destructor TFGVertexNormalTexIndexList.Destroy;
  4936. begin
  4937. FTexCoordIndices.Free;
  4938. FNormalIndices.Free;
  4939. inherited;
  4940. end;
  4941. procedure TFGVertexNormalTexIndexList.WriteToFiler(writer: TgxVirtualWriter);
  4942. begin
  4943. inherited WriteToFiler(writer);
  4944. with writer do
  4945. begin
  4946. WriteInteger(0); // Archive Version 0
  4947. FNormalIndices.WriteToFiler(writer);
  4948. FTexCoordIndices.WriteToFiler(writer);
  4949. end;
  4950. end;
  4951. procedure TFGVertexNormalTexIndexList.ReadFromFiler(reader: TgxVirtualReader);
  4952. var
  4953. archiveVersion: Integer;
  4954. begin
  4955. inherited ReadFromFiler(reader);
  4956. archiveVersion := reader.ReadInteger;
  4957. if archiveVersion = 0 then
  4958. with reader do
  4959. begin
  4960. FNormalIndices.ReadFromFiler(reader);
  4961. FTexCoordIndices.ReadFromFiler(reader);
  4962. end
  4963. else
  4964. RaiseFilerException(archiveVersion);
  4965. end;
  4966. procedure TFGVertexNormalTexIndexList.SetNormalIndices(const val: TgxIntegerList);
  4967. begin
  4968. FNormalIndices.Assign(val);
  4969. end;
  4970. procedure TFGVertexNormalTexIndexList.SetTexCoordIndices(const val: TgxIntegerList);
  4971. begin
  4972. FTexCoordIndices.Assign(val);
  4973. end;
  4974. procedure TFGVertexNormalTexIndexList.BuildList(var mrci: TgxRenderContextInfo);
  4975. var
  4976. i: Integer;
  4977. vertexPool: PAffineVectorArray;
  4978. normalPool: PAffineVectorArray;
  4979. texCoordPool: PAffineVectorArray;
  4980. colorPool: PVectorArray;
  4981. normalIdxList, texCoordIdxList, vertexIdxList: PIntegerVector;
  4982. begin
  4983. Assert(((TexCoordIndices.Count = 0) or (vertexIndices.Count <= TexCoordIndices.Count)) and
  4984. ((normalIndices.Count = 0) or (vertexIndices.Count <= normalIndices.Count)));
  4985. vertexPool := Owner.Owner.Vertices.list;
  4986. normalPool := Owner.Owner.normals.list;
  4987. colorPool := Owner.Owner.Colors.list;
  4988. texCoordPool := Owner.Owner.texCoords.list;
  4989. case mode of
  4990. fgmmTriangles, fgmmFlatTriangles:
  4991. glBegin(GL_TRIANGLES);
  4992. fgmmTriangleStrip:
  4993. glBegin(GL_TRIANGLE_STRIP);
  4994. fgmmTriangleFan:
  4995. glBegin(GL_TRIANGLE_FAN);
  4996. else
  4997. Assert(False);
  4998. end;
  4999. vertexIdxList := vertexIndices.list;
  5000. if normalIndices.Count > 0 then
  5001. normalIdxList := normalIndices.list
  5002. else
  5003. normalIdxList := vertexIdxList;
  5004. if TexCoordIndices.Count > 0 then
  5005. texCoordIdxList := TexCoordIndices.list
  5006. else
  5007. texCoordIdxList := vertexIdxList;
  5008. for i := 0 to vertexIndices.Count - 1 do
  5009. begin
  5010. glNormal3fv(@normalPool[normalIdxList^[i]]);
  5011. if Assigned(colorPool) then
  5012. glColor4fv(@colorPool[vertexIdxList^[i]]);
  5013. if Assigned(texCoordPool) then
  5014. glTexCoord2fv(@texCoordPool[texCoordIdxList^[i]]);
  5015. glVertex3fv(@vertexPool[vertexIdxList^[i]]);
  5016. end;
  5017. glEnd;
  5018. end;
  5019. procedure TFGVertexNormalTexIndexList.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  5020. aNormals: TgxAffineVectorList = nil);
  5021. begin
  5022. AddToList(Owner.Owner.Vertices, aList, vertexIndices);
  5023. AddToList(Owner.Owner.texCoords, aTexCoords, TexCoordIndices);
  5024. AddToList(Owner.Owner.normals, aNormals, normalIndices);
  5025. end;
  5026. procedure TFGVertexNormalTexIndexList.Add(vertexIdx, normalIdx, texCoordIdx: Integer);
  5027. begin
  5028. inherited Add(vertexIdx);
  5029. FNormalIndices.Add(normalIdx);
  5030. FTexCoordIndices.Add(texCoordIdx);
  5031. end;
  5032. // ------------------
  5033. // ------------------ TgxFGIndexTexCoordList ------------------
  5034. // ------------------
  5035. constructor TgxFGIndexTexCoordList.Create;
  5036. begin
  5037. inherited;
  5038. FTexCoords := TgxAffineVectorList.Create;
  5039. end;
  5040. destructor TgxFGIndexTexCoordList.Destroy;
  5041. begin
  5042. FTexCoords.Free;
  5043. inherited;
  5044. end;
  5045. procedure TgxFGIndexTexCoordList.WriteToFiler(writer: TgxVirtualWriter);
  5046. begin
  5047. inherited WriteToFiler(writer);
  5048. with writer do
  5049. begin
  5050. WriteInteger(0); // Archive Version 0
  5051. FTexCoords.WriteToFiler(writer);
  5052. end;
  5053. end;
  5054. procedure TgxFGIndexTexCoordList.ReadFromFiler(reader: TgxVirtualReader);
  5055. var
  5056. archiveVersion: Integer;
  5057. begin
  5058. inherited ReadFromFiler(reader);
  5059. archiveVersion := reader.ReadInteger;
  5060. if archiveVersion = 0 then
  5061. with reader do
  5062. begin
  5063. FTexCoords.ReadFromFiler(reader);
  5064. end
  5065. else
  5066. RaiseFilerException(archiveVersion);
  5067. end;
  5068. procedure TgxFGIndexTexCoordList.SetTexCoords(const val: TgxAffineVectorList);
  5069. begin
  5070. FTexCoords.Assign(val);
  5071. end;
  5072. procedure TgxFGIndexTexCoordList.BuildList(var mrci: TgxRenderContextInfo);
  5073. var
  5074. i, k: Integer;
  5075. texCoordPool: PAffineVectorArray;
  5076. vertexPool: PAffineVectorArray;
  5077. normalPool: PAffineVectorArray;
  5078. indicesPool: PIntegerArray;
  5079. colorPool: PVectorArray;
  5080. gotColor: Boolean;
  5081. begin
  5082. Assert(vertexIndices.Count = texCoords.Count);
  5083. texCoordPool := texCoords.list;
  5084. vertexPool := Owner.Owner.Vertices.list;
  5085. indicesPool := @vertexIndices.list[0];
  5086. colorPool := @Owner.Owner.Colors.list[0];
  5087. gotColor := (Owner.Owner.Vertices.Count = Owner.Owner.Colors.Count);
  5088. case mode of
  5089. fgmmTriangles:
  5090. glBegin(GL_TRIANGLES);
  5091. fgmmFlatTriangles:
  5092. glBegin(GL_TRIANGLES);
  5093. fgmmTriangleStrip:
  5094. glBegin(GL_TRIANGLE_STRIP);
  5095. fgmmTriangleFan:
  5096. glBegin(GL_TRIANGLE_FAN);
  5097. fgmmQuads:
  5098. glBegin(GL_QUADS);
  5099. else
  5100. Assert(False);
  5101. end;
  5102. if Owner.Owner.normals.Count = Owner.Owner.Vertices.Count then
  5103. begin
  5104. normalPool := Owner.Owner.normals.list;
  5105. for i := 0 to vertexIndices.Count - 1 do
  5106. begin
  5107. glTexCoord2fv(@texCoordPool[i]);
  5108. k := indicesPool[i];
  5109. if gotColor then
  5110. glColor4fv(@colorPool[k]);
  5111. glNormal3fv(@normalPool[k]);
  5112. glVertex3fv(@vertexPool[k]);
  5113. end;
  5114. end
  5115. else
  5116. begin
  5117. for i := 0 to vertexIndices.Count - 1 do
  5118. begin
  5119. glTexCoord2fv(@texCoordPool[i]);
  5120. if gotColor then
  5121. glColor4fv(@colorPool[indicesPool[i]]);
  5122. glVertex3fv(@vertexPool[indicesPool[i]]);
  5123. end;
  5124. end;
  5125. glEnd;
  5126. /// CheckOpenGLError;
  5127. end;
  5128. procedure TgxFGIndexTexCoordList.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  5129. aNormals: TgxAffineVectorList = nil);
  5130. var
  5131. i, n: Integer;
  5132. texCoordList: TgxAffineVectorList;
  5133. begin
  5134. AddToList(Owner.Owner.Vertices, aList, vertexIndices);
  5135. AddToList(Owner.Owner.normals, aNormals, vertexIndices);
  5136. texCoordList := Self.texCoords;
  5137. case mode of
  5138. fgmmTriangles, fgmmFlatTriangles:
  5139. begin
  5140. if Assigned(aTexCoords) then
  5141. begin
  5142. n := (vertexIndices.Count div 3) * 3;
  5143. aTexCoords.AdjustCapacityToAtLeast(aTexCoords.Count + n);
  5144. for i := 0 to n - 1 do
  5145. aTexCoords.Add(texCoordList[i]);
  5146. end;
  5147. end;
  5148. fgmmTriangleStrip:
  5149. begin
  5150. if Assigned(aTexCoords) then
  5151. ConvertStripToList(aTexCoords, texCoordList);
  5152. end;
  5153. fgmmTriangleFan:
  5154. begin
  5155. if Assigned(aTexCoords) then
  5156. begin
  5157. aTexCoords.AdjustCapacityToAtLeast(aTexCoords.Count + (vertexIndices.Count - 2) * 3);
  5158. for i := 2 to vertexIndices.Count - 1 do
  5159. begin
  5160. aTexCoords.Add(texCoordList[0], texCoordList[i - 1], texCoordList[i]);
  5161. end;
  5162. end;
  5163. end;
  5164. else
  5165. Assert(False);
  5166. end;
  5167. end;
  5168. procedure TgxFGIndexTexCoordList.Add(idx: Integer; const texCoord: TAffineVector);
  5169. begin
  5170. texCoords.Add(texCoord);
  5171. inherited Add(idx);
  5172. end;
  5173. procedure TgxFGIndexTexCoordList.Add(idx: Integer; const s, t: Single);
  5174. begin
  5175. texCoords.Add(s, t, 0);
  5176. inherited Add(idx);
  5177. end;
  5178. // ------------------
  5179. // ------------------ TgxFaceGroups ------------------
  5180. // ------------------
  5181. constructor TgxFaceGroups.CreateOwned(aOwner: TgxMeshObject);
  5182. begin
  5183. FOwner := aOwner;
  5184. Create;
  5185. end;
  5186. destructor TgxFaceGroups.Destroy;
  5187. begin
  5188. Clear;
  5189. inherited;
  5190. end;
  5191. procedure TgxFaceGroups.ReadFromFiler(reader: TgxVirtualReader);
  5192. var
  5193. i: Integer;
  5194. begin
  5195. inherited;
  5196. for i := 0 to Count - 1 do
  5197. Items[i].FOwner := Self;
  5198. end;
  5199. procedure TgxFaceGroups.Clear;
  5200. var
  5201. i: Integer;
  5202. fg: TgxFaceGroup;
  5203. begin
  5204. for i := 0 to Count - 1 do
  5205. begin
  5206. fg := GetFaceGroup(i);
  5207. if Assigned(fg) then
  5208. begin
  5209. fg.FOwner := nil;
  5210. fg.Free;
  5211. end;
  5212. end;
  5213. inherited;
  5214. end;
  5215. function TgxFaceGroups.GetFaceGroup(Index: Integer): TgxFaceGroup;
  5216. begin
  5217. Result := TgxFaceGroup(list^[Index]);
  5218. end;
  5219. procedure TgxFaceGroups.PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  5220. var
  5221. i: Integer;
  5222. begin
  5223. for i := 0 to Count - 1 do
  5224. TgxFaceGroup(list^[i]).PrepareMaterialLibraryCache(matLib);
  5225. end;
  5226. procedure TgxFaceGroups.DropMaterialLibraryCache;
  5227. var
  5228. i: Integer;
  5229. begin
  5230. for i := 0 to Count - 1 do
  5231. TgxFaceGroup(list^[i]).DropMaterialLibraryCache;
  5232. end;
  5233. procedure TgxFaceGroups.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  5234. aNormals: TgxAffineVectorList = nil);
  5235. var
  5236. i: Integer;
  5237. begin
  5238. for i := 0 to Count - 1 do
  5239. Items[i].AddToTriangles(aList, aTexCoords, aNormals);
  5240. end;
  5241. function TgxFaceGroups.MaterialLibrary: TgxMaterialLibrary;
  5242. var
  5243. mol: TgxMeshObjectList;
  5244. bm: TgxBaseMesh;
  5245. begin
  5246. if Assigned(Owner) then
  5247. begin
  5248. mol := Owner.Owner;
  5249. if Assigned(mol) then
  5250. begin
  5251. bm := mol.Owner;
  5252. if Assigned(bm) then
  5253. begin
  5254. Result := bm.MaterialLibrary;;
  5255. Exit;
  5256. end;
  5257. end;
  5258. end;
  5259. Result := nil;
  5260. end;
  5261. function CompareMaterials(item1, item2: TObject): Integer;
  5262. function MaterialIsOpaque(fg: TgxFaceGroup): Boolean;
  5263. var
  5264. libMat: TgxLibMaterial;
  5265. begin
  5266. libMat := fg.MaterialCache;
  5267. Result := (not Assigned(libMat)) or (not libMat.Material.Blended);
  5268. end;
  5269. var
  5270. fg1, fg2: TgxFaceGroup;
  5271. opaque1, opaque2: Boolean;
  5272. begin
  5273. fg1 := TgxFaceGroup(item1);
  5274. opaque1 := MaterialIsOpaque(fg1);
  5275. fg2 := TgxFaceGroup(item2);
  5276. opaque2 := MaterialIsOpaque(fg2);
  5277. if opaque1 = opaque2 then
  5278. begin
  5279. Result := CompareStr(fg1.MaterialName, fg2.MaterialName);
  5280. if Result = 0 then
  5281. Result := fg1.LightMapIndex - fg2.LightMapIndex;
  5282. end
  5283. else if opaque1 then
  5284. Result := -1
  5285. else
  5286. Result := 1;
  5287. end;
  5288. procedure TgxFaceGroups.SortByMaterial;
  5289. begin
  5290. PrepareMaterialLibraryCache(Owner.Owner.Owner.MaterialLibrary);
  5291. Sort(@CompareMaterials);
  5292. end;
  5293. // ------------------
  5294. // ------------------ TgxVectorFile ------------------
  5295. // ------------------
  5296. constructor TgxVectorFile.Create(aOwner: TPersistent);
  5297. begin
  5298. Assert(aOwner is TgxBaseMesh);
  5299. inherited;
  5300. end;
  5301. function TgxVectorFile.Owner: TgxBaseMesh;
  5302. begin
  5303. Result := TgxBaseMesh(GetOwner);
  5304. end;
  5305. procedure TgxVectorFile.SetNormalsOrientation(const val: TgxMeshNormalsOrientation);
  5306. begin
  5307. FNormalsOrientation := val;
  5308. end;
  5309. // ------------------
  5310. // ------------------ TgxVectorFileGLSM ------------------
  5311. // ------------------
  5312. class function TgxVectorFileGLSM.Capabilities: TDataFileCapabilities;
  5313. begin
  5314. Result := [dfcRead, dfcWrite];
  5315. end;
  5316. procedure TgxVectorFileGLSM.LoadFromStream(aStream: TStream);
  5317. begin
  5318. Owner.MeshObjects.LoadFromStream(aStream);
  5319. end;
  5320. procedure TgxVectorFileGLSM.SaveToStream(aStream: TStream);
  5321. begin
  5322. Owner.MeshObjects.SaveToStream(aStream);
  5323. end;
  5324. // ------------------
  5325. // ------------------ TgxBaseMesh ------------------
  5326. // ------------------
  5327. constructor TgxBaseMesh.Create(aOwner: TComponent);
  5328. begin
  5329. inherited Create(aOwner);
  5330. if FMeshObjects = nil then
  5331. FMeshObjects := TgxMeshObjectList.CreateOwned(Self);
  5332. if FSkeleton = nil then
  5333. FSkeleton := TgxSkeleton.CreateOwned(Self);
  5334. FUseMeshMaterials := True;
  5335. FAutoCentering := [];
  5336. FAxisAlignedDimensionsCache.X := -1;
  5337. FBaryCenterOffsetChanged := True;
  5338. FAutoScaling := TgxCoordinates.CreateInitialized(Self, XYZWHmgVector, csPoint);
  5339. end;
  5340. destructor TgxBaseMesh.Destroy;
  5341. begin
  5342. FConnectivity.Free;
  5343. DropMaterialLibraryCache;
  5344. FSkeleton.Free;
  5345. FMeshObjects.Free;
  5346. FAutoScaling.Free;
  5347. inherited Destroy;
  5348. end;
  5349. procedure TgxBaseMesh.Assign(Source: TPersistent);
  5350. begin
  5351. if Source is TgxBaseMesh then
  5352. begin
  5353. FSkeleton.Clear;
  5354. FNormalsOrientation := TgxBaseMesh(Source).FNormalsOrientation;
  5355. FMaterialLibrary := TgxBaseMesh(Source).FMaterialLibrary;
  5356. FLightmapLibrary := TgxBaseMesh(Source).FLightmapLibrary;
  5357. FAxisAlignedDimensionsCache := TgxBaseMesh(Source).FAxisAlignedDimensionsCache;
  5358. FBaryCenterOffset := TgxBaseMesh(Source).FBaryCenterOffset;
  5359. FUseMeshMaterials := TgxBaseMesh(Source).FUseMeshMaterials;
  5360. FOverlaySkeleton := TgxBaseMesh(Source).FOverlaySkeleton;
  5361. FIgnoreMissingTextures := TgxBaseMesh(Source).FIgnoreMissingTextures;
  5362. FAutoCentering := TgxBaseMesh(Source).FAutoCentering;
  5363. FAutoScaling.Assign(TgxBaseMesh(Source).FAutoScaling);
  5364. FSkeleton.Assign(TgxBaseMesh(Source).FSkeleton);
  5365. FSkeleton.RootBones.PrepareGlobalMatrices;
  5366. FMeshObjects.Assign(TgxBaseMesh(Source).FMeshObjects);
  5367. end;
  5368. inherited Assign(Source);
  5369. end;
  5370. procedure TgxBaseMesh.LoadFromFile(const filename: string);
  5371. var
  5372. fs: TStream;
  5373. begin
  5374. FLastLoadedFilename := '';
  5375. if filename <> '' then
  5376. begin
  5377. fs := TFileStream.Create(filename, fmOpenRead + fmShareDenyWrite);
  5378. try
  5379. LoadFromStream(filename, fs);
  5380. FLastLoadedFilename := filename;
  5381. finally
  5382. fs.Free;
  5383. end;
  5384. end;
  5385. end;
  5386. procedure TgxBaseMesh.LoadFromStream(const filename: string; aStream: TStream);
  5387. var
  5388. newVectorFile: TgxVectorFile;
  5389. VectorFileClass: TgxVectorFileClass;
  5390. begin
  5391. FLastLoadedFilename := '';
  5392. if filename <> '' then
  5393. begin
  5394. MeshObjects.Clear;
  5395. Skeleton.Clear;
  5396. VectorFileClass := GetVectorFileFormats.FindFromFileName(filename);
  5397. newVectorFile := VectorFileClass.Create(Self);
  5398. try
  5399. newVectorFile.ResourceName := filename;
  5400. PrepareVectorFile(newVectorFile);
  5401. if Assigned(Scene) then
  5402. Scene.BeginUpdate;
  5403. try
  5404. newVectorFile.LoadFromStream(aStream);
  5405. FLastLoadedFilename := filename;
  5406. finally
  5407. if Assigned(Scene) then
  5408. Scene.EndUpdate;
  5409. end;
  5410. finally
  5411. newVectorFile.Free;
  5412. end;
  5413. PerformAutoScaling;
  5414. PerformAutoCentering;
  5415. PrepareMesh;
  5416. end;
  5417. end;
  5418. procedure TgxBaseMesh.SaveToFile(const filename: string);
  5419. var
  5420. fs: TStream;
  5421. begin
  5422. if filename <> '' then
  5423. begin
  5424. fs := TFileStream.Create(filename, fmCreate);
  5425. try
  5426. SaveToStream(filename, fs);
  5427. finally
  5428. fs.Free;
  5429. end;
  5430. end;
  5431. end;
  5432. procedure TgxBaseMesh.SaveToStream(const filename: string; aStream: TStream);
  5433. var
  5434. newVectorFile: TgxVectorFile;
  5435. VectorFileClass: TgxVectorFileClass;
  5436. begin
  5437. if filename <> '' then
  5438. begin
  5439. VectorFileClass := GetVectorFileFormats.FindFromFileName(filename);
  5440. newVectorFile := VectorFileClass.Create(Self);
  5441. try
  5442. newVectorFile.ResourceName := filename;
  5443. PrepareVectorFile(newVectorFile);
  5444. newVectorFile.SaveToStream(aStream);
  5445. finally
  5446. newVectorFile.Free;
  5447. end;
  5448. end;
  5449. end;
  5450. procedure TgxBaseMesh.AddDataFromFile(const filename: string);
  5451. var
  5452. fs: TStream;
  5453. begin
  5454. if filename <> '' then
  5455. begin
  5456. fs := TFileStream.Create(filename, fmOpenRead + fmShareDenyWrite);
  5457. try
  5458. AddDataFromStream(filename, fs);
  5459. finally
  5460. fs.Free;
  5461. end;
  5462. end;
  5463. end;
  5464. procedure TgxBaseMesh.AddDataFromStream(const filename: string; aStream: TStream);
  5465. var
  5466. newVectorFile: TgxVectorFile;
  5467. VectorFileClass: TgxVectorFileClass;
  5468. begin
  5469. if filename <> '' then
  5470. begin
  5471. VectorFileClass := GetVectorFileFormats.FindFromFileName(filename);
  5472. newVectorFile := VectorFileClass.Create(Self);
  5473. newVectorFile.ResourceName := filename;
  5474. PrepareVectorFile(newVectorFile);
  5475. try
  5476. if Assigned(Scene) then
  5477. Scene.BeginUpdate;
  5478. newVectorFile.LoadFromStream(aStream);
  5479. if Assigned(Scene) then
  5480. Scene.EndUpdate;
  5481. finally
  5482. newVectorFile.Free;
  5483. end;
  5484. PrepareMesh;
  5485. end;
  5486. end;
  5487. procedure TgxBaseMesh.GetExtents(out min, max: TAffineVector);
  5488. var
  5489. i, k: Integer;
  5490. lMin, lMax: TAffineVector;
  5491. const
  5492. cBigValue: Single = 1E50;
  5493. cSmallValue: Single = -1E50;
  5494. begin
  5495. SetVector(min, cBigValue, cBigValue, cBigValue);
  5496. SetVector(max, cSmallValue, cSmallValue, cSmallValue);
  5497. for i := 0 to MeshObjects.Count - 1 do
  5498. begin
  5499. TgxMeshObject(MeshObjects[i]).GetExtents(lMin, lMax);
  5500. for k := 0 to 2 do
  5501. begin
  5502. if lMin.v[k] < min.v[k] then
  5503. min.v[k] := lMin.v[k];
  5504. if lMax.v[k] > max.v[k] then
  5505. max.v[k] := lMax.v[k];
  5506. end;
  5507. end;
  5508. end;
  5509. function TgxBaseMesh.GetBarycenter: TAffineVector;
  5510. var
  5511. i, nb: Integer;
  5512. begin
  5513. Result := NullVector;
  5514. nb := 0;
  5515. for i := 0 to MeshObjects.Count - 1 do
  5516. TgxMeshObject(MeshObjects[i]).ContributeToBarycenter(Result, nb);
  5517. if nb > 0 then
  5518. ScaleVector(Result, 1 / nb);
  5519. end;
  5520. function TgxBaseMesh.LastLoadedFilename: string;
  5521. begin
  5522. Result := FLastLoadedFilename;
  5523. end;
  5524. procedure TgxBaseMesh.SetMaterialLibrary(const val: TgxMaterialLibrary);
  5525. begin
  5526. if FMaterialLibrary <> val then
  5527. begin
  5528. if FMaterialLibraryCachesPrepared then
  5529. DropMaterialLibraryCache;
  5530. if Assigned(FMaterialLibrary) then
  5531. begin
  5532. DestroyHandle;
  5533. FMaterialLibrary.RemoveFreeNotification(Self);
  5534. end;
  5535. FMaterialLibrary := val;
  5536. if Assigned(FMaterialLibrary) then
  5537. FMaterialLibrary.FreeNotification(Self);
  5538. StructureChanged;
  5539. end;
  5540. end;
  5541. procedure TgxBaseMesh.SetLightmapLibrary(const val: TgxMaterialLibrary);
  5542. begin
  5543. if FLightmapLibrary <> val then
  5544. begin
  5545. if Assigned(FLightmapLibrary) then
  5546. begin
  5547. DestroyHandle;
  5548. FLightmapLibrary.RemoveFreeNotification(Self);
  5549. end;
  5550. FLightmapLibrary := val;
  5551. if Assigned(FLightmapLibrary) then
  5552. FLightmapLibrary.FreeNotification(Self);
  5553. StructureChanged;
  5554. end;
  5555. end;
  5556. procedure TgxBaseMesh.SetNormalsOrientation(const val: TgxMeshNormalsOrientation);
  5557. begin
  5558. if val <> FNormalsOrientation then
  5559. begin
  5560. FNormalsOrientation := val;
  5561. StructureChanged;
  5562. end;
  5563. end;
  5564. procedure TgxBaseMesh.SetOverlaySkeleton(const val: Boolean);
  5565. begin
  5566. if FOverlaySkeleton <> val then
  5567. begin
  5568. FOverlaySkeleton := val;
  5569. NotifyChange(Self);
  5570. end;
  5571. end;
  5572. procedure TgxBaseMesh.SetAutoScaling(const Value: TgxCoordinates);
  5573. begin
  5574. FAutoScaling.SetPoint(Value.DirectX, Value.DirectY, Value.DirectZ);
  5575. end;
  5576. procedure TgxBaseMesh.Notification(AComponent: TComponent; Operation: TOperation);
  5577. begin
  5578. if Operation = opRemove then
  5579. begin
  5580. if AComponent = FMaterialLibrary then
  5581. MaterialLibrary := nil
  5582. else if AComponent = FLightmapLibrary then
  5583. LightmapLibrary := nil;
  5584. end;
  5585. inherited;
  5586. end;
  5587. function TgxBaseMesh.AxisAlignedDimensionsUnscaled: TVector4f;
  5588. var
  5589. dMin, dMax: TAffineVector;
  5590. begin
  5591. if FAxisAlignedDimensionsCache.X < 0 then
  5592. begin
  5593. MeshObjects.GetExtents(dMin, dMax);
  5594. FAxisAlignedDimensionsCache.X := (dMax.X - dMin.X) / 2;
  5595. FAxisAlignedDimensionsCache.Y := (dMax.Y - dMin.Y) / 2;
  5596. FAxisAlignedDimensionsCache.Z := (dMax.Z - dMin.Z) / 2;
  5597. FAxisAlignedDimensionsCache.W := 0;
  5598. end;
  5599. SetVector(Result, FAxisAlignedDimensionsCache);
  5600. end;
  5601. function TgxBaseMesh.BarycenterOffset: TVector4f;
  5602. var
  5603. dMin, dMax: TAffineVector;
  5604. begin
  5605. if FBaryCenterOffsetChanged then
  5606. begin
  5607. MeshObjects.GetExtents(dMin, dMax);
  5608. FBaryCenterOffset.X := (dMin.X + dMax.X) / 2;
  5609. FBaryCenterOffset.Y := (dMin.Y + dMax.Y) / 2;
  5610. FBaryCenterOffset.Z := (dMin.Z + dMax.Z) / 2;
  5611. FBaryCenterOffset.W := 0;
  5612. FBaryCenterOffsetChanged := False;
  5613. end;
  5614. Result := FBaryCenterOffset;
  5615. end;
  5616. function TgxBaseMesh.BarycenterPosition: TVector4f;
  5617. begin
  5618. Result := VectorAdd(Position.DirectVector, BarycenterOffset);
  5619. end;
  5620. function TgxBaseMesh.BarycenterAbsolutePosition: TVector4f;
  5621. begin
  5622. Result := LocalToAbsolute(BarycenterPosition);
  5623. end;
  5624. procedure TgxBaseMesh.DestroyHandle;
  5625. begin
  5626. if Assigned(FMaterialLibrary) then
  5627. MaterialLibrary.DestroyHandles;
  5628. if Assigned(FLightmapLibrary) then
  5629. LightmapLibrary.DestroyHandles;
  5630. inherited;
  5631. end;
  5632. procedure TgxBaseMesh.PrepareVectorFile(aFile: TgxVectorFile);
  5633. begin
  5634. aFile.NormalsOrientation := NormalsOrientation;
  5635. end;
  5636. procedure TgxBaseMesh.PerformAutoCentering;
  5637. var
  5638. delta, min, max: TAffineVector;
  5639. begin
  5640. if macUseBarycenter in AutoCentering then
  5641. begin
  5642. delta := VectorNegate(GetBarycenter);
  5643. end
  5644. else
  5645. begin
  5646. GetExtents(min, max);
  5647. if macCenterX in AutoCentering then
  5648. delta.X := -0.5 * (min.X + max.X)
  5649. else
  5650. delta.X := 0;
  5651. if macCenterY in AutoCentering then
  5652. delta.Y := -0.5 * (min.Y + max.Y)
  5653. else
  5654. delta.Y := 0;
  5655. if macCenterZ in AutoCentering then
  5656. delta.Z := -0.5 * (min.Z + max.Z)
  5657. else
  5658. delta.Z := 0;
  5659. end;
  5660. MeshObjects.Translate(delta);
  5661. if macRestorePosition in AutoCentering then
  5662. Position.Translate(VectorNegate(delta));
  5663. end;
  5664. procedure TgxBaseMesh.PerformAutoScaling;
  5665. var
  5666. i: Integer;
  5667. vScal: TAffineFltVector;
  5668. begin
  5669. if (FAutoScaling.DirectX <> 1) or (FAutoScaling.DirectY <> 1) or (FAutoScaling.DirectZ <> 1) then
  5670. begin
  5671. MakeVector(vScal, FAutoScaling.DirectX, FAutoScaling.DirectY, FAutoScaling.DirectZ);
  5672. for i := 0 to MeshObjects.Count - 1 do
  5673. begin
  5674. MeshObjects[i].Vertices.Scale(vScal);
  5675. end;
  5676. end;
  5677. end;
  5678. procedure TgxBaseMesh.PrepareMesh;
  5679. begin
  5680. StructureChanged;
  5681. end;
  5682. procedure TgxBaseMesh.PrepareMaterialLibraryCache;
  5683. begin
  5684. if FMaterialLibraryCachesPrepared then
  5685. DropMaterialLibraryCache;
  5686. MeshObjects.PrepareMaterialLibraryCache(FMaterialLibrary);
  5687. FMaterialLibraryCachesPrepared := True;
  5688. end;
  5689. procedure TgxBaseMesh.DropMaterialLibraryCache;
  5690. begin
  5691. if FMaterialLibraryCachesPrepared then
  5692. begin
  5693. MeshObjects.DropMaterialLibraryCache;
  5694. FMaterialLibraryCachesPrepared := False;
  5695. end;
  5696. end;
  5697. procedure TgxBaseMesh.PrepareBuildList(var mrci: TgxRenderContextInfo);
  5698. begin
  5699. MeshObjects.PrepareBuildList(mrci);
  5700. if LightmapLibrary <> nil then
  5701. LightmapLibrary.Materials.PrepareBuildList
  5702. end;
  5703. procedure TgxBaseMesh.SetUseMeshMaterials(const val: Boolean);
  5704. begin
  5705. if val <> FUseMeshMaterials then
  5706. begin
  5707. FUseMeshMaterials := val;
  5708. if FMaterialLibraryCachesPrepared and (not val) then
  5709. DropMaterialLibraryCache;
  5710. StructureChanged;
  5711. end;
  5712. end;
  5713. procedure TgxBaseMesh.BuildList(var rci: TgxRenderContextInfo);
  5714. begin
  5715. MeshObjects.BuildList(rci);
  5716. end;
  5717. procedure TgxBaseMesh.DoRender(var rci: TgxRenderContextInfo; renderSelf, renderChildren: Boolean);
  5718. begin
  5719. if Assigned(LightmapLibrary) then
  5720. xglForbidSecondTextureUnit;
  5721. if renderSelf then
  5722. begin
  5723. // set winding
  5724. case FNormalsOrientation of
  5725. mnoDefault:
  5726. ; // nothing
  5727. mnoInvert:
  5728. rci.gxStates.InvertFrontFace;
  5729. else
  5730. Assert(False);
  5731. end;
  5732. if not rci.ignoreMaterials then
  5733. begin
  5734. if UseMeshMaterials and Assigned(MaterialLibrary) then
  5735. begin
  5736. rci.MaterialLibrary := MaterialLibrary;
  5737. if not FMaterialLibraryCachesPrepared then
  5738. PrepareMaterialLibraryCache;
  5739. end
  5740. else
  5741. rci.MaterialLibrary := nil;
  5742. if Assigned(LightmapLibrary) then
  5743. rci.LightmapLibrary := LightmapLibrary
  5744. else
  5745. rci.LightmapLibrary := nil;
  5746. if rci.amalgamating or not(ListHandleAllocated or (osDirectDraw in ObjectStyle)) then
  5747. PrepareBuildList(rci);
  5748. Material.Apply(rci);
  5749. repeat
  5750. if (osDirectDraw in ObjectStyle) or rci.amalgamating or UseMeshMaterials then
  5751. BuildList(rci)
  5752. else
  5753. rci.gxStates.CallList(GetHandle(rci));
  5754. until not Material.UnApply(rci);
  5755. rci.MaterialLibrary := nil;
  5756. end
  5757. else
  5758. begin
  5759. if (osDirectDraw in ObjectStyle) or rci.amalgamating then
  5760. BuildList(rci)
  5761. else
  5762. rci.gxStates.CallList(GetHandle(rci));
  5763. end;
  5764. if FNormalsOrientation <> mnoDefault then
  5765. rci.gxStates.InvertFrontFace;
  5766. end;
  5767. if Assigned(LightmapLibrary) then
  5768. xglAllowSecondTextureUnit;
  5769. if renderChildren and (Count > 0) then
  5770. Self.renderChildren(0, Count - 1, rci);
  5771. end;
  5772. procedure TgxBaseMesh.StructureChanged;
  5773. begin
  5774. FAxisAlignedDimensionsCache.X := -1;
  5775. FBaryCenterOffsetChanged := True;
  5776. DropMaterialLibraryCache;
  5777. MeshObjects.Prepare;
  5778. inherited;
  5779. end;
  5780. procedure TgxBaseMesh.StructureChangedNoPrepare;
  5781. begin
  5782. inherited StructureChanged;
  5783. end;
  5784. function TgxBaseMesh.RayCastIntersect(const rayStart, rayVector: TVector4f; intersectPoint: PVector4f = nil;
  5785. intersectNormal: PVector4f = nil): Boolean;
  5786. var
  5787. i: Integer;
  5788. tris: TgxAffineVectorList;
  5789. locRayStart, locRayVector, iPoint, iNormal: TVector4f;
  5790. d, minD: Single;
  5791. begin
  5792. // BEWARE! Utterly inefficient implementation!
  5793. tris := MeshObjects.ExtractTriangles;
  5794. try
  5795. SetVector(locRayStart, AbsoluteToLocal(rayStart));
  5796. SetVector(locRayVector, AbsoluteToLocal(rayVector));
  5797. minD := -1;
  5798. i := 0;
  5799. while i < tris.Count do
  5800. begin
  5801. if RayCastTriangleIntersect(locRayStart, locRayVector, tris.list^[i], tris.list^[i + 1], tris.list^[i + 2], @iPoint,
  5802. @iNormal) then
  5803. begin
  5804. d := VectorDistance2(locRayStart, iPoint);
  5805. if (d < minD) or (minD < 0) then
  5806. begin
  5807. minD := d;
  5808. if intersectPoint <> nil then
  5809. intersectPoint^ := iPoint;
  5810. if intersectNormal <> nil then
  5811. intersectNormal^ := iNormal;
  5812. end;
  5813. end;
  5814. Inc(i, 3);
  5815. end;
  5816. finally
  5817. tris.Free;
  5818. end;
  5819. Result := (minD >= 0);
  5820. if Result then
  5821. begin
  5822. if intersectPoint <> nil then
  5823. SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
  5824. if intersectNormal <> nil then
  5825. begin
  5826. SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
  5827. if NormalsOrientation = mnoInvert then
  5828. NegateVector(intersectNormal^);
  5829. end;
  5830. end;
  5831. end;
  5832. function TgxBaseMesh.GenerateSilhouette(const SilhouetteParameters: TgxSilhouetteParameters): TgxSilhouette;
  5833. var
  5834. mc: TgxBaseMeshConnectivity;
  5835. sil: TgxSilhouette;
  5836. begin
  5837. sil := nil;
  5838. if Assigned(FConnectivity) then
  5839. begin
  5840. mc := TgxBaseMeshConnectivity(FConnectivity);
  5841. mc.CreateSilhouette(silhouetteParameters, sil, True);
  5842. end
  5843. else
  5844. begin
  5845. mc := TgxBaseMeshConnectivity.CreateFromMesh(Self);
  5846. try
  5847. mc.CreateSilhouette(silhouetteParameters, sil, True);
  5848. finally
  5849. mc.Free;
  5850. end;
  5851. end;
  5852. Result := sil;
  5853. end;
  5854. procedure TgxBaseMesh.BuildSilhouetteConnectivityData;
  5855. var
  5856. i, j: Integer;
  5857. mo: TgxMeshObject;
  5858. begin
  5859. FreeAndNil(FConnectivity);
  5860. // connectivity data works only on facegroups of TgxFGVertexIndexList class
  5861. for i := 0 to MeshObjects.Count - 1 do
  5862. begin
  5863. mo := (MeshObjects[i] as TgxMeshObject);
  5864. if mo.mode <> momFaceGroups then
  5865. Exit;
  5866. for j := 0 to mo.FaceGroups.Count - 1 do
  5867. if not mo.FaceGroups[j].InheritsFrom(TgxFGVertexIndexList) then
  5868. Exit;
  5869. end;
  5870. FConnectivity := TgxBaseMeshConnectivity.CreateFromMesh(Self);
  5871. end;
  5872. // ------------------
  5873. // ------------------ TgxFreeForm ------------------
  5874. // ------------------
  5875. constructor TgxFreeForm.Create(aOwner: TComponent);
  5876. begin
  5877. inherited;
  5878. // ObjectStyle := [osDirectDraw];
  5879. FUseMeshMaterials := True;
  5880. end;
  5881. destructor TgxFreeForm.Destroy;
  5882. begin
  5883. FOctree.Free;
  5884. inherited Destroy;
  5885. end;
  5886. function TgxFreeForm.GetOctree: TgxOctree;
  5887. begin
  5888. // if not Assigned(FOctree) then //If auto-created, can never use "if Assigned(GLFreeform1.Octree)"
  5889. // FOctree:=TOctree.Create; //moved this code to BuildOctree
  5890. Result := FOctree;
  5891. end;
  5892. procedure TgxFreeForm.BuildOctree(TreeDepth: Integer = 3);
  5893. var
  5894. emin, emax: TAffineVector;
  5895. tl: TgxAffineVectorList;
  5896. begin
  5897. if not Assigned(FOctree) then // moved here from GetOctree
  5898. FOctree := TgxOctree.Create;
  5899. GetExtents(emin, emax);
  5900. tl := MeshObjects.ExtractTriangles;
  5901. try
  5902. with Octree do
  5903. begin
  5904. DisposeTree;
  5905. InitializeTree(emin, emax, tl, TreeDepth);
  5906. end;
  5907. finally
  5908. tl.Free;
  5909. end;
  5910. end;
  5911. function TgxFreeForm.OctreeRayCastIntersect(const rayStart, rayVector: TVector4f; intersectPoint: PVector4f = nil;
  5912. intersectNormal: PVector4f = nil): Boolean;
  5913. var
  5914. locRayStart, locRayVector: TVector4f;
  5915. begin
  5916. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  5917. SetVector(locRayStart, AbsoluteToLocal(rayStart));
  5918. SetVector(locRayVector, AbsoluteToLocal(rayVector));
  5919. Result := Octree.RayCastIntersect(locRayStart, locRayVector, intersectPoint, intersectNormal);
  5920. if Result then
  5921. begin
  5922. if intersectPoint <> nil then
  5923. SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
  5924. if intersectNormal <> nil then
  5925. begin
  5926. SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
  5927. if NormalsOrientation = mnoInvert then
  5928. NegateVector(intersectNormal^);
  5929. end;
  5930. end;
  5931. end;
  5932. function TgxFreeForm.OctreePointInMesh(const Point: TVector4f): Boolean;
  5933. const
  5934. cPointRadiusStep = 10000;
  5935. var
  5936. rayStart, rayVector, hitPoint, hitNormal: TVector4f;
  5937. BRad: double;
  5938. HitCount: Integer;
  5939. hitDot: double;
  5940. begin
  5941. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  5942. Result := False;
  5943. // Makes calculations sligthly faster by ignoring cases that are guaranteed
  5944. // to be outside the object
  5945. if not PointInObject(Point) then
  5946. Exit;
  5947. BRad := BoundingSphereRadius;
  5948. // This could be a fixed vector, but a fixed vector could have a systemic
  5949. // bug on an non-closed mesh, making it fail constantly for one or several
  5950. // faces.
  5951. rayVector := VectorMake(2 * random - 1, 2 * random - 1, 2 * random - 1);
  5952. rayStart := VectorAdd(VectorScale(rayVector, -BRad), Point);
  5953. HitCount := 0;
  5954. while OctreeRayCastIntersect(rayStart, rayVector, @hitPoint, @hitNormal) do
  5955. begin
  5956. // Are we past our taget?
  5957. if VectorDotProduct(rayVector, VectorSubtract(Point, hitPoint)) < 0 then
  5958. begin
  5959. Result := HitCount > 0;
  5960. Exit;
  5961. end;
  5962. hitDot := VectorDotProduct(hitNormal, rayVector);
  5963. if hitDot < 0 then
  5964. Inc(HitCount)
  5965. else if hitDot > 0 then
  5966. Dec(HitCount);
  5967. // ditDot = 0 is a tricky special case where the ray is just grazing the
  5968. // side of a face - this case means that it doesn't necessarily actually
  5969. // enter the mesh - but it _could_ enter the mesh. If this situation occurs,
  5970. // we should restart the run using a new rayVector - but this implementation
  5971. // currently doesn't.
  5972. // Restart the ray slightly beyond the point it hit the previous face. Note
  5973. // that this step introduces a possible issue with faces that are very close
  5974. rayStart := VectorAdd(hitPoint, VectorScale(rayVector, BRad / cPointRadiusStep));
  5975. end;
  5976. end;
  5977. function TgxFreeForm.OctreeSphereSweepIntersect(const rayStart, rayVector: TVector4f; const velocity, radius: Single;
  5978. intersectPoint: PVector4f = nil; intersectNormal: PVector4f = nil): Boolean;
  5979. var
  5980. locRayStart, locRayVector: TVector4f;
  5981. begin
  5982. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  5983. SetVector(locRayStart, AbsoluteToLocal(rayStart));
  5984. SetVector(locRayVector, AbsoluteToLocal(rayVector));
  5985. Result := Octree.SphereSweepIntersect(locRayStart, locRayVector, velocity, radius, intersectPoint, intersectNormal);
  5986. if Result then
  5987. begin
  5988. if intersectPoint <> nil then
  5989. SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
  5990. if intersectNormal <> nil then
  5991. begin
  5992. SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
  5993. if NormalsOrientation = mnoInvert then
  5994. NegateVector(intersectNormal^);
  5995. end;
  5996. end;
  5997. end;
  5998. function TgxFreeForm.OctreeTriangleIntersect(const v1, v2, v3: TAffineVector): Boolean;
  5999. var
  6000. t1, t2, t3: TAffineVector;
  6001. begin
  6002. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  6003. SetVector(t1, AbsoluteToLocal(v1));
  6004. SetVector(t2, AbsoluteToLocal(v2));
  6005. SetVector(t3, AbsoluteToLocal(v3));
  6006. Result := Octree.TriangleIntersect(t1, t2, t3);
  6007. end;
  6008. function TgxFreeForm.OctreeAABBIntersect(const aabb: TAABB; objMatrix, invObjMatrix: TMatrix4f;
  6009. triangles: TgxAffineVectorList = nil): Boolean;
  6010. var
  6011. m1to2, m2to1: TMatrix4f;
  6012. begin
  6013. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  6014. // get matrixes needed
  6015. // object to self
  6016. MatrixMultiply(objMatrix, InvAbsoluteMatrix, m1to2);
  6017. // self to object
  6018. MatrixMultiply(AbsoluteMatrix, invObjMatrix, m2to1);
  6019. Result := Octree.AABBIntersect(aabb, m1to2, m2to1, triangles);
  6020. end;
  6021. // ------------------
  6022. // ------------------ TgxActorAnimation ------------------
  6023. // ------------------
  6024. constructor TgxActorAnimation.Create(Collection: TCollection);
  6025. begin
  6026. inherited Create(Collection);
  6027. end;
  6028. destructor TgxActorAnimation.Destroy;
  6029. begin
  6030. with (Collection as TgxActorAnimations).FOwner do
  6031. if FTargetSmoothAnimation = Self then
  6032. FTargetSmoothAnimation := nil;
  6033. inherited Destroy;
  6034. end;
  6035. procedure TgxActorAnimation.Assign(Source: TPersistent);
  6036. begin
  6037. if Source is TgxActorAnimation then
  6038. begin
  6039. FName := TgxActorAnimation(Source).FName;
  6040. FStartFrame := TgxActorAnimation(Source).FStartFrame;
  6041. FEndFrame := TgxActorAnimation(Source).FEndFrame;
  6042. FReference := TgxActorAnimation(Source).FReference;
  6043. end
  6044. else
  6045. inherited;
  6046. end;
  6047. function TgxActorAnimation.GetDisplayName: string;
  6048. begin
  6049. Result := Format('%d - %s [%d - %d]', [Index, Name, startFrame, endFrame]);
  6050. end;
  6051. function TgxActorAnimation.FrameCount: Integer;
  6052. begin
  6053. case reference of
  6054. aarMorph:
  6055. Result := TgxActorAnimations(Collection).FOwner.MeshObjects.MorphTargetCount;
  6056. aarSkeleton:
  6057. Result := TgxActorAnimations(Collection).FOwner.Skeleton.Frames.Count;
  6058. else
  6059. Result := 0;
  6060. Assert(False);
  6061. end;
  6062. end;
  6063. procedure TgxActorAnimation.SetStartFrame(const val: Integer);
  6064. var
  6065. m: Integer;
  6066. begin
  6067. if val < 0 then
  6068. FStartFrame := 0
  6069. else
  6070. begin
  6071. m := FrameCount;
  6072. if val >= m then
  6073. FStartFrame := m - 1
  6074. else
  6075. FStartFrame := val;
  6076. end;
  6077. if FStartFrame > FEndFrame then
  6078. FEndFrame := FStartFrame;
  6079. end;
  6080. procedure TgxActorAnimation.SetEndFrame(const val: Integer);
  6081. var
  6082. m: Integer;
  6083. begin
  6084. if val < 0 then
  6085. FEndFrame := 0
  6086. else
  6087. begin
  6088. m := FrameCount;
  6089. if val >= m then
  6090. FEndFrame := m - 1
  6091. else
  6092. FEndFrame := val;
  6093. end;
  6094. if FStartFrame > FEndFrame then
  6095. FStartFrame := FEndFrame;
  6096. end;
  6097. procedure TgxActorAnimation.SetReference(val: TgxActorAnimationReference);
  6098. begin
  6099. if val <> FReference then
  6100. begin
  6101. FReference := val;
  6102. startFrame := startFrame;
  6103. endFrame := endFrame;
  6104. end;
  6105. end;
  6106. procedure TgxActorAnimation.SetAsString(const val: string);
  6107. var
  6108. sl: TStringList;
  6109. begin
  6110. sl := TStringList.Create;
  6111. try
  6112. sl.CommaText := val;
  6113. Assert(sl.Count >= 3);
  6114. FName := sl[0];
  6115. FStartFrame := StrToInt(sl[1]);
  6116. FEndFrame := StrToInt(sl[2]);
  6117. if sl.Count = 4 then
  6118. begin
  6119. if LowerCase(sl[3]) = 'morph' then
  6120. reference := aarMorph
  6121. else if LowerCase(sl[3]) = 'skeleton' then
  6122. reference := aarSkeleton
  6123. else
  6124. Assert(False);
  6125. end
  6126. else
  6127. reference := aarMorph;
  6128. finally
  6129. sl.Free;
  6130. end;
  6131. end;
  6132. function TgxActorAnimation.GetAsString: string;
  6133. const
  6134. cAARToString: array [aarMorph .. aarSkeleton] of string = ('morph', 'skeleton');
  6135. begin
  6136. Result := Format('"%s",%d,%d,%s', [FName, FStartFrame, FEndFrame, cAARToString[reference]]);
  6137. end;
  6138. function TgxActorAnimation.OwnerActor: TgxActor;
  6139. begin
  6140. Result := ((Collection as TgxActorAnimations).GetOwner as TgxActor);
  6141. end;
  6142. procedure TgxActorAnimation.MakeSkeletalTranslationStatic;
  6143. begin
  6144. OwnerActor.Skeleton.MakeSkeletalTranslationStatic(startFrame, endFrame);
  6145. end;
  6146. procedure TgxActorAnimation.MakeSkeletalRotationDelta;
  6147. begin
  6148. OwnerActor.Skeleton.MakeSkeletalRotationDelta(startFrame, endFrame);
  6149. end;
  6150. // ------------------
  6151. // ------------------ TgxActorAnimations ------------------
  6152. // ------------------
  6153. constructor TgxActorAnimations.Create(aOwner: TgxActor);
  6154. begin
  6155. FOwner := aOwner;
  6156. inherited Create(TgxActorAnimation);
  6157. end;
  6158. function TgxActorAnimations.GetOwner: TPersistent;
  6159. begin
  6160. Result := FOwner;
  6161. end;
  6162. procedure TgxActorAnimations.SetItems(Index: Integer; const val: TgxActorAnimation);
  6163. begin
  6164. inherited Items[index] := val;
  6165. end;
  6166. function TgxActorAnimations.GetItems(Index: Integer): TgxActorAnimation;
  6167. begin
  6168. Result := TgxActorAnimation(inherited Items[index]);
  6169. end;
  6170. function TgxActorAnimations.Last: TgxActorAnimation;
  6171. begin
  6172. if Count > 0 then
  6173. Result := TgxActorAnimation(inherited Items[Count - 1])
  6174. else
  6175. Result := nil;
  6176. end;
  6177. function TgxActorAnimations.Add: TgxActorAnimation;
  6178. begin
  6179. Result := (inherited Add) as TgxActorAnimation;
  6180. end;
  6181. function TgxActorAnimations.FindItemID(ID: Integer): TgxActorAnimation;
  6182. begin
  6183. Result := (inherited FindItemID(ID)) as TgxActorAnimation;
  6184. end;
  6185. function TgxActorAnimations.FindName(const aName: string): TgxActorAnimation;
  6186. var
  6187. i: Integer;
  6188. begin
  6189. Result := nil;
  6190. for i := 0 to Count - 1 do
  6191. if CompareText(Items[i].Name, aName) = 0 then
  6192. begin
  6193. Result := Items[i];
  6194. Break;
  6195. end;
  6196. end;
  6197. function TgxActorAnimations.FindFrame(aFrame: Integer; aReference: TgxActorAnimationReference): TgxActorAnimation;
  6198. var
  6199. i: Integer;
  6200. begin
  6201. Result := nil;
  6202. for i := 0 to Count - 1 do
  6203. with Items[i] do
  6204. if (startFrame <= aFrame) and (endFrame >= aFrame) and (reference = aReference) then
  6205. begin
  6206. Result := Items[i];
  6207. Break;
  6208. end;
  6209. end;
  6210. procedure TgxActorAnimations.SetToStrings(aStrings: TStrings);
  6211. var
  6212. i: Integer;
  6213. begin
  6214. with aStrings do
  6215. begin
  6216. BeginUpdate;
  6217. Clear;
  6218. for i := 0 to Self.Count - 1 do
  6219. Add(Self.Items[i].Name);
  6220. EndUpdate;
  6221. end;
  6222. end;
  6223. procedure TgxActorAnimations.SaveToStream(aStream: TStream);
  6224. var
  6225. i: Integer;
  6226. begin
  6227. WriteCRLFString(aStream, cAAFHeader);
  6228. WriteCRLFString(aStream, AnsiString(IntToStr(Count)));
  6229. for i := 0 to Count - 1 do
  6230. WriteCRLFString(aStream, AnsiString(Items[i].AsString));
  6231. end;
  6232. procedure TgxActorAnimations.LoadFromStream(aStream: TStream);
  6233. var
  6234. i, n: Integer;
  6235. begin
  6236. Clear;
  6237. if ReadCRLFString(aStream) <> cAAFHeader then
  6238. Assert(False);
  6239. n := StrToInt(string(ReadCRLFString(aStream)));
  6240. for i := 0 to n - 1 do
  6241. Add.AsString := string(ReadCRLFString(aStream));
  6242. end;
  6243. procedure TgxActorAnimations.SaveToFile(const filename: string);
  6244. var
  6245. fs: TStream;
  6246. begin
  6247. fs := TFileStream.Create(filename, fmCreate);
  6248. try
  6249. SaveToStream(fs);
  6250. finally
  6251. fs.Free;
  6252. end;
  6253. end;
  6254. procedure TgxActorAnimations.LoadFromFile(const filename: string);
  6255. var
  6256. fs: TStream;
  6257. begin
  6258. fs := TFileStream.Create(filename, fmOpenRead + fmShareDenyWrite);
  6259. try
  6260. LoadFromStream(fs);
  6261. finally
  6262. fs.Free;
  6263. end;
  6264. end;
  6265. // ------------------
  6266. // ------------------ TgxBaseAnimationControler ------------------
  6267. // ------------------
  6268. constructor TgxBaseAnimationControler.Create(aOwner: TComponent);
  6269. begin
  6270. inherited Create(aOwner);
  6271. FEnabled := True;
  6272. end;
  6273. destructor TgxBaseAnimationControler.Destroy;
  6274. begin
  6275. SetActor(nil);
  6276. inherited Destroy;
  6277. end;
  6278. procedure TgxBaseAnimationControler.Notification(AComponent: TComponent; Operation: TOperation);
  6279. begin
  6280. if (AComponent = FActor) and (Operation = opRemove) then
  6281. SetActor(nil);
  6282. inherited;
  6283. end;
  6284. procedure TgxBaseAnimationControler.DoChange;
  6285. begin
  6286. if Assigned(FActor) then
  6287. FActor.NotifyChange(Self);
  6288. end;
  6289. procedure TgxBaseAnimationControler.SetEnabled(const val: Boolean);
  6290. begin
  6291. if val <> FEnabled then
  6292. begin
  6293. FEnabled := val;
  6294. if Assigned(FActor) then
  6295. DoChange;
  6296. end;
  6297. end;
  6298. procedure TgxBaseAnimationControler.SetActor(const val: TgxActor);
  6299. begin
  6300. if FActor <> val then
  6301. begin
  6302. if Assigned(FActor) then
  6303. FActor.UnRegisterControler(Self);
  6304. FActor := val;
  6305. if Assigned(FActor) then
  6306. begin
  6307. FActor.RegisterControler(Self);
  6308. DoChange;
  6309. end;
  6310. end;
  6311. end;
  6312. function TgxBaseAnimationControler.Apply(var lerpInfo: TGXBlendedLerpInfo): Boolean;
  6313. begin
  6314. // virtual
  6315. Result := False;
  6316. end;
  6317. // ------------------
  6318. // ------------------ TgxAnimationControler ------------------
  6319. // ------------------
  6320. procedure TgxAnimationControler.DoChange;
  6321. begin
  6322. if AnimationName <> '' then
  6323. inherited;
  6324. end;
  6325. procedure TgxAnimationControler.SetAnimationName(const val: TgxActorAnimationName);
  6326. begin
  6327. if FAnimationName <> val then
  6328. begin
  6329. FAnimationName := val;
  6330. DoChange;
  6331. end;
  6332. end;
  6333. procedure TgxAnimationControler.SetRatio(const val: Single);
  6334. begin
  6335. if FRatio <> val then
  6336. begin
  6337. FRatio := ClampValue(val, 0, 1);
  6338. DoChange;
  6339. end;
  6340. end;
  6341. function TgxAnimationControler.Apply(var lerpInfo: TGXBlendedLerpInfo): Boolean;
  6342. var
  6343. anim: TgxActorAnimation;
  6344. baseDelta: Integer;
  6345. begin
  6346. if not Enabled then
  6347. begin
  6348. Result := False;
  6349. Exit;
  6350. end;
  6351. anim := Actor.Animations.FindName(AnimationName);
  6352. Result := (anim <> nil);
  6353. if not Result then
  6354. Exit;
  6355. with lerpInfo do
  6356. begin
  6357. if Ratio = 0 then
  6358. begin
  6359. frameIndex1 := anim.startFrame;
  6360. frameIndex2 := frameIndex1;
  6361. lerpFactor := 0;
  6362. end
  6363. else if Ratio = 1 then
  6364. begin
  6365. frameIndex1 := anim.endFrame;
  6366. frameIndex2 := frameIndex1;
  6367. lerpFactor := 0;
  6368. end
  6369. else
  6370. begin
  6371. baseDelta := anim.endFrame - anim.startFrame;
  6372. lerpFactor := anim.startFrame + baseDelta * Ratio;
  6373. frameIndex1 := Trunc(lerpFactor);
  6374. frameIndex2 := frameIndex1 + 1;
  6375. lerpFactor := Frac(lerpFactor);
  6376. end;
  6377. weight := 1;
  6378. externalRotations := nil;
  6379. externalQuaternions := nil;
  6380. end;
  6381. end;
  6382. // ------------------
  6383. // ------------------ TgxActor ------------------
  6384. // ------------------
  6385. constructor TgxActor.Create(aOwner: TComponent);
  6386. begin
  6387. inherited Create(aOwner);
  6388. ObjectStyle := ObjectStyle + [osDirectDraw];
  6389. FFrameInterpolation := afpLinear;
  6390. FAnimationMode := aamNone;
  6391. FInterval := 100; // 10 animation frames per second
  6392. FAnimations := TgxActorAnimations.Create(Self);
  6393. FControlers := nil; // created on request
  6394. FOptions := cDefaultActorOptions;
  6395. end;
  6396. destructor TgxActor.Destroy;
  6397. begin
  6398. inherited Destroy;
  6399. FControlers.Free;
  6400. FAnimations.Free;
  6401. end;
  6402. procedure TgxActor.Assign(Source: TPersistent);
  6403. begin
  6404. inherited Assign(Source);
  6405. if Source is TgxActor then
  6406. begin
  6407. FAnimations.Assign(TgxActor(Source).FAnimations);
  6408. FAnimationMode := TgxActor(Source).FAnimationMode;
  6409. Synchronize(TgxActor(Source));
  6410. end;
  6411. end;
  6412. procedure TgxActor.RegisterControler(aControler: TgxBaseAnimationControler);
  6413. begin
  6414. if not Assigned(FControlers) then
  6415. FControlers := TList.Create;
  6416. FControlers.Add(aControler);
  6417. FreeNotification(aControler);
  6418. end;
  6419. procedure TgxActor.UnRegisterControler(aControler: TgxBaseAnimationControler);
  6420. begin
  6421. Assert(Assigned(FControlers));
  6422. FControlers.Remove(aControler);
  6423. RemoveFreeNotification(aControler);
  6424. if FControlers.Count = 0 then
  6425. FreeAndNil(FControlers);
  6426. end;
  6427. procedure TgxActor.SetCurrentFrame(val: Integer);
  6428. begin
  6429. if val <> CurrentFrame then
  6430. begin
  6431. if val > FrameCount - 1 then
  6432. FCurrentFrame := FrameCount - 1
  6433. else if val < 0 then
  6434. FCurrentFrame := 0
  6435. else
  6436. FCurrentFrame := val;
  6437. FCurrentFrameDelta := 0;
  6438. case AnimationMode of
  6439. aamPlayOnce:
  6440. if (CurrentFrame = endFrame) and (FTargetSmoothAnimation = nil) then
  6441. FAnimationMode := aamNone;
  6442. aamBounceForward:
  6443. if CurrentFrame = endFrame then
  6444. FAnimationMode := aamBounceBackward;
  6445. aamBounceBackward:
  6446. if CurrentFrame = startFrame then
  6447. FAnimationMode := aamBounceForward;
  6448. end;
  6449. StructureChanged;
  6450. if Assigned(FOnFrameChanged) then
  6451. FOnFrameChanged(Self);
  6452. end;
  6453. end;
  6454. procedure TgxActor.SetCurrentFrameDirect(const Value: Integer);
  6455. begin
  6456. FCurrentFrame := Value;
  6457. end;
  6458. procedure TgxActor.SetStartFrame(val: Integer);
  6459. begin
  6460. if (val >= 0) and (val < FrameCount) and (val <> startFrame) then
  6461. FStartFrame := val;
  6462. if endFrame < startFrame then
  6463. FEndFrame := FStartFrame;
  6464. if CurrentFrame < startFrame then
  6465. CurrentFrame := FStartFrame;
  6466. end;
  6467. procedure TgxActor.SetEndFrame(val: Integer);
  6468. begin
  6469. if (val >= 0) and (val < FrameCount) and (val <> endFrame) then
  6470. FEndFrame := val;
  6471. if CurrentFrame > endFrame then
  6472. CurrentFrame := FEndFrame;
  6473. end;
  6474. procedure TgxActor.SetReference(val: TgxActorAnimationReference);
  6475. begin
  6476. if val <> reference then
  6477. begin
  6478. FReference := val;
  6479. startFrame := startFrame;
  6480. endFrame := endFrame;
  6481. CurrentFrame := CurrentFrame;
  6482. StructureChanged;
  6483. end;
  6484. end;
  6485. procedure TgxActor.SetAnimations(const val: TgxActorAnimations);
  6486. begin
  6487. FAnimations.Assign(val);
  6488. end;
  6489. function TgxActor.StoreAnimations: Boolean;
  6490. begin
  6491. Result := (FAnimations.Count > 0);
  6492. end;
  6493. procedure TgxActor.SetOptions(const val: TgxActorOptions);
  6494. begin
  6495. if val <> FOptions then
  6496. begin
  6497. FOptions := val;
  6498. StructureChanged;
  6499. end;
  6500. end;
  6501. function TgxActor.NextFrameIndex: Integer;
  6502. begin
  6503. case AnimationMode of
  6504. aamLoop, aamBounceForward:
  6505. begin
  6506. if FTargetSmoothAnimation <> nil then
  6507. Result := FTargetSmoothAnimation.startFrame
  6508. else
  6509. begin
  6510. Result := CurrentFrame + 1;
  6511. if Result > endFrame then
  6512. begin
  6513. Result := startFrame + (Result - endFrame - 1);
  6514. if Result > endFrame then
  6515. Result := endFrame;
  6516. end;
  6517. end;
  6518. end;
  6519. aamNone, aamPlayOnce:
  6520. begin
  6521. if FTargetSmoothAnimation <> nil then
  6522. Result := FTargetSmoothAnimation.startFrame
  6523. else
  6524. begin
  6525. Result := CurrentFrame + 1;
  6526. if Result > endFrame then
  6527. Result := endFrame;
  6528. end;
  6529. end;
  6530. aamBounceBackward, aamLoopBackward:
  6531. begin
  6532. if FTargetSmoothAnimation <> nil then
  6533. Result := FTargetSmoothAnimation.startFrame
  6534. else
  6535. begin
  6536. Result := CurrentFrame - 1;
  6537. if Result < startFrame then
  6538. begin
  6539. Result := endFrame - (startFrame - Result - 1);
  6540. if Result < startFrame then
  6541. Result := startFrame;
  6542. end;
  6543. end;
  6544. end;
  6545. aamExternal:
  6546. Result := CurrentFrame; // Do nothing
  6547. else
  6548. Result := CurrentFrame;
  6549. Assert(False);
  6550. end;
  6551. end;
  6552. procedure TgxActor.NextFrame(nbSteps: Integer = 1);
  6553. var
  6554. n: Integer;
  6555. begin
  6556. n := nbSteps;
  6557. while n > 0 do
  6558. begin
  6559. CurrentFrame := NextFrameIndex;
  6560. Dec(n);
  6561. if Assigned(FOnEndFrameReached) and (CurrentFrame = endFrame) then
  6562. FOnEndFrameReached(Self);
  6563. if Assigned(FOnStartFrameReached) and (CurrentFrame = startFrame) then
  6564. FOnStartFrameReached(Self);
  6565. end;
  6566. end;
  6567. procedure TgxActor.PrevFrame(nbSteps: Integer = 1);
  6568. var
  6569. Value: Integer;
  6570. begin
  6571. Value := FCurrentFrame - nbSteps;
  6572. if Value < FStartFrame then
  6573. begin
  6574. Value := FEndFrame - (FStartFrame - Value);
  6575. if Value < FStartFrame then
  6576. Value := FStartFrame;
  6577. end;
  6578. CurrentFrame := Value;
  6579. end;
  6580. procedure TgxActor.DoAnimate();
  6581. var
  6582. i, k: Integer;
  6583. nextFrameIdx: Integer;
  6584. lerpInfos: array of TGXBlendedLerpInfo;
  6585. begin
  6586. nextFrameIdx := NextFrameIndex;
  6587. case reference of
  6588. aarMorph:
  6589. if nextFrameIdx >= 0 then
  6590. begin
  6591. case FrameInterpolation of
  6592. afpLinear:
  6593. MeshObjects.Lerp(CurrentFrame, nextFrameIdx, CurrentFrameDelta)
  6594. else
  6595. MeshObjects.MorphTo(CurrentFrame);
  6596. end;
  6597. end;
  6598. aarSkeleton:
  6599. if Skeleton.Frames.Count > 0 then
  6600. begin
  6601. if Assigned(FControlers) and (AnimationMode <> aamExternal) then
  6602. begin
  6603. // Blended Skeletal Lerping
  6604. SetLength(lerpInfos, FControlers.Count + 1);
  6605. if nextFrameIdx >= 0 then
  6606. begin
  6607. case FrameInterpolation of
  6608. afpLinear:
  6609. with lerpInfos[0] do
  6610. begin
  6611. frameIndex1 := CurrentFrame;
  6612. frameIndex2 := nextFrameIdx;
  6613. lerpFactor := CurrentFrameDelta;
  6614. weight := 1;
  6615. end;
  6616. else
  6617. with lerpInfos[0] do
  6618. begin
  6619. frameIndex1 := CurrentFrame;
  6620. frameIndex2 := CurrentFrame;
  6621. lerpFactor := 0;
  6622. weight := 1;
  6623. end;
  6624. end;
  6625. end
  6626. else
  6627. begin
  6628. with lerpInfos[0] do
  6629. begin
  6630. frameIndex1 := CurrentFrame;
  6631. frameIndex2 := CurrentFrame;
  6632. lerpFactor := 0;
  6633. weight := 1;
  6634. end;
  6635. end;
  6636. k := 1;
  6637. for i := 0 to FControlers.Count - 1 do
  6638. if TgxBaseAnimationControler(FControlers[i]).Apply(lerpInfos[k]) then
  6639. Inc(k);
  6640. SetLength(lerpInfos, k);
  6641. Skeleton.BlendedLerps(lerpInfos);
  6642. end
  6643. else if (nextFrameIdx >= 0) and (AnimationMode <> aamExternal) then
  6644. begin
  6645. // Single Skeletal Lerp
  6646. case FrameInterpolation of
  6647. afpLinear:
  6648. Skeleton.Lerp(CurrentFrame, nextFrameIdx, CurrentFrameDelta);
  6649. else
  6650. Skeleton.SetCurrentFrame(Skeleton.Frames[CurrentFrame]);
  6651. end;
  6652. end;
  6653. Skeleton.MorphMesh(aoSkeletonNormalizeNormals in Options);
  6654. end;
  6655. aarNone:
  6656. ; // do nothing
  6657. end;
  6658. end;
  6659. procedure TgxActor.BuildList(var rci: TgxRenderContextInfo);
  6660. begin
  6661. DoAnimate;
  6662. inherited;
  6663. if OverlaySkeleton then
  6664. begin
  6665. rci.gxStates.Disable(stDepthTest);
  6666. Skeleton.RootBones.BuildList(rci);
  6667. end;
  6668. end;
  6669. procedure TgxActor.PrepareMesh;
  6670. begin
  6671. FStartFrame := 0;
  6672. FEndFrame := FrameCount - 1;
  6673. FCurrentFrame := 0;
  6674. if Assigned(FOnFrameChanged) then
  6675. FOnFrameChanged(Self);
  6676. inherited;
  6677. end;
  6678. procedure TgxActor.PrepareBuildList(var mrci: TgxRenderContextInfo);
  6679. begin
  6680. // no preparation needed for actors, they don't use buildlists
  6681. end;
  6682. function TgxActor.FrameCount: Integer;
  6683. begin
  6684. case reference of
  6685. aarMorph:
  6686. Result := MeshObjects.MorphTargetCount;
  6687. aarSkeleton:
  6688. Result := Skeleton.Frames.Count;
  6689. aarNone:
  6690. Result := 0;
  6691. else
  6692. Result := 0;
  6693. Assert(False);
  6694. end;
  6695. end;
  6696. procedure TgxActor.DoProgress(const progressTime: TgxProgressTimes);
  6697. var
  6698. fDelta: Single;
  6699. begin
  6700. inherited;
  6701. if (AnimationMode <> aamNone) and (Interval > 0) then
  6702. begin
  6703. if (startFrame <> endFrame) and (FrameCount > 1) then
  6704. begin
  6705. FCurrentFrameDelta := FCurrentFrameDelta + (progressTime.deltaTime * 1000) / FInterval;
  6706. if FCurrentFrameDelta > 1 then
  6707. begin
  6708. if Assigned(FTargetSmoothAnimation) then
  6709. begin
  6710. SwitchToAnimation(FTargetSmoothAnimation);
  6711. FTargetSmoothAnimation := nil;
  6712. end;
  6713. // we need to step on
  6714. fDelta := Frac(FCurrentFrameDelta);
  6715. NextFrame(Trunc(FCurrentFrameDelta));
  6716. FCurrentFrameDelta := fDelta;
  6717. StructureChanged;
  6718. end
  6719. else if FrameInterpolation <> afpNone then
  6720. StructureChanged;
  6721. end;
  6722. end;
  6723. end;
  6724. procedure TgxActor.LoadFromStream(const filename: string; aStream: TStream);
  6725. begin
  6726. if filename <> '' then
  6727. begin
  6728. Animations.Clear;
  6729. inherited LoadFromStream(filename, aStream);
  6730. end;
  6731. end;
  6732. procedure TgxActor.SwitchToAnimation(const AnimationName: string; smooth: Boolean = False);
  6733. begin
  6734. SwitchToAnimation(Animations.FindName(AnimationName), smooth);
  6735. end;
  6736. procedure TgxActor.SwitchToAnimation(animationIndex: Integer; smooth: Boolean = False);
  6737. begin
  6738. if (animationIndex >= 0) and (animationIndex < Animations.Count) then
  6739. SwitchToAnimation(Animations[animationIndex], smooth);
  6740. end;
  6741. procedure TgxActor.SwitchToAnimation(anAnimation: TgxActorAnimation; smooth: Boolean = False);
  6742. begin
  6743. if Assigned(anAnimation) then
  6744. begin
  6745. if smooth then
  6746. begin
  6747. FTargetSmoothAnimation := anAnimation;
  6748. FCurrentFrameDelta := 0;
  6749. end
  6750. else
  6751. begin
  6752. reference := anAnimation.reference;
  6753. startFrame := anAnimation.startFrame;
  6754. endFrame := anAnimation.endFrame;
  6755. CurrentFrame := startFrame;
  6756. end;
  6757. end;
  6758. end;
  6759. function TgxActor.CurrentAnimation: string;
  6760. var
  6761. aa: TgxActorAnimation;
  6762. begin
  6763. aa := Animations.FindFrame(CurrentFrame, reference);
  6764. if Assigned(aa) then
  6765. Result := aa.Name
  6766. else
  6767. Result := '';
  6768. end;
  6769. procedure TgxActor.Synchronize(referenceActor: TgxActor);
  6770. begin
  6771. if Assigned(referenceActor) then
  6772. begin
  6773. if referenceActor.startFrame < FrameCount then
  6774. FStartFrame := referenceActor.startFrame;
  6775. if referenceActor.endFrame < FrameCount then
  6776. FEndFrame := referenceActor.endFrame;
  6777. FReference := referenceActor.reference;
  6778. if referenceActor.CurrentFrame < FrameCount then
  6779. FCurrentFrame := referenceActor.CurrentFrame;
  6780. FCurrentFrameDelta := referenceActor.CurrentFrameDelta;
  6781. FAnimationMode := referenceActor.AnimationMode;
  6782. FFrameInterpolation := referenceActor.FrameInterpolation;
  6783. if referenceActor.FTargetSmoothAnimation <> nil then
  6784. FTargetSmoothAnimation := Animations.FindName(referenceActor.FTargetSmoothAnimation.Name)
  6785. else
  6786. FTargetSmoothAnimation := nil;
  6787. if (Skeleton.Frames.Count > 0) and (referenceActor.Skeleton.Frames.Count > 0) then
  6788. Skeleton.Synchronize(referenceActor.Skeleton);
  6789. end;
  6790. end;
  6791. function TgxActor.isSwitchingAnimation: Boolean;
  6792. begin
  6793. Result := FTargetSmoothAnimation <> nil;
  6794. end;
  6795. // ------------------------------------------------------------------
  6796. initialization
  6797. // ------------------------------------------------------------------
  6798. RegisterVectorFileFormat('glsm', 'GXScene Mesh', TgxVectorFileGLSM);
  6799. RegisterClasses([TgxFreeForm, TgxActor, TgxSkeleton, TgxSkeletonFrame, TgxSkeletonBone, TgxSkeletonMeshObject, TgxMeshObject,
  6800. TgxSkeletonFrameList, TgxMeshMorphTarget, TgxMorphableMeshObject, TgxFaceGroup, TgxFGVertexIndexList,
  6801. TFGVertexNormalTexIndexList, TgxAnimationControler, TgxFGIndexTexCoordList, TgxSkeletonCollider, TgxSkeletonColliderList]);
  6802. finalization
  6803. FreeAndNil(vVectorFileFormats);
  6804. end.