GLS.VectorFileObjects.pas 221 KB

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