PasGLTF.pas 218 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107
  1. (* *****************************************************************************
  2. * PasGLTF *
  3. ******************************************************************************
  4. * Version 2021-07-29-15-54 *
  5. ******************************************************************************
  6. * zlib license *
  7. *============================================================================*
  8. * *
  9. * Copyright (C) 2018-2021, Benjamin Rosseaux ([email protected]) *
  10. * *
  11. * This software is provided 'as-is', without any express or implied *
  12. * warranty. In no event will the authors be held liable for any damages *
  13. * arising from the use of this software. *
  14. * *
  15. * Permission is granted to anyone to use this software for any purpose, *
  16. * including commercial applications, and to alter it and redistribute it *
  17. * freely, subject to the following restrictions: *
  18. * *
  19. * 1. The origin of this software must not be misrepresented; you must not *
  20. * claim that you wrote the original software. If you use this software *
  21. * in a product, an acknowledgement in the product documentation would be *
  22. * appreciated but is not required. *
  23. * 2. Altered source versions must be plainly marked as such, and must not be *
  24. * misrepresented as being the original software. *
  25. * 3. This notice may not be removed or altered from any source distribution. *
  26. * *
  27. ******************************************************************************
  28. * General guidelines for code contributors *
  29. *============================================================================*
  30. * *
  31. * 1. Make sure you are legally allowed to make a contribution under the zlib *
  32. * license. *
  33. * 2. The zlib license header goes at the top of each source file, with *
  34. * appropriate copyright notice. *
  35. * 3. After a pull request, check the status of your pull request on *
  36. * http://github.com/BeRo1985/pasGLTF *
  37. * 4. Write code which's compatible with newer modern Delphi versions and *
  38. * FreePascal >= 3.0.0 *
  39. * 5. Don't use Delphi-only, FreePascal-only or Lazarus-only libraries/units, *
  40. * but if needed, make it out-ifdef-able. *
  41. * 6. No use of third-party libraries/units as possible, but if needed, make *
  42. * it out-ifdef-able. *
  43. * 7. Try to use const when possible. *
  44. * 8. Make sure to comment out writeln, used while debugging. *
  45. * 9. Make sure the code compiles on 32-bit and 64-bit platforms (x86-32, *
  46. * x86-64, ARM, ARM64, etc.). *
  47. * *
  48. ***************************************************************************** *)
  49. unit PasGLTF;
  50. {$ifdef fpc}
  51. {$mode delphi}
  52. {$ifdef cpui386}
  53. {$define cpu386}
  54. {$endif}
  55. {$ifdef cpu386}
  56. {$asmmode intel}
  57. {$endif}
  58. {$ifdef cpuamd64}
  59. {$asmmode intel}
  60. {$endif}
  61. {$ifdef FPC_LITTLE_ENDIAN}
  62. {$define LITTLE_ENDIAN}
  63. {$else}
  64. {$ifdef FPC_BIG_ENDIAN}
  65. {$define BIG_ENDIAN}
  66. {$endif}
  67. {$endif}
  68. { -$pic off }
  69. {$ifdef fpc_has_internal_sar}
  70. {$define HasSAR}
  71. {$endif}
  72. {$ifdef FPC_HAS_TYPE_EXTENDED}
  73. {$define HAS_TYPE_EXTENDED}
  74. {$else}
  75. {$undef HAS_TYPE_EXTENDED}
  76. {$endif}
  77. {$ifdef FPC_HAS_TYPE_DOUBLE}
  78. {$define HAS_TYPE_DOUBLE}
  79. {$else}
  80. {$undef HAS_TYPE_DOUBLE}
  81. {$endif}
  82. {$ifdef FPC_HAS_TYPE_SINGLE}
  83. {$define HAS_TYPE_SINGLE}
  84. {$else}
  85. {$undef HAS_TYPE_SINGLE}
  86. {$endif}
  87. {$define CAN_INLINE}
  88. {$define HAS_ADVANCED_RECORDS}
  89. {$else}
  90. {$realcompatibility off}
  91. {$localsymbols on}
  92. {$define LITTLE_ENDIAN}
  93. {$ifndef cpu64}
  94. {$define cpu32}
  95. {$endif}
  96. {$define HAS_TYPE_EXTENDED}
  97. {$define HAS_TYPE_DOUBLE}
  98. {$define HAS_TYPE_SINGLE}
  99. {$undef CAN_INLINE}
  100. {$undef HAS_ADVANCED_RECORDS}
  101. {$ifndef BCB}
  102. {$ifdef ver120}
  103. {$define Delphi4or5}
  104. {$endif}
  105. {$ifdef ver130}
  106. {$define Delphi4or5}
  107. {$endif}
  108. {$ifdef ver140}
  109. {$define Delphi6}
  110. {$endif}
  111. {$ifdef ver150}
  112. {$define Delphi7}
  113. {$endif}
  114. {$ifdef ver170}
  115. {$define Delphi2005}
  116. {$endif}
  117. {$else}
  118. {$ifdef ver120}
  119. {$define Delphi4or5}
  120. {$define BCB4}
  121. {$endif}
  122. {$ifdef ver130}
  123. {$define Delphi4or5}
  124. {$endif}
  125. {$endif}
  126. {$ifdef conditionalexpressions}
  127. {$if CompilerVersion>=24.0}
  128. {$legacyifend on}
  129. {$ifend}
  130. {$if CompilerVersion>=14.0}
  131. {$if CompilerVersion=14.0}
  132. {$define Delphi6}
  133. {$ifend}
  134. {$define Delphi6AndUp}
  135. {$ifend}
  136. {$if CompilerVersion>=15.0}
  137. {$if CompilerVersion=15.0}
  138. {$define Delphi7}
  139. {$ifend}
  140. {$define Delphi7AndUp}
  141. {$ifend}
  142. {$if CompilerVersion>=17.0}
  143. {$if CompilerVersion=17.0}
  144. {$define Delphi2005}
  145. {$ifend}
  146. {$define Delphi2005AndUp}
  147. {$ifend}
  148. {$if CompilerVersion>=18.0}
  149. {$if CompilerVersion=18.0}
  150. {$define BDS2006}
  151. {$define Delphi2006}
  152. {$ifend}
  153. {$define Delphi2006AndUp}
  154. {$define CAN_INLINE}
  155. {$define HAS_ADVANCED_RECORDS}
  156. {$ifend}
  157. {$if CompilerVersion>=18.5}
  158. {$if CompilerVersion=18.5}
  159. {$define Delphi2007}
  160. {$ifend}
  161. {$define Delphi2007AndUp}
  162. {$ifend}
  163. {$if CompilerVersion=19.0}
  164. {$define Delphi2007Net}
  165. {$ifend}
  166. {$if CompilerVersion>=20.0}
  167. {$if CompilerVersion=20.0}
  168. {$define Delphi2009}
  169. {$ifend}
  170. {$define Delphi2009AndUp}
  171. {$ifend}
  172. {$if CompilerVersion>=21.0}
  173. {$if CompilerVersion=21.0}
  174. {$define Delphi2010}
  175. {$ifend}
  176. {$define Delphi2010AndUp}
  177. {$ifend}
  178. {$if CompilerVersion>=22.0}
  179. {$if CompilerVersion=22.0}
  180. {$define DelphiXE}
  181. {$ifend}
  182. {$define DelphiXEAndUp}
  183. {$ifend}
  184. {$if CompilerVersion>=23.0}
  185. {$if CompilerVersion=23.0}
  186. {$define DelphiXE2}
  187. {$ifend}
  188. {$define DelphiXE2AndUp}
  189. {$ifend}
  190. {$if CompilerVersion>=24.0}
  191. {$legacyifend on}
  192. {$if CompilerVersion=24.0}
  193. {$define DelphiXE3}
  194. {$ifend}
  195. {$define DelphiXE3AndUp}
  196. {$ifend}
  197. {$if CompilerVersion>=25.0}
  198. {$if CompilerVersion=25.0}
  199. {$define DelphiXE4}
  200. {$ifend}
  201. {$define DelphiXE4AndUp}
  202. {$ifend}
  203. {$if CompilerVersion>=26.0}
  204. {$if CompilerVersion=26.0}
  205. {$define DelphiXE5}
  206. {$ifend}
  207. {$define DelphiXE5AndUp}
  208. {$ifend}
  209. {$if CompilerVersion>=27.0}
  210. {$if CompilerVersion=27.0}
  211. {$define DelphiXE6}
  212. {$ifend}
  213. {$define DelphiXE6AndUp}
  214. {$ifend}
  215. {$if CompilerVersion>=28.0}
  216. {$if CompilerVersion=28.0}
  217. {$define DelphiXE7}
  218. {$ifend}
  219. {$define DelphiXE7AndUp}
  220. {$ifend}
  221. {$if CompilerVersion>=29.0}
  222. {$if CompilerVersion=29.0}
  223. {$define DelphiXE8}
  224. {$ifend}
  225. {$define DelphiXE8AndUp}
  226. {$ifend}
  227. {$if CompilerVersion>=30.0}
  228. {$if CompilerVersion=30.0}
  229. {$define Delphi10Seattle}
  230. {$ifend}
  231. {$define Delphi10SeattleAndUp}
  232. {$ifend}
  233. {$if CompilerVersion>=31.0}
  234. {$if CompilerVersion=31.0}
  235. {$define Delphi10Berlin}
  236. {$ifend}
  237. {$define Delphi10BerlinAndUp}
  238. {$ifend}
  239. {$if CompilerVersion>=32.0}
  240. {$if CompilerVersion=32.0}
  241. {$define Delphi10Tokyo}
  242. {$ifend}
  243. {$define Delphi10TokyoAndUp}
  244. {$ifend}
  245. {$if CompilerVersion>=33.0}
  246. {$if CompilerVersion=33.0}
  247. {$define Delphi10Rio}
  248. {$ifend}
  249. {$define Delphi10RioAndUp}
  250. {$ifend}
  251. {$endif}
  252. {$ifndef Delphi4or5}
  253. {$ifndef BCB}
  254. {$define Delphi6AndUp}
  255. {$endif}
  256. {$ifndef Delphi6}
  257. {$define BCB6OrDelphi7AndUp}
  258. {$ifndef BCB}
  259. {$define Delphi7AndUp}
  260. {$endif}
  261. {$ifndef BCB}
  262. {$ifndef Delphi7}
  263. {$ifndef Delphi2005}
  264. {$define BDS2006AndUp}
  265. {$endif}
  266. {$endif}
  267. {$endif}
  268. {$endif}
  269. {$endif}
  270. {$ifdef Delphi6AndUp}
  271. {$warn symbol_platform off}
  272. {$warn symbol_deprecated off}
  273. {$endif}
  274. {$endif}
  275. {$if defined(Win32) or defined(Win64)}
  276. {$define Windows}
  277. {$ifend}
  278. {$rangechecks off}
  279. {$extendedsyntax on}
  280. {$writeableconst on}
  281. {$hints off}
  282. {$booleval off}
  283. {$typedaddress off}
  284. {$stackframes off}
  285. {$varstringchecks on}
  286. {$typeinfo on}
  287. {$overflowchecks off}
  288. {$longstrings on}
  289. {$openstrings on}
  290. {$ifndef HAS_TYPE_SINGLE}
  291. {$error No single floating point precision}
  292. {$endif}
  293. {$ifndef HAS_TYPE_DOUBLE}
  294. {$error No double floating point precision}
  295. {$endif}
  296. {$scopedenums on}
  297. {$ifndef fpc}
  298. {$ifdef conditionalexpressions}
  299. {$if CompilerVersion>=24.0}
  300. {$legacyifend on}
  301. {$ifend}
  302. {$endif}
  303. {$endif}
  304. interface
  305. uses
  306. System.SysUtils,
  307. System.Classes,
  308. System.Math,
  309. PasJSON;
  310. type
  311. PPPasGLTFInt8 = ^PPasGLTFInt8;
  312. PPasGLTFInt8 = ^TPasGLTFInt8;
  313. TPasGLTFInt8 = {$IFDEF fpc}Int8{$ELSE}shortint{$ENDIF};
  314. PPPasGLTFUInt8 = ^PPasGLTFUInt8;
  315. PPasGLTFUInt8 = ^TPasGLTFUInt8;
  316. TPasGLTFUInt8 = {$IFDEF fpc}UInt8{$ELSE}byte{$ENDIF};
  317. PPPasGLTFUInt8Array = ^PPasGLTFUInt8Array;
  318. PPasGLTFUInt8Array = ^TPasGLTFUInt8Array;
  319. TPasGLTFUInt8Array = array [0 .. 65535] of TPasGLTFUInt8;
  320. TPasGLTFUInt8DynamicArray = array of TPasGLTFUInt8;
  321. PPPasGLTFInt16 = ^PPasGLTFInt16;
  322. PPasGLTFInt16 = ^TPasGLTFInt16;
  323. TPasGLTFInt16 = {$IFDEF fpc}Int16{$ELSE}smallint{$ENDIF};
  324. PPPasGLTFUInt16 = ^PPasGLTFUInt16;
  325. PPasGLTFUInt16 = ^TPasGLTFUInt16;
  326. TPasGLTFUInt16 = {$IFDEF fpc}UInt16{$ELSE}word{$ENDIF};
  327. PPPasGLTFInt32 = ^PPasGLTFInt32;
  328. PPasGLTFInt32 = ^TPasGLTFInt32;
  329. TPasGLTFInt32 = {$IFDEF fpc}Int32{$ELSE}longint{$ENDIF};
  330. TPasGLTFInt32DynamicArray = array of TPasGLTFInt32;
  331. PPPasGLTFUInt32 = ^PPasGLTFUInt32;
  332. PPasGLTFUInt32 = ^TPasGLTFUInt32;
  333. TPasGLTFUInt32 = {$IFDEF fpc}UInt32{$ELSE}longword{$ENDIF};
  334. PPPasGLTFUInt32Array = ^PPasGLTFUInt32Array;
  335. PPasGLTFUInt32Array = ^TPasGLTFUInt32Array;
  336. TPasGLTFUInt32Array = array [0 .. 65535] of TPasGLTFUInt32;
  337. TPasGLTFUInt32DynamicArray = array of TPasGLTFUInt32;
  338. PPPasGLTFInt64 = ^PPasGLTFInt64;
  339. PPasGLTFInt64 = ^TPasGLTFInt64;
  340. TPasGLTFInt64 = Int64;
  341. TPasGLTFInt64DynamicArray = array of TPasGLTFInt64;
  342. PPPasGLTFUInt64 = ^PPasGLTFUInt64;
  343. PPasGLTFUInt64 = ^TPasGLTFUInt64;
  344. TPasGLTFUInt64 = UInt64;
  345. TPasGLTFUInt64DynamicArray = array of TPasGLTFUInt64;
  346. PPPasGLTFChar = ^PAnsiChar;
  347. PPasGLTFChar = PAnsiChar;
  348. TPasGLTFChar = AnsiChar;
  349. PPPasGLTFRawByteChar = ^PAnsiChar;
  350. PPasGLTFRawByteChar = PAnsiChar;
  351. TPasGLTFRawByteChar = AnsiChar;
  352. PPPasGLTFUTF16Char = ^PWideChar;
  353. PPasGLTFUTF16Char = PWideChar;
  354. TPasGLTFUTF16Char = WideChar;
  355. PPPasGLTFPointer = ^PPasGLTFPointer;
  356. PPasGLTFPointer = ^TPasGLTFPointer;
  357. TPasGLTFPointer = Pointer;
  358. PPPasGLTFPointers = ^PPasGLTFPointers;
  359. PPasGLTFPointers = ^TPasGLTFPointers;
  360. TPasGLTFPointers = array [0 .. 65535] of TPasGLTFPointer;
  361. PPPasGLTFVoid = ^PPasGLTFVoid;
  362. PPasGLTFVoid = TPasGLTFPointer;
  363. PPPasGLTFFloat = ^PPasGLTFFloat;
  364. PPasGLTFFloat = ^TPasGLTFFloat;
  365. TPasGLTFFloat = Single;
  366. TPasGLTFFloatDynamicArray = array of TPasGLTFFloat;
  367. PPPasGLTFDouble = ^PPasGLTFDouble;
  368. PPasGLTFDouble = ^TPasGLTFDouble;
  369. TPasGLTFDouble = Double;
  370. TPasGLTFDoubleDynamicArray = array of TPasGLTFDouble;
  371. PPPasGLTFPtrUInt = ^PPasGLTFPtrUInt;
  372. PPPasGLTFPtrInt = ^PPasGLTFPtrInt;
  373. PPasGLTFPtrUInt = ^TPasGLTFPtrUInt;
  374. PPasGLTFPtrInt = ^TPasGLTFPtrInt;
  375. {$IFDEF fpc}
  376. TPasGLTFPtrUInt = PtrUInt;
  377. TPasGLTFPtrInt = PtrInt;
  378. {$UNDEF OldDelphi}
  379. {$ELSE}
  380. {$IFDEF conditionalexpressions}
  381. {$IF CompilerVersion>=23.0}
  382. {$UNDEF OldDelphi}
  383. TPasGLTFPtrUInt = NativeUInt;
  384. TPasGLTFPtrInt = NativeInt;
  385. {$ELSE}
  386. {$DEFINE OldDelphi}
  387. {$IFEND}
  388. {$ELSE}
  389. {$DEFINE OldDelphi}
  390. {$ENDIF}
  391. {$ENDIF}
  392. {$IFDEF OldDelphi}
  393. {$IFDEF cpu64}
  394. TPasGLTFPtrUInt = UInt64;
  395. TPasGLTFPtrInt = Int64;
  396. {$ELSE}
  397. TPasGLTFPtrUInt = longword;
  398. TPasGLTFPtrInt = longint;
  399. {$ENDIF}
  400. {$ENDIF}
  401. PPPasGLTFSizeUInt = ^PPasGLTFSizeUInt;
  402. PPasGLTFSizeUInt = ^TPasGLTFSizeUInt;
  403. TPasGLTFSizeUInt = TPasGLTFPtrUInt;
  404. TPasGLTFSizeUIntDynamicArray = array of TPasGLTFSizeUInt;
  405. PPPasGLTFSizeInt = ^PPasGLTFSizeInt;
  406. PPasGLTFSizeInt = ^TPasGLTFSizeInt;
  407. TPasGLTFSizeInt = TPasGLTFPtrInt;
  408. TPasGLTFSizeIntDynamicArray = array of TPasGLTFSizeInt;
  409. PPPasGLTFNativeUInt = ^PPasGLTFNativeUInt;
  410. PPasGLTFNativeUInt = ^TPasGLTFNativeUInt;
  411. TPasGLTFNativeUInt = TPasGLTFPtrUInt;
  412. PPPasGLTFNativeInt = ^PPasGLTFNativeInt;
  413. PPasGLTFNativeInt = ^TPasGLTFNativeInt;
  414. TPasGLTFNativeInt = TPasGLTFPtrInt;
  415. PPPasGLTFSize = ^PPasGLTFSizeUInt;
  416. PPasGLTFSize = ^TPasGLTFSizeUInt;
  417. TPasGLTFSize = TPasGLTFPtrUInt;
  418. PPPasGLTFPtrDiff = ^PPasGLTFPtrDiff;
  419. PPasGLTFPtrDiff = ^TPasGLTFPtrDiff;
  420. TPasGLTFPtrDiff = TPasGLTFPtrInt;
  421. PPPasGLTFRawByteString = ^PPasGLTFRawByteString;
  422. PPasGLTFRawByteString = ^TPasGLTFRawByteString;
  423. TPasGLTFRawByteString =
  424. {$IF declared(RawByteString)}RawByteString{$ELSE}AnsiString{$IFEND};
  425. PPPasGLTFUTF8String = ^PPasGLTFUTF8String;
  426. PPasGLTFUTF8String = ^TPasGLTFUTF8String;
  427. TPasGLTFUTF8String =
  428. {$IF declared(UTF8String)}UTF8String{$ELSE}AnsiString{$IFEND};
  429. PPPasGLTFUTF16String = ^PPasGLTFUTF16String;
  430. PPasGLTFUTF16String = ^TPasGLTFUTF16String;
  431. TPasGLTFUTF16String =
  432. {$IF declared(UnicodeString)}UnicodeString{$ELSE}WideString{$IFEND};
  433. EPasGLTF = class(Exception);
  434. EPasGLTFInvalidDocument = class(EPasGLTF);
  435. EPasGLTFInvalidBase64 = class(EPasGLTF);
  436. TPasGLTFTypedSort < T >= class private type TStackItem = record
  437. Left: TPasGLTFSizeInt;
  438. Right: TPasGLTFSizeInt;
  439. Depth: TPasGLTFInt32;
  440. end;
  441. PStackItem = ^TStackItem;
  442. public type
  443. TPasGLTFTypedSortCompareFunction = function(const a, b: T): TPasGLTFInt32;
  444. {$IFNDEF fpc}
  445. private
  446. class
  447. function BSRDWord(aValue: TPasGLTFUInt32): TPasGLTFInt32;
  448. static;
  449. {$ENDIF}
  450. public
  451. class
  452. procedure IntroSort(const pItems: TPasGLTFPointer;
  453. const pLeft, pRight: TPasGLTFSizeInt;
  454. const pCompareFunc: TPasGLTFTypedSortCompareFunction);
  455. static;
  456. end;
  457. TPasGLTFDynamicArray < T >= class
  458. private type TValueEnumerator = record
  459. private fDynamicArray: TPasGLTFDynamicArray<T>;
  460. fIndex: TPasGLTFSizeInt;
  461. function GetCurrent: T; inline;
  462. public
  463. constructor Create(const aDynamicArray: TPasGLTFDynamicArray<T>);
  464. function MoveNext: boolean; inline;
  465. property Current: T read GetCurrent;
  466. end;
  467. private
  468. fItems: array of T;
  469. fCount: TPasGLTFSizeInt;
  470. fAllocated: TPasGLTFSizeInt;
  471. procedure SetCount(const pNewCount: TPasGLTFSizeInt);
  472. function GetItem(const pIndex: TPasGLTFSizeInt): T;
  473. inline;
  474. procedure SetItem(const pIndex: TPasGLTFSizeInt; const pItem: T);
  475. inline;
  476. protected
  477. public
  478. constructor Create;
  479. destructor Destroy;
  480. override;
  481. procedure Clear;
  482. function Add(const pItem: T): TPasGLTFSizeInt;
  483. overload;
  484. function Add(const pItems: array of T): TPasGLTFSizeInt;
  485. overload;
  486. procedure Insert(const pIndex: TPasGLTFSizeInt; const pItem: T);
  487. procedure Delete(const pIndex: TPasGLTFSizeInt);
  488. procedure Exchange(const pIndex, pWithIndex: TPasGLTFSizeInt);
  489. inline;
  490. function GetEnumerator: TValueEnumerator;
  491. function Memory: TPasGLTFPointer;
  492. inline;
  493. property Count: TPasGLTFSizeInt read fCount write SetCount;
  494. property Allocated: TPasGLTFSizeInt read fAllocated;
  495. property Items[const pIndex: TPasGLTFSizeInt]: T read GetItem write SetItem;
  496. default;
  497. end;
  498. TPasGLTFObjectList < T: class >= class private type TValueEnumerator = record
  499. private fObjectList: TPasGLTFObjectList<T>;
  500. fIndex: TPasGLTFSizeInt;
  501. function GetCurrent: T;
  502. inline;
  503. public
  504. constructor Create(const aObjectList: TPasGLTFObjectList<T>);
  505. function MoveNext: boolean;
  506. inline;
  507. property Current: T read GetCurrent;
  508. end;
  509. private
  510. fItems: array of T;
  511. fCount: TPasGLTFSizeInt;
  512. fAllocated: TPasGLTFSizeInt;
  513. fOwnsObjects: boolean;
  514. function RoundUpToPowerOfTwoSizeUInt(x: TPasGLTFSizeUInt): TPasGLTFSizeUInt;
  515. procedure SetCount(const pNewCount: TPasGLTFSizeInt);
  516. function GetItem(const pIndex: TPasGLTFSizeInt): T;
  517. procedure SetItem(const pIndex: TPasGLTFSizeInt; const pItem: T);
  518. public
  519. constructor Create;
  520. destructor Destroy;
  521. override;
  522. procedure Clear;
  523. function IndexOf(const pItem: T): TPasGLTFSizeInt;
  524. function Add(const pItem: T): TPasGLTFSizeInt;
  525. procedure Insert(const pIndex: TPasGLTFSizeInt; const pItem: T);
  526. procedure Delete(const pIndex: TPasGLTFSizeInt);
  527. procedure Remove(const pItem: T);
  528. procedure Exchange(const pIndex, pWithIndex: TPasGLTFSizeInt);
  529. function GetEnumerator: TValueEnumerator;
  530. property Count: TPasGLTFSizeInt read fCount write SetCount;
  531. property Allocated: TPasGLTFSizeInt read fAllocated;
  532. property Items[const pIndex: TPasGLTFSizeInt]: T read GetItem write SetItem;
  533. default;
  534. property OwnsObjects: boolean read fOwnsObjects write fOwnsObjects;
  535. end;
  536. TPasGLTFHashMapEntityIndices = array of TPasGLTFInt32;
  537. TPasGLTFHashMapUInt128 = array [0 .. 1] of TPasGLTFUInt64;
  538. TPasGLTFUTF8StringHashMap < TPasGLTFHashMapValue >= class public
  539. const
  540. CELL_EMPTY = -1;
  541. CELL_DELETED = -2;
  542. ENT_EMPTY = -1;
  543. ENT_DELETED = -2;
  544. type
  545. TPasGLTFHashMapKey = TPasGLTFUTF8String;
  546. PPasGLTFHashMapEntity = ^TPasGLTFHashMapEntity;
  547. TPasGLTFHashMapEntity = record
  548. Key: TPasGLTFHashMapKey;
  549. Value: TPasGLTFHashMapValue;
  550. end;
  551. TPasGLTFHashMapEntities = array of TPasGLTFHashMapEntity;
  552. private type
  553. TPasGLTFHashMapEntityEnumerator = record
  554. private
  555. fHashMap: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
  556. fIndex: TPasGLTFSizeInt;
  557. function GetCurrent: TPasGLTFHashMapEntity; inline;
  558. public
  559. constructor Create(const aHashMap
  560. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  561. function MoveNext: boolean; inline;
  562. property Current: TPasGLTFHashMapEntity read GetCurrent;
  563. end;
  564. TPasGLTFHashMapKeyEnumerator = record
  565. private
  566. fHashMap: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
  567. fIndex: TPasGLTFSizeInt;
  568. function GetCurrent: TPasGLTFHashMapKey; inline;
  569. public
  570. constructor Create(const aHashMap
  571. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  572. function MoveNext: boolean; inline;
  573. property Current: TPasGLTFHashMapKey read GetCurrent;
  574. end;
  575. TPasGLTFHashMapValueEnumerator = record
  576. private
  577. fHashMap: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
  578. fIndex: TPasGLTFSizeInt;
  579. function GetCurrent: TPasGLTFHashMapValue; inline;
  580. public
  581. constructor Create(const aHashMap
  582. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  583. function MoveNext: boolean; inline;
  584. property Current: TPasGLTFHashMapValue read GetCurrent;
  585. end;
  586. TPasGLTFHashMapEntitiesObject = class
  587. private
  588. fOwner: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
  589. public
  590. constructor Create(const aOwner
  591. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  592. function GetEnumerator: TPasGLTFHashMapEntityEnumerator;
  593. end;
  594. TPasGLTFHashMapKeysObject = class
  595. private
  596. fOwner: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
  597. public
  598. constructor Create(const aOwner
  599. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  600. function GetEnumerator: TPasGLTFHashMapKeyEnumerator;
  601. end;
  602. TPasGLTFHashMapValuesObject = class
  603. private
  604. fOwner: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
  605. function GetValue(const Key: TPasGLTFHashMapKey)
  606. : TPasGLTFHashMapValue; inline;
  607. procedure SetValue(const Key: TPasGLTFHashMapKey;
  608. const aValue: TPasGLTFHashMapValue); inline;
  609. public
  610. constructor Create(const aOwner
  611. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  612. function GetEnumerator: TPasGLTFHashMapValueEnumerator;
  613. property Values[const Key: TPasGLTFHashMapKey]: TPasGLTFHashMapValue
  614. read GetValue write SetValue; default;
  615. end;
  616. private
  617. fRealSize: TPasGLTFInt32;
  618. fLogSize: TPasGLTFInt32;
  619. fSize: TPasGLTFInt32;
  620. fEntities: TPasGLTFHashMapEntities;
  621. fEntityToCellIndex: TPasGLTFHashMapEntityIndices;
  622. fCellToEntityIndex: TPasGLTFHashMapEntityIndices;
  623. fDefaultValue: TPasGLTFHashMapValue;
  624. fCanShrink: boolean;
  625. fEntitiesObject: TPasGLTFHashMapEntitiesObject;
  626. fKeysObject: TPasGLTFHashMapKeysObject;
  627. fValuesObject: TPasGLTFHashMapValuesObject;
  628. function HashData(const Data: TPasGLTFPointer;
  629. const DataLength: TPasGLTFSizeUInt): TPasGLTFUInt32;
  630. function HashKey(const Key: TPasGLTFHashMapKey): TPasGLTFUInt32;
  631. function CompareKey(const KeyA, KeyB: TPasGLTFHashMapKey): boolean;
  632. function FindCell(const Key: TPasGLTFHashMapKey): TPasGLTFUInt32;
  633. procedure Resize;
  634. protected
  635. function GetValue(const Key: TPasGLTFHashMapKey): TPasGLTFHashMapValue;
  636. procedure SetValue(const Key: TPasGLTFHashMapKey;
  637. const Value: TPasGLTFHashMapValue);
  638. public
  639. constructor Create(const DefaultValue: TPasGLTFHashMapValue);
  640. destructor Destroy; override;
  641. procedure Clear;
  642. function Add(const Key: TPasGLTFHashMapKey; const Value: TPasGLTFHashMapValue)
  643. : PPasGLTFHashMapEntity;
  644. function Get(const Key: TPasGLTFHashMapKey;
  645. const CreateIfNotExist: boolean = false): PPasGLTFHashMapEntity;
  646. function TryGet(const Key: TPasGLTFHashMapKey;
  647. out Value: TPasGLTFHashMapValue): boolean;
  648. function ExistKey(const Key: TPasGLTFHashMapKey): boolean;
  649. function Delete(const Key: TPasGLTFHashMapKey): boolean;
  650. property EntityValues[const Key: TPasGLTFHashMapKey]: TPasGLTFHashMapValue
  651. read GetValue write SetValue; default;
  652. property Entities: TPasGLTFHashMapEntitiesObject read fEntitiesObject;
  653. property Keys: TPasGLTFHashMapKeysObject read fKeysObject;
  654. property Values: TPasGLTFHashMapValuesObject read fValuesObject;
  655. property CanShrink: boolean read fCanShrink write fCanShrink;
  656. end;
  657. TPasGLTF = class public type TBase64 = class public
  658. const
  659. EncodingLookUpTable: array [0 .. 63] of TPasGLTFRawByteChar = ('A', 'B', 'C',
  660. 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
  661. 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
  662. 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  663. 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  664. '+', '/');
  665. DecodingLookUpTable: array [TPasGLTFRawByteChar] of TPasGLTFInt8 = (-1, -1,
  666. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  667. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  668. -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1,
  669. -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  670. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27,
  671. 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
  672. 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  673. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  674. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  675. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  676. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  677. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  678. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  679. -1, -1, -1, -1, -1);
  680. public
  681. class function Encode(const aData; const aDataLength: TPasGLTFSizeInt)
  682. : TPasGLTFRawByteString; overload; static;
  683. class function Encode(const aData: array of TPasGLTFUInt8): TPasGLTFRawByteString;
  684. overload;
  685. static;
  686. class function Encode(const aData: TPasGLTFRawByteString): TPasGLTFRawByteString;
  687. overload;
  688. static;
  689. class function Encode(const aData: TStream): TPasGLTFRawByteString;
  690. overload;
  691. static;
  692. class function Decode(const aInput: TPasGLTFRawByteString;
  693. const aOutput: TStream): boolean;
  694. overload;
  695. static;
  696. end;
  697. TChunkHeader = packed record ChunkLength: TPasGLTFUInt32;
  698. ChunkType: TPasGLTFUInt32;
  699. end;
  700. PChunkHeader = ^TChunkHeader;
  701. TGLBHeader = packed record Magic: TPasGLTFUInt32;
  702. Version: TPasGLTFUInt32;
  703. Length: TPasGLTFUInt32;
  704. JSONChunkHeader: TChunkHeader;
  705. end;
  706. TVector2 = array [0 .. 1] of TPasGLTFFloat;
  707. PVector2 = ^TVector2;
  708. TVector2DynamicArray = array of TVector2;
  709. TVector3 = array [0 .. 2] of TPasGLTFFloat;
  710. PVector3 = ^TVector3;
  711. TVector3DynamicArray = array of TVector3;
  712. TVector4 = array [0 .. 3] of TPasGLTFFloat;
  713. PVector4 = ^TVector4;
  714. TVector4DynamicArray = array of TVector4;
  715. TInt32Vector4 = array [0 .. 3] of TPasGLTFInt32;
  716. PInt32Vector4 = ^TInt32Vector4;
  717. TInt32Vector4DynamicArray = array of TInt32Vector4;
  718. TUInt32Vector4 = array [0 .. 3] of TPasGLTFUInt32;
  719. PUInt32Vector4 = ^TUInt32Vector4;
  720. TUInt32Vector4DynamicArray = array of TUInt32Vector4;
  721. TMatrix2x2 = array [0 .. 3] of TPasGLTFFloat;
  722. PMatrix2x2 = ^TMatrix2x2;
  723. TMatrix2x2DynamicArray = array of TMatrix2x2;
  724. TMatrix3x3 = array [0 .. 9] of TPasGLTFFloat;
  725. PMatrix3x3 = ^TMatrix3x3;
  726. TMatrix3x3DynamicArray = array of TMatrix3x3;
  727. TMatrix4x4 = array [0 .. 15] of TPasGLTFFloat;
  728. PMatrix4x4 = ^TMatrix4x4;
  729. TMatrix4x4DynamicArray = array of TMatrix4x4;
  730. const
  731. ChunkHeaderSize = SizeOf(TChunkHeader);
  732. GLBHeaderSize = SizeOf(TGLBHeader);
  733. GLBHeaderMagicNativeEndianness = TPasGLTFUInt32($46546C67);
  734. GLBHeaderMagicOtherEndianness = TPasGLTFUInt32($676C5446);
  735. GLBChunkJSONNativeEndianness = TPasGLTFUInt32($4E4F534A);
  736. GLBChunkJSONOtherEndianness = TPasGLTFUInt32($4A534F4E);
  737. GLBChunkBinaryNativeEndianness = TPasGLTFUInt32($004E4942);
  738. GLBChunkBinaryOtherEndianness = TPasGLTFUInt32($42494E00);
  739. MimeTypeApplicationOctet = 'application/octet-stream';
  740. MimeTypeImagePNG = 'image/png';
  741. MimeTypeImageJPG = 'image/jpg';
  742. type
  743. TDefaults = class
  744. public const
  745. AccessorNormalized = false;
  746. MaterialAlphaCutoff = 0.5;
  747. MaterialDoubleSided = false;
  748. IdentityScalar = 1.0;
  749. FloatSentinel = 1E+27;
  750. NullVector3: TVector3 = (0.0, 0.0, 0.0);
  751. IdentityVector3: TVector3 = (1.0, 1.0, 1.0);
  752. IdentityVector4: TVector4 = (1.0, 1.0, 1.0, 1.0);
  753. IdentityQuaternion: TVector4 = (0.0, 0.0, 0.0, 1.0);
  754. NullMatrix4x4: TMatrix4x4 = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
  755. 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
  756. IdentityMatrix4x4: TMatrix4x4 = (1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
  757. 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);
  758. end;
  759. TDocument = class;
  760. TBaseObject = class
  761. private
  762. fDocument: TDocument;
  763. public
  764. constructor Create(const aDocument: TDocument); reintroduce; virtual;
  765. destructor Destroy; override;
  766. end;
  767. TBaseExtensionsExtrasObject = class(TBaseObject)
  768. private
  769. fExtensions: TPasJSONItemObject;
  770. fExtras: TPasJSONItemObject;
  771. public
  772. constructor Create(const aDocument: TDocument); override;
  773. destructor Destroy; override;
  774. published
  775. property Extensions: TPasJSONItemObject read fExtensions;
  776. property Extras: TPasJSONItemObject read fExtras;
  777. end;
  778. TAttributes = TPasGLTFUTF8StringHashMap<TPasGLTFSizeInt>;
  779. TAttributesList = TPasGLTFObjectList<TAttributes>;
  780. TAccessor = class(TBaseExtensionsExtrasObject)
  781. public type
  782. TComponentType = (None = 0, SignedByte = 5120, UnsignedByte = 5121,
  783. SignedShort = 5122, UnsignedShort = 5123, UnsignedInt = 5125,
  784. Float = 5126);
  785. PComponentType = ^TComponentType;
  786. TComponentTypeHelper = record helper for TComponentType
  787. function GetSize: TPasGLTFSizeInt; inline;
  788. end;
  789. TRawComponentType = TPasGLTFUInt16;
  790. PRawComponentType = ^TRawComponentType;
  791. TType = (None = 0, Scalar = 1, Vec2 = 2, Vec3 = 3, Vec4 = 4, Mat2 = 5,
  792. Mat3 = 6, Mat4 = 7);
  793. PType = ^TType;
  794. TTypeHelper = record helper for TType
  795. function GetComponentCount: TPasGLTFSizeInt; inline;
  796. end;
  797. TRawType = TPasGLTFUInt8;
  798. PRawType = ^TRawType;
  799. TMinMaxDynamicArray = TPasGLTFDynamicArray<TPasGLTFFloat>;
  800. TSparse = class(TBaseExtensionsExtrasObject)
  801. public type
  802. TIndices = class(TBaseExtensionsExtrasObject)
  803. private
  804. fComponentType: TComponentType;
  805. fBufferView: TPasGLTFSizeInt;
  806. fByteOffset: TPasGLTFSizeUInt;
  807. fEmpty: boolean;
  808. public
  809. constructor Create(const aDocument: TDocument); override;
  810. destructor Destroy; override;
  811. published
  812. property ComponentType: TComponentType read fComponentType
  813. write fComponentType default TComponentType.None;
  814. property BufferView: TPasGLTFSizeInt read fBufferView write fBufferView
  815. default 0;
  816. property ByteOffset: TPasGLTFSizeUInt read fByteOffset write fByteOffset
  817. default 0;
  818. property Empty: boolean read fEmpty write fEmpty;
  819. end;
  820. TValues = class(TBaseExtensionsExtrasObject)
  821. private
  822. fBufferView: TPasGLTFSizeInt;
  823. fByteOffset: TPasGLTFSizeUInt;
  824. fEmpty: boolean;
  825. public
  826. constructor Create(const aDocument: TDocument); override;
  827. destructor Destroy; override;
  828. published
  829. property BufferView: TPasGLTFSizeInt read fBufferView write fBufferView
  830. default 0;
  831. property ByteOffset: TPasGLTFSizeUInt read fByteOffset write fByteOffset
  832. default 0;
  833. property Empty: boolean read fEmpty write fEmpty;
  834. end;
  835. private
  836. fCount: TPasGLTFSizeInt;
  837. fIndices: TIndices;
  838. fValues: TValues;
  839. function GetEmpty: boolean;
  840. public
  841. constructor Create(const aDocument: TDocument); override;
  842. destructor Destroy; override;
  843. published
  844. property Count: TPasGLTFSizeInt read fCount write fCount default 0;
  845. property Indices: TIndices read fIndices;
  846. property Values: TValues read fValues;
  847. property Empty: boolean read GetEmpty;
  848. end;
  849. const
  850. TypeComponentCountTable: array [TType] of TPasGLTFSizeInt = (0, 1, 2, 3, 4,
  851. 4, 9, 16);
  852. private
  853. fName: TPasGLTFUTF8String;
  854. fComponentType: TComponentType;
  855. fType: TType;
  856. fBufferView: TPasGLTFSizeInt;
  857. fByteOffset: TPasGLTFSizeUInt;
  858. fCount: TPasGLTFSizeUInt;
  859. fNormalized: boolean;
  860. fMinArray: TMinMaxDynamicArray;
  861. fMaxArray: TMinMaxDynamicArray;
  862. fSparse: TSparse;
  863. public
  864. constructor Create(const aDocument: TDocument); override;
  865. destructor Destroy; override;
  866. function DecodeAsDoubleArray(const aForVertex: boolean = true)
  867. : TPasGLTFDoubleDynamicArray;
  868. function DecodeAsInt32Array(const aForVertex: boolean = true)
  869. : TPasGLTFInt32DynamicArray;
  870. function DecodeAsUInt32Array(const aForVertex: boolean = true)
  871. : TPasGLTFUInt32DynamicArray;
  872. function DecodeAsInt64Array(const aForVertex: boolean = true)
  873. : TPasGLTFInt64DynamicArray;
  874. function DecodeAsUInt64Array(const aForVertex: boolean = true)
  875. : TPasGLTFUInt64DynamicArray;
  876. function DecodeAsFloatArray(const aForVertex: boolean = true)
  877. : TPasGLTFFloatDynamicArray;
  878. function DecodeAsVector2Array(const aForVertex: boolean = true)
  879. : TVector2DynamicArray;
  880. function DecodeAsVector3Array(const aForVertex: boolean = true)
  881. : TVector3DynamicArray;
  882. function DecodeAsVector4Array(const aForVertex: boolean = true)
  883. : TVector4DynamicArray;
  884. function DecodeAsInt32Vector4Array(const aForVertex: boolean = true)
  885. : TInt32Vector4DynamicArray;
  886. function DecodeAsUInt32Vector4Array(const aForVertex: boolean = true)
  887. : TUInt32Vector4DynamicArray;
  888. function DecodeAsColorArray(const aForVertex: boolean = true)
  889. : TVector4DynamicArray;
  890. function DecodeAsMatrix2x2Array(const aForVertex: boolean = true)
  891. : TMatrix2x2DynamicArray;
  892. function DecodeAsMatrix3x3Array(const aForVertex: boolean = true)
  893. : TMatrix3x3DynamicArray;
  894. function DecodeAsMatrix4x4Array(const aForVertex: boolean = true)
  895. : TMatrix4x4DynamicArray;
  896. published
  897. property ComponentType: TComponentType read fComponentType
  898. write fComponentType default TComponentType.None;
  899. property Type_: TType read fType write fType default TType.None;
  900. property BufferView: TPasGLTFSizeInt read fBufferView write fBufferView
  901. default -1;
  902. property ByteOffset: TPasGLTFSizeUInt read fByteOffset write fByteOffset
  903. default 0;
  904. property Count: TPasGLTFSizeUInt read fCount write fCount default 0;
  905. property MinArray: TMinMaxDynamicArray read fMinArray;
  906. property MaxArray: TMinMaxDynamicArray read fMaxArray;
  907. property Normalized: boolean read fNormalized write fNormalized
  908. default false;
  909. property Sparse: TSparse read fSparse;
  910. end;
  911. TAccessors = TPasGLTFObjectList<TAccessor>;
  912. TAnimation = class(TBaseExtensionsExtrasObject)
  913. public type
  914. TChannel = class(TBaseExtensionsExtrasObject)
  915. public type
  916. TTarget = class(TBaseExtensionsExtrasObject)
  917. private
  918. fNode: TPasGLTFSizeInt;
  919. fPath: TPasGLTFUTF8String;
  920. fEmpty: boolean;
  921. public
  922. constructor Create(const aDocument: TDocument); override;
  923. destructor Destroy; override;
  924. published
  925. property Node: TPasGLTFSizeInt read fNode write fNode default -1;
  926. property Path: TPasGLTFUTF8String read fPath write fPath;
  927. property Empty: boolean read fEmpty write fEmpty;
  928. end;
  929. private
  930. fSampler: TPasGLTFSizeInt;
  931. fTarget: TChannel.TTarget;
  932. public
  933. constructor Create(const aDocument: TDocument); override;
  934. destructor Destroy; override;
  935. published
  936. property Sampler: TPasGLTFSizeInt read fSampler write fSampler default -1;
  937. property Target: TChannel.TTarget read fTarget;
  938. end;
  939. TChannels = TPasGLTFObjectList<TChannel>;
  940. TSampler = class(TBaseExtensionsExtrasObject)
  941. public type
  942. TType = (Linear = 0, Step = 1, CubicSpline = 2);
  943. PType = ^TType;
  944. private
  945. fInput: TPasGLTFSizeInt;
  946. fOutput: TPasGLTFSizeInt;
  947. fInterpolation: TType;
  948. public
  949. constructor Create(const aDocument: TDocument); override;
  950. destructor Destroy; override;
  951. published
  952. property Input: TPasGLTFSizeInt read fInput write fInput default -1;
  953. property Output: TPasGLTFSizeInt read fOutput write fOutput default -1;
  954. property Interpolation: TType read fInterpolation write fInterpolation
  955. default TType.Linear;
  956. end;
  957. TSamplers = TPasGLTFObjectList<TSampler>;
  958. private
  959. fName: TPasGLTFUTF8String;
  960. fChannels: TChannels;
  961. fSamplers: TSamplers;
  962. public
  963. constructor Create(const aDocument: TDocument); override;
  964. destructor Destroy; override;
  965. published
  966. property Name: TPasGLTFUTF8String read fName write fName;
  967. property Channels: TChannels read fChannels;
  968. property Samplers: TSamplers read fSamplers;
  969. end;
  970. TAnimations = TPasGLTFObjectList<TAnimation>;
  971. TAsset = class(TBaseExtensionsExtrasObject)
  972. private
  973. fCopyright: TPasGLTFUTF8String;
  974. fGenerator: TPasGLTFUTF8String;
  975. fMinVersion: TPasGLTFUTF8String;
  976. fVersion: TPasGLTFUTF8String;
  977. fEmpty: boolean;
  978. public
  979. constructor Create(const aDocument: TDocument); override;
  980. destructor Destroy; override;
  981. published
  982. property Copyright: TPasGLTFUTF8String read fCopyright write fCopyright;
  983. property Generator: TPasGLTFUTF8String read fGenerator write fGenerator;
  984. property MinVersion: TPasGLTFUTF8String read fMinVersion write fMinVersion;
  985. property Version: TPasGLTFUTF8String read fVersion write fVersion;
  986. property Empty: boolean read fEmpty write fEmpty;
  987. end;
  988. TBuffer = class(TBaseExtensionsExtrasObject)
  989. private
  990. fByteLength: TPasGLTFSizeUInt;
  991. fName: TPasGLTFUTF8String;
  992. fURI: TPasGLTFUTF8String;
  993. fData: TMemoryStream;
  994. public
  995. constructor Create(const aDocument: TDocument); override;
  996. destructor Destroy; override;
  997. procedure SetEmbeddedResourceData;
  998. published
  999. property ByteLength: TPasGLTFSizeUInt read fByteLength write fByteLength;
  1000. property Name: TPasGLTFUTF8String read fName write fName;
  1001. property URI: TPasGLTFUTF8String read fURI write fURI;
  1002. property Data: TMemoryStream read fData write fData;
  1003. end;
  1004. TBuffers = TPasGLTFObjectList<TBuffer>;
  1005. TBufferView = class(TBaseExtensionsExtrasObject)
  1006. public type
  1007. TTargetType = (None = 0, ArrayBuffer = 34962, ElementArrayBuffer = 34963);
  1008. PTargetType = ^TTargetType;
  1009. private
  1010. fName: TPasGLTFUTF8String;
  1011. fBuffer: TPasGLTFSizeInt;
  1012. fByteOffset: TPasGLTFSizeUInt;
  1013. fByteLength: TPasGLTFSizeUInt;
  1014. fByteStride: TPasGLTFSizeUInt;
  1015. fTarget: TTargetType;
  1016. public
  1017. constructor Create(const aDocument: TDocument); override;
  1018. destructor Destroy; override;
  1019. function Decode(const aSkipEvery: TPasGLTFSizeUInt;
  1020. const aSkipBytes: TPasGLTFSizeUInt; const aElementSize: TPasGLTFSizeUInt;
  1021. const aCount: TPasGLTFSizeUInt; const aType: TPasGLTF.TAccessor.TType;
  1022. const aComponentCount: TPasGLTFSizeUInt;
  1023. const aComponentType: TPasGLTF.TAccessor.TComponentType;
  1024. const aComponentSize: TPasGLTFSizeUInt;
  1025. const aByteOffset: TPasGLTFSizeUInt; const aNormalized: boolean;
  1026. const aForVertex: boolean): TPasGLTFDoubleDynamicArray;
  1027. published
  1028. property Name: TPasGLTFUTF8String read fName write fName;
  1029. property Buffer: TPasGLTFSizeInt read fBuffer write fBuffer;
  1030. property ByteOffset: TPasGLTFSizeUInt read fByteOffset write fByteOffset;
  1031. property ByteLength: TPasGLTFSizeUInt read fByteLength write fByteLength;
  1032. property ByteStride: TPasGLTFSizeUInt read fByteStride write fByteStride;
  1033. property Target: TTargetType read fTarget write fTarget
  1034. default TTargetType.None;
  1035. end;
  1036. TBufferViews = TPasGLTFObjectList<TBufferView>;
  1037. TCamera = class(TBaseExtensionsExtrasObject)
  1038. public type
  1039. TType = (None = 0, Orthographic = 1, Perspective = 2);
  1040. TOrthographic = class(TBaseExtensionsExtrasObject)
  1041. private
  1042. fXMag: TPasGLTFFloat;
  1043. fYMag: TPasGLTFFloat;
  1044. fZNear: TPasGLTFFloat;
  1045. fZFar: TPasGLTFFloat;
  1046. fEmpty: boolean;
  1047. public
  1048. constructor Create(const aDocument: TDocument); override;
  1049. destructor Destroy; override;
  1050. published
  1051. property XMag: TPasGLTFFloat read fXMag write fXMag;
  1052. property YMag: TPasGLTFFloat read fYMag write fYMag;
  1053. property ZNear: TPasGLTFFloat read fZNear write fZNear;
  1054. property ZFar: TPasGLTFFloat read fZFar write fZFar;
  1055. property Empty: boolean read fEmpty write fEmpty;
  1056. end;
  1057. TPerspective = class(TBaseExtensionsExtrasObject)
  1058. private
  1059. fAspectRatio: TPasGLTFFloat;
  1060. fYFov: TPasGLTFFloat;
  1061. fZNear: TPasGLTFFloat;
  1062. fZFar: TPasGLTFFloat;
  1063. fEmpty: boolean;
  1064. public
  1065. constructor Create(const aDocument: TDocument); override;
  1066. destructor Destroy; override;
  1067. published
  1068. property AspectRatio: TPasGLTFFloat read fAspectRatio write fAspectRatio;
  1069. property YFov: TPasGLTFFloat read fYFov write fYFov;
  1070. property ZNear: TPasGLTFFloat read fZNear write fZNear;
  1071. property ZFar: TPasGLTFFloat read fZFar write fZFar;
  1072. property Empty: boolean read fEmpty write fEmpty;
  1073. end;
  1074. private
  1075. fType: TType;
  1076. fOrthographic: TOrthographic;
  1077. fPerspective: TPerspective;
  1078. fName: TPasGLTFUTF8String;
  1079. public
  1080. constructor Create(const aDocument: TDocument); override;
  1081. destructor Destroy; override;
  1082. published
  1083. property Type_: TType read fType write fType;
  1084. property Orthographic: TOrthographic read fOrthographic;
  1085. property Perspective: TPerspective read fPerspective;
  1086. property Name: TPasGLTFUTF8String read fName write fName;
  1087. end;
  1088. TCameras = TPasGLTFObjectList<TCamera>;
  1089. TImage = class(TBaseExtensionsExtrasObject)
  1090. private
  1091. fBufferView: TPasGLTFSizeInt;
  1092. fName: TPasGLTFUTF8String;
  1093. fURI: TPasGLTFUTF8String;
  1094. fMimeType: TPasGLTFUTF8String;
  1095. public
  1096. constructor Create(const aDocument: TDocument); override;
  1097. destructor Destroy; override;
  1098. procedure SetEmbeddedResourceData(const aStream: TStream);
  1099. procedure GetResourceData(const aStream: TStream);
  1100. function IsExternalResource: boolean;
  1101. published
  1102. property BufferView: TPasGLTFSizeInt read fBufferView write fBufferView;
  1103. property Name: TPasGLTFUTF8String read fName write fName;
  1104. property URI: TPasGLTFUTF8String read fURI write fURI;
  1105. property MimeType: TPasGLTFUTF8String read fMimeType write fMimeType;
  1106. end;
  1107. TImages = TPasGLTFObjectList<TImage>;
  1108. TMaterial = class(TBaseExtensionsExtrasObject)
  1109. public type
  1110. TAlphaMode = (Opaque = 0, Mask = 1, Blend = 2);
  1111. PAlphaMode = ^TAlphaMode;
  1112. TAlphaModes = set of TAlphaMode;
  1113. TTexture = class(TBaseExtensionsExtrasObject)
  1114. private
  1115. fIndex: TPasGLTFSizeInt;
  1116. fTexCoord: TPasGLTFSizeInt;
  1117. function GetEmpty: boolean;
  1118. public
  1119. constructor Create(const aDocument: TDocument); override;
  1120. destructor Destroy; override;
  1121. published
  1122. property Index: TPasGLTFSizeInt read fIndex write fIndex;
  1123. property TexCoord: TPasGLTFSizeInt read fTexCoord write fTexCoord;
  1124. property Empty: boolean read GetEmpty;
  1125. end;
  1126. TNormalTexture = class(TTexture)
  1127. private
  1128. fScale: TPasGLTFFloat;
  1129. public
  1130. constructor Create(const aDocument: TDocument); override;
  1131. published
  1132. property Scale: TPasGLTFFloat read fScale write fScale;
  1133. end;
  1134. TOcclusionTexture = class(TTexture)
  1135. private
  1136. fStrength: TPasGLTFFloat;
  1137. public
  1138. constructor Create(const aDocument: TDocument); override;
  1139. published
  1140. property Strength: TPasGLTFFloat read fStrength write fStrength;
  1141. end;
  1142. TPBRMetallicRoughness = class(TBaseExtensionsExtrasObject)
  1143. private
  1144. fBaseColorFactor: TVector4;
  1145. fBaseColorTexture: TTexture;
  1146. fRoughnessFactor: TPasGLTFFloat;
  1147. fMetallicFactor: TPasGLTFFloat;
  1148. fMetallicRoughnessTexture: TTexture;
  1149. function GetEmpty: boolean;
  1150. public
  1151. constructor Create(const aDocument: TDocument); override;
  1152. destructor Destroy; override;
  1153. public
  1154. property BaseColorFactor: TVector4 read fBaseColorFactor
  1155. write fBaseColorFactor;
  1156. published
  1157. property BaseColorTexture: TTexture read fBaseColorTexture;
  1158. property RoughnessFactor: TPasGLTFFloat read fRoughnessFactor
  1159. write fRoughnessFactor;
  1160. property MetallicFactor: TPasGLTFFloat read fMetallicFactor
  1161. write fMetallicFactor;
  1162. property MetallicRoughnessTexture: TTexture
  1163. read fMetallicRoughnessTexture;
  1164. property Empty: boolean read GetEmpty;
  1165. end;
  1166. private
  1167. fName: TPasGLTFUTF8String;
  1168. fAlphaCutOff: TPasGLTFFloat;
  1169. fAlphaMode: TAlphaMode;
  1170. fDoubleSided: boolean;
  1171. fNormalTexture: TNormalTexture;
  1172. fOcclusionTexture: TOcclusionTexture;
  1173. fPBRMetallicRoughness: TPBRMetallicRoughness;
  1174. fEmissiveTexture: TTexture;
  1175. fEmissiveFactor: TVector3;
  1176. public
  1177. constructor Create(const aDocument: TDocument); override;
  1178. destructor Destroy; override;
  1179. public
  1180. property EmissiveFactor: TVector3 read fEmissiveFactor
  1181. write fEmissiveFactor;
  1182. published
  1183. property Name: TPasGLTFUTF8String read fName write fName;
  1184. property AlphaCutOff: TPasGLTFFloat read fAlphaCutOff write fAlphaCutOff;
  1185. property AlphaMode: TAlphaMode read fAlphaMode write fAlphaMode;
  1186. property DoubleSided: boolean read fDoubleSided write fDoubleSided;
  1187. property NormalTexture: TNormalTexture read fNormalTexture;
  1188. property OcclusionTexture: TOcclusionTexture read fOcclusionTexture;
  1189. property PBRMetallicRoughness: TPBRMetallicRoughness
  1190. read fPBRMetallicRoughness;
  1191. property EmissiveTexture: TTexture read fEmissiveTexture;
  1192. end;
  1193. TMaterials = TPasGLTFObjectList<TMaterial>;
  1194. TMesh = class(TBaseExtensionsExtrasObject)
  1195. public type
  1196. TPrimitive = class(TBaseExtensionsExtrasObject)
  1197. public type
  1198. TMode = (Points = 0, Lines = 1, LineLoop = 2, LineStrip = 3,
  1199. Triangles = 4, TriangleStrip = 5, TriangleFan = 6);
  1200. PMode = ^TMode;
  1201. private
  1202. fMode: TMode;
  1203. fIndices: TPasGLTFSizeInt;
  1204. fMaterial: TPasGLTFSizeInt;
  1205. fAttributes: TAttributes;
  1206. fTargets: TAttributesList;
  1207. public
  1208. constructor Create(const aDocument: TDocument); override;
  1209. destructor Destroy; override;
  1210. published
  1211. property Mode: TMode read fMode write fMode;
  1212. property Indices: TPasGLTFSizeInt read fIndices write fIndices;
  1213. property Material: TPasGLTFSizeInt read fMaterial write fMaterial;
  1214. property Attributes: TAttributes read fAttributes;
  1215. property Targets: TAttributesList read fTargets;
  1216. end;
  1217. TPrimitives = TPasGLTFObjectList<TPrimitive>;
  1218. TWeights = TPasGLTFDynamicArray<TPasGLTFFloat>;
  1219. private
  1220. fName: TPasGLTFUTF8String;
  1221. fWeights: TWeights;
  1222. fPrimitives: TPrimitives;
  1223. public
  1224. constructor Create(const aDocument: TDocument); override;
  1225. destructor Destroy; override;
  1226. public
  1227. published
  1228. property Name: TPasGLTFUTF8String read fName write fName;
  1229. property Weights: TWeights read fWeights;
  1230. property Primitives: TPrimitives read fPrimitives;
  1231. end;
  1232. TMeshes = TPasGLTFObjectList<TMesh>;
  1233. TNode = class(TBaseExtensionsExtrasObject)
  1234. public type
  1235. TChildren = TPasGLTFDynamicArray<TPasGLTFSizeInt>;
  1236. TWeights = TPasGLTFDynamicArray<TPasGLTFFloat>;
  1237. private
  1238. fName: TPasGLTFUTF8String;
  1239. fCamera: TPasGLTFSizeInt;
  1240. fMesh: TPasGLTFSizeInt;
  1241. fSkin: TPasGLTFSizeInt;
  1242. fMatrix: TMatrix4x4;
  1243. fRotation: TVector4;
  1244. fScale: TVector3;
  1245. fTranslation: TVector3;
  1246. fChildren: TChildren;
  1247. fWeights: TWeights;
  1248. public
  1249. constructor Create(const aDocument: TDocument); override;
  1250. destructor Destroy; override;
  1251. public
  1252. property Matrix: TMatrix4x4 read fMatrix write fMatrix;
  1253. property Rotation: TVector4 read fRotation write fRotation;
  1254. property Scale: TVector3 read fScale write fScale;
  1255. property Translation: TVector3 read fTranslation write fTranslation;
  1256. published
  1257. property Name: TPasGLTFUTF8String read fName write fName;
  1258. property Camera: TPasGLTFSizeInt read fCamera write fCamera;
  1259. property Mesh: TPasGLTFSizeInt read fMesh write fMesh;
  1260. property Skin: TPasGLTFSizeInt read fSkin write fSkin;
  1261. property Children: TChildren read fChildren;
  1262. property Weights: TWeights read fWeights;
  1263. end;
  1264. TNodes = TPasGLTFObjectList<TNode>;
  1265. TSampler = class(TBaseExtensionsExtrasObject)
  1266. public type
  1267. TMagFilter = (None = 0, Nearest = 9728, Linear = 9729);
  1268. PMagFilter = ^TMagFilter;
  1269. TMinFilter = (None = 0, Nearest = 9728, Linear = 9729,
  1270. NearestMipMapNearest = 9984, LinearMipMapNearest = 9985,
  1271. NearestMipMapLinear = 9986, LinearMipMapLinear = 9987);
  1272. PMinFilter = ^TMinFilter;
  1273. TWrappingMode = (Repeat_ = 10497, ClampToEdge = 33071,
  1274. MirroredRepeat = 33648);
  1275. PWrappingMode = ^TWrappingMode;
  1276. private
  1277. fName: TPasGLTFUTF8String;
  1278. fMagFilter: TMagFilter;
  1279. fMinFilter: TMinFilter;
  1280. fWrapS: TWrappingMode;
  1281. fWrapT: TWrappingMode;
  1282. function GetEmpty: boolean;
  1283. public
  1284. constructor Create(const aDocument: TDocument); override;
  1285. destructor Destroy; override;
  1286. published
  1287. property Name: TPasGLTFUTF8String read fName write fName;
  1288. property MagFilter: TMagFilter read fMagFilter write fMagFilter;
  1289. property MinFilter: TMinFilter read fMinFilter write fMinFilter;
  1290. property WrapS: TWrappingMode read fWrapS write fWrapS;
  1291. property WrapT: TWrappingMode read fWrapT write fWrapT;
  1292. property Empty: boolean read GetEmpty;
  1293. end;
  1294. TSamplers = TPasGLTFObjectList<TSampler>;
  1295. TScene = class(TBaseExtensionsExtrasObject)
  1296. public type
  1297. TNodes = TPasGLTFDynamicArray<TPasGLTFSizeUInt>;
  1298. private
  1299. fName: TPasGLTFUTF8String;
  1300. fNodes: TScene.TNodes;
  1301. public
  1302. constructor Create(const aDocument: TDocument); override;
  1303. destructor Destroy; override;
  1304. published
  1305. property Name: TPasGLTFUTF8String read fName write fName;
  1306. property Nodes: TScene.TNodes read fNodes;
  1307. end;
  1308. TScenes = TPasGLTFObjectList<TScene>;
  1309. TSkin = class(TBaseExtensionsExtrasObject)
  1310. public type
  1311. TJoints = TPasGLTFDynamicArray<TPasGLTFSizeUInt>;
  1312. private
  1313. fName: TPasGLTFUTF8String;
  1314. fInverseBindMatrices: TPasGLTFSizeInt;
  1315. fSkeleton: TPasGLTFSizeInt;
  1316. fJoints: TSkin.TJoints;
  1317. public
  1318. constructor Create(const aDocument: TDocument); override;
  1319. destructor Destroy; override;
  1320. published
  1321. property Name: TPasGLTFUTF8String read fName write fName;
  1322. property InverseBindMatrices: TPasGLTFSizeInt read fInverseBindMatrices
  1323. write fInverseBindMatrices;
  1324. property Skeleton: TPasGLTFSizeInt read fSkeleton write fSkeleton;
  1325. property Joints: TSkin.TJoints read fJoints;
  1326. end;
  1327. TSkins = TPasGLTFObjectList<TSkin>;
  1328. TTexture = class(TBaseExtensionsExtrasObject)
  1329. private
  1330. fName: TPasGLTFUTF8String;
  1331. fSampler: TPasGLTFSizeInt;
  1332. fSource: TPasGLTFSizeInt;
  1333. public
  1334. constructor Create(const aDocument: TDocument); override;
  1335. destructor Destroy; override;
  1336. published
  1337. property Name: TPasGLTFUTF8String read fName write fName;
  1338. property Sampler: TPasGLTFSizeInt read fSampler write fSampler;
  1339. property Source: TPasGLTFSizeInt read fSource write fSource;
  1340. end;
  1341. TTextures = TPasGLTFObjectList<TTexture>;
  1342. TDocument = class(TBaseExtensionsExtrasObject)
  1343. public type
  1344. TGetURI = function(const aURI: TPasGLTFUTF8String): TStream of object;
  1345. private
  1346. fAsset: TAsset;
  1347. fAccessors: TAccessors;
  1348. fAnimations: TAnimations;
  1349. fBuffers: TBuffers;
  1350. fBufferViews: TBufferViews;
  1351. fCameras: TCameras;
  1352. fImages: TImages;
  1353. fMaterials: TMaterials;
  1354. fMeshes: TMeshes;
  1355. fNodes: TNodes;
  1356. fSamplers: TSamplers;
  1357. fScene: TPasGLTFSizeInt;
  1358. fScenes: TScenes;
  1359. fSkins: TSkins;
  1360. fTextures: TTextures;
  1361. fExtensionsUsed: TStringList;
  1362. fExtensionsRequired: TStringList;
  1363. fRootPath: TPasGLTFUTF8String;
  1364. fGetURI: TGetURI;
  1365. function DefaultGetURI(const aURI: TPasGLTFUTF8String): TStream;
  1366. procedure LoadURISource(const aURI: TPasGLTFUTF8String;
  1367. const aStream: TStream);
  1368. procedure LoadURISources;
  1369. public
  1370. constructor Create(const aDocument: TDocument = nil); override;
  1371. destructor Destroy; override;
  1372. procedure LoadFromJSON(const aJSONRootItem: TPasJSONItem);
  1373. procedure LoadFromBinary(const aStream: TStream);
  1374. procedure LoadFromStream(const aStream: TStream);
  1375. function SaveToJSON(const aFormatted: boolean = false)
  1376. : TPasJSONRawByteString;
  1377. procedure SaveToBinary(const aStream: TStream);
  1378. procedure SaveToStream(const aStream: TStream;
  1379. const aBinary: boolean = false; const aFormatted: boolean = false);
  1380. published
  1381. property Asset: TAsset read fAsset;
  1382. property Accessors: TAccessors read fAccessors;
  1383. property Animations: TAnimations read fAnimations;
  1384. property Buffers: TBuffers read fBuffers;
  1385. property BufferViews: TBufferViews read fBufferViews;
  1386. property Cameras: TCameras read fCameras;
  1387. property Images: TImages read fImages;
  1388. property Materials: TMaterials read fMaterials;
  1389. property Meshes: TMeshes read fMeshes;
  1390. property Nodes: TNodes read fNodes;
  1391. property Samplers: TSamplers read fSamplers;
  1392. property Scene: TPasGLTFSizeInt read fScene write fScene;
  1393. property Scenes: TScenes read fScenes;
  1394. property Skins: TSkins read fSkins;
  1395. property Textures: TTextures read fTextures;
  1396. property ExtensionsUsed: TStringList read fExtensionsUsed;
  1397. property ExtensionsRequired: TStringList read fExtensionsRequired;
  1398. property RootPath: TPasGLTFUTF8String read fRootPath write fRootPath;
  1399. property GetURI: TGetURI read fGetURI write fGetURI;
  1400. end;
  1401. public
  1402. class function ResolveURIToPath(const aURI: TPasGLTFUTF8String): TPasGLTFUTF8String; static;
  1403. end;
  1404. implementation
  1405. {$IFNDEF fpc}
  1406. class function TPasGLTFTypedSort<T>.BSRDWord(aValue: TPasGLTFUInt32)
  1407. : TPasGLTFInt32;
  1408. const
  1409. BSRDebruijn32Multiplicator = TPasGLTFUInt32($07C4ACDD);
  1410. BSRDebruijn32Shift = 27;
  1411. BSRDebruijn32Mask = 31;
  1412. BSRDebruijn32Table: array [0 .. 31] of TPasGLTFInt32 = (0, 9, 1, 10, 13, 21,
  1413. 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27,
  1414. 23, 6, 26, 5, 4, 31);
  1415. var
  1416. Value: TPasGLTFUInt32;
  1417. begin
  1418. if aValue = 0 then
  1419. begin
  1420. result := 255;
  1421. end
  1422. else
  1423. begin
  1424. Value := aValue or (aValue shr 1);
  1425. Value := Value or (Value shr 2);
  1426. Value := Value or (Value shr 4);
  1427. Value := Value or (Value shr 8);
  1428. Value := Value or (Value shr 16);
  1429. result := BSRDebruijn32Table
  1430. [((Value * BSRDebruijn32Multiplicator) shr BSRDebruijn32Shift) and
  1431. BSRDebruijn32Mask];
  1432. end;
  1433. end;
  1434. {$ENDIF}
  1435. class procedure TPasGLTFTypedSort<T>.IntroSort(const pItems: TPasGLTFPointer;
  1436. const pLeft, pRight: TPasGLTFSizeInt;
  1437. const pCompareFunc: TPasGLTFTypedSortCompareFunction);
  1438. type
  1439. TItem = T;
  1440. pItem = ^TItem;
  1441. TItemArray = array [0 .. 65535] of TItem;
  1442. PItemArray = ^TItemArray;
  1443. var
  1444. Left, Right, i, j, Middle, Size, Parent, Child, Pivot, iA, iB,
  1445. iC: TPasGLTFSizeInt;
  1446. Depth: TPasGLTFInt32;
  1447. StackItem: PStackItem;
  1448. Stack: array [0 .. 31] of TStackItem;
  1449. Temp: T;
  1450. begin
  1451. if pLeft < pRight then
  1452. begin
  1453. StackItem := @Stack[0];
  1454. StackItem^.Left := pLeft;
  1455. StackItem^.Right := pRight;
  1456. if (TPasGLTFInt64(pRight) - TPasGLTFInt64(pLeft)) <=
  1457. TPasGLTFInt64(High(TPasGLTFUInt32)) then
  1458. begin
  1459. StackItem^.Depth := BSRDWord((pRight - pLeft) + 1) shl 1;
  1460. if StackItem^.Depth > 31 then
  1461. begin
  1462. StackItem^.Depth := 31;
  1463. end;
  1464. end
  1465. else
  1466. begin
  1467. StackItem^.Depth := 31;
  1468. end;
  1469. inc(StackItem);
  1470. while {%H-}TPasGLTFPtrUInt(TPasGLTFPointer(StackItem)) >
  1471. TPasGLTFPtrUInt(TPasGLTFPointer(@Stack[0])) do
  1472. begin
  1473. dec(StackItem);
  1474. Left := StackItem^.Left;
  1475. Right := StackItem^.Right;
  1476. Depth := StackItem^.Depth;
  1477. Size := (Right - Left) + 1;
  1478. if Size < 16 then
  1479. begin
  1480. // Insertion sort
  1481. iA := Left;
  1482. iB := iA + 1;
  1483. while iB <= Right do
  1484. begin
  1485. iC := iB;
  1486. while (iA >= Left) and (iC >= Left) and
  1487. (pCompareFunc(PItemArray(pItems)^[iA],
  1488. PItemArray(pItems)^[iC]) > 0) do
  1489. begin
  1490. Temp := PItemArray(pItems)^[iA];
  1491. PItemArray(pItems)^[iA] := PItemArray(pItems)^[iC];
  1492. PItemArray(pItems)^[iC] := Temp;
  1493. dec(iA);
  1494. dec(iC);
  1495. end;
  1496. iA := iB;
  1497. inc(iB);
  1498. end;
  1499. end
  1500. else
  1501. begin
  1502. if (Depth = 0) or ({%H-}TPasGLTFPtrUInt(TPasGLTFPointer(StackItem)) >=
  1503. TPasGLTFPtrUInt(TPasGLTFPointer(@Stack[high(Stack) - 1]))) then
  1504. begin
  1505. // Heap sort
  1506. i := Size div 2;
  1507. repeat
  1508. if i > 0 then
  1509. begin
  1510. dec(i);
  1511. end
  1512. else
  1513. begin
  1514. dec(Size);
  1515. if Size > 0 then
  1516. begin
  1517. Temp := PItemArray(pItems)^[Left + Size];
  1518. PItemArray(pItems)^[Left + Size] := PItemArray(pItems)^[Left];
  1519. PItemArray(pItems)^[Left] := Temp;
  1520. end
  1521. else
  1522. begin
  1523. break;
  1524. end;
  1525. end;
  1526. Parent := i;
  1527. repeat
  1528. Child := (Parent * 2) + 1;
  1529. if Child < Size then
  1530. begin
  1531. if (Child < (Size - 1)) and
  1532. (pCompareFunc(PItemArray(pItems)^[Left + Child],
  1533. PItemArray(pItems)^[Left + Child + 1]) < 0) then
  1534. begin
  1535. inc(Child);
  1536. end;
  1537. if pCompareFunc(PItemArray(pItems)^[Left + Parent],
  1538. PItemArray(pItems)^[Left + Child]) < 0 then
  1539. begin
  1540. Temp := PItemArray(pItems)^[Left + Parent];
  1541. PItemArray(pItems)^[Left + Parent] := PItemArray(pItems)
  1542. ^[Left + Child];
  1543. PItemArray(pItems)^[Left + Child] := Temp;
  1544. Parent := Child;
  1545. continue;
  1546. end;
  1547. end;
  1548. break;
  1549. until false;
  1550. until false;
  1551. end
  1552. else
  1553. begin
  1554. // Quick sort width median-of-three optimization
  1555. Middle := Left + ((Right - Left) shr 1);
  1556. if (Right - Left) > 3 then
  1557. begin
  1558. if pCompareFunc(PItemArray(pItems)^[Left],
  1559. PItemArray(pItems)^[Middle]) > 0 then
  1560. begin
  1561. Temp := PItemArray(pItems)^[Left];
  1562. PItemArray(pItems)^[Left] := PItemArray(pItems)^[Middle];
  1563. PItemArray(pItems)^[Middle] := Temp;
  1564. end;
  1565. if pCompareFunc(PItemArray(pItems)^[Left],
  1566. PItemArray(pItems)^[Right]) > 0 then
  1567. begin
  1568. Temp := PItemArray(pItems)^[Left];
  1569. PItemArray(pItems)^[Left] := PItemArray(pItems)^[Right];
  1570. PItemArray(pItems)^[Right] := Temp;
  1571. end;
  1572. if pCompareFunc(PItemArray(pItems)^[Middle],
  1573. PItemArray(pItems)^[Right]) > 0 then
  1574. begin
  1575. Temp := PItemArray(pItems)^[Middle];
  1576. PItemArray(pItems)^[Middle] := PItemArray(pItems)^[Right];
  1577. PItemArray(pItems)^[Right] := Temp;
  1578. end;
  1579. end;
  1580. Pivot := Middle;
  1581. i := Left;
  1582. j := Right;
  1583. repeat
  1584. while (i < Right) and
  1585. (pCompareFunc(PItemArray(pItems)^[i],
  1586. PItemArray(pItems)^[Pivot]) < 0) do
  1587. begin
  1588. inc(i);
  1589. end;
  1590. while (j >= i) and
  1591. (pCompareFunc(PItemArray(pItems)^[j],
  1592. PItemArray(pItems)^[Pivot]) > 0) do
  1593. begin
  1594. dec(j);
  1595. end;
  1596. if i > j then
  1597. begin
  1598. break;
  1599. end
  1600. else
  1601. begin
  1602. if i <> j then
  1603. begin
  1604. Temp := PItemArray(pItems)^[i];
  1605. PItemArray(pItems)^[i] := PItemArray(pItems)^[j];
  1606. PItemArray(pItems)^[j] := Temp;
  1607. if Pivot = i then
  1608. begin
  1609. Pivot := j;
  1610. end
  1611. else if Pivot = j then
  1612. begin
  1613. Pivot := i;
  1614. end;
  1615. end;
  1616. inc(i);
  1617. dec(j);
  1618. end;
  1619. until false;
  1620. if i < Right then
  1621. begin
  1622. StackItem^.Left := i;
  1623. StackItem^.Right := Right;
  1624. StackItem^.Depth := Depth - 1;
  1625. inc(StackItem);
  1626. end;
  1627. if Left < j then
  1628. begin
  1629. StackItem^.Left := Left;
  1630. StackItem^.Right := j;
  1631. StackItem^.Depth := Depth - 1;
  1632. inc(StackItem);
  1633. end;
  1634. end;
  1635. end;
  1636. end;
  1637. end;
  1638. end;
  1639. constructor TPasGLTFDynamicArray<T>.TValueEnumerator.Create(const aDynamicArray
  1640. : TPasGLTFDynamicArray<T>);
  1641. begin
  1642. fDynamicArray := aDynamicArray;
  1643. fIndex := -1;
  1644. end;
  1645. function TPasGLTFDynamicArray<T>.TValueEnumerator.MoveNext: boolean;
  1646. begin
  1647. inc(fIndex);
  1648. result := fIndex < fDynamicArray.fCount;
  1649. end;
  1650. function TPasGLTFDynamicArray<T>.TValueEnumerator.GetCurrent: T;
  1651. begin
  1652. result := fDynamicArray.fItems[fIndex];
  1653. end;
  1654. constructor TPasGLTFDynamicArray<T>.Create;
  1655. begin
  1656. fItems := nil;
  1657. fCount := 0;
  1658. fAllocated := 0;
  1659. inherited Create;
  1660. end;
  1661. destructor TPasGLTFDynamicArray<T>.Destroy;
  1662. begin
  1663. SetLength(fItems, 0);
  1664. fCount := 0;
  1665. fAllocated := 0;
  1666. inherited Destroy;
  1667. end;
  1668. procedure TPasGLTFDynamicArray<T>.Clear;
  1669. begin
  1670. SetLength(fItems, 0);
  1671. fCount := 0;
  1672. fAllocated := 0;
  1673. end;
  1674. procedure TPasGLTFDynamicArray<T>.SetCount(const pNewCount: TPasGLTFSizeInt);
  1675. begin
  1676. if pNewCount <= 0 then
  1677. begin
  1678. SetLength(fItems, 0);
  1679. fCount := 0;
  1680. fAllocated := 0;
  1681. end
  1682. else
  1683. begin
  1684. if pNewCount < fCount then
  1685. begin
  1686. fCount := pNewCount;
  1687. if (fCount + fCount) < fAllocated then
  1688. begin
  1689. fAllocated := fCount + fCount;
  1690. SetLength(fItems, fAllocated);
  1691. end;
  1692. end
  1693. else
  1694. begin
  1695. fCount := pNewCount;
  1696. if fAllocated < fCount then
  1697. begin
  1698. fAllocated := fCount + fCount;
  1699. SetLength(fItems, fAllocated);
  1700. end;
  1701. end;
  1702. end;
  1703. end;
  1704. function TPasGLTFDynamicArray<T>.GetItem(const pIndex: TPasGLTFSizeInt): T;
  1705. begin
  1706. result := fItems[pIndex];
  1707. end;
  1708. procedure TPasGLTFDynamicArray<T>.SetItem(const pIndex: TPasGLTFSizeInt;
  1709. const pItem: T);
  1710. begin
  1711. fItems[pIndex] := pItem;
  1712. end;
  1713. function TPasGLTFDynamicArray<T>.Add(const pItem: T): TPasGLTFSizeInt;
  1714. begin
  1715. result := fCount;
  1716. inc(fCount);
  1717. if fAllocated < fCount then
  1718. begin
  1719. fAllocated := fCount + fCount;
  1720. SetLength(fItems, fAllocated);
  1721. end;
  1722. fItems[result] := pItem;
  1723. end;
  1724. function TPasGLTFDynamicArray<T>.Add(const pItems: array of T): TPasGLTFSizeInt;
  1725. var
  1726. Index: TPasGLTFSizeInt;
  1727. begin
  1728. result := fCount;
  1729. if Length(pItems) > 0 then
  1730. begin
  1731. inc(fCount, Length(pItems));
  1732. if fAllocated < fCount then
  1733. begin
  1734. fAllocated := fCount + fCount;
  1735. SetLength(fItems, fAllocated);
  1736. end;
  1737. for Index := 0 to Length(pItems) - 1 do
  1738. begin
  1739. fItems[result + Index] := pItems[Index];
  1740. end;
  1741. end;
  1742. end;
  1743. procedure TPasGLTFDynamicArray<T>.Insert(const pIndex: TPasGLTFSizeInt;
  1744. const pItem: T);
  1745. begin
  1746. if pIndex >= 0 then
  1747. begin
  1748. if pIndex < fCount then
  1749. begin
  1750. inc(fCount);
  1751. if fCount < fAllocated then
  1752. begin
  1753. fAllocated := fCount shl 1;
  1754. SetLength(fItems, fAllocated);
  1755. end;
  1756. Move(fItems[pIndex], fItems[pIndex + 1], (fCount - pIndex) * SizeOf(T));
  1757. FillChar(fItems[pIndex], SizeOf(T), #0);
  1758. end
  1759. else
  1760. begin
  1761. fCount := pIndex + 1;
  1762. if fCount < fAllocated then
  1763. begin
  1764. fAllocated := fCount shl 1;
  1765. SetLength(fItems, fAllocated);
  1766. end;
  1767. end;
  1768. fItems[pIndex] := pItem;
  1769. end;
  1770. end;
  1771. procedure TPasGLTFDynamicArray<T>.Delete(const pIndex: TPasGLTFSizeInt);
  1772. begin
  1773. Finalize(fItems[pIndex]);
  1774. Move(fItems[pIndex + 1], fItems[pIndex], (fCount - pIndex) * SizeOf(T));
  1775. dec(fCount);
  1776. FillChar(fItems[fCount], SizeOf(T), #0);
  1777. if fCount < (fAllocated shr 1) then
  1778. begin
  1779. fAllocated := fAllocated shr 1;
  1780. SetLength(fItems, fAllocated);
  1781. end;
  1782. end;
  1783. procedure TPasGLTFDynamicArray<T>.Exchange(const pIndex,
  1784. pWithIndex: TPasGLTFSizeInt);
  1785. var
  1786. Temporary: T;
  1787. begin
  1788. Temporary := fItems[pIndex];
  1789. fItems[pIndex] := fItems[pWithIndex];
  1790. fItems[pWithIndex] := Temporary;
  1791. end;
  1792. function TPasGLTFDynamicArray<T>.Memory: TPasGLTFPointer;
  1793. begin
  1794. result := @fItems[0];
  1795. end;
  1796. function TPasGLTFDynamicArray<T>.GetEnumerator
  1797. : TPasGLTFDynamicArray<T>.TValueEnumerator;
  1798. begin
  1799. result := TValueEnumerator.Create(self);
  1800. end;
  1801. constructor TPasGLTFObjectList<T>.TValueEnumerator.Create(const aObjectList
  1802. : TPasGLTFObjectList<T>);
  1803. begin
  1804. fObjectList := aObjectList;
  1805. fIndex := -1;
  1806. end;
  1807. function TPasGLTFObjectList<T>.TValueEnumerator.MoveNext: boolean;
  1808. begin
  1809. inc(fIndex);
  1810. result := fIndex < fObjectList.fCount;
  1811. end;
  1812. function TPasGLTFObjectList<T>.TValueEnumerator.GetCurrent: T;
  1813. begin
  1814. result := fObjectList.fItems[fIndex];
  1815. end;
  1816. constructor TPasGLTFObjectList<T>.Create;
  1817. begin
  1818. inherited Create;
  1819. fItems := nil;
  1820. fCount := 0;
  1821. fAllocated := 0;
  1822. fOwnsObjects := true;
  1823. end;
  1824. destructor TPasGLTFObjectList<T>.Destroy;
  1825. begin
  1826. Clear;
  1827. inherited Destroy;
  1828. end;
  1829. function TPasGLTFObjectList<T>.RoundUpToPowerOfTwoSizeUInt(x: TPasGLTFSizeUInt)
  1830. : TPasGLTFSizeUInt;
  1831. begin
  1832. dec(x);
  1833. x := x or (x shr 1);
  1834. x := x or (x shr 2);
  1835. x := x or (x shr 4);
  1836. x := x or (x shr 8);
  1837. x := x or (x shr 16);
  1838. {$IFDEF CPU64}
  1839. x := x or (x shr 32);
  1840. {$ENDIF}
  1841. result := x + 1;
  1842. end;
  1843. procedure TPasGLTFObjectList<T>.Clear;
  1844. var
  1845. Index: TPasGLTFSizeInt;
  1846. begin
  1847. if fOwnsObjects then
  1848. begin
  1849. for Index := fCount - 1 downto 0 do
  1850. begin
  1851. FreeAndNil(fItems[Index]);
  1852. end;
  1853. end;
  1854. fItems := nil;
  1855. fCount := 0;
  1856. fAllocated := 0;
  1857. end;
  1858. procedure TPasGLTFObjectList<T>.SetCount(const pNewCount: TPasGLTFSizeInt);
  1859. var
  1860. Index, NewAllocated: TPasGLTFSizeInt;
  1861. begin
  1862. if fCount < pNewCount then
  1863. begin
  1864. NewAllocated := RoundUpToPowerOfTwoSizeUInt(pNewCount);
  1865. if fAllocated < NewAllocated then
  1866. begin
  1867. SetLength(fItems, NewAllocated);
  1868. FillChar(fItems[fAllocated], (NewAllocated - fAllocated) * SizeOf(T), #0);
  1869. fAllocated := NewAllocated;
  1870. end;
  1871. FillChar(fItems[fCount], (pNewCount - fCount) * SizeOf(T), #0);
  1872. fCount := pNewCount;
  1873. end
  1874. else if fCount > pNewCount then
  1875. begin
  1876. if fOwnsObjects then
  1877. begin
  1878. for Index := fCount - 1 downto pNewCount do
  1879. begin
  1880. FreeAndNil(fItems[Index]);
  1881. end;
  1882. end;
  1883. fCount := pNewCount;
  1884. if pNewCount < (fAllocated shr 2) then
  1885. begin
  1886. if pNewCount = 0 then
  1887. begin
  1888. fItems := nil;
  1889. fAllocated := 0;
  1890. end
  1891. else
  1892. begin
  1893. NewAllocated := fAllocated shr 1;
  1894. SetLength(fItems, NewAllocated);
  1895. fAllocated := NewAllocated;
  1896. end;
  1897. end;
  1898. end;
  1899. end;
  1900. function TPasGLTFObjectList<T>.GetItem(const pIndex: TPasGLTFSizeInt): T;
  1901. begin
  1902. if (pIndex < 0) or (pIndex >= fCount) then
  1903. begin
  1904. raise ERangeError.Create('Out of index range');
  1905. end;
  1906. result := fItems[pIndex];
  1907. end;
  1908. procedure TPasGLTFObjectList<T>.SetItem(const pIndex: TPasGLTFSizeInt;
  1909. const pItem: T);
  1910. begin
  1911. if (pIndex < 0) or (pIndex >= fCount) then
  1912. begin
  1913. raise ERangeError.Create('Out of index range');
  1914. end;
  1915. fItems[pIndex] := pItem;
  1916. end;
  1917. function TPasGLTFObjectList<T>.IndexOf(const pItem: T): TPasGLTFSizeInt;
  1918. var
  1919. Index: TPasGLTFSizeInt;
  1920. begin
  1921. for Index := 0 to fCount - 1 do
  1922. begin
  1923. if fItems[Index] = pItem then
  1924. begin
  1925. result := Index;
  1926. exit;
  1927. end;
  1928. end;
  1929. result := -1;
  1930. end;
  1931. function TPasGLTFObjectList<T>.Add(const pItem: T): TPasGLTFSizeInt;
  1932. begin
  1933. result := fCount;
  1934. inc(fCount);
  1935. if fAllocated < fCount then
  1936. begin
  1937. fAllocated := fCount + fCount;
  1938. SetLength(fItems, fAllocated);
  1939. end;
  1940. fItems[result] := pItem;
  1941. end;
  1942. procedure TPasGLTFObjectList<T>.Insert(const pIndex: TPasGLTFSizeInt;
  1943. const pItem: T);
  1944. var
  1945. OldCount: TPasGLTFSizeInt;
  1946. begin
  1947. if pIndex >= 0 then
  1948. begin
  1949. OldCount := fCount;
  1950. if fCount < pIndex then
  1951. begin
  1952. fCount := pIndex + 1;
  1953. end
  1954. else
  1955. begin
  1956. inc(fCount);
  1957. end;
  1958. if fAllocated < fCount then
  1959. begin
  1960. fAllocated := fCount shl 1;
  1961. SetLength(fItems, fAllocated);
  1962. end;
  1963. if OldCount < fCount then
  1964. begin
  1965. FillChar(fItems[OldCount], (fCount - OldCount) * SizeOf(T), #0);
  1966. end;
  1967. if pIndex < OldCount then
  1968. begin
  1969. System.Move(fItems[pIndex], fItems[pIndex + 1],
  1970. (OldCount - pIndex) * SizeOf(T));
  1971. FillChar(fItems[pIndex], SizeOf(T), #0);
  1972. end;
  1973. fItems[pIndex] := pItem;
  1974. end;
  1975. end;
  1976. procedure TPasGLTFObjectList<T>.Delete(const pIndex: TPasGLTFSizeInt);
  1977. var
  1978. Old: T;
  1979. begin
  1980. if (pIndex < 0) or (pIndex >= fCount) then
  1981. begin
  1982. raise ERangeError.Create('Out of index range');
  1983. end;
  1984. Old := fItems[pIndex];
  1985. dec(fCount);
  1986. FillChar(fItems[pIndex], SizeOf(T), #0);
  1987. if pIndex <> fCount then
  1988. begin
  1989. System.Move(fItems[pIndex + 1], fItems[pIndex],
  1990. (fCount - pIndex) * SizeOf(T));
  1991. FillChar(fItems[fCount], SizeOf(T), #0);
  1992. end;
  1993. if fCount < (fAllocated shr 1) then
  1994. begin
  1995. fAllocated := fAllocated shr 1;
  1996. SetLength(fItems, fAllocated);
  1997. end;
  1998. if fOwnsObjects then
  1999. begin
  2000. FreeAndNil(Old);
  2001. end;
  2002. end;
  2003. procedure TPasGLTFObjectList<T>.Remove(const pItem: T);
  2004. var
  2005. Index: TPasGLTFSizeInt;
  2006. begin
  2007. Index := IndexOf(pItem);
  2008. if Index >= 0 then
  2009. begin
  2010. Delete(Index);
  2011. end;
  2012. end;
  2013. procedure TPasGLTFObjectList<T>.Exchange(const pIndex,
  2014. pWithIndex: TPasGLTFSizeInt);
  2015. var
  2016. Temporary: T;
  2017. begin
  2018. if ((pIndex < 0) or (pIndex >= fCount)) or
  2019. ((pWithIndex < 0) or (pWithIndex >= fCount)) then
  2020. begin
  2021. raise ERangeError.Create('Out of index range');
  2022. end;
  2023. Temporary := fItems[pIndex];
  2024. fItems[pIndex] := fItems[pWithIndex];
  2025. fItems[pWithIndex] := Temporary;
  2026. end;
  2027. function TPasGLTFObjectList<T>.GetEnumerator
  2028. : TPasGLTFObjectList<T>.TValueEnumerator;
  2029. begin
  2030. result := TValueEnumerator.Create(self);
  2031. end;
  2032. constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2033. TPasGLTFHashMapEntityEnumerator.Create(const aHashMap
  2034. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  2035. begin
  2036. fHashMap := aHashMap;
  2037. fIndex := -1;
  2038. end;
  2039. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2040. TPasGLTFHashMapEntityEnumerator.GetCurrent: TPasGLTFHashMapEntity;
  2041. begin
  2042. result := fHashMap.fEntities[fIndex];
  2043. end;
  2044. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2045. TPasGLTFHashMapEntityEnumerator.MoveNext: boolean;
  2046. begin
  2047. repeat
  2048. inc(fIndex);
  2049. if fIndex < fHashMap.fSize then
  2050. begin
  2051. if fHashMap.fEntityToCellIndex[fIndex] >= 0 then
  2052. begin
  2053. result := true;
  2054. exit;
  2055. end;
  2056. end
  2057. else
  2058. begin
  2059. break;
  2060. end;
  2061. until false;
  2062. result := false;
  2063. end;
  2064. constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2065. TPasGLTFHashMapKeyEnumerator.Create(const aHashMap
  2066. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  2067. begin
  2068. fHashMap := aHashMap;
  2069. fIndex := -1;
  2070. end;
  2071. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2072. TPasGLTFHashMapKeyEnumerator.GetCurrent: TPasGLTFHashMapKey;
  2073. begin
  2074. result := fHashMap.fEntities[fIndex].Key;
  2075. end;
  2076. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2077. TPasGLTFHashMapKeyEnumerator.MoveNext: boolean;
  2078. begin
  2079. repeat
  2080. inc(fIndex);
  2081. if fIndex < fHashMap.fSize then
  2082. begin
  2083. if fHashMap.fEntityToCellIndex[fIndex] >= 0 then
  2084. begin
  2085. result := true;
  2086. exit;
  2087. end;
  2088. end
  2089. else
  2090. begin
  2091. break;
  2092. end;
  2093. until false;
  2094. result := false;
  2095. end;
  2096. constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2097. TPasGLTFHashMapValueEnumerator.Create(const aHashMap
  2098. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  2099. begin
  2100. fHashMap := aHashMap;
  2101. fIndex := -1;
  2102. end;
  2103. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2104. TPasGLTFHashMapValueEnumerator.GetCurrent: TPasGLTFHashMapValue;
  2105. begin
  2106. result := fHashMap.fEntities[fIndex].Value;
  2107. end;
  2108. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2109. TPasGLTFHashMapValueEnumerator.MoveNext: boolean;
  2110. begin
  2111. repeat
  2112. inc(fIndex);
  2113. if fIndex < fHashMap.fSize then
  2114. begin
  2115. if fHashMap.fEntityToCellIndex[fIndex] >= 0 then
  2116. begin
  2117. result := true;
  2118. exit;
  2119. end;
  2120. end
  2121. else
  2122. begin
  2123. break;
  2124. end;
  2125. until false;
  2126. result := false;
  2127. end;
  2128. constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2129. TPasGLTFHashMapEntitiesObject.Create(const aOwner
  2130. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  2131. begin
  2132. inherited Create;
  2133. fOwner := aOwner;
  2134. end;
  2135. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2136. TPasGLTFHashMapEntitiesObject.GetEnumerator: TPasGLTFHashMapEntityEnumerator;
  2137. begin
  2138. result := TPasGLTFHashMapEntityEnumerator.Create(fOwner);
  2139. end;
  2140. constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2141. TPasGLTFHashMapKeysObject.Create(const aOwner
  2142. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  2143. begin
  2144. inherited Create;
  2145. fOwner := aOwner;
  2146. end;
  2147. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2148. TPasGLTFHashMapKeysObject.GetEnumerator: TPasGLTFHashMapKeyEnumerator;
  2149. begin
  2150. result := TPasGLTFHashMapKeyEnumerator.Create(fOwner);
  2151. end;
  2152. constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2153. TPasGLTFHashMapValuesObject.Create(const aOwner
  2154. : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
  2155. begin
  2156. inherited Create;
  2157. fOwner := aOwner;
  2158. end;
  2159. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2160. TPasGLTFHashMapValuesObject.GetEnumerator: TPasGLTFHashMapValueEnumerator;
  2161. begin
  2162. result := TPasGLTFHashMapValueEnumerator.Create(fOwner);
  2163. end;
  2164. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2165. TPasGLTFHashMapValuesObject.GetValue(const Key: TPasGLTFHashMapKey)
  2166. : TPasGLTFHashMapValue;
  2167. begin
  2168. result := fOwner.GetValue(Key);
  2169. end;
  2170. procedure TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
  2171. TPasGLTFHashMapValuesObject.SetValue(const Key: TPasGLTFHashMapKey;
  2172. const aValue: TPasGLTFHashMapValue);
  2173. begin
  2174. fOwner.SetValue(Key, aValue);
  2175. end;
  2176. constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Create
  2177. (const DefaultValue: TPasGLTFHashMapValue);
  2178. begin
  2179. inherited Create;
  2180. fRealSize := 0;
  2181. fLogSize := 0;
  2182. fSize := 0;
  2183. fEntities := nil;
  2184. fEntityToCellIndex := nil;
  2185. fCellToEntityIndex := nil;
  2186. fDefaultValue := DefaultValue;
  2187. fCanShrink := true;
  2188. fEntitiesObject := TPasGLTFHashMapEntitiesObject.Create(self);
  2189. fKeysObject := TPasGLTFHashMapKeysObject.Create(self);
  2190. fValuesObject := TPasGLTFHashMapValuesObject.Create(self);
  2191. Resize;
  2192. end;
  2193. destructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Destroy;
  2194. var
  2195. Counter: TPasGLTFSizeInt;
  2196. begin
  2197. Clear;
  2198. for Counter := 0 to Length(fEntities) - 1 do
  2199. begin
  2200. Finalize(fEntities[Counter].Key);
  2201. Finalize(fEntities[Counter].Value);
  2202. end;
  2203. SetLength(fEntities, 0);
  2204. SetLength(fEntityToCellIndex, 0);
  2205. SetLength(fCellToEntityIndex, 0);
  2206. FreeAndNil(fEntitiesObject);
  2207. FreeAndNil(fKeysObject);
  2208. FreeAndNil(fValuesObject);
  2209. inherited Destroy;
  2210. end;
  2211. procedure TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Clear;
  2212. var
  2213. Counter: TPasGLTFSizeInt;
  2214. begin
  2215. for Counter := 0 to Length(fEntities) - 1 do
  2216. begin
  2217. Finalize(fEntities[Counter].Key);
  2218. Finalize(fEntities[Counter].Value);
  2219. end;
  2220. if fCanShrink then
  2221. begin
  2222. fRealSize := 0;
  2223. fLogSize := 0;
  2224. fSize := 0;
  2225. SetLength(fEntities, 0);
  2226. SetLength(fEntityToCellIndex, 0);
  2227. SetLength(fCellToEntityIndex, 0);
  2228. Resize;
  2229. end
  2230. else
  2231. begin
  2232. for Counter := 0 to Length(fCellToEntityIndex) - 1 do
  2233. begin
  2234. fCellToEntityIndex[Counter] := ENT_EMPTY;
  2235. end;
  2236. for Counter := 0 to Length(fEntityToCellIndex) - 1 do
  2237. begin
  2238. fEntityToCellIndex[Counter] := CELL_EMPTY;
  2239. end;
  2240. end;
  2241. end;
  2242. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.HashData
  2243. (const Data: TPasGLTFPointer; const DataLength: TPasGLTFSizeUInt)
  2244. : TPasGLTFUInt32;
  2245. // xxHash32
  2246. const
  2247. PRIME32_1 = TPasGLTFUInt32(2654435761);
  2248. PRIME32_2 = TPasGLTFUInt32(2246822519);
  2249. PRIME32_3 = TPasGLTFUInt32(3266489917);
  2250. PRIME32_4 = TPasGLTFUInt32(668265263);
  2251. PRIME32_5 = TPasGLTFUInt32(374761393);
  2252. Seed = TPasGLTFUInt32($1337C0D3);
  2253. v1Initialization = TPasGLTFUInt32
  2254. (TPasGLTFUInt64(TPasGLTFUInt64(Seed) + TPasGLTFUInt64(PRIME32_1) +
  2255. TPasGLTFUInt64(PRIME32_2)));
  2256. v2Initialization = TPasGLTFUInt32
  2257. (TPasGLTFUInt64(TPasGLTFUInt64(Seed) + TPasGLTFUInt64(PRIME32_2)));
  2258. v3Initialization = TPasGLTFUInt32
  2259. (TPasGLTFUInt64(TPasGLTFUInt64(Seed) + TPasGLTFUInt64(0)));
  2260. v4Initialization = TPasGLTFUInt32
  2261. (TPasGLTFUInt64(TPasGLTFInt64(TPasGLTFInt64(Seed) -
  2262. TPasGLTFInt64(PRIME32_1))));
  2263. HashInitialization = TPasGLTFUInt32
  2264. (TPasGLTFUInt64(TPasGLTFUInt64(Seed) + TPasGLTFUInt64(PRIME32_5)));
  2265. var
  2266. v1, v2, v3, v4: TPasGLTFUInt32;
  2267. p, e: PPasGLTFUInt8;
  2268. begin
  2269. p := Data;
  2270. if DataLength >= 16 then
  2271. begin
  2272. v1 := v1Initialization;
  2273. v2 := v2Initialization;
  2274. v3 := v3Initialization;
  2275. v4 := v4Initialization;
  2276. e := @PPasGLTFUInt8Array(Data)^[DataLength - 16];
  2277. repeat
  2278. {$IF defined(fpc) or declared(ROLDWord)}
  2279. v1 := ROLDWord(v1 + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
  2280. TPasGLTFUInt32(PRIME32_2)), 13) * TPasGLTFUInt32(PRIME32_1);
  2281. {$ELSE}
  2282. inc(v1, TPasGLTFUInt32(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_2));
  2283. v1 := ((v1 shl 13) or (v1 shr 19)) * TPasGLTFUInt32(PRIME32_1);
  2284. {$IFEND}
  2285. inc(p, SizeOf(TPasGLTFUInt32));
  2286. {$IF defined(fpc) or declared(ROLDWord)}
  2287. v2 := ROLDWord(v2 + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
  2288. TPasGLTFUInt32(PRIME32_2)), 13) * TPasGLTFUInt32(PRIME32_1);
  2289. {$ELSE}
  2290. inc(v2, TPasGLTFUInt32(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_2));
  2291. v2 := ((v2 shl 13) or (v2 shr 19)) * TPasGLTFUInt32(PRIME32_1);
  2292. {$IFEND}
  2293. inc(p, SizeOf(TPasGLTFUInt32));
  2294. {$IF defined(fpc) or declared(ROLDWord)}
  2295. v3 := ROLDWord(v3 + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
  2296. TPasGLTFUInt32(PRIME32_2)), 13) * TPasGLTFUInt32(PRIME32_1);
  2297. {$ELSE}
  2298. inc(v3, TPasGLTFUInt32(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_2));
  2299. v3 := ((v3 shl 13) or (v3 shr 19)) * TPasGLTFUInt32(PRIME32_1);
  2300. {$IFEND}
  2301. inc(p, SizeOf(TPasGLTFUInt32));
  2302. {$IF defined(fpc) or declared(ROLDWord)}
  2303. v4 := ROLDWord(v4 + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
  2304. TPasGLTFUInt32(PRIME32_2)), 13) * TPasGLTFUInt32(PRIME32_1);
  2305. {$ELSE}
  2306. inc(v4, TPasGLTFUInt32(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_2));
  2307. v4 := ((v4 shl 13) or (v4 shr 19)) * TPasGLTFUInt32(PRIME32_1);
  2308. {$IFEND}
  2309. inc(p, SizeOf(TPasGLTFUInt32));
  2310. until {%H-}TPasGLTFPtrUInt(p) > {%H-}TPasGLTFPtrUInt(e);
  2311. {$IF defined(fpc) or declared(ROLDWord)}
  2312. result := ROLDWord(v1, 1) + ROLDWord(v2, 7) + ROLDWord(v3, 12) +
  2313. ROLDWord(v4, 18);
  2314. {$ELSE}
  2315. result := ((v1 shl 1) or (v1 shr 31)) + ((v2 shl 7) or (v2 shr 25)) +
  2316. ((v3 shl 12) or (v3 shr 20)) + ((v4 shl 18) or (v4 shr 14));
  2317. {$IFEND}
  2318. end
  2319. else
  2320. begin
  2321. result := HashInitialization;
  2322. end;
  2323. inc(result, DataLength);
  2324. e := @PPasGLTFUInt8Array(Data)^[DataLength];
  2325. while ({%H-}TPasGLTFPtrUInt(p) + SizeOf(TPasGLTFUInt32)) <=
  2326. {%H-}TPasGLTFPtrUInt(e) do
  2327. begin
  2328. {$IF defined(fpc) or declared(ROLDWord)}
  2329. result := ROLDWord(result + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
  2330. TPasGLTFUInt32(PRIME32_3)), 17) * TPasGLTFUInt32(PRIME32_4);
  2331. {$ELSE}
  2332. inc(result, TPasGLTFUInt32(TPasGLTFPointer(p)^) *
  2333. TPasGLTFUInt32(PRIME32_3));
  2334. result := ((result shl 17) or (result shr 15)) * TPasGLTFUInt32(PRIME32_4);
  2335. {$IFEND}
  2336. inc(p, SizeOf(TPasGLTFUInt32));
  2337. end;
  2338. while {%H-}TPasGLTFPtrUInt(p) < {%H-}TPasGLTFPtrUInt(e) do
  2339. begin
  2340. {$IF defined(fpc) or declared(ROLDWord)}
  2341. result := ROLDWord(result + (TPasGLTFUInt8(TPasGLTFPointer(p)^) *
  2342. TPasGLTFUInt32(PRIME32_5)), 11) * TPasGLTFUInt32(PRIME32_1);
  2343. {$ELSE}
  2344. inc(result, TPasGLTFUInt8(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_5));
  2345. result := ((result shl 11) or (result shr 21)) * TPasGLTFUInt32(PRIME32_1);
  2346. {$IFEND}
  2347. inc(p, SizeOf(TPasGLTFUInt8));
  2348. end;
  2349. result := (result xor (result shr 15)) * TPasGLTFUInt32(PRIME32_2);
  2350. result := (result xor (result shr 13)) * TPasGLTFUInt32(PRIME32_3);
  2351. result := result xor (result shr 16);
  2352. end;
  2353. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.HashKey
  2354. (const Key: TPasGLTFHashMapKey): TPasGLTFUInt32;
  2355. begin
  2356. result := HashData(PPasGLTFUInt8(@Key[1]),
  2357. Length(Key) * SizeOf(TPasGLTFRawByteChar));
  2358. {$IF defined(CPU386) or defined(CPUAMD64)}
  2359. // Special case: The hash value may be never zero
  2360. result := result or (-TPasGLTFUInt32(ord(result = 0) and 1));
  2361. {$ELSE}
  2362. if result = 0 then
  2363. begin
  2364. // Special case: The hash value may be never zero
  2365. result := $FFFFFFFF;
  2366. end;
  2367. {$IFEND}
  2368. end;
  2369. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.CompareKey(const KeyA,
  2370. KeyB: TPasGLTFHashMapKey): boolean;
  2371. begin
  2372. result := KeyA = KeyB;
  2373. end;
  2374. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.FindCell
  2375. (const Key: TPasGLTFHashMapKey): TPasGLTFUInt32;
  2376. var
  2377. HashCode, Mask, Step: TPasGLTFUInt32;
  2378. Entity: TPasGLTFInt32;
  2379. begin
  2380. HashCode := HashKey(Key);
  2381. Mask := (2 shl fLogSize) - 1;
  2382. Step := ((HashCode shl 1) + 1) and Mask;
  2383. if fLogSize <> 0 then
  2384. begin
  2385. result := HashCode shr (32 - fLogSize);
  2386. end
  2387. else
  2388. begin
  2389. result := 0;
  2390. end;
  2391. repeat
  2392. Entity := fCellToEntityIndex[result];
  2393. if (Entity = ENT_EMPTY) or
  2394. ((Entity <> ENT_DELETED) and CompareKey(fEntities[Entity].Key, Key)) then
  2395. begin
  2396. exit;
  2397. end;
  2398. result := (result + Step) and Mask;
  2399. until false;
  2400. end;
  2401. procedure TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Resize;
  2402. var
  2403. NewLogSize, NewSize, Cell, Entity: TPasGLTFInt32;
  2404. Counter: TPasGLTFSizeInt;
  2405. OldEntities: TPasGLTFHashMapEntities;
  2406. OldCellToEntityIndex: TPasGLTFHashMapEntityIndices;
  2407. OldEntityToCellIndex: TPasGLTFHashMapEntityIndices;
  2408. begin
  2409. NewLogSize := 0;
  2410. NewSize := fRealSize;
  2411. while NewSize <> 0 do
  2412. begin
  2413. NewSize := NewSize shr 1;
  2414. inc(NewLogSize);
  2415. end;
  2416. if NewLogSize < 1 then
  2417. begin
  2418. NewLogSize := 1;
  2419. end;
  2420. fSize := 0;
  2421. fRealSize := 0;
  2422. fLogSize := NewLogSize;
  2423. OldEntities := fEntities;
  2424. OldCellToEntityIndex := fCellToEntityIndex;
  2425. OldEntityToCellIndex := fEntityToCellIndex;
  2426. fEntities := nil;
  2427. fCellToEntityIndex := nil;
  2428. fEntityToCellIndex := nil;
  2429. SetLength(fEntities, 2 shl fLogSize);
  2430. SetLength(fCellToEntityIndex, 2 shl fLogSize);
  2431. SetLength(fEntityToCellIndex, 2 shl fLogSize);
  2432. for Counter := 0 to Length(fCellToEntityIndex) - 1 do
  2433. begin
  2434. fCellToEntityIndex[Counter] := ENT_EMPTY;
  2435. end;
  2436. for Counter := 0 to Length(fEntityToCellIndex) - 1 do
  2437. begin
  2438. fEntityToCellIndex[Counter] := CELL_EMPTY;
  2439. end;
  2440. for Counter := 0 to Length(OldEntityToCellIndex) - 1 do
  2441. begin
  2442. Cell := OldEntityToCellIndex[Counter];
  2443. if Cell >= 0 then
  2444. begin
  2445. Entity := OldCellToEntityIndex[Cell];
  2446. if Entity >= 0 then
  2447. begin
  2448. Add(OldEntities[Counter].Key, OldEntities[Counter].Value);
  2449. end;
  2450. end;
  2451. end;
  2452. for Counter := 0 to Length(OldEntities) - 1 do
  2453. begin
  2454. Finalize(OldEntities[Counter].Key);
  2455. Finalize(OldEntities[Counter].Value);
  2456. end;
  2457. SetLength(OldEntities, 0);
  2458. SetLength(OldCellToEntityIndex, 0);
  2459. SetLength(OldEntityToCellIndex, 0);
  2460. end;
  2461. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Add
  2462. (const Key: TPasGLTFHashMapKey; const Value: TPasGLTFHashMapValue)
  2463. : PPasGLTFHashMapEntity;
  2464. var
  2465. Entity: TPasGLTFInt32;
  2466. Cell: TPasGLTFUInt32;
  2467. begin
  2468. result := nil;
  2469. while fRealSize >= (1 shl fLogSize) do
  2470. begin
  2471. Resize;
  2472. end;
  2473. Cell := FindCell(Key);
  2474. Entity := fCellToEntityIndex[Cell];
  2475. if Entity >= 0 then
  2476. begin
  2477. result := @fEntities[Entity];
  2478. result^.Key := Key;
  2479. result^.Value := Value;
  2480. exit;
  2481. end;
  2482. Entity := fSize;
  2483. inc(fSize);
  2484. if Entity < (2 shl fLogSize) then
  2485. begin
  2486. fCellToEntityIndex[Cell] := Entity;
  2487. fEntityToCellIndex[Entity] := Cell;
  2488. inc(fRealSize);
  2489. result := @fEntities[Entity];
  2490. result^.Key := Key;
  2491. result^.Value := Value;
  2492. end;
  2493. end;
  2494. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Get
  2495. (const Key: TPasGLTFHashMapKey; const CreateIfNotExist: boolean = false)
  2496. : PPasGLTFHashMapEntity;
  2497. var
  2498. Entity: TPasGLTFInt32;
  2499. Cell: TPasGLTFUInt32;
  2500. Value: TPasGLTFHashMapValue;
  2501. begin
  2502. result := nil;
  2503. Cell := FindCell(Key);
  2504. Entity := fCellToEntityIndex[Cell];
  2505. if Entity >= 0 then
  2506. begin
  2507. result := @fEntities[Entity];
  2508. end
  2509. else if CreateIfNotExist then
  2510. begin
  2511. Initialize(Value);
  2512. result := Add(Key, Value);
  2513. end;
  2514. end;
  2515. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.TryGet
  2516. (const Key: TPasGLTFHashMapKey; out Value: TPasGLTFHashMapValue): boolean;
  2517. var
  2518. Entity: TPasGLTFInt32;
  2519. begin
  2520. Entity := fCellToEntityIndex[FindCell(Key)];
  2521. result := Entity >= 0;
  2522. if result then
  2523. begin
  2524. Value := fEntities[Entity].Value;
  2525. end
  2526. else
  2527. begin
  2528. Initialize(Value);
  2529. end;
  2530. end;
  2531. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.ExistKey
  2532. (const Key: TPasGLTFHashMapKey): boolean;
  2533. begin
  2534. result := fCellToEntityIndex[FindCell(Key)] >= 0;
  2535. end;
  2536. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Delete
  2537. (const Key: TPasGLTFHashMapKey): boolean;
  2538. var
  2539. Entity: TPasGLTFInt32;
  2540. Cell: TPasGLTFUInt32;
  2541. begin
  2542. result := false;
  2543. Cell := FindCell(Key);
  2544. Entity := fCellToEntityIndex[Cell];
  2545. if Entity >= 0 then
  2546. begin
  2547. Finalize(fEntities[Entity].Key);
  2548. Finalize(fEntities[Entity].Value);
  2549. fEntityToCellIndex[Entity] := CELL_DELETED;
  2550. fCellToEntityIndex[Cell] := ENT_DELETED;
  2551. result := true;
  2552. end;
  2553. end;
  2554. function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.GetValue
  2555. (const Key: TPasGLTFHashMapKey): TPasGLTFHashMapValue;
  2556. var
  2557. Entity: TPasGLTFInt32;
  2558. Cell: TPasGLTFUInt32;
  2559. begin
  2560. Cell := FindCell(Key);
  2561. Entity := fCellToEntityIndex[Cell];
  2562. if Entity >= 0 then
  2563. begin
  2564. result := fEntities[Entity].Value;
  2565. end
  2566. else
  2567. begin
  2568. result := fDefaultValue;
  2569. end;
  2570. end;
  2571. procedure TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.SetValue
  2572. (const Key: TPasGLTFHashMapKey; const Value: TPasGLTFHashMapValue);
  2573. begin
  2574. Add(Key, Value);
  2575. end;
  2576. { TPasGLTF }
  2577. class function TPasGLTF.ResolveURIToPath(const aURI: TPasGLTFUTF8String)
  2578. : TPasGLTFUTF8String;
  2579. begin
  2580. result := TPasGLTFUTF8String(StringReplace(String(aURI),
  2581. {$IFDEF Windows}'/', '\'{$ELSE}'\', '/'{$ENDIF}, [rfReplaceAll]));
  2582. end;
  2583. { TPasGLTF.TBase64 }
  2584. class function TPasGLTF.TBase64.Encode(const aData;
  2585. const aDataLength: TPasGLTFSizeInt): TPasGLTFRawByteString;
  2586. var
  2587. Index, BitCount, OutputIndex: TPasGLTFSizeInt;
  2588. Value: TPasGLTFUInt32;
  2589. begin
  2590. result := '';
  2591. if aDataLength > 0 then
  2592. begin
  2593. SetLength(result, (((aDataLength * 4) div 3) + 3) and not 3);
  2594. OutputIndex := 0;
  2595. Value := 0;
  2596. BitCount := -6;
  2597. for Index := 0 to aDataLength - 1 do
  2598. begin
  2599. Value := (Value shl 8) or PPasGLTFUInt8Array(@aData)^[Index];
  2600. inc(BitCount, 8);
  2601. while BitCount >= 0 do
  2602. begin
  2603. result[Low(result) + OutputIndex] := EncodingLookUpTable
  2604. [(Value shr BitCount) and 63];
  2605. inc(OutputIndex);
  2606. dec(BitCount, 6);
  2607. end;
  2608. end;
  2609. if BitCount > -6 then
  2610. begin
  2611. result[Low(result) + OutputIndex] := EncodingLookUpTable
  2612. [((Value shl 8) shr (BitCount + 8)) and 63];
  2613. inc(OutputIndex);
  2614. end;
  2615. while (OutputIndex and 3) <> 0 do
  2616. begin
  2617. result[Low(result) + OutputIndex] := '=';
  2618. inc(OutputIndex);
  2619. end;
  2620. SetLength(result, OutputIndex);
  2621. end;
  2622. end;
  2623. class function TPasGLTF.TBase64.Encode(const aData: array of TPasGLTFUInt8)
  2624. : TPasGLTFRawByteString;
  2625. begin
  2626. result := Encode(aData[0], Length(aData));
  2627. end;
  2628. class function TPasGLTF.TBase64.Encode(const aData: TPasGLTFRawByteString)
  2629. : TPasGLTFRawByteString;
  2630. begin
  2631. result := Encode(aData[Low(aData)], Length(aData));
  2632. end;
  2633. class function TPasGLTF.TBase64.Encode(const aData: TStream)
  2634. : TPasGLTFRawByteString;
  2635. var
  2636. Bytes: TPasGLTFUInt8DynamicArray;
  2637. begin
  2638. Bytes := nil;
  2639. try
  2640. SetLength(Bytes, aData.Size);
  2641. aData.Seek(0, soBeginning);
  2642. aData.ReadBuffer(Bytes[0], aData.Size);
  2643. result := Encode(Bytes[0], Length(Bytes));
  2644. finally
  2645. Bytes := nil;
  2646. end;
  2647. end;
  2648. class function TPasGLTF.TBase64.Decode(const aInput: TPasGLTFRawByteString;
  2649. const aOutput: TStream): boolean;
  2650. var
  2651. Index, Size, BitCount, OutputIndex, LookUpTableValue,
  2652. Remaining: TPasGLTFSizeInt;
  2653. Value: TPasGLTFUInt32;
  2654. Buffer: TPasGLTFUInt8DynamicArray;
  2655. begin
  2656. result := false;
  2657. Buffer := nil;
  2658. try
  2659. Size := Length(aInput);
  2660. if Size > 0 then
  2661. begin
  2662. if (Size and 3) = 0 then
  2663. begin
  2664. result := true;
  2665. SetLength(Buffer, (Size * 3) shr 2);
  2666. Value := 0;
  2667. BitCount := -8;
  2668. OutputIndex := 0;
  2669. try
  2670. for Index := 1 to Size do
  2671. begin
  2672. LookUpTableValue := DecodingLookUpTable[aInput[Index]];
  2673. if LookUpTableValue >= 0 then
  2674. begin
  2675. Value := (Value shl 6) or LookUpTableValue;
  2676. inc(BitCount, 6);
  2677. while BitCount >= 0 do
  2678. begin
  2679. Buffer[OutputIndex] := (Value shr BitCount) and $FF;
  2680. inc(OutputIndex);
  2681. dec(BitCount, 8);
  2682. end;
  2683. end
  2684. else
  2685. begin
  2686. case aInput[Index] of
  2687. '=':
  2688. begin
  2689. Remaining := Size - Index;
  2690. if (Remaining > 1) or
  2691. ((Remaining = 1) and (aInput[Index + 1] <> '=')) then
  2692. begin
  2693. result := false;
  2694. end;
  2695. end;
  2696. else
  2697. begin
  2698. result := false;
  2699. end;
  2700. end;
  2701. break;
  2702. end;
  2703. end;
  2704. finally
  2705. SetLength(Buffer, OutputIndex);
  2706. end;
  2707. if result then
  2708. begin
  2709. aOutput.WriteBuffer(Buffer[0], OutputIndex);
  2710. end;
  2711. end;
  2712. end
  2713. else
  2714. begin
  2715. result := true;
  2716. end;
  2717. finally
  2718. Buffer := nil;
  2719. end;
  2720. end;
  2721. { TPasGLTF.TBaseObject }
  2722. constructor TPasGLTF.TBaseObject.Create(const aDocument: TDocument);
  2723. begin
  2724. inherited Create;
  2725. fDocument := aDocument;
  2726. end;
  2727. destructor TPasGLTF.TBaseObject.Destroy;
  2728. begin
  2729. inherited Destroy;
  2730. end;
  2731. { TPasGLTF.TBaseExtensionsExtrasObject }
  2732. constructor TPasGLTF.TBaseExtensionsExtrasObject.Create(const aDocument
  2733. : TDocument);
  2734. begin
  2735. inherited Create(aDocument);
  2736. fExtensions := TPasJSONItemObject.Create;
  2737. fExtras := TPasJSONItemObject.Create;
  2738. end;
  2739. destructor TPasGLTF.TBaseExtensionsExtrasObject.Destroy;
  2740. begin
  2741. FreeAndNil(fExtensions);
  2742. FreeAndNil(fExtras);
  2743. inherited Destroy;
  2744. end;
  2745. { TPasGLTF.TAccessor.TComponentTypeHelper }
  2746. function TPasGLTF.TAccessor.TComponentTypeHelper.GetSize: TPasGLTFSizeInt;
  2747. begin
  2748. case self of
  2749. TPasGLTF.TAccessor.TComponentType.SignedByte:
  2750. begin
  2751. result := SizeOf(TPasGLTFInt8);
  2752. end;
  2753. TPasGLTF.TAccessor.TComponentType.UnsignedByte:
  2754. begin
  2755. result := SizeOf(TPasGLTFUInt8);
  2756. end;
  2757. TPasGLTF.TAccessor.TComponentType.SignedShort:
  2758. begin
  2759. result := SizeOf(TPasGLTFInt16);
  2760. end;
  2761. TPasGLTF.TAccessor.TComponentType.UnsignedShort:
  2762. begin
  2763. result := SizeOf(TPasGLTFUInt16);
  2764. end;
  2765. TPasGLTF.TAccessor.TComponentType.UnsignedInt:
  2766. begin
  2767. result := SizeOf(TPasGLTFUInt32);
  2768. end;
  2769. TPasGLTF.TAccessor.TComponentType.Float:
  2770. begin
  2771. result := SizeOf(TPasGLTFFloat);
  2772. end;
  2773. else { TPasGLTF.TAccessor.TComponentType.None: }
  2774. begin
  2775. result := 0;
  2776. Assert(false);
  2777. end;
  2778. end;
  2779. end;
  2780. { TPasGLTF.TAccessor.TTypeHelper }
  2781. function TPasGLTF.TAccessor.TTypeHelper.GetComponentCount: TPasGLTFSizeInt;
  2782. begin
  2783. result := TPasGLTF.TAccessor.TypeComponentCountTable[self];
  2784. end;
  2785. { TPasGLTF.TAccessor.TSparse.TIndices }
  2786. constructor TPasGLTF.TAccessor.TSparse.TIndices.Create(const aDocument
  2787. : TDocument);
  2788. begin
  2789. inherited Create(aDocument);
  2790. fComponentType := TComponentType.None;
  2791. fBufferView := 0;
  2792. fByteOffset := 0;
  2793. fEmpty := false;
  2794. end;
  2795. destructor TPasGLTF.TAccessor.TSparse.TIndices.Destroy;
  2796. begin
  2797. inherited Destroy;
  2798. end;
  2799. { TPasGLTF.TAccessor.TSparse.TValues }
  2800. constructor TPasGLTF.TAccessor.TSparse.TValues.Create(const aDocument
  2801. : TDocument);
  2802. begin
  2803. inherited Create(aDocument);
  2804. fBufferView := 0;
  2805. fByteOffset := 0;
  2806. fEmpty := false;
  2807. end;
  2808. destructor TPasGLTF.TAccessor.TSparse.TValues.Destroy;
  2809. begin
  2810. inherited Destroy;
  2811. end;
  2812. { TPasGLTF.TAccessor.TSparse }
  2813. constructor TPasGLTF.TAccessor.TSparse.Create(const aDocument: TDocument);
  2814. begin
  2815. inherited Create(aDocument);
  2816. fCount := 0;
  2817. fIndices := TIndices.Create(fDocument);
  2818. fValues := TValues.Create(fDocument);
  2819. end;
  2820. destructor TPasGLTF.TAccessor.TSparse.Destroy;
  2821. begin
  2822. FreeAndNil(fIndices);
  2823. FreeAndNil(fValues);
  2824. inherited Destroy;
  2825. end;
  2826. function TPasGLTF.TAccessor.TSparse.GetEmpty: boolean;
  2827. begin
  2828. result := fCount = 0;
  2829. end;
  2830. { TPasGLTF.TAccessor }
  2831. constructor TPasGLTF.TAccessor.Create(const aDocument: TDocument);
  2832. begin
  2833. inherited Create(aDocument);
  2834. fComponentType := TComponentType.None;
  2835. fType := TType.None;
  2836. fBufferView := -1;
  2837. fByteOffset := 0;
  2838. fCount := 0;
  2839. fNormalized := TDefaults.AccessorNormalized;
  2840. fMinArray := TMinMaxDynamicArray.Create;
  2841. fMaxArray := TMinMaxDynamicArray.Create;
  2842. fSparse := TSparse.Create(fDocument);
  2843. end;
  2844. destructor TPasGLTF.TAccessor.Destroy;
  2845. begin
  2846. FreeAndNil(fMinArray);
  2847. FreeAndNil(fMaxArray);
  2848. FreeAndNil(fSparse);
  2849. inherited Destroy;
  2850. end;
  2851. function TPasGLTF.TAccessor.DecodeAsDoubleArray(const aForVertex
  2852. : boolean = true): TPasGLTFDoubleDynamicArray;
  2853. var
  2854. Index, ComponentIndex, ComponentCount, ComponentSize, ElementSize, SkipEvery,
  2855. SkipBytes, IndicesComponentSize, Base: TPasGLTFSizeInt;
  2856. Indices, Values: TPasGLTFDoubleDynamicArray;
  2857. begin
  2858. ComponentCount := fType.GetComponentCount;
  2859. ComponentSize := fComponentType.GetSize;
  2860. ElementSize := ComponentSize * ComponentCount;
  2861. SkipEvery := 0;
  2862. SkipBytes := 0;
  2863. case fComponentType of
  2864. TPasGLTF.TAccessor.TComponentType.SignedByte,
  2865. TPasGLTF.TAccessor.TComponentType.UnsignedByte:
  2866. begin
  2867. case fType of
  2868. TPasGLTF.TAccessor.TType.Mat2:
  2869. begin
  2870. SkipEvery := 2;
  2871. SkipBytes := 2;
  2872. ElementSize := 8;
  2873. end;
  2874. TPasGLTF.TAccessor.TType.Mat3:
  2875. begin
  2876. SkipEvery := 3;
  2877. SkipBytes := 1;
  2878. ElementSize := 12;
  2879. end;
  2880. end;
  2881. end;
  2882. TPasGLTF.TAccessor.TComponentType.SignedShort,
  2883. TPasGLTF.TAccessor.TComponentType.UnsignedShort:
  2884. begin
  2885. case fType of
  2886. TPasGLTF.TAccessor.TType.Mat3:
  2887. begin
  2888. SkipEvery := 6;
  2889. SkipBytes := 4;
  2890. ElementSize := 16;
  2891. end;
  2892. end;
  2893. end;
  2894. end;
  2895. result := nil;
  2896. if fBufferView >= 0 then
  2897. begin
  2898. if fBufferView < fDocument.fBufferViews.Count then
  2899. begin
  2900. result := fDocument.fBufferViews[fBufferView].Decode(SkipEvery, SkipBytes,
  2901. ElementSize, fCount, fType, ComponentCount, fComponentType,
  2902. ComponentSize, fByteOffset, fNormalized, aForVertex);
  2903. end
  2904. else
  2905. begin
  2906. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  2907. end;
  2908. end
  2909. else
  2910. begin
  2911. SetLength(result, ComponentCount * fCount);
  2912. for Index := 0 to Length(result) - 1 do
  2913. begin
  2914. result[Index] := 0;
  2915. end;
  2916. end;
  2917. if fSparse.fCount > 0 then
  2918. begin
  2919. if (fSparse.fIndices.fBufferView >= 0) and
  2920. (fSparse.fIndices.fBufferView < fDocument.fBufferViews.Count) then
  2921. begin
  2922. IndicesComponentSize := fSparse.fIndices.fComponentType.GetSize;
  2923. Indices := fDocument.fBufferViews[fSparse.fIndices.fBufferView]
  2924. .Decode(0, 0, IndicesComponentSize, fSparse.fCount, TType.Scalar, 1,
  2925. fSparse.fIndices.fComponentType, IndicesComponentSize,
  2926. fSparse.fIndices.fByteOffset, false, false);
  2927. if (fSparse.fValues.fBufferView >= 0) and
  2928. (fSparse.fValues.fBufferView < fDocument.fBufferViews.Count) then
  2929. begin
  2930. Values := fDocument.fBufferViews[fSparse.fValues.fBufferView]
  2931. .Decode(SkipEvery, SkipBytes, ElementSize, fSparse.fCount, fType,
  2932. ComponentCount, fComponentType, ComponentSize,
  2933. fSparse.fValues.fByteOffset, fNormalized, aForVertex);
  2934. for Index := 0 to Length(Indices) - 1 do
  2935. begin
  2936. Base := trunc(Indices[Index]) * ComponentCount;
  2937. for ComponentIndex := 0 to ComponentCount - 1 do
  2938. begin
  2939. result[Base + ComponentIndex] :=
  2940. Values[(Index * ComponentCount) + ComponentIndex];
  2941. end;
  2942. end;
  2943. end
  2944. else
  2945. begin
  2946. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  2947. end;
  2948. end
  2949. else
  2950. begin
  2951. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  2952. end;
  2953. end;
  2954. end;
  2955. function TPasGLTF.TAccessor.DecodeAsInt32Array(const aForVertex: boolean)
  2956. : TPasGLTFInt32DynamicArray;
  2957. var
  2958. Index: TPasGLTFSizeInt;
  2959. DoubleArray: TPasGLTFDoubleDynamicArray;
  2960. begin
  2961. result := nil;
  2962. DoubleArray := DecodeAsDoubleArray(aForVertex);
  2963. SetLength(result, Length(DoubleArray));
  2964. for Index := 0 to Length(result) - 1 do
  2965. begin
  2966. result[Index] := trunc(DoubleArray[Index]);
  2967. end;
  2968. end;
  2969. function TPasGLTF.TAccessor.DecodeAsUInt32Array(const aForVertex: boolean)
  2970. : TPasGLTFUInt32DynamicArray;
  2971. var
  2972. Index: TPasGLTFSizeInt;
  2973. DoubleArray: TPasGLTFDoubleDynamicArray;
  2974. begin
  2975. result := nil;
  2976. DoubleArray := DecodeAsDoubleArray(aForVertex);
  2977. SetLength(result, Length(DoubleArray));
  2978. for Index := 0 to Length(result) - 1 do
  2979. begin
  2980. result[Index] := trunc(DoubleArray[Index]);
  2981. end;
  2982. end;
  2983. function TPasGLTF.TAccessor.DecodeAsInt64Array(const aForVertex: boolean)
  2984. : TPasGLTFInt64DynamicArray;
  2985. var
  2986. Index: TPasGLTFSizeInt;
  2987. DoubleArray: TPasGLTFDoubleDynamicArray;
  2988. begin
  2989. result := nil;
  2990. DoubleArray := DecodeAsDoubleArray(aForVertex);
  2991. SetLength(result, Length(DoubleArray));
  2992. for Index := 0 to Length(result) - 1 do
  2993. begin
  2994. result[Index] := trunc(DoubleArray[Index]);
  2995. end;
  2996. end;
  2997. function TPasGLTF.TAccessor.DecodeAsUInt64Array(const aForVertex: boolean)
  2998. : TPasGLTFUInt64DynamicArray;
  2999. var
  3000. Index: TPasGLTFSizeInt;
  3001. DoubleArray: TPasGLTFDoubleDynamicArray;
  3002. begin
  3003. result := nil;
  3004. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3005. SetLength(result, Length(DoubleArray));
  3006. for Index := 0 to Length(result) - 1 do
  3007. begin
  3008. result[Index] := trunc(DoubleArray[Index]);
  3009. end;
  3010. end;
  3011. function TPasGLTF.TAccessor.DecodeAsFloatArray(const aForVertex: boolean)
  3012. : TPasGLTFFloatDynamicArray;
  3013. var
  3014. Index: TPasGLTFSizeInt;
  3015. DoubleArray: TPasGLTFDoubleDynamicArray;
  3016. begin
  3017. result := nil;
  3018. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3019. SetLength(result, Length(DoubleArray));
  3020. for Index := 0 to Length(result) - 1 do
  3021. begin
  3022. result[Index] := DoubleArray[Index];
  3023. end;
  3024. end;
  3025. function TPasGLTF.TAccessor.DecodeAsVector2Array(const aForVertex: boolean)
  3026. : TVector2DynamicArray;
  3027. var
  3028. Index: TPasGLTFSizeInt;
  3029. DoubleArray: TPasGLTFDoubleDynamicArray;
  3030. begin
  3031. result := nil;
  3032. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3033. Assert((Length(DoubleArray) and 1) = 0);
  3034. SetLength(result, Length(DoubleArray) shr 1);
  3035. for Index := 0 to Length(result) - 1 do
  3036. begin
  3037. result[Index, 0] := DoubleArray[(Index shl 1) or 0];
  3038. result[Index, 1] := DoubleArray[(Index shl 1) or 1];
  3039. end;
  3040. end;
  3041. function TPasGLTF.TAccessor.DecodeAsVector3Array(const aForVertex: boolean)
  3042. : TVector3DynamicArray;
  3043. var
  3044. Index: TPasGLTFSizeInt;
  3045. DoubleArray: TPasGLTFDoubleDynamicArray;
  3046. begin
  3047. result := nil;
  3048. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3049. Assert((Length(DoubleArray) mod 3) = 0);
  3050. SetLength(result, Length(DoubleArray) div 3);
  3051. for Index := 0 to Length(result) - 1 do
  3052. begin
  3053. result[Index, 0] := DoubleArray[(Index * 3) + 0];
  3054. result[Index, 1] := DoubleArray[(Index * 3) + 1];
  3055. result[Index, 2] := DoubleArray[(Index * 3) + 2];
  3056. end;
  3057. end;
  3058. function TPasGLTF.TAccessor.DecodeAsVector4Array(const aForVertex: boolean)
  3059. : TVector4DynamicArray;
  3060. var
  3061. Index: TPasGLTFSizeInt;
  3062. DoubleArray: TPasGLTFDoubleDynamicArray;
  3063. begin
  3064. result := nil;
  3065. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3066. Assert((Length(DoubleArray) and 3) = 0);
  3067. SetLength(result, Length(DoubleArray) shr 2);
  3068. for Index := 0 to Length(result) - 1 do
  3069. begin
  3070. result[Index, 0] := DoubleArray[(Index shl 2) or 0];
  3071. result[Index, 1] := DoubleArray[(Index shl 2) or 1];
  3072. result[Index, 2] := DoubleArray[(Index shl 2) or 2];
  3073. result[Index, 3] := DoubleArray[(Index shl 2) or 3];
  3074. end;
  3075. end;
  3076. function TPasGLTF.TAccessor.DecodeAsInt32Vector4Array(const aForVertex: boolean)
  3077. : TInt32Vector4DynamicArray;
  3078. var
  3079. Index: TPasGLTFSizeInt;
  3080. DoubleArray: TPasGLTFDoubleDynamicArray;
  3081. begin
  3082. result := nil;
  3083. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3084. Assert((Length(DoubleArray) and 3) = 0);
  3085. SetLength(result, Length(DoubleArray) shr 2);
  3086. for Index := 0 to Length(result) - 1 do
  3087. begin
  3088. result[Index, 0] := trunc(DoubleArray[(Index shl 2) or 0]);
  3089. result[Index, 1] := trunc(DoubleArray[(Index shl 2) or 1]);
  3090. result[Index, 2] := trunc(DoubleArray[(Index shl 2) or 2]);
  3091. result[Index, 3] := trunc(DoubleArray[(Index shl 2) or 3]);
  3092. end;
  3093. end;
  3094. function TPasGLTF.TAccessor.DecodeAsUInt32Vector4Array(const aForVertex
  3095. : boolean): TUInt32Vector4DynamicArray;
  3096. var
  3097. Index: TPasGLTFSizeInt;
  3098. DoubleArray: TPasGLTFDoubleDynamicArray;
  3099. begin
  3100. result := nil;
  3101. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3102. Assert((Length(DoubleArray) and 3) = 0);
  3103. SetLength(result, Length(DoubleArray) shr 2);
  3104. for Index := 0 to Length(result) - 1 do
  3105. begin
  3106. result[Index, 0] := trunc(DoubleArray[(Index shl 2) or 0]);
  3107. result[Index, 1] := trunc(DoubleArray[(Index shl 2) or 1]);
  3108. result[Index, 2] := trunc(DoubleArray[(Index shl 2) or 2]);
  3109. result[Index, 3] := trunc(DoubleArray[(Index shl 2) or 3]);
  3110. end;
  3111. end;
  3112. function TPasGLTF.TAccessor.DecodeAsColorArray(const aForVertex: boolean = true)
  3113. : TVector4DynamicArray;
  3114. var
  3115. Index: TPasGLTFSizeInt;
  3116. DoubleArray: TPasGLTFDoubleDynamicArray;
  3117. begin
  3118. result := nil;
  3119. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3120. if fType = TType.Vec3 then
  3121. begin
  3122. Assert((Length(DoubleArray) mod 3) = 0);
  3123. SetLength(result, Length(DoubleArray) div 3);
  3124. for Index := 0 to Length(result) - 1 do
  3125. begin
  3126. result[Index, 0] := DoubleArray[(Index * 3) + 0];
  3127. result[Index, 1] := DoubleArray[(Index * 3) + 1];
  3128. result[Index, 2] := DoubleArray[(Index * 3) + 2];
  3129. result[Index, 3] := 1.0;
  3130. end;
  3131. end
  3132. else
  3133. begin
  3134. Assert((Length(DoubleArray) and 3) = 0);
  3135. SetLength(result, Length(DoubleArray) shr 2);
  3136. for Index := 0 to Length(result) - 1 do
  3137. begin
  3138. result[Index, 0] := DoubleArray[(Index shl 2) or 0];
  3139. result[Index, 1] := DoubleArray[(Index shl 2) or 1];
  3140. result[Index, 2] := DoubleArray[(Index shl 2) or 2];
  3141. result[Index, 3] := DoubleArray[(Index shl 2) or 3];
  3142. end;
  3143. end;
  3144. end;
  3145. function TPasGLTF.TAccessor.DecodeAsMatrix2x2Array(const aForVertex
  3146. : boolean = true): TMatrix2x2DynamicArray;
  3147. var
  3148. Index: TPasGLTFSizeInt;
  3149. DoubleArray: TPasGLTFDoubleDynamicArray;
  3150. begin
  3151. result := nil;
  3152. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3153. Assert((Length(DoubleArray) and 3) = 0);
  3154. SetLength(result, Length(DoubleArray) shr 2);
  3155. for Index := 0 to Length(result) - 1 do
  3156. begin
  3157. result[Index, 0] := DoubleArray[(Index shl 2) or 0];
  3158. result[Index, 1] := DoubleArray[(Index shl 2) or 1];
  3159. result[Index, 2] := DoubleArray[(Index shl 2) or 2];
  3160. result[Index, 3] := DoubleArray[(Index shl 2) or 3];
  3161. end;
  3162. end;
  3163. function TPasGLTF.TAccessor.DecodeAsMatrix3x3Array(const aForVertex
  3164. : boolean = true): TMatrix3x3DynamicArray;
  3165. var
  3166. Index: TPasGLTFSizeInt;
  3167. DoubleArray: TPasGLTFDoubleDynamicArray;
  3168. begin
  3169. result := nil;
  3170. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3171. Assert((Length(DoubleArray) mod 9) = 0);
  3172. SetLength(result, Length(DoubleArray) div 9);
  3173. for Index := 0 to Length(result) - 1 do
  3174. begin
  3175. result[Index, 0] := DoubleArray[(Index * 9) + 0];
  3176. result[Index, 1] := DoubleArray[(Index * 9) + 1];
  3177. result[Index, 2] := DoubleArray[(Index * 9) + 2];
  3178. result[Index, 3] := DoubleArray[(Index * 9) + 3];
  3179. result[Index, 4] := DoubleArray[(Index * 9) + 4];
  3180. result[Index, 5] := DoubleArray[(Index * 9) + 5];
  3181. result[Index, 6] := DoubleArray[(Index * 9) + 6];
  3182. result[Index, 7] := DoubleArray[(Index * 9) + 7];
  3183. result[Index, 8] := DoubleArray[(Index * 9) + 8];
  3184. end;
  3185. end;
  3186. function TPasGLTF.TAccessor.DecodeAsMatrix4x4Array(const aForVertex
  3187. : boolean = true): TMatrix4x4DynamicArray;
  3188. var
  3189. Index: TPasGLTFSizeInt;
  3190. DoubleArray: TPasGLTFDoubleDynamicArray;
  3191. begin
  3192. result := nil;
  3193. DoubleArray := DecodeAsDoubleArray(aForVertex);
  3194. Assert((Length(DoubleArray) and 15) = 0);
  3195. SetLength(result, Length(DoubleArray) shr 4);
  3196. for Index := 0 to Length(result) - 1 do
  3197. begin
  3198. result[Index, 0] := DoubleArray[(Index shl 4) or 0];
  3199. result[Index, 1] := DoubleArray[(Index shl 4) or 1];
  3200. result[Index, 2] := DoubleArray[(Index shl 4) or 2];
  3201. result[Index, 3] := DoubleArray[(Index shl 4) or 3];
  3202. result[Index, 4] := DoubleArray[(Index shl 4) or 4];
  3203. result[Index, 5] := DoubleArray[(Index shl 4) or 5];
  3204. result[Index, 6] := DoubleArray[(Index shl 4) or 6];
  3205. result[Index, 7] := DoubleArray[(Index shl 4) or 7];
  3206. result[Index, 8] := DoubleArray[(Index shl 4) or 8];
  3207. result[Index, 9] := DoubleArray[(Index shl 4) or 9];
  3208. result[Index, 10] := DoubleArray[(Index shl 4) or 10];
  3209. result[Index, 11] := DoubleArray[(Index shl 4) or 11];
  3210. result[Index, 12] := DoubleArray[(Index shl 4) or 12];
  3211. result[Index, 13] := DoubleArray[(Index shl 4) or 13];
  3212. result[Index, 14] := DoubleArray[(Index shl 4) or 14];
  3213. result[Index, 15] := DoubleArray[(Index shl 4) or 15];
  3214. end;
  3215. end;
  3216. { TPasGLTF.TAnimation.TChannel.TTarget }
  3217. constructor TPasGLTF.TAnimation.TChannel.TTarget.Create(const aDocument
  3218. : TDocument);
  3219. begin
  3220. inherited Create(aDocument);
  3221. fNode := -1;
  3222. fPath := '';
  3223. fEmpty := false;
  3224. end;
  3225. destructor TPasGLTF.TAnimation.TChannel.TTarget.Destroy;
  3226. begin
  3227. inherited Destroy;
  3228. end;
  3229. { TPasGLTF.TAnimation.TChannel }
  3230. constructor TPasGLTF.TAnimation.TChannel.Create(const aDocument: TDocument);
  3231. begin
  3232. inherited Create(aDocument);
  3233. fSampler := -1;
  3234. fTarget := TTarget.Create(aDocument);
  3235. end;
  3236. destructor TPasGLTF.TAnimation.TChannel.Destroy;
  3237. begin
  3238. FreeAndNil(fTarget);
  3239. inherited Destroy;
  3240. end;
  3241. { TPasGLTF.TAnimation.TSampler }
  3242. constructor TPasGLTF.TAnimation.TSampler.Create(const aDocument: TDocument);
  3243. begin
  3244. inherited Create(aDocument);
  3245. fInput := -1;
  3246. fOutput := -1;
  3247. fInterpolation := TType.Linear;
  3248. end;
  3249. destructor TPasGLTF.TAnimation.TSampler.Destroy;
  3250. begin
  3251. inherited Destroy;
  3252. end;
  3253. { TPasGLTF.TAnimation }
  3254. constructor TPasGLTF.TAnimation.Create(const aDocument: TDocument);
  3255. begin
  3256. inherited Create(aDocument);
  3257. fName := '';
  3258. fChannels := TChannels.Create;
  3259. fSamplers := TSamplers.Create;
  3260. end;
  3261. destructor TPasGLTF.TAnimation.Destroy;
  3262. begin
  3263. FreeAndNil(fChannels);
  3264. FreeAndNil(fSamplers);
  3265. inherited Destroy;
  3266. end;
  3267. { TPasGLTF.TAsset }
  3268. constructor TPasGLTF.TAsset.Create(const aDocument: TDocument);
  3269. begin
  3270. inherited Create(aDocument);
  3271. fCopyright := '';
  3272. fGenerator := '';
  3273. fMinVersion := '';
  3274. fVersion := '2.0';
  3275. fEmpty := false;
  3276. end;
  3277. destructor TPasGLTF.TAsset.Destroy;
  3278. begin
  3279. inherited Destroy;
  3280. end;
  3281. { TPasGLTF.TBuffer }
  3282. constructor TPasGLTF.TBuffer.Create(const aDocument: TDocument);
  3283. begin
  3284. inherited Create(aDocument);
  3285. fByteLength := 0;
  3286. fName := '';
  3287. fURI := '';
  3288. fData := TMemoryStream.Create;
  3289. end;
  3290. destructor TPasGLTF.TBuffer.Destroy;
  3291. begin
  3292. FreeAndNil(fData);
  3293. inherited Destroy;
  3294. end;
  3295. procedure TPasGLTF.TBuffer.SetEmbeddedResourceData;
  3296. begin
  3297. fURI := 'data:' + MimeTypeApplicationOctet + ';base64,' +
  3298. TBase64.Encode(fData);
  3299. end;
  3300. { TPasGLTF.TBufferView }
  3301. constructor TPasGLTF.TBufferView.Create(const aDocument: TDocument);
  3302. begin
  3303. inherited Create(aDocument);
  3304. fName := '';
  3305. fBuffer := -1;
  3306. fByteOffset := 0;
  3307. fByteLength := 0;
  3308. fByteStride := 0;
  3309. fTarget := TTargetType.None;
  3310. end;
  3311. destructor TPasGLTF.TBufferView.Destroy;
  3312. begin
  3313. inherited Destroy;
  3314. end;
  3315. function TPasGLTF.TBufferView.Decode(const aSkipEvery: TPasGLTFSizeUInt;
  3316. const aSkipBytes: TPasGLTFSizeUInt; const aElementSize: TPasGLTFSizeUInt;
  3317. const aCount: TPasGLTFSizeUInt; const aType: TPasGLTF.TAccessor.TType;
  3318. const aComponentCount: TPasGLTFSizeUInt;
  3319. const aComponentType: TPasGLTF.TAccessor.TComponentType;
  3320. const aComponentSize: TPasGLTFSizeUInt; const aByteOffset: TPasGLTFSizeUInt;
  3321. const aNormalized: boolean; const aForVertex: boolean)
  3322. : TPasGLTFDoubleDynamicArray;
  3323. var
  3324. Stride, Offset, Index, ComponentIndex, OutputIndex: TPasGLTFSizeUInt;
  3325. Buffer: TPasGLTF.TBuffer;
  3326. BufferData, Source: PPasGLTFUInt8Array;
  3327. Value: TPasGLTFDouble;
  3328. begin
  3329. result := nil;
  3330. Buffer := fDocument.fBuffers[fBuffer];
  3331. if fByteStride <> 0 then
  3332. begin
  3333. Stride := fByteStride;
  3334. end
  3335. else
  3336. begin
  3337. Stride := aElementSize;
  3338. end;
  3339. if aForVertex and ((Stride and 3) <> 0) then
  3340. begin
  3341. inc(Stride, 4 - (Stride and 3));
  3342. end;
  3343. SetLength(result, aCount * aComponentCount);
  3344. Offset := fByteOffset + aByteOffset;
  3345. BufferData := Buffer.fData.Memory;
  3346. if (((Stride * (aCount - 1)) + aElementSize) > fByteLength) or
  3347. ((Offset + ((Stride * (aCount - 1)) + aElementSize)) >
  3348. TPasGLTFSizeUInt(Buffer.fData.Size)) then
  3349. begin
  3350. raise EPasGLTFInvalidDocument.Create('Invalid document');
  3351. end;
  3352. OutputIndex := 0;
  3353. for Index := 1 to aCount do
  3354. begin
  3355. Source := @BufferData^[Offset + ((Index - 1) * Stride)];
  3356. for ComponentIndex := 1 to aComponentCount do
  3357. begin
  3358. if (aSkipEvery > 0) and (ComponentIndex > 1) and
  3359. (((ComponentIndex - 1) mod aSkipEvery) = 0) then
  3360. begin
  3361. Source := @Source^[aSkipBytes];
  3362. end;
  3363. Value := 0.0;
  3364. case aComponentType of
  3365. TPasGLTF.TAccessor.TComponentType.SignedByte:
  3366. begin
  3367. if aNormalized then
  3368. begin
  3369. Value := TPasGLTFInt8(TPasGLTFPointer(@Source^[0])^) / 128.0;
  3370. end
  3371. else
  3372. begin
  3373. Value := TPasGLTFInt8(TPasGLTFPointer(@Source^[0])^);
  3374. end;
  3375. end;
  3376. TPasGLTF.TAccessor.TComponentType.UnsignedByte:
  3377. begin
  3378. if aNormalized then
  3379. begin
  3380. Value := TPasGLTFUInt8(TPasGLTFPointer(@Source^[0])^) / 255.0;
  3381. end
  3382. else
  3383. begin
  3384. Value := TPasGLTFUInt8(TPasGLTFPointer(@Source^[0])^);
  3385. end;
  3386. end;
  3387. TPasGLTF.TAccessor.TComponentType.SignedShort:
  3388. begin
  3389. if aNormalized then
  3390. begin
  3391. Value := TPasGLTFInt16(TPasGLTFPointer(@Source^[0])^) / 32768.0;
  3392. end
  3393. else
  3394. begin
  3395. Value := TPasGLTFInt16(TPasGLTFPointer(@Source^[0])^);
  3396. end;
  3397. end;
  3398. TPasGLTF.TAccessor.TComponentType.UnsignedShort:
  3399. begin
  3400. if aNormalized then
  3401. begin
  3402. Value := TPasGLTFUInt16(TPasGLTFPointer(@Source^[0])^) / 65535.0;
  3403. end
  3404. else
  3405. begin
  3406. Value := TPasGLTFUInt16(TPasGLTFPointer(@Source^[0])^);
  3407. end;
  3408. end;
  3409. TPasGLTF.TAccessor.TComponentType.UnsignedInt:
  3410. begin
  3411. if aNormalized then
  3412. begin
  3413. Value := TPasGLTFUInt32(TPasGLTFPointer(@Source^[0])^) /
  3414. 4294967295.0;
  3415. end
  3416. else
  3417. begin
  3418. Value := TPasGLTFUInt32(TPasGLTFPointer(@Source^[0])^);
  3419. end;
  3420. end;
  3421. TPasGLTF.TAccessor.TComponentType.Float:
  3422. begin
  3423. Value := TPasGLTFFloat(TPasGLTFPointer(@Source^[0])^);
  3424. end;
  3425. else { TPasGLTF.TAccessor.TComponentType.None: }
  3426. begin
  3427. raise EPasGLTFInvalidDocument.Create('Invalid document');
  3428. end;
  3429. end;
  3430. result[OutputIndex] := Value;
  3431. inc(OutputIndex);
  3432. Source := @Source^[aComponentSize];
  3433. end;
  3434. end;
  3435. end;
  3436. { TPasGLTF.TCamera.TOrthographic }
  3437. constructor TPasGLTF.TCamera.TOrthographic.Create(const aDocument: TDocument);
  3438. begin
  3439. inherited Create(aDocument);
  3440. fXMag := TDefaults.FloatSentinel;
  3441. fYMag := TDefaults.FloatSentinel;
  3442. fZNear := -TDefaults.FloatSentinel;
  3443. fZFar := -TDefaults.FloatSentinel;
  3444. fEmpty := false;
  3445. end;
  3446. destructor TPasGLTF.TCamera.TOrthographic.Destroy;
  3447. begin
  3448. inherited Destroy;
  3449. end;
  3450. { TPasGLTF.TCamera.TPerspective }
  3451. constructor TPasGLTF.TCamera.TPerspective.Create(const aDocument: TDocument);
  3452. begin
  3453. inherited Create(aDocument);
  3454. fAspectRatio := 1.778;
  3455. fYFov := 0.252;
  3456. fZNear := 0.1;
  3457. fZFar := 1000.0;
  3458. fEmpty := false;
  3459. end;
  3460. destructor TPasGLTF.TCamera.TPerspective.Destroy;
  3461. begin
  3462. inherited Destroy;
  3463. end;
  3464. { TPasGLTF.TCamera }
  3465. constructor TPasGLTF.TCamera.Create(const aDocument: TDocument);
  3466. begin
  3467. inherited Create(aDocument);
  3468. fType := TType.None;
  3469. fOrthographic := TOrthographic.Create(fDocument);
  3470. fPerspective := TPerspective.Create(fDocument);
  3471. end;
  3472. destructor TPasGLTF.TCamera.Destroy;
  3473. begin
  3474. FreeAndNil(fOrthographic);
  3475. FreeAndNil(fPerspective);
  3476. inherited Destroy;
  3477. end;
  3478. { TPasGLTF.TImage }
  3479. constructor TPasGLTF.TImage.Create(const aDocument: TDocument);
  3480. begin
  3481. inherited Create(aDocument);
  3482. fBufferView := -1;
  3483. fName := '';
  3484. fURI := '';
  3485. fMimeType := '';
  3486. end;
  3487. destructor TPasGLTF.TImage.Destroy;
  3488. begin
  3489. inherited Destroy;
  3490. end;
  3491. procedure TPasGLTF.TImage.SetEmbeddedResourceData(const aStream: TStream);
  3492. begin
  3493. fURI := 'data:' + fMimeType + ';base64,' + TBase64.Encode(aStream);
  3494. end;
  3495. procedure TPasGLTF.TImage.GetResourceData(const aStream: TStream);
  3496. var
  3497. BufferView: TBufferView;
  3498. Buffer: TBuffer;
  3499. begin
  3500. if fBufferView >= 0 then
  3501. begin
  3502. if fBufferView < fDocument.fBufferViews.Count then
  3503. begin
  3504. BufferView := fDocument.fBufferViews[fBufferView];
  3505. if (BufferView.fBuffer >= 0) and
  3506. (BufferView.fBuffer < fDocument.fBuffers.Count) then
  3507. begin
  3508. Buffer := fDocument.fBuffers[BufferView.fBuffer];
  3509. if (BufferView.fByteOffset + BufferView.fByteLength) <= Buffer.fData.Size
  3510. then
  3511. begin
  3512. aStream.WriteBuffer(PPasGLTFUInt8Array(Buffer.fData.Memory)
  3513. ^[BufferView.fByteOffset], BufferView.fByteLength);
  3514. aStream.Seek(-BufferView.fByteLength, soCurrent);
  3515. end
  3516. else
  3517. begin
  3518. raise EInOutError.Create('I/O error');
  3519. end;
  3520. end
  3521. else
  3522. begin
  3523. raise EInOutError.Create('I/O error');
  3524. end;
  3525. end
  3526. else
  3527. begin
  3528. raise EInOutError.Create('I/O error');
  3529. end;
  3530. end
  3531. else
  3532. begin
  3533. fDocument.LoadURISource(fURI, aStream);
  3534. end;
  3535. end;
  3536. function TPasGLTF.TImage.IsExternalResource: boolean;
  3537. begin
  3538. result := not((fBufferView >= 0) or (pos('data:', fURI) = 1));
  3539. end;
  3540. { TPasGLTF.TMaterial.TTexture }
  3541. constructor TPasGLTF.TMaterial.TTexture.Create(const aDocument: TDocument);
  3542. begin
  3543. inherited Create(aDocument);
  3544. fIndex := -1;
  3545. fTexCoord := 0;
  3546. end;
  3547. destructor TPasGLTF.TMaterial.TTexture.Destroy;
  3548. begin
  3549. inherited Destroy;
  3550. end;
  3551. function TPasGLTF.TMaterial.TTexture.GetEmpty: boolean;
  3552. begin
  3553. result := fIndex < 0;
  3554. end;
  3555. { TPasGLTF.TMaterial.TNormalTexture }
  3556. constructor TPasGLTF.TMaterial.TNormalTexture.Create(const aDocument
  3557. : TDocument);
  3558. begin
  3559. inherited Create(aDocument);
  3560. fScale := TDefaults.IdentityScalar;
  3561. end;
  3562. { TPasGLTF.TMaterial.TOcclusionTexture }
  3563. constructor TPasGLTF.TMaterial.TOcclusionTexture.Create(const aDocument
  3564. : TDocument);
  3565. begin
  3566. inherited Create(aDocument);
  3567. fStrength := TDefaults.IdentityScalar;
  3568. end;
  3569. { TPasGLTF.TMaterial.TPBRMetallicRoughness }
  3570. constructor TPasGLTF.TMaterial.TPBRMetallicRoughness.Create(const aDocument
  3571. : TDocument);
  3572. begin
  3573. inherited Create(aDocument);
  3574. fBaseColorFactor := TDefaults.IdentityVector4;
  3575. fBaseColorTexture := TTexture.Create(fDocument);
  3576. fRoughnessFactor := TDefaults.IdentityScalar;
  3577. fMetallicFactor := TDefaults.IdentityScalar;
  3578. fMetallicRoughnessTexture := TTexture.Create(fDocument);
  3579. end;
  3580. destructor TPasGLTF.TMaterial.TPBRMetallicRoughness.Destroy;
  3581. begin
  3582. FreeAndNil(fBaseColorTexture);
  3583. FreeAndNil(fMetallicRoughnessTexture);
  3584. inherited Destroy;
  3585. end;
  3586. function TPasGLTF.TMaterial.TPBRMetallicRoughness.GetEmpty: boolean;
  3587. begin
  3588. result := fBaseColorTexture.Empty and fMetallicRoughnessTexture.Empty and
  3589. SameValue(fRoughnessFactor, TDefaults.IdentityScalar) and
  3590. SameValue(fMetallicFactor, TDefaults.IdentityScalar);
  3591. end;
  3592. { TPasGLTF.TMaterial }
  3593. constructor TPasGLTF.TMaterial.Create(const aDocument: TDocument);
  3594. begin
  3595. inherited Create(aDocument);
  3596. fName := '';
  3597. fAlphaCutOff := TDefaults.MaterialAlphaCutoff;
  3598. fAlphaMode := TAlphaMode.Opaque;
  3599. fDoubleSided := TDefaults.MaterialDoubleSided;
  3600. fNormalTexture := TNormalTexture.Create(fDocument);
  3601. fOcclusionTexture := TOcclusionTexture.Create(fDocument);
  3602. fPBRMetallicRoughness := TPBRMetallicRoughness.Create(fDocument);
  3603. fEmissiveTexture := TTexture.Create(fDocument);
  3604. fEmissiveFactor := TDefaults.NullVector3;
  3605. end;
  3606. destructor TPasGLTF.TMaterial.Destroy;
  3607. begin
  3608. FreeAndNil(fNormalTexture);
  3609. FreeAndNil(fOcclusionTexture);
  3610. FreeAndNil(fPBRMetallicRoughness);
  3611. FreeAndNil(fEmissiveTexture);
  3612. inherited Destroy;
  3613. end;
  3614. { TPasGLTF.TMesh.TPrimitive }
  3615. constructor TPasGLTF.TMesh.TPrimitive.Create(const aDocument: TDocument);
  3616. begin
  3617. inherited Create(aDocument);
  3618. fMode := TMode.Triangles;
  3619. fIndices := -1;
  3620. fMaterial := -1;
  3621. fAttributes := TAttributes.Create(-1);
  3622. fTargets := TAttributesList.Create;
  3623. end;
  3624. destructor TPasGLTF.TMesh.TPrimitive.Destroy;
  3625. begin
  3626. FreeAndNil(fAttributes);
  3627. FreeAndNil(fTargets);
  3628. inherited Destroy;
  3629. end;
  3630. { TPasGLTF.TMesh }
  3631. constructor TPasGLTF.TMesh.Create(const aDocument: TDocument);
  3632. begin
  3633. inherited Create(aDocument);
  3634. fName := '';
  3635. fWeights := TWeights.Create;
  3636. fPrimitives := TPrimitives.Create;
  3637. end;
  3638. destructor TPasGLTF.TMesh.Destroy;
  3639. begin
  3640. FreeAndNil(fWeights);
  3641. FreeAndNil(fPrimitives);
  3642. inherited Destroy;
  3643. end;
  3644. { TPasGLTF.TNode }
  3645. constructor TPasGLTF.TNode.Create(const aDocument: TDocument);
  3646. begin
  3647. inherited Create(aDocument);
  3648. fName := '';
  3649. fCamera := -1;
  3650. fMesh := -1;
  3651. fSkin := -1;
  3652. fMatrix := TDefaults.IdentityMatrix4x4;
  3653. fRotation := TDefaults.IdentityQuaternion;
  3654. fScale := TDefaults.IdentityVector3;
  3655. fTranslation := TDefaults.NullVector3;
  3656. fChildren := TChildren.Create;
  3657. fWeights := TWeights.Create;
  3658. end;
  3659. destructor TPasGLTF.TNode.Destroy;
  3660. begin
  3661. FreeAndNil(fChildren);
  3662. FreeAndNil(fWeights);
  3663. inherited Destroy;
  3664. end;
  3665. { TPasGLTF.TSampler }
  3666. constructor TPasGLTF.TSampler.Create(const aDocument: TDocument);
  3667. begin
  3668. inherited Create(aDocument);
  3669. fName := '';
  3670. fMagFilter := TMagFilter.None;
  3671. fMinFilter := TMinFilter.None;
  3672. fWrapS := TWrappingMode.Repeat_;
  3673. fWrapT := TWrappingMode.Repeat_;
  3674. end;
  3675. destructor TPasGLTF.TSampler.Destroy;
  3676. begin
  3677. inherited Destroy;
  3678. end;
  3679. function TPasGLTF.TSampler.GetEmpty: boolean;
  3680. begin
  3681. result := (Length(fName) = 0) and (fMagFilter = TMagFilter.None) and
  3682. (fMinFilter = TMinFilter.None) and (fWrapS = TWrappingMode.Repeat_) and
  3683. (fWrapT = TWrappingMode.Repeat_);
  3684. end;
  3685. { TPasGLTF.TScene }
  3686. constructor TPasGLTF.TScene.Create(const aDocument: TDocument);
  3687. begin
  3688. inherited Create(aDocument);
  3689. fName := '';
  3690. fNodes := TPasGLTF.TScene.TNodes.Create;
  3691. end;
  3692. destructor TPasGLTF.TScene.Destroy;
  3693. begin
  3694. FreeAndNil(fNodes);
  3695. inherited Destroy;
  3696. end;
  3697. { TPasGLTF.TSkin }
  3698. constructor TPasGLTF.TSkin.Create(const aDocument: TDocument);
  3699. begin
  3700. inherited Create(aDocument);
  3701. fName := '';
  3702. fInverseBindMatrices := -1;
  3703. fSkeleton := -1;
  3704. fJoints := TPasGLTF.TSkin.TJoints.Create;
  3705. end;
  3706. destructor TPasGLTF.TSkin.Destroy;
  3707. begin
  3708. FreeAndNil(fJoints);
  3709. inherited Destroy;
  3710. end;
  3711. { TPasGLTF.TTexture }
  3712. constructor TPasGLTF.TTexture.Create(const aDocument: TDocument);
  3713. begin
  3714. inherited Create(aDocument);
  3715. fName := '';
  3716. fSampler := -1;
  3717. fSource := -1;
  3718. end;
  3719. destructor TPasGLTF.TTexture.Destroy;
  3720. begin
  3721. inherited Destroy;
  3722. end;
  3723. { TPasGLTF.TDocument }
  3724. constructor TPasGLTF.TDocument.Create(const aDocument: TDocument = nil);
  3725. begin
  3726. inherited Create(aDocument);
  3727. fAsset := TAsset.Create(fDocument);
  3728. fAccessors := TAccessors.Create;
  3729. fAnimations := TAnimations.Create;
  3730. fBuffers := TBuffers.Create;
  3731. fBufferViews := TBufferViews.Create;
  3732. fCameras := TCameras.Create;
  3733. fImages := TImages.Create;
  3734. fMaterials := TMaterials.Create;
  3735. fMeshes := TMeshes.Create;
  3736. fNodes := TNodes.Create;
  3737. fSamplers := TSamplers.Create;
  3738. fScene := -1;
  3739. fScenes := TScenes.Create;
  3740. fSkins := TSkins.Create;
  3741. fTextures := TTextures.Create;
  3742. fExtensionsUsed := TStringList.Create;
  3743. fExtensionsRequired := TStringList.Create;
  3744. fRootPath := '';
  3745. fGetURI := DefaultGetURI;
  3746. end;
  3747. destructor TPasGLTF.TDocument.Destroy;
  3748. begin
  3749. FreeAndNil(fAsset);
  3750. FreeAndNil(fAccessors);
  3751. FreeAndNil(fAnimations);
  3752. FreeAndNil(fBuffers);
  3753. FreeAndNil(fBufferViews);
  3754. FreeAndNil(fCameras);
  3755. FreeAndNil(fImages);
  3756. FreeAndNil(fMaterials);
  3757. FreeAndNil(fMeshes);
  3758. FreeAndNil(fNodes);
  3759. FreeAndNil(fSamplers);
  3760. FreeAndNil(fScenes);
  3761. FreeAndNil(fSkins);
  3762. FreeAndNil(fTextures);
  3763. FreeAndNil(fExtensionsUsed);
  3764. FreeAndNil(fExtensionsRequired);
  3765. inherited Destroy;
  3766. end;
  3767. function TPasGLTF.TDocument.DefaultGetURI(const aURI
  3768. : TPasGLTFUTF8String): TStream;
  3769. var
  3770. FileName: String;
  3771. begin
  3772. FileName := ExpandFileName(IncludeTrailingPathDelimiter(fRootPath) +
  3773. String(TPasGLTF.ResolveURIToPath(aURI)));
  3774. result := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  3775. end;
  3776. procedure TPasGLTF.TDocument.LoadURISource(const aURI: TPasGLTFUTF8String;
  3777. const aStream: TStream);
  3778. const
  3779. Base64Signature = ';base64,';
  3780. var
  3781. Stream: TStream;
  3782. Base64Position: TPasGLTFSizeInt;
  3783. begin
  3784. if Length(trim(aURI)) > 0 then
  3785. begin
  3786. if (Length(aURI) > 5) and (aURI[1] = 'd') and (aURI[2] = 'a') and
  3787. (aURI[3] = 't') and (aURI[4] = 'a') and (aURI[5] = ':') then
  3788. begin
  3789. Base64Position := pos(Base64Signature, aURI);
  3790. if Base64Position > 0 then
  3791. begin
  3792. TBase64.Decode(copy(aURI, Base64Position + Length(Base64Signature),
  3793. (Length(aURI) - (Base64Position + Length(Base64Signature))) +
  3794. 1), aStream);
  3795. end;
  3796. end
  3797. else if assigned(fGetURI) then
  3798. begin
  3799. Stream := fGetURI(aURI);
  3800. if assigned(Stream) then
  3801. begin
  3802. try
  3803. Stream.Seek(0, soBeginning);
  3804. if aStream.CopyFrom(Stream, Stream.Size) <> Stream.Size then
  3805. begin
  3806. raise EInOutError.Create('I/O error');
  3807. end;
  3808. finally
  3809. FreeAndNil(Stream);
  3810. end;
  3811. end;
  3812. end;
  3813. aStream.Seek(0, soBeginning);
  3814. end;
  3815. end;
  3816. procedure TPasGLTF.TDocument.LoadURISources;
  3817. var
  3818. Buffer: TBuffer;
  3819. begin
  3820. for Buffer in fBuffers do
  3821. begin
  3822. if Length(trim(Buffer.fURI)) > 0 then
  3823. begin
  3824. LoadURISource(Buffer.fURI, Buffer.fData);
  3825. end;
  3826. end;
  3827. end;
  3828. procedure TPasGLTF.TDocument.LoadFromJSON(const aJSONRootItem: TPasJSONItem);
  3829. function Required(const aJSONItem: TPasJSONItem;
  3830. const aName: TPasGLTFUTF8String = ''): TPasJSONItem;
  3831. begin
  3832. result := aJSONItem;
  3833. if not assigned(result) then
  3834. begin
  3835. if Length(aName) > 0 then
  3836. begin
  3837. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document, missing "'
  3838. + String(aName) + '" field');
  3839. end
  3840. else
  3841. begin
  3842. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  3843. end;
  3844. end;
  3845. end;
  3846. procedure ProcessExtensionsAndExtras(const aJSONItem: TPasJSONItem;
  3847. const aBaseExtensionsExtrasObject: TBaseExtensionsExtrasObject);
  3848. var
  3849. JSONObject: TPasJSONItemObject;
  3850. JSONObjectItem: TPasJSONItem;
  3851. begin
  3852. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  3853. begin
  3854. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  3855. end;
  3856. JSONObject := TPasJSONItemObject(aJSONItem);
  3857. begin
  3858. JSONObjectItem := JSONObject.Properties['extensions'];
  3859. if assigned(JSONObjectItem) and (JSONObjectItem is TPasJSONItemObject)
  3860. then
  3861. begin
  3862. aBaseExtensionsExtrasObject.fExtensions.Merge(JSONObjectItem);
  3863. end;
  3864. end;
  3865. begin
  3866. JSONObjectItem := JSONObject.Properties['extras'];
  3867. if assigned(JSONObjectItem) and (JSONObjectItem is TPasJSONItemObject)
  3868. then
  3869. begin
  3870. aBaseExtensionsExtrasObject.fExtras.Merge(JSONObjectItem);
  3871. end;
  3872. end;
  3873. end;
  3874. procedure ProcessAccessors(const aJSONItem: TPasJSONItem);
  3875. function ProcessAccessor(const aJSONItem: TPasJSONItem): TAccessor;
  3876. procedure ProcessSparse(const aJSONItem: TPasJSONItem;
  3877. const aSparse: TAccessor.TSparse);
  3878. var
  3879. JSONObject: TPasJSONItemObject;
  3880. JSONItem: TPasJSONItem;
  3881. begin
  3882. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  3883. begin
  3884. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  3885. end;
  3886. JSONObject := TPasJSONItemObject(aJSONItem);
  3887. ProcessExtensionsAndExtras(JSONObject, aSparse);
  3888. aSparse.fCount := TPasJSON.GetInt64
  3889. (Required(JSONObject.Properties['count'], 'count'), aSparse.fCount);
  3890. begin
  3891. JSONItem := JSONObject.Properties['indices'];
  3892. if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject)) then
  3893. begin
  3894. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  3895. end;
  3896. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
  3897. aSparse.fIndices);
  3898. aSparse.fIndices.fBufferView :=
  3899. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
  3900. .Properties['bufferView'], 'bufferView'),
  3901. aSparse.fIndices.fBufferView);
  3902. aSparse.fIndices.fComponentType :=
  3903. TAccessor.TComponentType
  3904. (TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
  3905. .Properties['componentType'], 'componentType'),
  3906. TPasGLTFInt64(TAccessor.TComponentType.None)));
  3907. aSparse.fIndices.fByteOffset :=
  3908. TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
  3909. ['byteOffset'], aSparse.fIndices.fByteOffset);
  3910. end;
  3911. begin
  3912. JSONItem := JSONObject.Properties['values'];
  3913. if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject)) then
  3914. begin
  3915. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  3916. end;
  3917. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
  3918. aSparse.fValues);
  3919. aSparse.fValues.fBufferView :=
  3920. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
  3921. .Properties['bufferView'], 'bufferView'),
  3922. aSparse.fValues.fBufferView);
  3923. aSparse.fValues.fByteOffset :=
  3924. TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
  3925. ['byteOffset'], aSparse.fValues.fByteOffset);
  3926. end;
  3927. end;
  3928. var
  3929. JSONObject: TPasJSONItemObject;
  3930. JSONItem, JSONArrayItem: TPasJSONItem;
  3931. Type_: TPasGLTFUTF8String;
  3932. begin
  3933. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  3934. begin
  3935. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  3936. end;
  3937. JSONObject := TPasJSONItemObject(aJSONItem);
  3938. result := TAccessor.Create(self);
  3939. try
  3940. ProcessExtensionsAndExtras(JSONObject, result);
  3941. result.fComponentType := TAccessor.TComponentType
  3942. (TPasJSON.GetInt64(Required(JSONObject.Properties['componentType'],
  3943. 'componentType'), TPasGLTFInt64(TAccessor.TComponentType.None)));
  3944. result.fCount := TPasJSON.GetInt64
  3945. (Required(JSONObject.Properties['count'], 'count'), result.fCount);
  3946. begin
  3947. Type_ := TPasJSON.GetString(Required(JSONObject.Properties['type'],
  3948. 'type'), 'NONE');
  3949. if Type_ = 'SCALAR' then
  3950. begin
  3951. result.fType := TAccessor.TType.Scalar;
  3952. end
  3953. else if Type_ = 'VEC2' then
  3954. begin
  3955. result.fType := TAccessor.TType.Vec2;
  3956. end
  3957. else if Type_ = 'VEC3' then
  3958. begin
  3959. result.fType := TAccessor.TType.Vec3;
  3960. end
  3961. else if Type_ = 'VEC4' then
  3962. begin
  3963. result.fType := TAccessor.TType.Vec4;
  3964. end
  3965. else if Type_ = 'MAT2' then
  3966. begin
  3967. result.fType := TAccessor.TType.Mat2;
  3968. end
  3969. else if Type_ = 'MAT3' then
  3970. begin
  3971. result.fType := TAccessor.TType.Mat3;
  3972. end
  3973. else if Type_ = 'MAT4' then
  3974. begin
  3975. result.fType := TAccessor.TType.Mat4;
  3976. end
  3977. else
  3978. begin
  3979. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  3980. end;
  3981. end;
  3982. result.fBufferView := TPasJSON.GetInt64
  3983. (JSONObject.Properties['bufferView'], result.fBufferView);
  3984. result.fByteOffset := TPasJSON.GetInt64
  3985. (JSONObject.Properties['byteOffset'], result.fByteOffset);
  3986. begin
  3987. JSONItem := JSONObject.Properties['min'];
  3988. if assigned(JSONItem) then
  3989. begin
  3990. if not(JSONItem is TPasJSONItemArray) then
  3991. begin
  3992. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  3993. end;
  3994. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  3995. begin
  3996. if not(assigned(JSONArrayItem) and
  3997. (JSONArrayItem is TPasJSONItemNumber)) then
  3998. begin
  3999. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4000. end;
  4001. result.fMinArray.Add(TPasJSON.GetNumber(JSONArrayItem, 0.0));
  4002. end;
  4003. end;
  4004. end;
  4005. begin
  4006. JSONItem := JSONObject.Properties['max'];
  4007. if assigned(JSONItem) then
  4008. begin
  4009. if not(JSONItem is TPasJSONItemArray) then
  4010. begin
  4011. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4012. end;
  4013. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  4014. begin
  4015. if not(assigned(JSONArrayItem) and
  4016. (JSONArrayItem is TPasJSONItemNumber)) then
  4017. begin
  4018. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4019. end;
  4020. result.fMaxArray.Add(TPasJSON.GetNumber(JSONArrayItem, 0.0));
  4021. end;
  4022. end;
  4023. end;
  4024. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4025. result.fName);
  4026. result.fNormalized := TPasJSON.GetBoolean
  4027. (JSONObject.Properties['normalized'], result.fNormalized);
  4028. begin
  4029. JSONItem := JSONObject.Properties['sparse'];
  4030. if assigned(JSONItem) then
  4031. begin
  4032. ProcessSparse(JSONItem, result.fSparse);
  4033. end;
  4034. end;
  4035. except
  4036. FreeAndNil(result);
  4037. raise;
  4038. end;
  4039. end;
  4040. var
  4041. JSONArray: TPasJSONItemArray;
  4042. JSONItem: TPasJSONItem;
  4043. begin
  4044. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4045. begin
  4046. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4047. end;
  4048. JSONArray := TPasJSONItemArray(aJSONItem);
  4049. for JSONItem in JSONArray do
  4050. begin
  4051. fAccessors.Add(ProcessAccessor(JSONItem));
  4052. end;
  4053. end;
  4054. procedure ProcessAnimations(const aJSONItem: TPasJSONItem);
  4055. function ProcessAnimation(const aJSONItem: TPasJSONItem): TAnimation;
  4056. var
  4057. JSONObject: TPasJSONItemObject;
  4058. JSONItem, JSONArrayItem, TargetItem, InterpolationItem: TPasJSONItem;
  4059. Interpolation: TPasGLTFUTF8String;
  4060. Channel: TAnimation.TChannel;
  4061. Sampler: TAnimation.TSampler;
  4062. begin
  4063. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4064. begin
  4065. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4066. end;
  4067. JSONObject := TPasJSONItemObject(aJSONItem);
  4068. result := TAnimation.Create(self);
  4069. try
  4070. ProcessExtensionsAndExtras(JSONObject, result);
  4071. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4072. result.fName);
  4073. begin
  4074. JSONItem := JSONObject.Properties['channels'];
  4075. if not(assigned(JSONItem) and (JSONItem is TPasJSONItemArray)) then
  4076. begin
  4077. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4078. end;
  4079. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  4080. begin
  4081. if not(assigned(JSONArrayItem) and
  4082. (JSONArrayItem is TPasJSONItemObject)) then
  4083. begin
  4084. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4085. end;
  4086. Channel := TAnimation.TChannel.Create(self);
  4087. try
  4088. ProcessExtensionsAndExtras
  4089. (TPasJSONItemObject(JSONArrayItem), Channel);
  4090. Channel.fSampler :=
  4091. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONArrayItem)
  4092. .Properties['sampler'], 'sampler'), Channel.fSampler);
  4093. begin
  4094. TargetItem := Required(TPasJSONItemObject(JSONArrayItem)
  4095. .Properties['target'], 'target');
  4096. if not(assigned(TargetItem) and
  4097. (TargetItem is TPasJSONItemObject)) then
  4098. begin
  4099. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4100. end;
  4101. ProcessExtensionsAndExtras(TPasJSONItemObject(TargetItem),
  4102. Channel.fTarget);
  4103. Channel.fTarget.fPath :=
  4104. TPasJSON.GetString
  4105. (Required(TPasJSONItemObject(TargetItem).Properties['path'],
  4106. 'path'), Channel.fTarget.fPath);
  4107. Channel.fTarget.fNode :=
  4108. TPasJSON.GetInt64(TPasJSONItemObject(TargetItem).Properties
  4109. ['node'], Channel.fTarget.fNode);
  4110. end;
  4111. finally
  4112. result.fChannels.Add(Channel);
  4113. end;
  4114. end;
  4115. end;
  4116. begin
  4117. JSONItem := JSONObject.Properties['samplers'];
  4118. if not(assigned(JSONItem) and (JSONItem is TPasJSONItemArray)) then
  4119. begin
  4120. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4121. end;
  4122. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  4123. begin
  4124. if not(assigned(JSONArrayItem) and
  4125. (JSONArrayItem is TPasJSONItemObject)) then
  4126. begin
  4127. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4128. end;
  4129. Sampler := TAnimation.TSampler.Create(self);
  4130. try
  4131. ProcessExtensionsAndExtras
  4132. (TPasJSONItemObject(JSONArrayItem), Sampler);
  4133. Sampler.fInput :=
  4134. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONArrayItem)
  4135. .Properties['input'], 'input'), Sampler.fInput);
  4136. Sampler.fOutput :=
  4137. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONArrayItem)
  4138. .Properties['output'], 'output'), Sampler.fOutput);
  4139. begin
  4140. InterpolationItem := TPasJSONItemObject(JSONArrayItem)
  4141. .Properties['interpolation'];
  4142. if assigned(InterpolationItem) then
  4143. begin
  4144. if not(InterpolationItem is TPasJSONItemString) then
  4145. begin
  4146. raise EPasGLTFInvalidDocument.Create
  4147. ('Invalid GLTF document');
  4148. end;
  4149. Interpolation :=
  4150. TPasJSON.GetString(InterpolationItem, 'NONE');
  4151. if Interpolation = 'LINEAR' then
  4152. begin
  4153. Sampler.fInterpolation := TAnimation.TSampler.TType.Linear;
  4154. end
  4155. else if Interpolation = 'STEP' then
  4156. begin
  4157. Sampler.fInterpolation := TAnimation.TSampler.TType.Step;
  4158. end
  4159. else if Interpolation = 'CUBICSPLINE' then
  4160. begin
  4161. Sampler.fInterpolation :=
  4162. TAnimation.TSampler.TType.CubicSpline;
  4163. end
  4164. else
  4165. begin
  4166. raise EPasGLTFInvalidDocument.Create
  4167. ('Invalid GLTF document');
  4168. end;
  4169. end;
  4170. end;
  4171. finally
  4172. result.fSamplers.Add(Sampler);
  4173. end;
  4174. end;
  4175. end;
  4176. except
  4177. FreeAndNil(result);
  4178. raise;
  4179. end;
  4180. end;
  4181. var
  4182. JSONArray: TPasJSONItemArray;
  4183. JSONItem: TPasJSONItem;
  4184. begin
  4185. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4186. begin
  4187. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4188. end;
  4189. JSONArray := TPasJSONItemArray(aJSONItem);
  4190. for JSONItem in JSONArray do
  4191. begin
  4192. fAnimations.Add(ProcessAnimation(JSONItem));
  4193. end;
  4194. end;
  4195. procedure ProcessAsset(const aJSONItem: TPasJSONItem);
  4196. var
  4197. JSONObject: TPasJSONItemObject;
  4198. begin
  4199. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4200. begin
  4201. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4202. end;
  4203. JSONObject := TPasJSONItemObject(aJSONItem);
  4204. ProcessExtensionsAndExtras(JSONObject, fAsset);
  4205. fAsset.fCopyright := TPasJSON.GetString(JSONObject.Properties['copyright'],
  4206. fAsset.fCopyright);
  4207. fAsset.fGenerator := TPasJSON.GetString(JSONObject.Properties['generator'],
  4208. fAsset.fGenerator);
  4209. fAsset.fMinVersion := TPasJSON.GetString
  4210. (JSONObject.Properties['minVersion'], fAsset.fMinVersion);
  4211. fAsset.fVersion := TPasJSON.GetString
  4212. (Required(JSONObject.Properties['version'], 'version'), fAsset.fVersion);
  4213. end;
  4214. procedure ProcessBuffers(const aJSONItem: TPasJSONItem);
  4215. function ProcessBuffer(const aJSONItem: TPasJSONItem): TBuffer;
  4216. var
  4217. JSONObject: TPasJSONItemObject;
  4218. begin
  4219. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4220. begin
  4221. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4222. end;
  4223. JSONObject := TPasJSONItemObject(aJSONItem);
  4224. result := TBuffer.Create(self);
  4225. try
  4226. ProcessExtensionsAndExtras(JSONObject, result);
  4227. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4228. result.fName);
  4229. result.fURI := TPasJSON.GetString(JSONObject.Properties['uri'],
  4230. result.fURI);
  4231. result.fByteLength := TPasJSON.GetInt64
  4232. (Required(JSONObject.Properties['byteLength'], 'byteLength'),
  4233. result.fByteLength);
  4234. except
  4235. FreeAndNil(result);
  4236. raise;
  4237. end;
  4238. end;
  4239. var
  4240. JSONArray: TPasJSONItemArray;
  4241. JSONItem: TPasJSONItem;
  4242. begin
  4243. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4244. begin
  4245. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4246. end;
  4247. JSONArray := TPasJSONItemArray(aJSONItem);
  4248. for JSONItem in JSONArray do
  4249. begin
  4250. fBuffers.Add(ProcessBuffer(JSONItem));
  4251. end;
  4252. end;
  4253. procedure ProcessBufferViews(const aJSONItem: TPasJSONItem);
  4254. function ProcessBufferView(const aJSONItem: TPasJSONItem): TBufferView;
  4255. var
  4256. JSONObject: TPasJSONItemObject;
  4257. begin
  4258. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4259. begin
  4260. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4261. end;
  4262. JSONObject := TPasJSONItemObject(aJSONItem);
  4263. result := TBufferView.Create(self);
  4264. try
  4265. ProcessExtensionsAndExtras(JSONObject, result);
  4266. result.fBuffer := TPasJSON.GetInt64
  4267. (Required(JSONObject.Properties['buffer'], 'buffer'), result.fBuffer);
  4268. result.fByteLength := TPasJSON.GetInt64
  4269. (Required(JSONObject.Properties['byteLength'], 'byteLength'),
  4270. result.fByteLength);
  4271. result.fByteOffset := TPasJSON.GetInt64
  4272. (JSONObject.Properties['byteOffset'], result.fByteOffset);
  4273. result.fByteStride := TPasJSON.GetInt64
  4274. (JSONObject.Properties['byteStride'], result.fByteStride);
  4275. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4276. result.fName);
  4277. result.fTarget := TBufferView.TTargetType
  4278. (TPasJSON.GetInt64(JSONObject.Properties['target'],
  4279. TPasGLTFInt64(result.fTarget)));
  4280. except
  4281. FreeAndNil(result);
  4282. raise;
  4283. end;
  4284. end;
  4285. var
  4286. JSONArray: TPasJSONItemArray;
  4287. JSONItem: TPasJSONItem;
  4288. begin
  4289. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4290. begin
  4291. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4292. end;
  4293. JSONArray := TPasJSONItemArray(aJSONItem);
  4294. for JSONItem in JSONArray do
  4295. begin
  4296. fBufferViews.Add(ProcessBufferView(JSONItem));
  4297. end;
  4298. end;
  4299. procedure ProcessCameras(const aJSONItem: TPasJSONItem);
  4300. function ProcessCamera(const aJSONItem: TPasJSONItem): TCamera;
  4301. var
  4302. JSONObject: TPasJSONItemObject;
  4303. JSONItem: TPasJSONItem;
  4304. Type_: TPasGLTFUTF8String;
  4305. begin
  4306. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4307. begin
  4308. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4309. end;
  4310. JSONObject := TPasJSONItemObject(aJSONItem);
  4311. result := TCamera.Create(self);
  4312. try
  4313. ProcessExtensionsAndExtras(JSONObject, result);
  4314. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4315. result.fName);
  4316. begin
  4317. Type_ := TPasJSON.GetString(Required(JSONObject.Properties['type'],
  4318. 'type'), 'none');
  4319. if Type_ = 'orthographic' then
  4320. begin
  4321. result.fType := TCamera.TType.Orthographic;
  4322. end
  4323. else if Type_ = 'perspective' then
  4324. begin
  4325. result.fType := TCamera.TType.Perspective;
  4326. end
  4327. else
  4328. begin
  4329. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4330. end;
  4331. end;
  4332. case result.fType of
  4333. TCamera.TType.Orthographic:
  4334. begin
  4335. JSONItem := JSONObject.Properties['orthographic'];
  4336. if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject))
  4337. then
  4338. begin
  4339. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4340. end;
  4341. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
  4342. result.fOrthographic);
  4343. result.fOrthographic.fXMag :=
  4344. TPasJSON.GetNumber
  4345. (Required(TPasJSONItemObject(JSONItem).Properties['xmag'],
  4346. 'xmag'), result.fOrthographic.fXMag);
  4347. result.fOrthographic.fYMag :=
  4348. TPasJSON.GetNumber
  4349. (Required(TPasJSONItemObject(JSONItem).Properties['ymag'],
  4350. 'ymag'), result.fOrthographic.fYMag);
  4351. result.fOrthographic.fZNear :=
  4352. TPasJSON.GetNumber
  4353. (Required(TPasJSONItemObject(JSONItem).Properties['znear'],
  4354. 'znear'), result.fOrthographic.fZNear);
  4355. result.fOrthographic.fZFar :=
  4356. TPasJSON.GetNumber
  4357. (Required(TPasJSONItemObject(JSONItem).Properties['zfar'],
  4358. 'zfar'), result.fOrthographic.fZFar);
  4359. end;
  4360. TCamera.TType.Perspective:
  4361. begin
  4362. JSONItem := JSONObject.Properties['perspective'];
  4363. if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject))
  4364. then
  4365. begin
  4366. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4367. end;
  4368. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
  4369. result.fPerspective);
  4370. result.fPerspective.fAspectRatio :=
  4371. TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
  4372. ['aspectRatio'], result.fPerspective.fAspectRatio);
  4373. result.fPerspective.fYFov :=
  4374. TPasJSON.GetNumber
  4375. (Required(TPasJSONItemObject(JSONItem).Properties['yfov'],
  4376. 'yfov'), result.fPerspective.fYFov);
  4377. result.fPerspective.fZNear :=
  4378. TPasJSON.GetNumber
  4379. (Required(TPasJSONItemObject(JSONItem).Properties['znear'],
  4380. 'znear'), result.fPerspective.fZNear);
  4381. result.fPerspective.fZFar :=
  4382. TPasJSON.GetNumber
  4383. (Required(TPasJSONItemObject(JSONItem).Properties['zfar'],
  4384. 'zfar'), result.fPerspective.fZFar);
  4385. end;
  4386. else
  4387. begin
  4388. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4389. end;
  4390. end;
  4391. except
  4392. FreeAndNil(result);
  4393. raise;
  4394. end;
  4395. end;
  4396. var
  4397. JSONArray: TPasJSONItemArray;
  4398. JSONItem: TPasJSONItem;
  4399. begin
  4400. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4401. begin
  4402. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4403. end;
  4404. JSONArray := TPasJSONItemArray(aJSONItem);
  4405. for JSONItem in JSONArray do
  4406. begin
  4407. fCameras.Add(ProcessCamera(JSONItem));
  4408. end;
  4409. end;
  4410. procedure ProcessImages(const aJSONItem: TPasJSONItem);
  4411. function ProcessImage(const aJSONItem: TPasJSONItem): TImage;
  4412. var
  4413. JSONObject: TPasJSONItemObject;
  4414. begin
  4415. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4416. begin
  4417. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4418. end;
  4419. JSONObject := TPasJSONItemObject(aJSONItem);
  4420. result := TImage.Create(self);
  4421. try
  4422. ProcessExtensionsAndExtras(JSONObject, result);
  4423. result.fBufferView := TPasJSON.GetInt64
  4424. (JSONObject.Properties['bufferView'], result.fBufferView);
  4425. result.fMimeType := TPasJSON.GetString
  4426. (JSONObject.Properties['mimeType'], result.fMimeType);
  4427. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4428. result.fName);
  4429. result.fURI := TPasJSON.GetString(JSONObject.Properties['uri'],
  4430. result.fURI);
  4431. except
  4432. FreeAndNil(result);
  4433. raise;
  4434. end;
  4435. end;
  4436. var
  4437. JSONArray: TPasJSONItemArray;
  4438. JSONItem: TPasJSONItem;
  4439. begin
  4440. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4441. begin
  4442. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4443. end;
  4444. JSONArray := TPasJSONItemArray(aJSONItem);
  4445. for JSONItem in JSONArray do
  4446. begin
  4447. fImages.Add(ProcessImage(JSONItem));
  4448. end;
  4449. end;
  4450. procedure ProcessMaterials(const aJSONItem: TPasJSONItem);
  4451. function ProcessMaterial(const aJSONItem: TPasJSONItem): TMaterial;
  4452. var
  4453. JSONObject: TPasJSONItemObject;
  4454. JSONItem, JSONSubItem: TPasJSONItem;
  4455. Mode: TPasGLTFUTF8String;
  4456. Index: TPasGLTFSizeInt;
  4457. begin
  4458. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4459. begin
  4460. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4461. end;
  4462. JSONObject := TPasJSONItemObject(aJSONItem);
  4463. result := TMaterial.Create(self);
  4464. try
  4465. ProcessExtensionsAndExtras(JSONObject, result);
  4466. result.fAlphaCutOff := TPasJSON.GetNumber
  4467. (JSONObject.Properties['alphaCutoff'], result.fAlphaCutOff);
  4468. begin
  4469. JSONItem := JSONObject.Properties['alphaMode'];
  4470. if assigned(JSONItem) then
  4471. begin
  4472. Mode := TPasJSON.GetString(JSONItem, 'NONE');
  4473. if Mode = 'OPAQUE' then
  4474. begin
  4475. result.fAlphaMode := TMaterial.TAlphaMode.Opaque;
  4476. end
  4477. else if Mode = 'MASK' then
  4478. begin
  4479. result.fAlphaMode := TMaterial.TAlphaMode.Mask;
  4480. end
  4481. else if Mode = 'BLEND' then
  4482. begin
  4483. result.fAlphaMode := TMaterial.TAlphaMode.Blend;
  4484. end
  4485. else
  4486. begin
  4487. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4488. end;
  4489. end;
  4490. end;
  4491. result.fDoubleSided := TPasJSON.GetBoolean
  4492. (JSONObject.Properties['doubleSided'], result.fDoubleSided);
  4493. begin
  4494. JSONItem := JSONObject.Properties['emissiveFactor'];
  4495. if assigned(JSONItem) then
  4496. begin
  4497. if not((JSONItem is TPasJSONItemArray) and
  4498. (TPasJSONItemArray(JSONItem).Count = 3)) then
  4499. begin
  4500. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4501. end;
  4502. for Index := 0 to 2 do
  4503. begin
  4504. result.fEmissiveFactor[Index] :=
  4505. TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
  4506. result.fEmissiveFactor[Index]);
  4507. end;
  4508. end;
  4509. end;
  4510. begin
  4511. JSONItem := JSONObject.Properties['emissiveTexture'];
  4512. if assigned(JSONItem) then
  4513. begin
  4514. if not(JSONItem is TPasJSONItemObject) then
  4515. begin
  4516. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4517. end;
  4518. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
  4519. result.fEmissiveTexture);
  4520. result.fEmissiveTexture.fIndex :=
  4521. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
  4522. .Properties['index'], 'index'), result.fEmissiveTexture.fIndex);
  4523. result.fEmissiveTexture.fTexCoord :=
  4524. TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
  4525. ['texCoord'], result.fEmissiveTexture.fTexCoord);
  4526. end;
  4527. end;
  4528. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4529. result.fName);
  4530. begin
  4531. JSONItem := JSONObject.Properties['normalTexture'];
  4532. if assigned(JSONItem) then
  4533. begin
  4534. if not(JSONItem is TPasJSONItemObject) then
  4535. begin
  4536. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4537. end;
  4538. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
  4539. result.fNormalTexture);
  4540. result.fNormalTexture.fIndex :=
  4541. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
  4542. .Properties['index'], 'index'), result.fNormalTexture.fIndex);
  4543. result.fNormalTexture.fTexCoord :=
  4544. TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
  4545. ['texCoord'], result.fNormalTexture.fTexCoord);
  4546. result.fNormalTexture.fScale :=
  4547. TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
  4548. ['scale'], result.fNormalTexture.fScale);
  4549. end;
  4550. end;
  4551. begin
  4552. JSONItem := JSONObject.Properties['occlusionTexture'];
  4553. if assigned(JSONItem) then
  4554. begin
  4555. if not(JSONItem is TPasJSONItemObject) then
  4556. begin
  4557. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4558. end;
  4559. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
  4560. result.fOcclusionTexture);
  4561. result.fOcclusionTexture.fIndex :=
  4562. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
  4563. .Properties['index'], 'index'), result.fOcclusionTexture.fIndex);
  4564. result.fOcclusionTexture.fTexCoord :=
  4565. TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
  4566. ['texCoord'], result.fOcclusionTexture.fTexCoord);
  4567. result.fOcclusionTexture.fStrength :=
  4568. TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
  4569. ['scale'], result.fOcclusionTexture.fStrength);
  4570. end;
  4571. end;
  4572. begin
  4573. JSONItem := JSONObject.Properties['pbrMetallicRoughness'];
  4574. if assigned(JSONItem) then
  4575. begin
  4576. if not(JSONItem is TPasJSONItemObject) then
  4577. begin
  4578. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4579. end;
  4580. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
  4581. result.fPBRMetallicRoughness);
  4582. begin
  4583. JSONSubItem := TPasJSONItemObject(JSONItem).Properties
  4584. ['baseColorFactor'];
  4585. if assigned(JSONSubItem) then
  4586. begin
  4587. if not((JSONSubItem is TPasJSONItemArray) and
  4588. (TPasJSONItemArray(JSONSubItem).Count = 4)) then
  4589. begin
  4590. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4591. end;
  4592. for Index := 0 to 3 do
  4593. begin
  4594. result.fPBRMetallicRoughness.fBaseColorFactor[Index] :=
  4595. TPasJSON.GetNumber(TPasJSONItemArray(JSONSubItem)
  4596. .Items[Index],
  4597. result.fPBRMetallicRoughness.fBaseColorFactor[Index]);
  4598. end;
  4599. end;
  4600. end;
  4601. begin
  4602. JSONSubItem := TPasJSONItemObject(JSONItem).Properties
  4603. ['baseColorTexture'];
  4604. if assigned(JSONSubItem) then
  4605. begin
  4606. if not(JSONSubItem is TPasJSONItemObject) then
  4607. begin
  4608. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4609. end;
  4610. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONSubItem),
  4611. result.fPBRMetallicRoughness.fBaseColorTexture);
  4612. result.fPBRMetallicRoughness.fBaseColorTexture.fIndex :=
  4613. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONSubItem)
  4614. .Properties['index'], 'index'),
  4615. result.fPBRMetallicRoughness.fBaseColorTexture.fIndex);
  4616. result.fPBRMetallicRoughness.fBaseColorTexture.fTexCoord :=
  4617. TPasJSON.GetInt64(TPasJSONItemObject(JSONSubItem)
  4618. .Properties['texCoord'],
  4619. result.fPBRMetallicRoughness.fBaseColorTexture.fTexCoord);
  4620. end;
  4621. end;
  4622. result.fPBRMetallicRoughness.fMetallicFactor :=
  4623. TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
  4624. ['metallicFactor'], result.fPBRMetallicRoughness.fMetallicFactor);
  4625. begin
  4626. JSONSubItem := TPasJSONItemObject(JSONItem).Properties
  4627. ['metallicRoughnessTexture'];
  4628. if assigned(JSONSubItem) then
  4629. begin
  4630. if not(JSONSubItem is TPasJSONItemObject) then
  4631. begin
  4632. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4633. end;
  4634. ProcessExtensionsAndExtras(TPasJSONItemObject(JSONSubItem),
  4635. result.fPBRMetallicRoughness.fMetallicRoughnessTexture);
  4636. result.fPBRMetallicRoughness.fMetallicRoughnessTexture.fIndex :=
  4637. TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONSubItem)
  4638. .Properties['index'], 'index'),
  4639. result.fPBRMetallicRoughness.
  4640. fMetallicRoughnessTexture.fIndex);
  4641. result.fPBRMetallicRoughness.fMetallicRoughnessTexture.fTexCoord
  4642. := TPasJSON.GetInt64(TPasJSONItemObject(JSONSubItem)
  4643. .Properties['texCoord'],
  4644. result.fPBRMetallicRoughness.fMetallicRoughnessTexture.
  4645. fTexCoord);
  4646. end;
  4647. end;
  4648. result.fPBRMetallicRoughness.fRoughnessFactor :=
  4649. TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
  4650. ['roughnessFactor'],
  4651. result.fPBRMetallicRoughness.fRoughnessFactor);
  4652. end;
  4653. end;
  4654. except
  4655. FreeAndNil(result);
  4656. raise;
  4657. end;
  4658. end;
  4659. var
  4660. JSONArray: TPasJSONItemArray;
  4661. JSONItem: TPasJSONItem;
  4662. begin
  4663. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4664. begin
  4665. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4666. end;
  4667. JSONArray := TPasJSONItemArray(aJSONItem);
  4668. for JSONItem in JSONArray do
  4669. begin
  4670. fMaterials.Add(ProcessMaterial(JSONItem));
  4671. end;
  4672. end;
  4673. procedure ProcessMeshes(const aJSONItem: TPasJSONItem);
  4674. function ProcessMesh(const aJSONItem: TPasJSONItem): TMesh;
  4675. function ProcessPrimitive(const aJSONItem: TPasJSONItem)
  4676. : TMesh.TPrimitive;
  4677. var
  4678. JSONObject: TPasJSONItemObject;
  4679. JSONItem, JSONArrayItem: TPasJSONItem;
  4680. JSONObjectProperty: TPasJSONItemObjectProperty;
  4681. Attributes: TAttributes;
  4682. begin
  4683. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4684. begin
  4685. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4686. end;
  4687. JSONObject := TPasJSONItemObject(aJSONItem);
  4688. result := TMesh.TPrimitive.Create(self);
  4689. try
  4690. ProcessExtensionsAndExtras(JSONObject, result);
  4691. begin
  4692. JSONItem := Required(JSONObject.Properties['attributes'],
  4693. 'attributes');
  4694. if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject)) then
  4695. begin
  4696. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4697. end;
  4698. for JSONObjectProperty in TPasJSONItemObject(JSONItem) do
  4699. begin
  4700. result.fAttributes.Add(JSONObjectProperty.Key,
  4701. TPasJSON.GetInt64(JSONObjectProperty.Value, 0));
  4702. end;
  4703. end;
  4704. result.fIndices := TPasJSON.GetInt64(JSONObject.Properties['indices'],
  4705. result.fIndices);
  4706. result.fMaterial := TPasJSON.GetInt64
  4707. (JSONObject.Properties['material'], result.fMaterial);
  4708. result.fMode := TMesh.TPrimitive.TMode
  4709. (TPasJSON.GetInt64(JSONObject.Properties['mode'],
  4710. TPasGLTFInt64(result.fMode)));
  4711. begin
  4712. JSONItem := JSONObject.Properties['targets'];
  4713. if assigned(JSONItem) then
  4714. begin
  4715. if not(JSONItem is TPasJSONItemArray) then
  4716. begin
  4717. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4718. end;
  4719. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  4720. begin
  4721. if not(assigned(JSONArrayItem) and
  4722. (JSONArrayItem is TPasJSONItemObject)) then
  4723. begin
  4724. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4725. end;
  4726. Attributes := TAttributes.Create(-1);
  4727. try
  4728. for JSONObjectProperty in TPasJSONItemObject(JSONArrayItem) do
  4729. begin
  4730. Attributes.Add(JSONObjectProperty.Key,
  4731. TPasJSON.GetInt64(JSONObjectProperty.Value, 0));
  4732. end;
  4733. finally
  4734. result.fTargets.Add(Attributes);
  4735. end;
  4736. end;
  4737. end;
  4738. end;
  4739. except
  4740. FreeAndNil(result);
  4741. raise;
  4742. end;
  4743. end;
  4744. var
  4745. JSONObject: TPasJSONItemObject;
  4746. JSONItem, JSONArrayItem: TPasJSONItem;
  4747. begin
  4748. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4749. begin
  4750. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4751. end;
  4752. JSONObject := TPasJSONItemObject(aJSONItem);
  4753. result := TMesh.Create(self);
  4754. try
  4755. ProcessExtensionsAndExtras(JSONObject, result);
  4756. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4757. result.fName);
  4758. begin
  4759. JSONItem := Required(JSONObject.Properties['primitives'],
  4760. 'primitives');
  4761. if not(assigned(JSONItem) and (JSONItem is TPasJSONItemArray)) then
  4762. begin
  4763. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4764. end;
  4765. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  4766. begin
  4767. result.fPrimitives.Add(ProcessPrimitive(JSONArrayItem));
  4768. end;
  4769. end;
  4770. begin
  4771. JSONItem := JSONObject.Properties['weights'];
  4772. if assigned(JSONItem) then
  4773. begin
  4774. if not(JSONItem is TPasJSONItemArray) then
  4775. begin
  4776. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4777. end;
  4778. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  4779. begin
  4780. result.fWeights.Add(TPasJSON.GetNumber(JSONArrayItem, 0.0));
  4781. end;
  4782. end;
  4783. end;
  4784. except
  4785. FreeAndNil(result);
  4786. raise;
  4787. end;
  4788. end;
  4789. var
  4790. JSONArray: TPasJSONItemArray;
  4791. JSONItem: TPasJSONItem;
  4792. begin
  4793. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4794. begin
  4795. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4796. end;
  4797. JSONArray := TPasJSONItemArray(aJSONItem);
  4798. for JSONItem in JSONArray do
  4799. begin
  4800. fMeshes.Add(ProcessMesh(JSONItem));
  4801. end;
  4802. end;
  4803. procedure ProcessNodes(const aJSONItem: TPasJSONItem);
  4804. function ProcessNode(const aJSONItem: TPasJSONItem): TNode;
  4805. var
  4806. JSONObject: TPasJSONItemObject;
  4807. JSONItem, JSONArrayItem: TPasJSONItem;
  4808. Index: TPasGLTFSizeInt;
  4809. begin
  4810. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4811. begin
  4812. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4813. end;
  4814. JSONObject := TPasJSONItemObject(aJSONItem);
  4815. result := TNode.Create(self);
  4816. try
  4817. ProcessExtensionsAndExtras(JSONObject, result);
  4818. result.fCamera := TPasJSON.GetInt64(JSONObject.Properties['camera'],
  4819. result.fCamera);
  4820. begin
  4821. JSONItem := JSONObject.Properties['children'];
  4822. if assigned(JSONItem) then
  4823. begin
  4824. if not(JSONItem is TPasJSONItemArray) then
  4825. begin
  4826. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4827. end;
  4828. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  4829. begin
  4830. result.fChildren.Add(TPasJSON.GetInt64(JSONArrayItem));
  4831. end;
  4832. end;
  4833. end;
  4834. begin
  4835. JSONItem := JSONObject.Properties['matrix'];
  4836. if assigned(JSONItem) then
  4837. begin
  4838. if not((JSONItem is TPasJSONItemArray) and
  4839. (TPasJSONItemArray(JSONItem).Count = 16)) then
  4840. begin
  4841. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4842. end;
  4843. for Index := 0 to 15 do
  4844. begin
  4845. result.fMatrix[Index] :=
  4846. TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
  4847. result.fMatrix[Index]);
  4848. end;
  4849. end;
  4850. end;
  4851. result.fMesh := TPasJSON.GetInt64(JSONObject.Properties['mesh'],
  4852. result.fMesh);
  4853. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4854. result.fName);
  4855. begin
  4856. JSONItem := JSONObject.Properties['rotation'];
  4857. if assigned(JSONItem) then
  4858. begin
  4859. if not((JSONItem is TPasJSONItemArray) and
  4860. (TPasJSONItemArray(JSONItem).Count = 4)) then
  4861. begin
  4862. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4863. end;
  4864. for Index := 0 to 3 do
  4865. begin
  4866. result.fRotation[Index] :=
  4867. TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
  4868. result.fRotation[Index]);
  4869. end;
  4870. end;
  4871. end;
  4872. begin
  4873. JSONItem := JSONObject.Properties['scale'];
  4874. if assigned(JSONItem) then
  4875. begin
  4876. if not((JSONItem is TPasJSONItemArray) and
  4877. (TPasJSONItemArray(JSONItem).Count = 3)) then
  4878. begin
  4879. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4880. end;
  4881. for Index := 0 to 2 do
  4882. begin
  4883. result.fScale[Index] :=
  4884. TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
  4885. result.fScale[Index]);
  4886. end;
  4887. end;
  4888. end;
  4889. result.fSkin := TPasJSON.GetInt64(JSONObject.Properties['skin'],
  4890. result.fSkin);
  4891. begin
  4892. JSONItem := JSONObject.Properties['translation'];
  4893. if assigned(JSONItem) then
  4894. begin
  4895. if not((JSONItem is TPasJSONItemArray) and
  4896. (TPasJSONItemArray(JSONItem).Count = 3)) then
  4897. begin
  4898. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4899. end;
  4900. for Index := 0 to 2 do
  4901. begin
  4902. result.fTranslation[Index] :=
  4903. TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
  4904. result.fTranslation[Index]);
  4905. end;
  4906. end;
  4907. end;
  4908. except
  4909. FreeAndNil(result);
  4910. raise;
  4911. end;
  4912. end;
  4913. var
  4914. JSONArray: TPasJSONItemArray;
  4915. JSONItem: TPasJSONItem;
  4916. begin
  4917. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4918. begin
  4919. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4920. end;
  4921. JSONArray := TPasJSONItemArray(aJSONItem);
  4922. for JSONItem in JSONArray do
  4923. begin
  4924. fNodes.Add(ProcessNode(JSONItem));
  4925. end;
  4926. end;
  4927. procedure ProcessSamplers(const aJSONItem: TPasJSONItem);
  4928. function ProcessSampler(const aJSONItem: TPasJSONItem): TSampler;
  4929. var
  4930. JSONObject: TPasJSONItemObject;
  4931. begin
  4932. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4933. begin
  4934. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4935. end;
  4936. JSONObject := TPasJSONItemObject(aJSONItem);
  4937. result := TSampler.Create(self);
  4938. try
  4939. ProcessExtensionsAndExtras(JSONObject, result);
  4940. result.fMagFilter := TSampler.TMagFilter
  4941. (TPasJSON.GetInt64(JSONObject.Properties['magFilter'],
  4942. TPasGLTFInt64(result.fMagFilter)));
  4943. result.fMinFilter := TSampler.TMinFilter
  4944. (TPasJSON.GetInt64(JSONObject.Properties['minFilter'],
  4945. TPasGLTFInt64(result.fMinFilter)));
  4946. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4947. result.fName);
  4948. result.fWrapS := TSampler.TWrappingMode
  4949. (TPasJSON.GetInt64(JSONObject.Properties['wrapS'],
  4950. TPasGLTFInt64(result.fWrapS)));
  4951. result.fWrapT := TSampler.TWrappingMode
  4952. (TPasJSON.GetInt64(JSONObject.Properties['wrapT'],
  4953. TPasGLTFInt64(result.fWrapT)));
  4954. except
  4955. FreeAndNil(result);
  4956. raise;
  4957. end;
  4958. end;
  4959. var
  4960. JSONArray: TPasJSONItemArray;
  4961. JSONItem: TPasJSONItem;
  4962. begin
  4963. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  4964. begin
  4965. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4966. end;
  4967. JSONArray := TPasJSONItemArray(aJSONItem);
  4968. for JSONItem in JSONArray do
  4969. begin
  4970. fSamplers.Add(ProcessSampler(JSONItem));
  4971. end;
  4972. end;
  4973. procedure ProcessScenes(const aJSONItem: TPasJSONItem);
  4974. function ProcessScene(const aJSONItem: TPasJSONItem): TScene;
  4975. var
  4976. JSONObject: TPasJSONItemObject;
  4977. JSONItem, JSONArrayItem: TPasJSONItem;
  4978. begin
  4979. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  4980. begin
  4981. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4982. end;
  4983. JSONObject := TPasJSONItemObject(aJSONItem);
  4984. result := TScene.Create(self);
  4985. try
  4986. ProcessExtensionsAndExtras(JSONObject, result);
  4987. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  4988. result.fName);
  4989. begin
  4990. JSONItem := JSONObject.Properties['nodes'];
  4991. if assigned(JSONItem) then
  4992. begin
  4993. if not(JSONItem is TPasJSONItemArray) then
  4994. begin
  4995. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  4996. end;
  4997. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  4998. begin
  4999. result.fNodes.Add(TPasJSON.GetInt64(JSONArrayItem));
  5000. end;
  5001. end;
  5002. end;
  5003. except
  5004. FreeAndNil(result);
  5005. raise;
  5006. end;
  5007. end;
  5008. var
  5009. JSONArray: TPasJSONItemArray;
  5010. JSONItem: TPasJSONItem;
  5011. begin
  5012. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  5013. begin
  5014. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  5015. end;
  5016. JSONArray := TPasJSONItemArray(aJSONItem);
  5017. for JSONItem in JSONArray do
  5018. begin
  5019. fScenes.Add(ProcessScene(JSONItem));
  5020. end;
  5021. end;
  5022. procedure ProcessSkins(const aJSONItem: TPasJSONItem);
  5023. function ProcessSkin(const aJSONItem: TPasJSONItem): TSkin;
  5024. var
  5025. JSONObject: TPasJSONItemObject;
  5026. JSONItem, JSONArrayItem: TPasJSONItem;
  5027. begin
  5028. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  5029. begin
  5030. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  5031. end;
  5032. JSONObject := TPasJSONItemObject(aJSONItem);
  5033. result := TSkin.Create(self);
  5034. try
  5035. ProcessExtensionsAndExtras(JSONObject, result);
  5036. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  5037. result.fName);
  5038. begin
  5039. JSONItem := Required(JSONObject.Properties['joints']);
  5040. if assigned(JSONItem) then
  5041. begin
  5042. if not(JSONItem is TPasJSONItemArray) then
  5043. begin
  5044. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  5045. end;
  5046. for JSONArrayItem in TPasJSONItemArray(JSONItem) do
  5047. begin
  5048. result.fJoints.Add(TPasJSON.GetInt64(JSONArrayItem));
  5049. end;
  5050. end;
  5051. end;
  5052. result.fInverseBindMatrices :=
  5053. TPasJSON.GetInt64(JSONObject.Properties['inverseBindMatrices'],
  5054. result.fInverseBindMatrices);
  5055. result.fSkeleton := TPasJSON.GetInt64(JSONObject.Properties['skeleton'],
  5056. result.fSkeleton);
  5057. except
  5058. FreeAndNil(result);
  5059. raise;
  5060. end;
  5061. end;
  5062. var
  5063. JSONArray: TPasJSONItemArray;
  5064. JSONItem: TPasJSONItem;
  5065. begin
  5066. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  5067. begin
  5068. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  5069. end;
  5070. JSONArray := TPasJSONItemArray(aJSONItem);
  5071. for JSONItem in JSONArray do
  5072. begin
  5073. fSkins.Add(ProcessSkin(JSONItem));
  5074. end;
  5075. end;
  5076. procedure ProcessTextures(const aJSONItem: TPasJSONItem);
  5077. function ProcessTexture(const aJSONItem: TPasJSONItem): TTexture;
  5078. var
  5079. JSONObject: TPasJSONItemObject;
  5080. begin
  5081. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
  5082. begin
  5083. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  5084. end;
  5085. JSONObject := TPasJSONItemObject(aJSONItem);
  5086. result := TTexture.Create(self);
  5087. try
  5088. ProcessExtensionsAndExtras(JSONObject, result);
  5089. result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
  5090. result.fName);
  5091. result.fSampler := TPasJSON.GetInt64(JSONObject.Properties['sampler'],
  5092. result.fSampler);
  5093. result.fSource := TPasJSON.GetInt64(JSONObject.Properties['source'],
  5094. result.fSource);
  5095. except
  5096. FreeAndNil(result);
  5097. raise;
  5098. end;
  5099. end;
  5100. var
  5101. JSONArray: TPasJSONItemArray;
  5102. JSONItem: TPasJSONItem;
  5103. begin
  5104. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  5105. begin
  5106. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  5107. end;
  5108. JSONArray := TPasJSONItemArray(aJSONItem);
  5109. for JSONItem in JSONArray do
  5110. begin
  5111. fTextures.Add(ProcessTexture(JSONItem));
  5112. end;
  5113. end;
  5114. procedure ProcessStringList(const aJSONItem: TPasJSONItem;
  5115. const aStrings: TStrings);
  5116. var
  5117. JSONArray: TPasJSONItemArray;
  5118. JSONItem: TPasJSONItem;
  5119. begin
  5120. if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
  5121. begin
  5122. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  5123. end;
  5124. JSONArray := TPasJSONItemArray(aJSONItem);
  5125. for JSONItem in JSONArray do
  5126. begin
  5127. aStrings.Add(TPasJSON.GetString(JSONItem, ''));
  5128. end;
  5129. end;
  5130. var
  5131. JSONObject: TPasJSONItemObject;
  5132. JSONObjectProperty: TPasJSONItemObjectProperty;
  5133. HasAsset: boolean;
  5134. begin
  5135. if not(assigned(aJSONRootItem) and (aJSONRootItem is TPasJSONItemObject)) then
  5136. begin
  5137. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  5138. end;
  5139. JSONObject := TPasJSONItemObject(aJSONRootItem);
  5140. ProcessExtensionsAndExtras(JSONObject, self);
  5141. HasAsset := false;
  5142. for JSONObjectProperty in JSONObject do
  5143. begin
  5144. if JSONObjectProperty.Key = 'accessors' then
  5145. begin
  5146. ProcessAccessors(JSONObjectProperty.Value);
  5147. end
  5148. else if JSONObjectProperty.Key = 'animations' then
  5149. begin
  5150. ProcessAnimations(JSONObjectProperty.Value);
  5151. end
  5152. else if JSONObjectProperty.Key = 'asset' then
  5153. begin
  5154. HasAsset := true;
  5155. ProcessAsset(JSONObjectProperty.Value);
  5156. end
  5157. else if JSONObjectProperty.Key = 'buffers' then
  5158. begin
  5159. ProcessBuffers(JSONObjectProperty.Value);
  5160. end
  5161. else if JSONObjectProperty.Key = 'bufferViews' then
  5162. begin
  5163. ProcessBufferViews(JSONObjectProperty.Value);
  5164. end
  5165. else if JSONObjectProperty.Key = 'cameras' then
  5166. begin
  5167. ProcessCameras(JSONObjectProperty.Value);
  5168. end
  5169. else if JSONObjectProperty.Key = 'images' then
  5170. begin
  5171. ProcessImages(JSONObjectProperty.Value);
  5172. end
  5173. else if JSONObjectProperty.Key = 'materials' then
  5174. begin
  5175. ProcessMaterials(JSONObjectProperty.Value);
  5176. end
  5177. else if JSONObjectProperty.Key = 'meshes' then
  5178. begin
  5179. ProcessMeshes(JSONObjectProperty.Value);
  5180. end
  5181. else if JSONObjectProperty.Key = 'nodes' then
  5182. begin
  5183. ProcessNodes(JSONObjectProperty.Value);
  5184. end
  5185. else if JSONObjectProperty.Key = 'samplers' then
  5186. begin
  5187. ProcessSamplers(JSONObjectProperty.Value);
  5188. end
  5189. else if JSONObjectProperty.Key = 'scene' then
  5190. begin
  5191. fScene := TPasJSON.GetInt64(JSONObjectProperty.Value, fScene);
  5192. end
  5193. else if JSONObjectProperty.Key = 'scenes' then
  5194. begin
  5195. ProcessScenes(JSONObjectProperty.Value);
  5196. end
  5197. else if JSONObjectProperty.Key = 'skins' then
  5198. begin
  5199. ProcessSkins(JSONObjectProperty.Value);
  5200. end
  5201. else if JSONObjectProperty.Key = 'textures' then
  5202. begin
  5203. ProcessTextures(JSONObjectProperty.Value);
  5204. end
  5205. else if JSONObjectProperty.Key = 'extensionsUsed' then
  5206. begin
  5207. ProcessStringList(JSONObjectProperty.Value, fExtensionsUsed);
  5208. end
  5209. else if JSONObjectProperty.Key = 'extensionsRequired' then
  5210. begin
  5211. ProcessStringList(JSONObjectProperty.Value, fExtensionsRequired);
  5212. end;
  5213. end;
  5214. if not HasAsset then
  5215. begin
  5216. raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
  5217. end;
  5218. LoadURISources;
  5219. end;
  5220. procedure TPasGLTF.TDocument.LoadFromBinary(const aStream: TStream);
  5221. var
  5222. GLBHeader: TGLBHeader;
  5223. OtherEndianness: boolean;
  5224. CountBuffers: TPasGLTFSizeInt;
  5225. function SwapEndianness32(const aValue: TPasGLTFUInt32): TPasGLTFUInt32;
  5226. begin
  5227. if OtherEndianness then
  5228. begin
  5229. result := ((aValue and $000000FF) shl 24) or
  5230. ((aValue and $0000FF00) shl 8) or ((aValue and $00FF0000) shr 8) or
  5231. ((aValue and $FF000000) shr 24);
  5232. end
  5233. else
  5234. begin
  5235. result := aValue;
  5236. end;
  5237. end;
  5238. var
  5239. RawJSONRawByteString: TPasJSONRawByteString;
  5240. ChunkHeader: TChunkHeader;
  5241. Stream: TMemoryStream;
  5242. JSONItem: TPasJSONItem;
  5243. begin
  5244. if not(assigned(aStream) and (aStream.Size >= GLBHeaderSize)) then
  5245. begin
  5246. raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
  5247. end;
  5248. if aStream.Read(GLBHeader, SizeOf(TGLBHeader)) <> SizeOf(TGLBHeader) then
  5249. begin
  5250. raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
  5251. end;
  5252. if (GLBHeader.Magic <> GLBHeaderMagicNativeEndianness) and
  5253. (GLBHeader.Magic <> GLBHeaderMagicOtherEndianness) then
  5254. begin
  5255. raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
  5256. end;
  5257. OtherEndianness := GLBHeader.Magic = GLBHeaderMagicOtherEndianness;
  5258. if not((not OtherEndianness) and
  5259. (GLBHeader.JSONChunkHeader.ChunkType = GLBChunkJSONNativeEndianness)) or
  5260. (OtherEndianness and
  5261. (GLBHeader.JSONChunkHeader.ChunkType = GLBChunkJSONOtherEndianness)) then
  5262. begin
  5263. raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
  5264. end;
  5265. GLBHeader.Magic := SwapEndianness32(GLBHeader.Magic);
  5266. GLBHeader.Version := SwapEndianness32(GLBHeader.Version);
  5267. GLBHeader.Length := SwapEndianness32(GLBHeader.Length);
  5268. GLBHeader.JSONChunkHeader.ChunkLength :=
  5269. SwapEndianness32(GLBHeader.JSONChunkHeader.ChunkLength);
  5270. GLBHeader.JSONChunkHeader.ChunkType :=
  5271. SwapEndianness32(GLBHeader.JSONChunkHeader.ChunkType);
  5272. if ((GLBHeader.JSONChunkHeader.ChunkLength + GLBHeaderSize) >
  5273. GLBHeader.Length) or (GLBHeader.JSONChunkHeader.ChunkLength < 2) then
  5274. begin
  5275. raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
  5276. end;
  5277. RawJSONRawByteString := '';
  5278. SetLength(RawJSONRawByteString, GLBHeader.JSONChunkHeader.ChunkLength);
  5279. aStream.ReadBuffer(RawJSONRawByteString[1], Length(RawJSONRawByteString));
  5280. JSONItem := TPasJSON.Parse(RawJSONRawByteString, [], TPasJSONEncoding.UTF8);
  5281. if assigned(JSONItem) then
  5282. begin
  5283. try
  5284. LoadFromJSON(JSONItem);
  5285. finally
  5286. FreeAndNil(JSONItem);
  5287. end;
  5288. end;
  5289. CountBuffers := 0;
  5290. while aStream.Position < aStream.Size do
  5291. begin
  5292. if aStream.Read(ChunkHeader, SizeOf(TChunkHeader)) <> SizeOf(ChunkHeader)
  5293. then
  5294. begin
  5295. raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
  5296. end;
  5297. ChunkHeader.ChunkLength := SwapEndianness32(ChunkHeader.ChunkLength);
  5298. ChunkHeader.ChunkType := SwapEndianness32(ChunkHeader.ChunkType);
  5299. if ChunkHeader.ChunkType = GLBChunkBinaryNativeEndianness then
  5300. begin
  5301. if (ChunkHeader.ChunkType <> GLBChunkBinaryNativeEndianness) or
  5302. ((ChunkHeader.ChunkLength + aStream.Position) > GLBHeader.Length) then
  5303. begin
  5304. raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
  5305. end;
  5306. inc(CountBuffers);
  5307. if fBuffers.Count < CountBuffers then
  5308. begin
  5309. fBuffers.Add(TBuffer.Create(self));
  5310. end;
  5311. Stream := fBuffers[CountBuffers - 1].fData;
  5312. Stream.Clear;
  5313. Stream.CopyFrom(aStream, ChunkHeader.ChunkLength);
  5314. end
  5315. else
  5316. begin
  5317. if (ChunkHeader.ChunkLength + aStream.Position) <= GLBHeader.Length then
  5318. begin
  5319. Stream.Seek(ChunkHeader.ChunkLength, soCurrent);
  5320. end
  5321. else
  5322. begin
  5323. raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
  5324. end;
  5325. end;
  5326. end;
  5327. end;
  5328. procedure TPasGLTF.TDocument.LoadFromStream(const aStream: TStream);
  5329. var
  5330. FirstFourBytes: array [0 .. 3] of TPasGLTFUInt8;
  5331. JSONItem: TPasJSONItem;
  5332. begin
  5333. aStream.ReadBuffer(FirstFourBytes, SizeOf(FirstFourBytes));
  5334. aStream.Seek(-SizeOf(FirstFourBytes), soCurrent);
  5335. if (FirstFourBytes[0] = ord('g')) and (FirstFourBytes[1] = ord('l')) and
  5336. (FirstFourBytes[2] = ord('T')) and (FirstFourBytes[3] = ord('F')) then
  5337. begin
  5338. LoadFromBinary(aStream);
  5339. end
  5340. else
  5341. begin
  5342. JSONItem := TPasJSON.Parse(aStream, [],
  5343. TPasJSONEncoding.AutomaticDetection);
  5344. if assigned(JSONItem) then
  5345. begin
  5346. try
  5347. LoadFromJSON(JSONItem);
  5348. finally
  5349. FreeAndNil(JSONItem);
  5350. end;
  5351. end;
  5352. end;
  5353. end;
  5354. function TPasGLTF.TDocument.SaveToJSON(const aFormatted: boolean = false)
  5355. : TPasJSONRawByteString;
  5356. procedure ProcessExtensionsAndExtras(const aJSONObject: TPasJSONItemObject;
  5357. const aBaseExtensionsExtrasObject: TBaseExtensionsExtrasObject);
  5358. var
  5359. TemporaryObject, TemporarySubObject: TPasJSONItemObject;
  5360. begin
  5361. TemporaryObject := TPasJSONItemObject.Create;
  5362. try
  5363. if aBaseExtensionsExtrasObject.fExtensions.Count > 0 then
  5364. begin
  5365. TemporarySubObject := TPasJSONItemObject.Create;
  5366. try
  5367. TemporarySubObject.Merge(aBaseExtensionsExtrasObject.fExtensions);
  5368. finally
  5369. TemporaryObject.Add('extensions', TemporarySubObject);
  5370. end;
  5371. end;
  5372. if aBaseExtensionsExtrasObject.fExtras.Count > 0 then
  5373. begin
  5374. TemporarySubObject := TPasJSONItemObject.Create;
  5375. try
  5376. TemporarySubObject.Merge(aBaseExtensionsExtrasObject.fExtras);
  5377. finally
  5378. TemporaryObject.Add('extras', TemporarySubObject);
  5379. end;
  5380. end;
  5381. aJSONObject.Merge(TemporaryObject);
  5382. finally
  5383. FreeAndNil(TemporaryObject);
  5384. end;
  5385. end;
  5386. function ProcessAccessors: TPasJSONItemArray;
  5387. function ProcessAccessor(const aObject: TAccessor): TPasJSONItemObject;
  5388. var
  5389. Index: TPasJSONSizeInt;
  5390. JSONArray: TPasJSONItemArray;
  5391. JSONObject, JSONSubObject: TPasJSONItemObject;
  5392. begin
  5393. result := TPasJSONItemObject.Create;
  5394. try
  5395. if aObject.fBufferView >= 0 then
  5396. begin
  5397. result.Add('bufferView',
  5398. TPasJSONItemNumber.Create(aObject.fBufferView));
  5399. end;
  5400. result.Add('byteOffset',
  5401. TPasJSONItemNumber.Create(aObject.fByteOffset));
  5402. if aObject.fComponentType <> TAccessor.TComponentType.None then
  5403. begin
  5404. result.Add('componentType',
  5405. TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fComponentType)));
  5406. end;
  5407. result.Add('count', TPasJSONItemNumber.Create(aObject.fCount));
  5408. if aObject.fMinArray.Count > 0 then
  5409. begin
  5410. JSONArray := TPasJSONItemArray.Create;
  5411. try
  5412. for Index := 0 to aObject.fMinArray.Count - 1 do
  5413. begin
  5414. JSONArray.Add
  5415. (TPasJSONItemNumber.Create(aObject.fMinArray.Items[Index]));
  5416. end;
  5417. finally
  5418. result.Add('min', JSONArray);
  5419. end;
  5420. end;
  5421. if aObject.fMaxArray.Count > 0 then
  5422. begin
  5423. JSONArray := TPasJSONItemArray.Create;
  5424. try
  5425. for Index := 0 to aObject.fMaxArray.Count - 1 do
  5426. begin
  5427. JSONArray.Add
  5428. (TPasJSONItemNumber.Create(aObject.fMaxArray.Items[Index]));
  5429. end;
  5430. finally
  5431. result.Add('max', JSONArray);
  5432. end;
  5433. end;
  5434. if Length(aObject.fName) > 0 then
  5435. begin
  5436. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  5437. end;
  5438. if aObject.Normalized then
  5439. begin
  5440. result.Add('normalized',
  5441. TPasJSONItemBoolean.Create(aObject.Normalized));
  5442. end;
  5443. if not aObject.fSparse.Empty then
  5444. begin
  5445. JSONObject := TPasJSONItemObject.Create;
  5446. try
  5447. if aObject.fSparse.fCount >= 0 then
  5448. begin
  5449. JSONObject.Add('count',
  5450. TPasJSONItemNumber.Create(aObject.fSparse.fCount));
  5451. end;
  5452. if not aObject.fSparse.fIndices.Empty then
  5453. begin
  5454. JSONSubObject := TPasJSONItemObject.Create;
  5455. try
  5456. if aObject.fSparse.fIndices.fComponentType <>
  5457. TAccessor.TComponentType.None then
  5458. begin
  5459. JSONSubObject.Add('componentType',
  5460. TPasJSONItemNumber.Create
  5461. (TPasGLTFInt64(aObject.fSparse.fIndices.fComponentType)));
  5462. end;
  5463. if aObject.fSparse.fIndices.fBufferView >= 0 then
  5464. begin
  5465. JSONSubObject.Add('bufferView',
  5466. TPasJSONItemNumber.Create
  5467. (aObject.fSparse.fIndices.fBufferView));
  5468. end;
  5469. JSONSubObject.Add('byteOffset',
  5470. TPasJSONItemNumber.Create
  5471. (aObject.fSparse.fIndices.fByteOffset));
  5472. finally
  5473. JSONObject.Add('indices', JSONSubObject);
  5474. end;
  5475. end;
  5476. if not aObject.fSparse.fValues.Empty then
  5477. begin
  5478. JSONSubObject := TPasJSONItemObject.Create;
  5479. try
  5480. if aObject.fSparse.fValues.fBufferView >= 0 then
  5481. begin
  5482. JSONSubObject.Add('bufferView',
  5483. TPasJSONItemNumber.Create
  5484. (aObject.fSparse.fValues.fBufferView));
  5485. end;
  5486. JSONSubObject.Add('byteOffset',
  5487. TPasJSONItemNumber.Create
  5488. (aObject.fSparse.fValues.fByteOffset));
  5489. finally
  5490. JSONObject.Add('values', JSONSubObject);
  5491. end;
  5492. end;
  5493. finally
  5494. result.Add('sparse', JSONObject);
  5495. end;
  5496. end;
  5497. case aObject.fType of
  5498. TPasGLTF.TAccessor.TType.Scalar:
  5499. begin
  5500. result.Add('type', TPasJSONItemString.Create('SCALAR'));
  5501. end;
  5502. TPasGLTF.TAccessor.TType.Vec2:
  5503. begin
  5504. result.Add('type', TPasJSONItemString.Create('VEC2'));
  5505. end;
  5506. TPasGLTF.TAccessor.TType.Vec3:
  5507. begin
  5508. result.Add('type', TPasJSONItemString.Create('VEC3'));
  5509. end;
  5510. TPasGLTF.TAccessor.TType.Vec4:
  5511. begin
  5512. result.Add('type', TPasJSONItemString.Create('VEC4'));
  5513. end;
  5514. TPasGLTF.TAccessor.TType.Mat2:
  5515. begin
  5516. result.Add('type', TPasJSONItemString.Create('MAT2'));
  5517. end;
  5518. TPasGLTF.TAccessor.TType.Mat3:
  5519. begin
  5520. result.Add('type', TPasJSONItemString.Create('MAT3'));
  5521. end;
  5522. TPasGLTF.TAccessor.TType.Mat4:
  5523. begin
  5524. result.Add('type', TPasJSONItemString.Create('MAT4'));
  5525. end;
  5526. end;
  5527. ProcessExtensionsAndExtras(result, aObject);
  5528. except
  5529. FreeAndNil(result);
  5530. raise;
  5531. end;
  5532. end;
  5533. var
  5534. Accessor: TAccessor;
  5535. begin
  5536. result := TPasJSONItemArray.Create;
  5537. try
  5538. for Accessor in fAccessors do
  5539. begin
  5540. result.Add(ProcessAccessor(Accessor));
  5541. end;
  5542. except
  5543. FreeAndNil(result);
  5544. raise;
  5545. end;
  5546. end;
  5547. function ProcessAnimations: TPasJSONItemArray;
  5548. function ProcessAnimation(const aObject: TAnimation): TPasJSONItemObject;
  5549. var
  5550. JSONArray: TPasJSONItemArray;
  5551. JSONObject, JSONSubObject: TPasJSONItemObject;
  5552. Channel: TAnimation.TChannel;
  5553. Sampler: TAnimation.TSampler;
  5554. begin
  5555. result := TPasJSONItemObject.Create;
  5556. try
  5557. if Length(aObject.fName) > 0 then
  5558. begin
  5559. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  5560. end;
  5561. if aObject.fChannels.Count > 0 then
  5562. begin
  5563. JSONArray := TPasJSONItemArray.Create;
  5564. try
  5565. for Channel in aObject.fChannels do
  5566. begin
  5567. JSONObject := TPasJSONItemObject.Create;
  5568. try
  5569. if Channel.fSampler >= 0 then
  5570. begin
  5571. JSONObject.Add('sampler',
  5572. TPasJSONItemNumber.Create(Channel.fSampler));
  5573. end;
  5574. if not Channel.fTarget.Empty then
  5575. begin
  5576. JSONSubObject := TPasJSONItemObject.Create;
  5577. try
  5578. if Channel.fTarget.fNode >= 0 then
  5579. begin
  5580. JSONSubObject.Add('node',
  5581. TPasJSONItemNumber.Create(Channel.fTarget.fNode));
  5582. end;
  5583. if Length(Channel.fTarget.fPath) > 0 then
  5584. begin
  5585. JSONSubObject.Add('path',
  5586. TPasJSONItemString.Create(Channel.fTarget.fPath));
  5587. end;
  5588. ProcessExtensionsAndExtras(JSONSubObject, Channel.fTarget);
  5589. finally
  5590. JSONObject.Add('target', JSONSubObject);
  5591. end;
  5592. end;
  5593. ProcessExtensionsAndExtras(JSONObject, Channel);
  5594. finally
  5595. JSONArray.Add(JSONObject);
  5596. end;
  5597. end;
  5598. finally
  5599. result.Add('channels', JSONArray);
  5600. end;
  5601. end;
  5602. if aObject.fSamplers.Count > 0 then
  5603. begin
  5604. JSONArray := TPasJSONItemArray.Create;
  5605. try
  5606. for Sampler in aObject.fSamplers do
  5607. begin
  5608. JSONObject := TPasJSONItemObject.Create;
  5609. try
  5610. if Sampler.fInput >= 0 then
  5611. begin
  5612. JSONObject.Add('input',
  5613. TPasJSONItemNumber.Create(Sampler.fInput));
  5614. end;
  5615. if Sampler.fOutput >= 0 then
  5616. begin
  5617. JSONObject.Add('output',
  5618. TPasJSONItemNumber.Create(Sampler.fOutput));
  5619. end;
  5620. case Sampler.fInterpolation of
  5621. TPasGLTF.TAnimation.TSampler.TType.Linear:
  5622. begin
  5623. JSONObject.Add('interpolation',
  5624. TPasJSONItemString.Create('LINEAR'));
  5625. end;
  5626. TPasGLTF.TAnimation.TSampler.TType.Step:
  5627. begin
  5628. JSONObject.Add('interpolation',
  5629. TPasJSONItemString.Create('STEP'));
  5630. end;
  5631. TPasGLTF.TAnimation.TSampler.TType.CubicSpline:
  5632. begin
  5633. JSONObject.Add('interpolation',
  5634. TPasJSONItemString.Create('CUBICSPLINE'));
  5635. end;
  5636. else
  5637. begin
  5638. Assert(false);
  5639. end;
  5640. end;
  5641. finally
  5642. JSONArray.Add(JSONObject);
  5643. end;
  5644. end;
  5645. finally
  5646. result.Add('samplers', JSONArray);
  5647. end;
  5648. end;
  5649. ProcessExtensionsAndExtras(result, aObject);
  5650. except
  5651. FreeAndNil(result);
  5652. raise;
  5653. end;
  5654. end;
  5655. var
  5656. Animation: TAnimation;
  5657. begin
  5658. result := TPasJSONItemArray.Create;
  5659. try
  5660. for Animation in fAnimations do
  5661. begin
  5662. result.Add(ProcessAnimation(Animation));
  5663. end;
  5664. except
  5665. FreeAndNil(result);
  5666. raise;
  5667. end;
  5668. end;
  5669. function ProcessAsset: TPasJSONItemObject;
  5670. begin
  5671. result := TPasJSONItemObject.Create;
  5672. try
  5673. if Length(fAsset.fCopyright) > 0 then
  5674. begin
  5675. result.Add('copyright', TPasJSONItemString.Create(fAsset.fCopyright));
  5676. end;
  5677. if Length(fAsset.fGenerator) > 0 then
  5678. begin
  5679. result.Add('generator', TPasJSONItemString.Create(fAsset.fGenerator));
  5680. end;
  5681. if Length(fAsset.fMinVersion) > 0 then
  5682. begin
  5683. result.Add('minVersion', TPasJSONItemString.Create(fAsset.fMinVersion));
  5684. end;
  5685. result.Add('version', TPasJSONItemString.Create(fAsset.fVersion));
  5686. ProcessExtensionsAndExtras(result, fAsset);
  5687. except
  5688. FreeAndNil(result);
  5689. raise;
  5690. end;
  5691. end;
  5692. function ProcessBuffers: TPasJSONItemArray;
  5693. function ProcessBuffer(const aObject: TBuffer): TPasJSONItemObject;
  5694. begin
  5695. result := TPasJSONItemObject.Create;
  5696. try
  5697. if Length(aObject.fName) > 0 then
  5698. begin
  5699. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  5700. end;
  5701. if Length(aObject.fURI) > 0 then
  5702. begin
  5703. result.Add('uri', TPasJSONItemString.Create(aObject.fURI));
  5704. end;
  5705. result.Add('byteLength',
  5706. TPasJSONItemNumber.Create(aObject.fByteLength));
  5707. ProcessExtensionsAndExtras(result, aObject);
  5708. except
  5709. FreeAndNil(result);
  5710. raise;
  5711. end;
  5712. end;
  5713. var
  5714. Buffer: TBuffer;
  5715. begin
  5716. result := TPasJSONItemArray.Create;
  5717. try
  5718. for Buffer in fBuffers do
  5719. begin
  5720. result.Add(ProcessBuffer(Buffer));
  5721. end;
  5722. except
  5723. FreeAndNil(result);
  5724. raise;
  5725. end;
  5726. end;
  5727. function ProcessBufferViews: TPasJSONItemArray;
  5728. function ProcessBufferView(const aObject: TBufferView): TPasJSONItemObject;
  5729. begin
  5730. result := TPasJSONItemObject.Create;
  5731. try
  5732. if Length(aObject.fName) > 0 then
  5733. begin
  5734. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  5735. end;
  5736. if aObject.fBuffer >= 0 then
  5737. begin
  5738. result.Add('buffer', TPasJSONItemNumber.Create(aObject.fBuffer));
  5739. end;
  5740. result.Add('byteLength',
  5741. TPasJSONItemNumber.Create(aObject.fByteLength));
  5742. result.Add('byteOffset',
  5743. TPasJSONItemNumber.Create(aObject.fByteOffset));
  5744. if aObject.fByteStride > 0 then
  5745. begin
  5746. result.Add('byteStride',
  5747. TPasJSONItemNumber.Create(aObject.fByteStride));
  5748. end;
  5749. if aObject.fTarget <> TBufferView.TTargetType.None then
  5750. begin
  5751. result.Add('target',
  5752. TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fTarget)));
  5753. end;
  5754. ProcessExtensionsAndExtras(result, aObject);
  5755. except
  5756. FreeAndNil(result);
  5757. raise;
  5758. end;
  5759. end;
  5760. var
  5761. BufferView: TBufferView;
  5762. begin
  5763. result := TPasJSONItemArray.Create;
  5764. try
  5765. for BufferView in fBufferViews do
  5766. begin
  5767. result.Add(ProcessBufferView(BufferView));
  5768. end;
  5769. except
  5770. FreeAndNil(result);
  5771. raise;
  5772. end;
  5773. end;
  5774. function ProcessCameras: TPasJSONItemArray;
  5775. function ProcessCamera(const aObject: TCamera): TPasJSONItemObject;
  5776. var
  5777. JSONObject: TPasJSONItemObject;
  5778. begin
  5779. result := TPasJSONItemObject.Create;
  5780. try
  5781. if Length(aObject.fName) > 0 then
  5782. begin
  5783. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  5784. end;
  5785. case aObject.Type_ of
  5786. TPasGLTF.TCamera.TType.Orthographic:
  5787. begin
  5788. result.Add('type', TPasJSONItemString.Create('orthographic'));
  5789. if not aObject.Orthographic.Empty then
  5790. begin
  5791. JSONObject := TPasJSONItemObject.Create;
  5792. try
  5793. if aObject.Orthographic.fXMag <> TDefaults.FloatSentinel then
  5794. begin
  5795. JSONObject.Add('xmag',
  5796. TPasJSONItemNumber.Create(aObject.Orthographic.fXMag));
  5797. end;
  5798. if aObject.Orthographic.fYMag <> TDefaults.FloatSentinel then
  5799. begin
  5800. JSONObject.Add('ymag',
  5801. TPasJSONItemNumber.Create(aObject.Orthographic.fYMag));
  5802. end;
  5803. if aObject.Orthographic.fZNear <> -TDefaults.FloatSentinel
  5804. then
  5805. begin
  5806. JSONObject.Add('znear',
  5807. TPasJSONItemNumber.Create(aObject.Orthographic.fZNear));
  5808. end;
  5809. if aObject.Orthographic.fZFar <> -TDefaults.FloatSentinel then
  5810. begin
  5811. JSONObject.Add('zfar',
  5812. TPasJSONItemNumber.Create(aObject.Orthographic.fZFar));
  5813. end;
  5814. ProcessExtensionsAndExtras(JSONObject, aObject.Orthographic);
  5815. finally
  5816. result.Add('orthographic', JSONObject);
  5817. end;
  5818. end;
  5819. end;
  5820. TPasGLTF.TCamera.TType.Perspective:
  5821. begin
  5822. result.Add('type', TPasJSONItemString.Create('perspective'));
  5823. if not aObject.Perspective.Empty then
  5824. begin
  5825. JSONObject := TPasJSONItemObject.Create;
  5826. try
  5827. JSONObject.Add('aspectRatio',
  5828. TPasJSONItemNumber.Create
  5829. (aObject.Perspective.fAspectRatio));
  5830. JSONObject.Add('yfov',
  5831. TPasJSONItemNumber.Create(aObject.Perspective.fYFov));
  5832. JSONObject.Add('znear',
  5833. TPasJSONItemNumber.Create(aObject.Perspective.fZNear));
  5834. JSONObject.Add('zfar',
  5835. TPasJSONItemNumber.Create(aObject.Perspective.fZFar));
  5836. ProcessExtensionsAndExtras(JSONObject, aObject.Perspective);
  5837. finally
  5838. result.Add('perspective', JSONObject);
  5839. end;
  5840. end;
  5841. end;
  5842. else
  5843. begin
  5844. Assert(false);
  5845. end;
  5846. end;
  5847. ProcessExtensionsAndExtras(result, aObject);
  5848. except
  5849. FreeAndNil(result);
  5850. raise;
  5851. end;
  5852. end;
  5853. var
  5854. Camera: TCamera;
  5855. begin
  5856. result := TPasJSONItemArray.Create;
  5857. try
  5858. for Camera in fCameras do
  5859. begin
  5860. result.Add(ProcessCamera(Camera));
  5861. end;
  5862. except
  5863. FreeAndNil(result);
  5864. raise;
  5865. end;
  5866. end;
  5867. function ProcessImages: TPasJSONItemArray;
  5868. function ProcessImage(const aObject: TImage): TPasJSONItemObject;
  5869. begin
  5870. result := TPasJSONItemObject.Create;
  5871. try
  5872. if ((aObject.fBufferView >= 0) and (Length(aObject.fURI) = 0)) or
  5873. ((aObject.fBufferView > 0) and (Length(aObject.fURI) > 0)) then
  5874. begin
  5875. result.Add('bufferView',
  5876. TPasJSONItemNumber.Create(aObject.fBufferView));
  5877. end;
  5878. if Length(aObject.fName) > 0 then
  5879. begin
  5880. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  5881. end;
  5882. if Length(aObject.fMimeType) > 0 then
  5883. begin
  5884. result.Add('mimeType', TPasJSONItemString.Create(aObject.fMimeType));
  5885. end;
  5886. if Length(aObject.fURI) > 0 then
  5887. begin
  5888. result.Add('uri', TPasJSONItemString.Create(aObject.fURI));
  5889. end;
  5890. ProcessExtensionsAndExtras(result, aObject);
  5891. except
  5892. FreeAndNil(result);
  5893. raise;
  5894. end;
  5895. end;
  5896. var
  5897. Image: TImage;
  5898. begin
  5899. result := TPasJSONItemArray.Create;
  5900. try
  5901. for Image in fImages do
  5902. begin
  5903. result.Add(ProcessImage(Image));
  5904. end;
  5905. except
  5906. FreeAndNil(result);
  5907. raise;
  5908. end;
  5909. end;
  5910. function ProcessMaterials: TPasJSONItemArray;
  5911. function ProcessMaterial(const aObject: TMaterial): TPasJSONItemObject;
  5912. var
  5913. JSONArray: TPasJSONItemArray;
  5914. JSONObject, JSONSubObject: TPasJSONItemObject;
  5915. begin
  5916. result := TPasJSONItemObject.Create;
  5917. try
  5918. if aObject.fAlphaCutOff <> TDefaults.MaterialAlphaCutoff then
  5919. begin
  5920. result.Add('alphaCutoff',
  5921. TPasJSONItemNumber.Create(aObject.fAlphaCutOff));
  5922. end;
  5923. case aObject.fAlphaMode of
  5924. TPasGLTF.TMaterial.TAlphaMode.Opaque:
  5925. begin
  5926. // Default value
  5927. // result.Add('alphaMode',TPasJSONItemString.Create('OPAQUE'));
  5928. end;
  5929. TPasGLTF.TMaterial.TAlphaMode.Mask:
  5930. begin
  5931. result.Add('alphaMode', TPasJSONItemString.Create('MASK'));
  5932. end;
  5933. TPasGLTF.TMaterial.TAlphaMode.Blend:
  5934. begin
  5935. result.Add('alphaMode', TPasJSONItemString.Create('BLEND'));
  5936. end;
  5937. else
  5938. begin
  5939. Assert(false);
  5940. end;
  5941. end;
  5942. if aObject.fDoubleSided <> TDefaults.MaterialDoubleSided then
  5943. begin
  5944. result.Add('doubleSided',
  5945. TPasJSONItemBoolean.Create(aObject.fDoubleSided));
  5946. end;
  5947. if not CompareMem(@aObject.EmissiveFactor, @TDefaults.NullVector3,
  5948. SizeOf(TVector3)) then
  5949. begin
  5950. JSONArray := TPasJSONItemArray.Create;
  5951. try
  5952. JSONArray.Add(TPasJSONItemNumber.Create(aObject.EmissiveFactor[0]));
  5953. JSONArray.Add(TPasJSONItemNumber.Create(aObject.EmissiveFactor[1]));
  5954. JSONArray.Add(TPasJSONItemNumber.Create(aObject.EmissiveFactor[2]));
  5955. finally
  5956. result.Add('emissiveFactor', JSONArray);
  5957. end;
  5958. end;
  5959. if not aObject.fEmissiveTexture.Empty then
  5960. begin
  5961. JSONObject := TPasJSONItemObject.Create;
  5962. try
  5963. if aObject.fEmissiveTexture.fIndex >= 0 then
  5964. begin
  5965. JSONObject.Add('index',
  5966. TPasJSONItemNumber.Create(aObject.fEmissiveTexture.fIndex));
  5967. end;
  5968. if aObject.fEmissiveTexture.fTexCoord > 0 then
  5969. begin
  5970. JSONObject.Add('texCoord',
  5971. TPasJSONItemNumber.Create(aObject.fEmissiveTexture.fTexCoord));
  5972. end;
  5973. ProcessExtensionsAndExtras(JSONObject, aObject.fEmissiveTexture);
  5974. finally
  5975. result.Add('emissiveTexture', JSONObject);
  5976. end;
  5977. end;
  5978. if Length(aObject.fName) > 0 then
  5979. begin
  5980. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  5981. end;
  5982. if not aObject.fNormalTexture.Empty then
  5983. begin
  5984. JSONObject := TPasJSONItemObject.Create;
  5985. try
  5986. if aObject.fNormalTexture.fIndex >= 0 then
  5987. begin
  5988. JSONObject.Add('index',
  5989. TPasJSONItemNumber.Create(aObject.fNormalTexture.fIndex));
  5990. end;
  5991. if aObject.fNormalTexture.fTexCoord > 0 then
  5992. begin
  5993. JSONObject.Add('texCoord',
  5994. TPasJSONItemNumber.Create(aObject.fNormalTexture.fTexCoord));
  5995. end;
  5996. if aObject.fNormalTexture.fScale <> TDefaults.IdentityScalar then
  5997. begin
  5998. JSONObject.Add('scale',
  5999. TPasJSONItemNumber.Create(aObject.fNormalTexture.fScale));
  6000. end;
  6001. ProcessExtensionsAndExtras(JSONObject, aObject.fNormalTexture);
  6002. finally
  6003. result.Add('normalTexture', JSONObject);
  6004. end;
  6005. end;
  6006. if not aObject.fOcclusionTexture.Empty then
  6007. begin
  6008. JSONObject := TPasJSONItemObject.Create;
  6009. try
  6010. if aObject.fOcclusionTexture.fIndex >= 0 then
  6011. begin
  6012. JSONObject.Add('index',
  6013. TPasJSONItemNumber.Create(aObject.fOcclusionTexture.fIndex));
  6014. end;
  6015. if aObject.fOcclusionTexture.fTexCoord > 0 then
  6016. begin
  6017. JSONObject.Add('texCoord',
  6018. TPasJSONItemNumber.Create(aObject.fOcclusionTexture.fTexCoord));
  6019. end;
  6020. if aObject.fOcclusionTexture.fStrength <> TDefaults.IdentityScalar
  6021. then
  6022. begin
  6023. JSONObject.Add('strength',
  6024. TPasJSONItemNumber.Create(aObject.fOcclusionTexture.fStrength));
  6025. end;
  6026. ProcessExtensionsAndExtras(JSONObject, aObject.fOcclusionTexture);
  6027. finally
  6028. result.Add('occlusionTexture', JSONObject);
  6029. end;
  6030. end;
  6031. if not aObject.PBRMetallicRoughness.Empty then
  6032. begin
  6033. JSONObject := TPasJSONItemObject.Create;
  6034. try
  6035. if not CompareMem(@aObject.PBRMetallicRoughness.fBaseColorFactor,
  6036. @TDefaults.IdentityVector4, SizeOf(TVector4)) then
  6037. begin
  6038. JSONArray := TPasJSONItemArray.Create;
  6039. try
  6040. JSONArray.Add
  6041. (TPasJSONItemNumber.Create
  6042. (aObject.PBRMetallicRoughness.fBaseColorFactor[0]));
  6043. JSONArray.Add
  6044. (TPasJSONItemNumber.Create
  6045. (aObject.PBRMetallicRoughness.fBaseColorFactor[1]));
  6046. JSONArray.Add
  6047. (TPasJSONItemNumber.Create
  6048. (aObject.PBRMetallicRoughness.fBaseColorFactor[2]));
  6049. JSONArray.Add
  6050. (TPasJSONItemNumber.Create
  6051. (aObject.PBRMetallicRoughness.fBaseColorFactor[3]));
  6052. finally
  6053. JSONObject.Add('baseColorFactor', JSONArray);
  6054. end;
  6055. end;
  6056. if not aObject.fPBRMetallicRoughness.fBaseColorTexture.Empty then
  6057. begin
  6058. JSONSubObject := TPasJSONItemObject.Create;
  6059. try
  6060. if aObject.fPBRMetallicRoughness.fBaseColorTexture.fIndex >= 0
  6061. then
  6062. begin
  6063. JSONSubObject.Add('index',
  6064. TPasJSONItemNumber.Create
  6065. (aObject.fPBRMetallicRoughness.fBaseColorTexture.fIndex));
  6066. end;
  6067. if aObject.fPBRMetallicRoughness.fBaseColorTexture.fTexCoord > 0
  6068. then
  6069. begin
  6070. JSONSubObject.Add('texCoord',
  6071. TPasJSONItemNumber.Create
  6072. (aObject.fPBRMetallicRoughness.fBaseColorTexture.
  6073. fTexCoord));
  6074. end;
  6075. ProcessExtensionsAndExtras(JSONSubObject,
  6076. aObject.fPBRMetallicRoughness.fBaseColorTexture);
  6077. finally
  6078. JSONObject.Add('baseColorTexture', JSONSubObject);
  6079. end;
  6080. end;
  6081. if aObject.fPBRMetallicRoughness.fMetallicFactor <> TDefaults.IdentityScalar
  6082. then
  6083. begin
  6084. JSONObject.Add('metallicFactor',
  6085. TPasJSONItemNumber.Create
  6086. (aObject.fPBRMetallicRoughness.fMetallicFactor));
  6087. end;
  6088. if not aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture.Empty
  6089. then
  6090. begin
  6091. JSONSubObject := TPasJSONItemObject.Create;
  6092. try
  6093. if aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture.
  6094. fIndex >= 0 then
  6095. begin
  6096. JSONSubObject.Add('index',
  6097. TPasJSONItemNumber.Create
  6098. (aObject.fPBRMetallicRoughness.
  6099. fMetallicRoughnessTexture.fIndex));
  6100. end;
  6101. if aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture.
  6102. fTexCoord > 0 then
  6103. begin
  6104. JSONSubObject.Add('texCoord',
  6105. TPasJSONItemNumber.Create
  6106. (aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture.
  6107. fTexCoord));
  6108. end;
  6109. ProcessExtensionsAndExtras(JSONSubObject,
  6110. aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture);
  6111. finally
  6112. JSONObject.Add('metallicRoughnessTexture', JSONSubObject);
  6113. end;
  6114. end;
  6115. if aObject.fPBRMetallicRoughness.fRoughnessFactor <> TDefaults.IdentityScalar
  6116. then
  6117. begin
  6118. JSONObject.Add('roughnessFactor',
  6119. TPasJSONItemNumber.Create
  6120. (aObject.fPBRMetallicRoughness.fRoughnessFactor));
  6121. end;
  6122. ProcessExtensionsAndExtras(JSONObject,
  6123. aObject.fPBRMetallicRoughness);
  6124. finally
  6125. result.Add('pbrMetallicRoughness', JSONObject);
  6126. end;
  6127. end;
  6128. ProcessExtensionsAndExtras(result, aObject);
  6129. except
  6130. FreeAndNil(result);
  6131. raise;
  6132. end;
  6133. end;
  6134. var
  6135. Material: TMaterial;
  6136. begin
  6137. result := TPasJSONItemArray.Create;
  6138. try
  6139. for Material in fMaterials do
  6140. begin
  6141. result.Add(ProcessMaterial(Material));
  6142. end;
  6143. except
  6144. FreeAndNil(result);
  6145. raise;
  6146. end;
  6147. end;
  6148. function ProcessMeshes: TPasJSONItemArray;
  6149. function ProcessMesh(const aObject: TMesh): TPasJSONItemObject;
  6150. var
  6151. Index: TPasJSONSizeInt;
  6152. JSONArray: TPasJSONItemArray;
  6153. JSONObject, JSONSubObject: TPasJSONItemObject;
  6154. Primitive: TMesh.TPrimitive;
  6155. Attributes: TAttributes;
  6156. Used: boolean;
  6157. begin
  6158. result := TPasJSONItemObject.Create;
  6159. try
  6160. if aObject.fPrimitives.Count > 0 then
  6161. begin
  6162. JSONArray := TPasJSONItemArray.Create;
  6163. try
  6164. for Primitive in aObject.fPrimitives do
  6165. begin
  6166. JSONObject := TPasJSONItemObject.Create;
  6167. try
  6168. begin
  6169. Used := false;
  6170. for Index := 0 to Primitive.fAttributes.fSize - 1 do
  6171. begin
  6172. if Primitive.fAttributes.fEntityToCellIndex[Index] >= 0 then
  6173. begin
  6174. Used := true;
  6175. break;
  6176. end;
  6177. end;
  6178. if Used then
  6179. begin
  6180. JSONSubObject := TPasJSONItemObject.Create;
  6181. try
  6182. for Index := 0 to Primitive.fAttributes.fSize - 1 do
  6183. begin
  6184. if Primitive.fAttributes.fEntityToCellIndex[Index] >= 0
  6185. then
  6186. begin
  6187. JSONSubObject.Add(Primitive.fAttributes.fEntities
  6188. [Index].Key,
  6189. TPasJSONItemNumber.Create
  6190. (Primitive.fAttributes.fEntities[Index].Value));
  6191. end;
  6192. end;
  6193. finally
  6194. JSONObject.Add('attributes', JSONSubObject);
  6195. end;
  6196. end;
  6197. end;
  6198. if Primitive.fIndices >= 0 then
  6199. begin
  6200. JSONObject.Add('indices',
  6201. TPasJSONItemNumber.Create(Primitive.fIndices));
  6202. end;
  6203. if Primitive.fMaterial >= 0 then
  6204. begin
  6205. JSONObject.Add('material',
  6206. TPasJSONItemNumber.Create(Primitive.fMaterial));
  6207. end;
  6208. if Primitive.fMode <> TMesh.TPrimitive.TMode.Triangles then
  6209. begin
  6210. JSONObject.Add('mode',
  6211. TPasJSONItemNumber.Create(TPasGLTFInt64(Primitive.fMode)));
  6212. end;
  6213. if Primitive.fTargets.Count > 0 then
  6214. begin
  6215. JSONArray := TPasJSONItemArray.Create;
  6216. try
  6217. for Attributes in Primitive.fTargets do
  6218. begin
  6219. JSONSubObject := TPasJSONItemObject.Create;
  6220. try
  6221. for Index := 0 to Attributes.fSize - 1 do
  6222. begin
  6223. if Attributes.fEntityToCellIndex[Index] >= 0 then
  6224. begin
  6225. JSONSubObject.Add(Attributes.fEntities[Index].Key,
  6226. TPasJSONItemNumber.Create(Attributes.fEntities[
  6227. Index].Value));
  6228. end;
  6229. end;
  6230. finally
  6231. JSONArray.Add(JSONSubObject);
  6232. end;
  6233. end;
  6234. finally
  6235. JSONObject.Add('targets', JSONArray);
  6236. end;
  6237. end;
  6238. ProcessExtensionsAndExtras(JSONObject, Primitive);
  6239. finally
  6240. JSONArray.Add(JSONObject);
  6241. end;
  6242. end;
  6243. finally
  6244. result.Add('primitives', JSONArray);
  6245. end;
  6246. end;
  6247. if aObject.fWeights.Count > 0 then
  6248. begin
  6249. JSONArray := TPasJSONItemArray.Create;
  6250. try
  6251. for Index := 0 to aObject.fWeights.Count - 1 do
  6252. begin
  6253. JSONArray.Add
  6254. (TPasJSONItemNumber.Create(aObject.fWeights.Items[Index]));
  6255. end;
  6256. finally
  6257. result.Add('weights', JSONArray);
  6258. end;
  6259. end;
  6260. ProcessExtensionsAndExtras(result, aObject);
  6261. except
  6262. FreeAndNil(result);
  6263. raise;
  6264. end;
  6265. end;
  6266. var
  6267. Mesh: TMesh;
  6268. begin
  6269. result := TPasJSONItemArray.Create;
  6270. try
  6271. for Mesh in fMeshes do
  6272. begin
  6273. result.Add(ProcessMesh(Mesh));
  6274. end;
  6275. except
  6276. FreeAndNil(result);
  6277. raise;
  6278. end;
  6279. end;
  6280. function ProcessNodes: TPasJSONItemArray;
  6281. function ProcessNode(const aObject: TNode): TPasJSONItemObject;
  6282. var
  6283. Index: TPasJSONSizeInt;
  6284. JSONArray: TPasJSONItemArray;
  6285. begin
  6286. result := TPasJSONItemObject.Create;
  6287. try
  6288. if aObject.fCamera >= 0 then
  6289. begin
  6290. result.Add('camera', TPasJSONItemNumber.Create(aObject.fCamera));
  6291. end;
  6292. if aObject.fChildren.Count > 0 then
  6293. begin
  6294. JSONArray := TPasJSONItemArray.Create;
  6295. try
  6296. for Index := 0 to aObject.fChildren.Count - 1 do
  6297. begin
  6298. JSONArray.Add
  6299. (TPasJSONItemNumber.Create(aObject.fChildren.Items[Index]));
  6300. end;
  6301. finally
  6302. result.Add('children', JSONArray);
  6303. end;
  6304. end;
  6305. if not CompareMem(@aObject.fMatrix, @TDefaults.IdentityMatrix4x4,
  6306. SizeOf(TMatrix4x4)) then
  6307. begin
  6308. JSONArray := TPasJSONItemArray.Create;
  6309. try
  6310. for Index := 0 to 15 do
  6311. begin
  6312. JSONArray.Add(TPasJSONItemNumber.Create(aObject.fMatrix[Index]));
  6313. end;
  6314. finally
  6315. result.Add('matrix', JSONArray);
  6316. end;
  6317. end;
  6318. if Length(aObject.fName) > 0 then
  6319. begin
  6320. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  6321. end;
  6322. if aObject.fMesh >= 0 then
  6323. begin
  6324. result.Add('mesh', TPasJSONItemNumber.Create(aObject.fMesh));
  6325. end;
  6326. if not CompareMem(@aObject.fRotation, @TDefaults.IdentityQuaternion,
  6327. SizeOf(TVector4)) then
  6328. begin
  6329. JSONArray := TPasJSONItemArray.Create;
  6330. try
  6331. for Index := 0 to 3 do
  6332. begin
  6333. JSONArray.Add(TPasJSONItemNumber.Create(aObject.fRotation
  6334. [Index]));
  6335. end;
  6336. finally
  6337. result.Add('rotation', JSONArray);
  6338. end;
  6339. end;
  6340. if not CompareMem(@aObject.fScale, @TDefaults.IdentityVector3,
  6341. SizeOf(TVector3)) then
  6342. begin
  6343. JSONArray := TPasJSONItemArray.Create;
  6344. try
  6345. for Index := 0 to 2 do
  6346. begin
  6347. JSONArray.Add(TPasJSONItemNumber.Create(aObject.fScale[Index]));
  6348. end;
  6349. finally
  6350. result.Add('scale', JSONArray);
  6351. end;
  6352. end;
  6353. if aObject.fSkin >= 0 then
  6354. begin
  6355. result.Add('skin', TPasJSONItemNumber.Create(aObject.fSkin));
  6356. end;
  6357. if not CompareMem(@aObject.fTranslation, @TDefaults.NullVector3,
  6358. SizeOf(TVector3)) then
  6359. begin
  6360. JSONArray := TPasJSONItemArray.Create;
  6361. try
  6362. for Index := 0 to 2 do
  6363. begin
  6364. JSONArray.Add
  6365. (TPasJSONItemNumber.Create(aObject.fTranslation[Index]));
  6366. end;
  6367. finally
  6368. result.Add('translation', JSONArray);
  6369. end;
  6370. end;
  6371. if aObject.fWeights.Count > 0 then
  6372. begin
  6373. JSONArray := TPasJSONItemArray.Create;
  6374. try
  6375. for Index := 0 to aObject.fWeights.Count - 1 do
  6376. begin
  6377. JSONArray.Add
  6378. (TPasJSONItemNumber.Create(aObject.fWeights.Items[Index]));
  6379. end;
  6380. finally
  6381. result.Add('weights', JSONArray);
  6382. end;
  6383. end;
  6384. ProcessExtensionsAndExtras(result, aObject);
  6385. except
  6386. FreeAndNil(result);
  6387. raise;
  6388. end;
  6389. end;
  6390. var
  6391. Node: TNode;
  6392. begin
  6393. result := TPasJSONItemArray.Create;
  6394. try
  6395. for Node in fNodes do
  6396. begin
  6397. result.Add(ProcessNode(Node));
  6398. end;
  6399. except
  6400. FreeAndNil(result);
  6401. raise;
  6402. end;
  6403. end;
  6404. function ProcessSamplers: TPasJSONItemArray;
  6405. function ProcessSampler(const aObject: TSampler): TPasJSONItemObject;
  6406. begin
  6407. result := TPasJSONItemObject.Create;
  6408. try
  6409. if not aObject.Empty then
  6410. begin
  6411. if aObject.fMinFilter <> TSampler.TMinFilter.None then
  6412. begin
  6413. result.Add('minFilter',
  6414. TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fMinFilter)));
  6415. end;
  6416. if aObject.fMagFilter <> TSampler.TMagFilter.None then
  6417. begin
  6418. result.Add('magFilter',
  6419. TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fMagFilter)));
  6420. end;
  6421. if Length(aObject.fName) > 0 then
  6422. begin
  6423. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  6424. end;
  6425. if aObject.fWrapS <> TSampler.TWrappingMode.Repeat_ then
  6426. begin
  6427. result.Add('wrapS',
  6428. TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fWrapS)));
  6429. end;
  6430. if aObject.fWrapT <> TSampler.TWrappingMode.Repeat_ then
  6431. begin
  6432. result.Add('wrapS',
  6433. TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fWrapT)));
  6434. end;
  6435. ProcessExtensionsAndExtras(result, aObject);
  6436. end;
  6437. except
  6438. FreeAndNil(result);
  6439. raise;
  6440. end;
  6441. end;
  6442. var
  6443. Sampler: TSampler;
  6444. begin
  6445. result := TPasJSONItemArray.Create;
  6446. try
  6447. for Sampler in fSamplers do
  6448. begin
  6449. result.Add(ProcessSampler(Sampler));
  6450. end;
  6451. except
  6452. FreeAndNil(result);
  6453. raise;
  6454. end;
  6455. end;
  6456. function ProcessScenes: TPasJSONItemArray;
  6457. function ProcessScene(const aObject: TScene): TPasJSONItemObject;
  6458. var
  6459. Index: TPasJSONSizeInt;
  6460. JSONArray: TPasJSONItemArray;
  6461. begin
  6462. result := TPasJSONItemObject.Create;
  6463. try
  6464. if Length(aObject.fName) > 0 then
  6465. begin
  6466. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  6467. end;
  6468. if aObject.fNodes.Count > 0 then
  6469. begin
  6470. JSONArray := TPasJSONItemArray.Create;
  6471. try
  6472. for Index := 0 to aObject.fNodes.Count - 1 do
  6473. begin
  6474. JSONArray.Add
  6475. (TPasJSONItemNumber.Create(aObject.fNodes.Items[Index]));
  6476. end;
  6477. finally
  6478. result.Add('nodes', JSONArray);
  6479. end;
  6480. end;
  6481. ProcessExtensionsAndExtras(result, aObject);
  6482. except
  6483. FreeAndNil(result);
  6484. raise;
  6485. end;
  6486. end;
  6487. var
  6488. Scene: TScene;
  6489. begin
  6490. result := TPasJSONItemArray.Create;
  6491. try
  6492. for Scene in fScenes do
  6493. begin
  6494. result.Add(ProcessScene(Scene));
  6495. end;
  6496. except
  6497. FreeAndNil(result);
  6498. raise;
  6499. end;
  6500. end;
  6501. function ProcessSkins: TPasJSONItemArray;
  6502. function ProcessSkin(const aObject: TSkin): TPasJSONItemObject;
  6503. var
  6504. Index: TPasJSONSizeInt;
  6505. JSONArray: TPasJSONItemArray;
  6506. begin
  6507. result := TPasJSONItemObject.Create;
  6508. try
  6509. if aObject.fInverseBindMatrices >= 0 then
  6510. begin
  6511. result.Add('inverseBindMatrices',
  6512. TPasJSONItemNumber.Create(aObject.fInverseBindMatrices));
  6513. end;
  6514. if aObject.fJoints.Count > 0 then
  6515. begin
  6516. JSONArray := TPasJSONItemArray.Create;
  6517. try
  6518. for Index := 0 to aObject.fJoints.Count - 1 do
  6519. begin
  6520. JSONArray.Add
  6521. (TPasJSONItemNumber.Create(aObject.fJoints.Items[Index]));
  6522. end;
  6523. finally
  6524. result.Add('joints', JSONArray);
  6525. end;
  6526. end;
  6527. if Length(aObject.fName) > 0 then
  6528. begin
  6529. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  6530. end;
  6531. if aObject.fSkeleton >= 0 then
  6532. begin
  6533. result.Add('skeleton', TPasJSONItemNumber.Create(aObject.fSkeleton));
  6534. end;
  6535. ProcessExtensionsAndExtras(result, aObject);
  6536. except
  6537. FreeAndNil(result);
  6538. raise;
  6539. end;
  6540. end;
  6541. var
  6542. Skin: TSkin;
  6543. begin
  6544. result := TPasJSONItemArray.Create;
  6545. try
  6546. for Skin in fSkins do
  6547. begin
  6548. result.Add(ProcessSkin(Skin));
  6549. end;
  6550. except
  6551. FreeAndNil(result);
  6552. raise;
  6553. end;
  6554. end;
  6555. function ProcessTextures: TPasJSONItemArray;
  6556. function ProcessTexture(const aObject: TTexture): TPasJSONItemObject;
  6557. begin
  6558. result := TPasJSONItemObject.Create;
  6559. try
  6560. if Length(aObject.fName) > 0 then
  6561. begin
  6562. result.Add('name', TPasJSONItemString.Create(aObject.fName));
  6563. end;
  6564. if aObject.fSampler >= 0 then
  6565. begin
  6566. result.Add('sampler', TPasJSONItemNumber.Create(aObject.fSampler));
  6567. end;
  6568. if aObject.fSource >= 0 then
  6569. begin
  6570. result.Add('source', TPasJSONItemNumber.Create(aObject.fSource));
  6571. end;
  6572. ProcessExtensionsAndExtras(result, aObject);
  6573. except
  6574. FreeAndNil(result);
  6575. raise;
  6576. end;
  6577. end;
  6578. var
  6579. Texture: TTexture;
  6580. begin
  6581. result := TPasJSONItemArray.Create;
  6582. try
  6583. for Texture in fTextures do
  6584. begin
  6585. result.Add(ProcessTexture(Texture));
  6586. end;
  6587. except
  6588. FreeAndNil(result);
  6589. raise;
  6590. end;
  6591. end;
  6592. var
  6593. JSONRootItem: TPasJSONItemObject;
  6594. JSONArray: TPasJSONItemArray;
  6595. Extension: String;
  6596. begin
  6597. JSONRootItem := TPasJSONItemObject.Create;
  6598. try
  6599. if fAccessors.Count > 0 then
  6600. begin
  6601. JSONRootItem.Add('accessors', ProcessAccessors);
  6602. end;
  6603. if fAnimations.Count > 0 then
  6604. begin
  6605. JSONRootItem.Add('animations', ProcessAnimations);
  6606. end;
  6607. JSONRootItem.Add('asset', ProcessAsset);
  6608. if fBuffers.Count > 0 then
  6609. begin
  6610. JSONRootItem.Add('buffers', ProcessBuffers);
  6611. end;
  6612. if fBufferViews.Count > 0 then
  6613. begin
  6614. JSONRootItem.Add('bufferViews', ProcessBufferViews);
  6615. end;
  6616. if fCameras.Count > 0 then
  6617. begin
  6618. JSONRootItem.Add('cameras', ProcessCameras);
  6619. end;
  6620. if fImages.Count > 0 then
  6621. begin
  6622. JSONRootItem.Add('images', ProcessImages);
  6623. end;
  6624. if fMaterials.Count > 0 then
  6625. begin
  6626. JSONRootItem.Add('materials', ProcessMaterials);
  6627. end;
  6628. if fMeshes.Count > 0 then
  6629. begin
  6630. JSONRootItem.Add('meshes', ProcessMeshes);
  6631. end;
  6632. if fNodes.Count > 0 then
  6633. begin
  6634. JSONRootItem.Add('nodes', ProcessNodes);
  6635. end;
  6636. if fSamplers.Count > 0 then
  6637. begin
  6638. JSONRootItem.Add('samplers', ProcessSamplers);
  6639. end;
  6640. if fScene >= 0 then
  6641. begin
  6642. JSONRootItem.Add('scene', TPasJSONItemNumber.Create(fScene));
  6643. end;
  6644. if fScenes.Count > 0 then
  6645. begin
  6646. JSONRootItem.Add('scenes', ProcessScenes);
  6647. end;
  6648. if fSkins.Count > 0 then
  6649. begin
  6650. JSONRootItem.Add('skins', ProcessSkins);
  6651. end;
  6652. if fTextures.Count > 0 then
  6653. begin
  6654. JSONRootItem.Add('textures', ProcessTextures);
  6655. end;
  6656. if fExtensionsUsed.Count > 0 then
  6657. begin
  6658. JSONArray := TPasJSONItemArray.Create;
  6659. try
  6660. for Extension in fExtensionsUsed do
  6661. begin
  6662. JSONArray.Add(TPasJSONItemString.Create
  6663. (TPasJSONUTF8String(Extension)));
  6664. end;
  6665. finally
  6666. JSONRootItem.Add('extensionsUsed', JSONArray);
  6667. end;
  6668. end;
  6669. if fExtensionsRequired.Count > 0 then
  6670. begin
  6671. JSONArray := TPasJSONItemArray.Create;
  6672. try
  6673. for Extension in fExtensionsRequired do
  6674. begin
  6675. JSONArray.Add(TPasJSONItemString.Create
  6676. (TPasJSONUTF8String(Extension)));
  6677. end;
  6678. finally
  6679. JSONRootItem.Add('extensionsRequired', JSONArray);
  6680. end;
  6681. end;
  6682. ProcessExtensionsAndExtras(JSONRootItem, self);
  6683. result := TPasJSON.Stringify(JSONRootItem, aFormatted, []);
  6684. finally
  6685. FreeAndNil(JSONRootItem);
  6686. end;
  6687. end;
  6688. procedure TPasGLTF.TDocument.SaveToBinary(const aStream: TStream);
  6689. var
  6690. Index: TPasGLTFSizeInt;
  6691. JSONRawByteString: TPasJSONRawByteString;
  6692. GLBHeader: TGLBHeader;
  6693. ChunkHeader: TChunkHeader;
  6694. Buffer: TPasGLTF.TBuffer;
  6695. begin
  6696. JSONRawByteString := SaveToJSON(false);
  6697. while (Length(JSONRawByteString) = 0) or
  6698. ((Length(JSONRawByteString) and 3) <> 0) do
  6699. begin
  6700. JSONRawByteString := JSONRawByteString + #32;
  6701. end;
  6702. GLBHeader.Magic := GLBHeaderMagicNativeEndianness;
  6703. GLBHeader.Version := $00000002;
  6704. GLBHeader.Length := SizeOf(TGLBHeader) + Length(JSONRawByteString);
  6705. if (fBuffers.Count > 0) and (fBuffers[0].fData.Size > 0) then
  6706. begin
  6707. inc(GLBHeader.Length, SizeOf(TChunkHeader) + fBuffers[0].fData.Size);
  6708. end;
  6709. GLBHeader.JSONChunkHeader.ChunkLength := Length(JSONRawByteString);
  6710. GLBHeader.JSONChunkHeader.ChunkType := GLBChunkJSONNativeEndianness;
  6711. aStream.WriteBuffer(GLBHeader, SizeOf(TGLBHeader));
  6712. aStream.WriteBuffer(JSONRawByteString[1], Length(JSONRawByteString));
  6713. for Index := 0 to fBuffers.Count - 1 do
  6714. begin
  6715. Buffer := fBuffers[Index];
  6716. ChunkHeader.ChunkLength := Buffer.fData.Size;
  6717. ChunkHeader.ChunkType := GLBChunkBinaryNativeEndianness;
  6718. aStream.WriteBuffer(ChunkHeader, SizeOf(TChunkHeader));
  6719. if ChunkHeader.ChunkLength > 0 then
  6720. begin
  6721. aStream.WriteBuffer(Buffer.fData.Memory^, Buffer.fData.Size);
  6722. end;
  6723. end;
  6724. end;
  6725. procedure TPasGLTF.TDocument.SaveToStream(const aStream: TStream;
  6726. const aBinary: boolean = false; const aFormatted: boolean = false);
  6727. var
  6728. JSONRawByteString: TPasJSONRawByteString;
  6729. begin
  6730. if aBinary then
  6731. begin
  6732. SaveToBinary(aStream);
  6733. end
  6734. else
  6735. begin
  6736. JSONRawByteString := SaveToJSON(aFormatted);
  6737. if Length(JSONRawByteString) > 0 then
  6738. begin
  6739. aStream.WriteBuffer(JSONRawByteString[1], Length(JSONRawByteString));
  6740. end;
  6741. end;
  6742. end;
  6743. end.