123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107 |
- (* *****************************************************************************
- * PasGLTF *
- ******************************************************************************
- * Version 2021-07-29-15-54 *
- ******************************************************************************
- * zlib license *
- *============================================================================*
- * *
- * Copyright (C) 2018-2021, Benjamin Rosseaux ([email protected]) *
- * *
- * This software is provided 'as-is', without any express or implied *
- * warranty. In no event will the authors be held liable for any damages *
- * arising from the use of this software. *
- * *
- * Permission is granted to anyone to use this software for any purpose, *
- * including commercial applications, and to alter it and redistribute it *
- * freely, subject to the following restrictions: *
- * *
- * 1. The origin of this software must not be misrepresented; you must not *
- * claim that you wrote the original software. If you use this software *
- * in a product, an acknowledgement in the product documentation would be *
- * appreciated but is not required. *
- * 2. Altered source versions must be plainly marked as such, and must not be *
- * misrepresented as being the original software. *
- * 3. This notice may not be removed or altered from any source distribution. *
- * *
- ******************************************************************************
- * General guidelines for code contributors *
- *============================================================================*
- * *
- * 1. Make sure you are legally allowed to make a contribution under the zlib *
- * license. *
- * 2. The zlib license header goes at the top of each source file, with *
- * appropriate copyright notice. *
- * 3. After a pull request, check the status of your pull request on *
- * http://github.com/BeRo1985/pasGLTF *
- * 4. Write code which's compatible with newer modern Delphi versions and *
- * FreePascal >= 3.0.0 *
- * 5. Don't use Delphi-only, FreePascal-only or Lazarus-only libraries/units, *
- * but if needed, make it out-ifdef-able. *
- * 6. No use of third-party libraries/units as possible, but if needed, make *
- * it out-ifdef-able. *
- * 7. Try to use const when possible. *
- * 8. Make sure to comment out writeln, used while debugging. *
- * 9. Make sure the code compiles on 32-bit and 64-bit platforms (x86-32, *
- * x86-64, ARM, ARM64, etc.). *
- * *
- ***************************************************************************** *)
- unit PasGLTF;
- {$ifdef fpc}
- {$mode delphi}
- {$ifdef cpui386}
- {$define cpu386}
- {$endif}
- {$ifdef cpu386}
- {$asmmode intel}
- {$endif}
- {$ifdef cpuamd64}
- {$asmmode intel}
- {$endif}
- {$ifdef FPC_LITTLE_ENDIAN}
- {$define LITTLE_ENDIAN}
- {$else}
- {$ifdef FPC_BIG_ENDIAN}
- {$define BIG_ENDIAN}
- {$endif}
- {$endif}
- { -$pic off }
- {$ifdef fpc_has_internal_sar}
- {$define HasSAR}
- {$endif}
- {$ifdef FPC_HAS_TYPE_EXTENDED}
- {$define HAS_TYPE_EXTENDED}
- {$else}
- {$undef HAS_TYPE_EXTENDED}
- {$endif}
- {$ifdef FPC_HAS_TYPE_DOUBLE}
- {$define HAS_TYPE_DOUBLE}
- {$else}
- {$undef HAS_TYPE_DOUBLE}
- {$endif}
- {$ifdef FPC_HAS_TYPE_SINGLE}
- {$define HAS_TYPE_SINGLE}
- {$else}
- {$undef HAS_TYPE_SINGLE}
- {$endif}
- {$define CAN_INLINE}
- {$define HAS_ADVANCED_RECORDS}
- {$else}
- {$realcompatibility off}
- {$localsymbols on}
- {$define LITTLE_ENDIAN}
- {$ifndef cpu64}
- {$define cpu32}
- {$endif}
- {$define HAS_TYPE_EXTENDED}
- {$define HAS_TYPE_DOUBLE}
- {$define HAS_TYPE_SINGLE}
- {$undef CAN_INLINE}
- {$undef HAS_ADVANCED_RECORDS}
- {$ifndef BCB}
- {$ifdef ver120}
- {$define Delphi4or5}
- {$endif}
- {$ifdef ver130}
- {$define Delphi4or5}
- {$endif}
- {$ifdef ver140}
- {$define Delphi6}
- {$endif}
- {$ifdef ver150}
- {$define Delphi7}
- {$endif}
- {$ifdef ver170}
- {$define Delphi2005}
- {$endif}
- {$else}
- {$ifdef ver120}
- {$define Delphi4or5}
- {$define BCB4}
- {$endif}
- {$ifdef ver130}
- {$define Delphi4or5}
- {$endif}
- {$endif}
- {$ifdef conditionalexpressions}
- {$if CompilerVersion>=24.0}
- {$legacyifend on}
- {$ifend}
- {$if CompilerVersion>=14.0}
- {$if CompilerVersion=14.0}
- {$define Delphi6}
- {$ifend}
- {$define Delphi6AndUp}
- {$ifend}
- {$if CompilerVersion>=15.0}
- {$if CompilerVersion=15.0}
- {$define Delphi7}
- {$ifend}
- {$define Delphi7AndUp}
- {$ifend}
- {$if CompilerVersion>=17.0}
- {$if CompilerVersion=17.0}
- {$define Delphi2005}
- {$ifend}
- {$define Delphi2005AndUp}
- {$ifend}
- {$if CompilerVersion>=18.0}
- {$if CompilerVersion=18.0}
- {$define BDS2006}
- {$define Delphi2006}
- {$ifend}
- {$define Delphi2006AndUp}
- {$define CAN_INLINE}
- {$define HAS_ADVANCED_RECORDS}
- {$ifend}
- {$if CompilerVersion>=18.5}
- {$if CompilerVersion=18.5}
- {$define Delphi2007}
- {$ifend}
- {$define Delphi2007AndUp}
- {$ifend}
- {$if CompilerVersion=19.0}
- {$define Delphi2007Net}
- {$ifend}
- {$if CompilerVersion>=20.0}
- {$if CompilerVersion=20.0}
- {$define Delphi2009}
- {$ifend}
- {$define Delphi2009AndUp}
- {$ifend}
- {$if CompilerVersion>=21.0}
- {$if CompilerVersion=21.0}
- {$define Delphi2010}
- {$ifend}
- {$define Delphi2010AndUp}
- {$ifend}
- {$if CompilerVersion>=22.0}
- {$if CompilerVersion=22.0}
- {$define DelphiXE}
- {$ifend}
- {$define DelphiXEAndUp}
- {$ifend}
- {$if CompilerVersion>=23.0}
- {$if CompilerVersion=23.0}
- {$define DelphiXE2}
- {$ifend}
- {$define DelphiXE2AndUp}
- {$ifend}
- {$if CompilerVersion>=24.0}
- {$legacyifend on}
- {$if CompilerVersion=24.0}
- {$define DelphiXE3}
- {$ifend}
- {$define DelphiXE3AndUp}
- {$ifend}
- {$if CompilerVersion>=25.0}
- {$if CompilerVersion=25.0}
- {$define DelphiXE4}
- {$ifend}
- {$define DelphiXE4AndUp}
- {$ifend}
- {$if CompilerVersion>=26.0}
- {$if CompilerVersion=26.0}
- {$define DelphiXE5}
- {$ifend}
- {$define DelphiXE5AndUp}
- {$ifend}
- {$if CompilerVersion>=27.0}
- {$if CompilerVersion=27.0}
- {$define DelphiXE6}
- {$ifend}
- {$define DelphiXE6AndUp}
- {$ifend}
- {$if CompilerVersion>=28.0}
- {$if CompilerVersion=28.0}
- {$define DelphiXE7}
- {$ifend}
- {$define DelphiXE7AndUp}
- {$ifend}
- {$if CompilerVersion>=29.0}
- {$if CompilerVersion=29.0}
- {$define DelphiXE8}
- {$ifend}
- {$define DelphiXE8AndUp}
- {$ifend}
- {$if CompilerVersion>=30.0}
- {$if CompilerVersion=30.0}
- {$define Delphi10Seattle}
- {$ifend}
- {$define Delphi10SeattleAndUp}
- {$ifend}
- {$if CompilerVersion>=31.0}
- {$if CompilerVersion=31.0}
- {$define Delphi10Berlin}
- {$ifend}
- {$define Delphi10BerlinAndUp}
- {$ifend}
- {$if CompilerVersion>=32.0}
- {$if CompilerVersion=32.0}
- {$define Delphi10Tokyo}
- {$ifend}
- {$define Delphi10TokyoAndUp}
- {$ifend}
- {$if CompilerVersion>=33.0}
- {$if CompilerVersion=33.0}
- {$define Delphi10Rio}
- {$ifend}
- {$define Delphi10RioAndUp}
- {$ifend}
- {$endif}
- {$ifndef Delphi4or5}
- {$ifndef BCB}
- {$define Delphi6AndUp}
- {$endif}
- {$ifndef Delphi6}
- {$define BCB6OrDelphi7AndUp}
- {$ifndef BCB}
- {$define Delphi7AndUp}
- {$endif}
- {$ifndef BCB}
- {$ifndef Delphi7}
- {$ifndef Delphi2005}
- {$define BDS2006AndUp}
- {$endif}
- {$endif}
- {$endif}
- {$endif}
- {$endif}
- {$ifdef Delphi6AndUp}
- {$warn symbol_platform off}
- {$warn symbol_deprecated off}
- {$endif}
- {$endif}
- {$if defined(Win32) or defined(Win64)}
- {$define Windows}
- {$ifend}
- {$rangechecks off}
- {$extendedsyntax on}
- {$writeableconst on}
- {$hints off}
- {$booleval off}
- {$typedaddress off}
- {$stackframes off}
- {$varstringchecks on}
- {$typeinfo on}
- {$overflowchecks off}
- {$longstrings on}
- {$openstrings on}
- {$ifndef HAS_TYPE_SINGLE}
- {$error No single floating point precision}
- {$endif}
- {$ifndef HAS_TYPE_DOUBLE}
- {$error No double floating point precision}
- {$endif}
- {$scopedenums on}
- {$ifndef fpc}
- {$ifdef conditionalexpressions}
- {$if CompilerVersion>=24.0}
- {$legacyifend on}
- {$ifend}
- {$endif}
- {$endif}
- interface
- uses
- System.SysUtils,
- System.Classes,
- System.Math,
- PasJSON;
- type
- PPPasGLTFInt8 = ^PPasGLTFInt8;
- PPasGLTFInt8 = ^TPasGLTFInt8;
- TPasGLTFInt8 = {$IFDEF fpc}Int8{$ELSE}shortint{$ENDIF};
- PPPasGLTFUInt8 = ^PPasGLTFUInt8;
- PPasGLTFUInt8 = ^TPasGLTFUInt8;
- TPasGLTFUInt8 = {$IFDEF fpc}UInt8{$ELSE}byte{$ENDIF};
- PPPasGLTFUInt8Array = ^PPasGLTFUInt8Array;
- PPasGLTFUInt8Array = ^TPasGLTFUInt8Array;
- TPasGLTFUInt8Array = array [0 .. 65535] of TPasGLTFUInt8;
- TPasGLTFUInt8DynamicArray = array of TPasGLTFUInt8;
- PPPasGLTFInt16 = ^PPasGLTFInt16;
- PPasGLTFInt16 = ^TPasGLTFInt16;
- TPasGLTFInt16 = {$IFDEF fpc}Int16{$ELSE}smallint{$ENDIF};
- PPPasGLTFUInt16 = ^PPasGLTFUInt16;
- PPasGLTFUInt16 = ^TPasGLTFUInt16;
- TPasGLTFUInt16 = {$IFDEF fpc}UInt16{$ELSE}word{$ENDIF};
- PPPasGLTFInt32 = ^PPasGLTFInt32;
- PPasGLTFInt32 = ^TPasGLTFInt32;
- TPasGLTFInt32 = {$IFDEF fpc}Int32{$ELSE}longint{$ENDIF};
- TPasGLTFInt32DynamicArray = array of TPasGLTFInt32;
- PPPasGLTFUInt32 = ^PPasGLTFUInt32;
- PPasGLTFUInt32 = ^TPasGLTFUInt32;
- TPasGLTFUInt32 = {$IFDEF fpc}UInt32{$ELSE}longword{$ENDIF};
- PPPasGLTFUInt32Array = ^PPasGLTFUInt32Array;
- PPasGLTFUInt32Array = ^TPasGLTFUInt32Array;
- TPasGLTFUInt32Array = array [0 .. 65535] of TPasGLTFUInt32;
- TPasGLTFUInt32DynamicArray = array of TPasGLTFUInt32;
- PPPasGLTFInt64 = ^PPasGLTFInt64;
- PPasGLTFInt64 = ^TPasGLTFInt64;
- TPasGLTFInt64 = Int64;
- TPasGLTFInt64DynamicArray = array of TPasGLTFInt64;
- PPPasGLTFUInt64 = ^PPasGLTFUInt64;
- PPasGLTFUInt64 = ^TPasGLTFUInt64;
- TPasGLTFUInt64 = UInt64;
- TPasGLTFUInt64DynamicArray = array of TPasGLTFUInt64;
- PPPasGLTFChar = ^PAnsiChar;
- PPasGLTFChar = PAnsiChar;
- TPasGLTFChar = AnsiChar;
- PPPasGLTFRawByteChar = ^PAnsiChar;
- PPasGLTFRawByteChar = PAnsiChar;
- TPasGLTFRawByteChar = AnsiChar;
- PPPasGLTFUTF16Char = ^PWideChar;
- PPasGLTFUTF16Char = PWideChar;
- TPasGLTFUTF16Char = WideChar;
- PPPasGLTFPointer = ^PPasGLTFPointer;
- PPasGLTFPointer = ^TPasGLTFPointer;
- TPasGLTFPointer = Pointer;
- PPPasGLTFPointers = ^PPasGLTFPointers;
- PPasGLTFPointers = ^TPasGLTFPointers;
- TPasGLTFPointers = array [0 .. 65535] of TPasGLTFPointer;
- PPPasGLTFVoid = ^PPasGLTFVoid;
- PPasGLTFVoid = TPasGLTFPointer;
- PPPasGLTFFloat = ^PPasGLTFFloat;
- PPasGLTFFloat = ^TPasGLTFFloat;
- TPasGLTFFloat = Single;
- TPasGLTFFloatDynamicArray = array of TPasGLTFFloat;
- PPPasGLTFDouble = ^PPasGLTFDouble;
- PPasGLTFDouble = ^TPasGLTFDouble;
- TPasGLTFDouble = Double;
- TPasGLTFDoubleDynamicArray = array of TPasGLTFDouble;
- PPPasGLTFPtrUInt = ^PPasGLTFPtrUInt;
- PPPasGLTFPtrInt = ^PPasGLTFPtrInt;
- PPasGLTFPtrUInt = ^TPasGLTFPtrUInt;
- PPasGLTFPtrInt = ^TPasGLTFPtrInt;
- {$IFDEF fpc}
- TPasGLTFPtrUInt = PtrUInt;
- TPasGLTFPtrInt = PtrInt;
- {$UNDEF OldDelphi}
- {$ELSE}
- {$IFDEF conditionalexpressions}
- {$IF CompilerVersion>=23.0}
- {$UNDEF OldDelphi}
- TPasGLTFPtrUInt = NativeUInt;
- TPasGLTFPtrInt = NativeInt;
- {$ELSE}
- {$DEFINE OldDelphi}
- {$IFEND}
- {$ELSE}
- {$DEFINE OldDelphi}
- {$ENDIF}
- {$ENDIF}
- {$IFDEF OldDelphi}
- {$IFDEF cpu64}
- TPasGLTFPtrUInt = UInt64;
- TPasGLTFPtrInt = Int64;
- {$ELSE}
- TPasGLTFPtrUInt = longword;
- TPasGLTFPtrInt = longint;
- {$ENDIF}
- {$ENDIF}
- PPPasGLTFSizeUInt = ^PPasGLTFSizeUInt;
- PPasGLTFSizeUInt = ^TPasGLTFSizeUInt;
- TPasGLTFSizeUInt = TPasGLTFPtrUInt;
- TPasGLTFSizeUIntDynamicArray = array of TPasGLTFSizeUInt;
- PPPasGLTFSizeInt = ^PPasGLTFSizeInt;
- PPasGLTFSizeInt = ^TPasGLTFSizeInt;
- TPasGLTFSizeInt = TPasGLTFPtrInt;
- TPasGLTFSizeIntDynamicArray = array of TPasGLTFSizeInt;
- PPPasGLTFNativeUInt = ^PPasGLTFNativeUInt;
- PPasGLTFNativeUInt = ^TPasGLTFNativeUInt;
- TPasGLTFNativeUInt = TPasGLTFPtrUInt;
- PPPasGLTFNativeInt = ^PPasGLTFNativeInt;
- PPasGLTFNativeInt = ^TPasGLTFNativeInt;
- TPasGLTFNativeInt = TPasGLTFPtrInt;
- PPPasGLTFSize = ^PPasGLTFSizeUInt;
- PPasGLTFSize = ^TPasGLTFSizeUInt;
- TPasGLTFSize = TPasGLTFPtrUInt;
- PPPasGLTFPtrDiff = ^PPasGLTFPtrDiff;
- PPasGLTFPtrDiff = ^TPasGLTFPtrDiff;
- TPasGLTFPtrDiff = TPasGLTFPtrInt;
- PPPasGLTFRawByteString = ^PPasGLTFRawByteString;
- PPasGLTFRawByteString = ^TPasGLTFRawByteString;
- TPasGLTFRawByteString =
- {$IF declared(RawByteString)}RawByteString{$ELSE}AnsiString{$IFEND};
- PPPasGLTFUTF8String = ^PPasGLTFUTF8String;
- PPasGLTFUTF8String = ^TPasGLTFUTF8String;
- TPasGLTFUTF8String =
- {$IF declared(UTF8String)}UTF8String{$ELSE}AnsiString{$IFEND};
- PPPasGLTFUTF16String = ^PPasGLTFUTF16String;
- PPasGLTFUTF16String = ^TPasGLTFUTF16String;
- TPasGLTFUTF16String =
- {$IF declared(UnicodeString)}UnicodeString{$ELSE}WideString{$IFEND};
- EPasGLTF = class(Exception);
- EPasGLTFInvalidDocument = class(EPasGLTF);
- EPasGLTFInvalidBase64 = class(EPasGLTF);
- TPasGLTFTypedSort < T >= class private type TStackItem = record
- Left: TPasGLTFSizeInt;
- Right: TPasGLTFSizeInt;
- Depth: TPasGLTFInt32;
- end;
- PStackItem = ^TStackItem;
- public type
- TPasGLTFTypedSortCompareFunction = function(const a, b: T): TPasGLTFInt32;
- {$IFNDEF fpc}
- private
- class
- function BSRDWord(aValue: TPasGLTFUInt32): TPasGLTFInt32;
- static;
- {$ENDIF}
- public
- class
- procedure IntroSort(const pItems: TPasGLTFPointer;
- const pLeft, pRight: TPasGLTFSizeInt;
- const pCompareFunc: TPasGLTFTypedSortCompareFunction);
- static;
- end;
- TPasGLTFDynamicArray < T >= class
- private type TValueEnumerator = record
- private fDynamicArray: TPasGLTFDynamicArray<T>;
- fIndex: TPasGLTFSizeInt;
- function GetCurrent: T; inline;
- public
- constructor Create(const aDynamicArray: TPasGLTFDynamicArray<T>);
- function MoveNext: boolean; inline;
- property Current: T read GetCurrent;
- end;
- private
- fItems: array of T;
- fCount: TPasGLTFSizeInt;
- fAllocated: TPasGLTFSizeInt;
- procedure SetCount(const pNewCount: TPasGLTFSizeInt);
- function GetItem(const pIndex: TPasGLTFSizeInt): T;
- inline;
- procedure SetItem(const pIndex: TPasGLTFSizeInt; const pItem: T);
- inline;
- protected
- public
- constructor Create;
- destructor Destroy;
- override;
- procedure Clear;
- function Add(const pItem: T): TPasGLTFSizeInt;
- overload;
- function Add(const pItems: array of T): TPasGLTFSizeInt;
- overload;
- procedure Insert(const pIndex: TPasGLTFSizeInt; const pItem: T);
- procedure Delete(const pIndex: TPasGLTFSizeInt);
- procedure Exchange(const pIndex, pWithIndex: TPasGLTFSizeInt);
- inline;
- function GetEnumerator: TValueEnumerator;
- function Memory: TPasGLTFPointer;
- inline;
- property Count: TPasGLTFSizeInt read fCount write SetCount;
- property Allocated: TPasGLTFSizeInt read fAllocated;
- property Items[const pIndex: TPasGLTFSizeInt]: T read GetItem write SetItem;
- default;
- end;
- TPasGLTFObjectList < T: class >= class private type TValueEnumerator = record
- private fObjectList: TPasGLTFObjectList<T>;
- fIndex: TPasGLTFSizeInt;
- function GetCurrent: T;
- inline;
- public
- constructor Create(const aObjectList: TPasGLTFObjectList<T>);
- function MoveNext: boolean;
- inline;
- property Current: T read GetCurrent;
- end;
- private
- fItems: array of T;
- fCount: TPasGLTFSizeInt;
- fAllocated: TPasGLTFSizeInt;
- fOwnsObjects: boolean;
- function RoundUpToPowerOfTwoSizeUInt(x: TPasGLTFSizeUInt): TPasGLTFSizeUInt;
- procedure SetCount(const pNewCount: TPasGLTFSizeInt);
- function GetItem(const pIndex: TPasGLTFSizeInt): T;
- procedure SetItem(const pIndex: TPasGLTFSizeInt; const pItem: T);
- public
- constructor Create;
- destructor Destroy;
- override;
- procedure Clear;
- function IndexOf(const pItem: T): TPasGLTFSizeInt;
- function Add(const pItem: T): TPasGLTFSizeInt;
- procedure Insert(const pIndex: TPasGLTFSizeInt; const pItem: T);
- procedure Delete(const pIndex: TPasGLTFSizeInt);
- procedure Remove(const pItem: T);
- procedure Exchange(const pIndex, pWithIndex: TPasGLTFSizeInt);
- function GetEnumerator: TValueEnumerator;
- property Count: TPasGLTFSizeInt read fCount write SetCount;
- property Allocated: TPasGLTFSizeInt read fAllocated;
- property Items[const pIndex: TPasGLTFSizeInt]: T read GetItem write SetItem;
- default;
- property OwnsObjects: boolean read fOwnsObjects write fOwnsObjects;
- end;
- TPasGLTFHashMapEntityIndices = array of TPasGLTFInt32;
- TPasGLTFHashMapUInt128 = array [0 .. 1] of TPasGLTFUInt64;
- TPasGLTFUTF8StringHashMap < TPasGLTFHashMapValue >= class public
- const
- CELL_EMPTY = -1;
- CELL_DELETED = -2;
- ENT_EMPTY = -1;
- ENT_DELETED = -2;
- type
- TPasGLTFHashMapKey = TPasGLTFUTF8String;
- PPasGLTFHashMapEntity = ^TPasGLTFHashMapEntity;
- TPasGLTFHashMapEntity = record
- Key: TPasGLTFHashMapKey;
- Value: TPasGLTFHashMapValue;
- end;
- TPasGLTFHashMapEntities = array of TPasGLTFHashMapEntity;
- private type
- TPasGLTFHashMapEntityEnumerator = record
- private
- fHashMap: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
- fIndex: TPasGLTFSizeInt;
- function GetCurrent: TPasGLTFHashMapEntity; inline;
- public
- constructor Create(const aHashMap
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- function MoveNext: boolean; inline;
- property Current: TPasGLTFHashMapEntity read GetCurrent;
- end;
- TPasGLTFHashMapKeyEnumerator = record
- private
- fHashMap: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
- fIndex: TPasGLTFSizeInt;
- function GetCurrent: TPasGLTFHashMapKey; inline;
- public
- constructor Create(const aHashMap
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- function MoveNext: boolean; inline;
- property Current: TPasGLTFHashMapKey read GetCurrent;
- end;
- TPasGLTFHashMapValueEnumerator = record
- private
- fHashMap: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
- fIndex: TPasGLTFSizeInt;
- function GetCurrent: TPasGLTFHashMapValue; inline;
- public
- constructor Create(const aHashMap
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- function MoveNext: boolean; inline;
- property Current: TPasGLTFHashMapValue read GetCurrent;
- end;
- TPasGLTFHashMapEntitiesObject = class
- private
- fOwner: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
- public
- constructor Create(const aOwner
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- function GetEnumerator: TPasGLTFHashMapEntityEnumerator;
- end;
- TPasGLTFHashMapKeysObject = class
- private
- fOwner: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
- public
- constructor Create(const aOwner
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- function GetEnumerator: TPasGLTFHashMapKeyEnumerator;
- end;
- TPasGLTFHashMapValuesObject = class
- private
- fOwner: TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>;
- function GetValue(const Key: TPasGLTFHashMapKey)
- : TPasGLTFHashMapValue; inline;
- procedure SetValue(const Key: TPasGLTFHashMapKey;
- const aValue: TPasGLTFHashMapValue); inline;
- public
- constructor Create(const aOwner
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- function GetEnumerator: TPasGLTFHashMapValueEnumerator;
- property Values[const Key: TPasGLTFHashMapKey]: TPasGLTFHashMapValue
- read GetValue write SetValue; default;
- end;
- private
- fRealSize: TPasGLTFInt32;
- fLogSize: TPasGLTFInt32;
- fSize: TPasGLTFInt32;
- fEntities: TPasGLTFHashMapEntities;
- fEntityToCellIndex: TPasGLTFHashMapEntityIndices;
- fCellToEntityIndex: TPasGLTFHashMapEntityIndices;
- fDefaultValue: TPasGLTFHashMapValue;
- fCanShrink: boolean;
- fEntitiesObject: TPasGLTFHashMapEntitiesObject;
- fKeysObject: TPasGLTFHashMapKeysObject;
- fValuesObject: TPasGLTFHashMapValuesObject;
- function HashData(const Data: TPasGLTFPointer;
- const DataLength: TPasGLTFSizeUInt): TPasGLTFUInt32;
- function HashKey(const Key: TPasGLTFHashMapKey): TPasGLTFUInt32;
- function CompareKey(const KeyA, KeyB: TPasGLTFHashMapKey): boolean;
- function FindCell(const Key: TPasGLTFHashMapKey): TPasGLTFUInt32;
- procedure Resize;
- protected
- function GetValue(const Key: TPasGLTFHashMapKey): TPasGLTFHashMapValue;
- procedure SetValue(const Key: TPasGLTFHashMapKey;
- const Value: TPasGLTFHashMapValue);
- public
- constructor Create(const DefaultValue: TPasGLTFHashMapValue);
- destructor Destroy; override;
- procedure Clear;
- function Add(const Key: TPasGLTFHashMapKey; const Value: TPasGLTFHashMapValue)
- : PPasGLTFHashMapEntity;
- function Get(const Key: TPasGLTFHashMapKey;
- const CreateIfNotExist: boolean = false): PPasGLTFHashMapEntity;
- function TryGet(const Key: TPasGLTFHashMapKey;
- out Value: TPasGLTFHashMapValue): boolean;
- function ExistKey(const Key: TPasGLTFHashMapKey): boolean;
- function Delete(const Key: TPasGLTFHashMapKey): boolean;
- property EntityValues[const Key: TPasGLTFHashMapKey]: TPasGLTFHashMapValue
- read GetValue write SetValue; default;
- property Entities: TPasGLTFHashMapEntitiesObject read fEntitiesObject;
- property Keys: TPasGLTFHashMapKeysObject read fKeysObject;
- property Values: TPasGLTFHashMapValuesObject read fValuesObject;
- property CanShrink: boolean read fCanShrink write fCanShrink;
- end;
- TPasGLTF = class public type TBase64 = class public
- const
- EncodingLookUpTable: array [0 .. 63] of TPasGLTFRawByteChar = ('A', 'B', 'C',
- 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
- 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
- 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
- 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '+', '/');
- DecodingLookUpTable: array [TPasGLTFRawByteChar] of TPasGLTFInt8 = (-1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1,
- -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1);
- public
- class function Encode(const aData; const aDataLength: TPasGLTFSizeInt)
- : TPasGLTFRawByteString; overload; static;
- class function Encode(const aData: array of TPasGLTFUInt8): TPasGLTFRawByteString;
- overload;
- static;
- class function Encode(const aData: TPasGLTFRawByteString): TPasGLTFRawByteString;
- overload;
- static;
- class function Encode(const aData: TStream): TPasGLTFRawByteString;
- overload;
- static;
- class function Decode(const aInput: TPasGLTFRawByteString;
- const aOutput: TStream): boolean;
- overload;
- static;
- end;
- TChunkHeader = packed record ChunkLength: TPasGLTFUInt32;
- ChunkType: TPasGLTFUInt32;
- end;
- PChunkHeader = ^TChunkHeader;
- TGLBHeader = packed record Magic: TPasGLTFUInt32;
- Version: TPasGLTFUInt32;
- Length: TPasGLTFUInt32;
- JSONChunkHeader: TChunkHeader;
- end;
- TVector2 = array [0 .. 1] of TPasGLTFFloat;
- PVector2 = ^TVector2;
- TVector2DynamicArray = array of TVector2;
- TVector3 = array [0 .. 2] of TPasGLTFFloat;
- PVector3 = ^TVector3;
- TVector3DynamicArray = array of TVector3;
- TVector4 = array [0 .. 3] of TPasGLTFFloat;
- PVector4 = ^TVector4;
- TVector4DynamicArray = array of TVector4;
- TInt32Vector4 = array [0 .. 3] of TPasGLTFInt32;
- PInt32Vector4 = ^TInt32Vector4;
- TInt32Vector4DynamicArray = array of TInt32Vector4;
- TUInt32Vector4 = array [0 .. 3] of TPasGLTFUInt32;
- PUInt32Vector4 = ^TUInt32Vector4;
- TUInt32Vector4DynamicArray = array of TUInt32Vector4;
- TMatrix2x2 = array [0 .. 3] of TPasGLTFFloat;
- PMatrix2x2 = ^TMatrix2x2;
- TMatrix2x2DynamicArray = array of TMatrix2x2;
- TMatrix3x3 = array [0 .. 9] of TPasGLTFFloat;
- PMatrix3x3 = ^TMatrix3x3;
- TMatrix3x3DynamicArray = array of TMatrix3x3;
- TMatrix4x4 = array [0 .. 15] of TPasGLTFFloat;
- PMatrix4x4 = ^TMatrix4x4;
- TMatrix4x4DynamicArray = array of TMatrix4x4;
- const
- ChunkHeaderSize = SizeOf(TChunkHeader);
- GLBHeaderSize = SizeOf(TGLBHeader);
- GLBHeaderMagicNativeEndianness = TPasGLTFUInt32($46546C67);
- GLBHeaderMagicOtherEndianness = TPasGLTFUInt32($676C5446);
- GLBChunkJSONNativeEndianness = TPasGLTFUInt32($4E4F534A);
- GLBChunkJSONOtherEndianness = TPasGLTFUInt32($4A534F4E);
- GLBChunkBinaryNativeEndianness = TPasGLTFUInt32($004E4942);
- GLBChunkBinaryOtherEndianness = TPasGLTFUInt32($42494E00);
- MimeTypeApplicationOctet = 'application/octet-stream';
- MimeTypeImagePNG = 'image/png';
- MimeTypeImageJPG = 'image/jpg';
- type
- TDefaults = class
- public const
- AccessorNormalized = false;
- MaterialAlphaCutoff = 0.5;
- MaterialDoubleSided = false;
- IdentityScalar = 1.0;
- FloatSentinel = 1E+27;
- NullVector3: TVector3 = (0.0, 0.0, 0.0);
- IdentityVector3: TVector3 = (1.0, 1.0, 1.0);
- IdentityVector4: TVector4 = (1.0, 1.0, 1.0, 1.0);
- IdentityQuaternion: TVector4 = (0.0, 0.0, 0.0, 1.0);
- NullMatrix4x4: TMatrix4x4 = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
- IdentityMatrix4x4: TMatrix4x4 = (1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);
- end;
- TDocument = class;
- TBaseObject = class
- private
- fDocument: TDocument;
- public
- constructor Create(const aDocument: TDocument); reintroduce; virtual;
- destructor Destroy; override;
- end;
- TBaseExtensionsExtrasObject = class(TBaseObject)
- private
- fExtensions: TPasJSONItemObject;
- fExtras: TPasJSONItemObject;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Extensions: TPasJSONItemObject read fExtensions;
- property Extras: TPasJSONItemObject read fExtras;
- end;
- TAttributes = TPasGLTFUTF8StringHashMap<TPasGLTFSizeInt>;
- TAttributesList = TPasGLTFObjectList<TAttributes>;
- TAccessor = class(TBaseExtensionsExtrasObject)
- public type
- TComponentType = (None = 0, SignedByte = 5120, UnsignedByte = 5121,
- SignedShort = 5122, UnsignedShort = 5123, UnsignedInt = 5125,
- Float = 5126);
- PComponentType = ^TComponentType;
- TComponentTypeHelper = record helper for TComponentType
- function GetSize: TPasGLTFSizeInt; inline;
- end;
- TRawComponentType = TPasGLTFUInt16;
- PRawComponentType = ^TRawComponentType;
- TType = (None = 0, Scalar = 1, Vec2 = 2, Vec3 = 3, Vec4 = 4, Mat2 = 5,
- Mat3 = 6, Mat4 = 7);
- PType = ^TType;
- TTypeHelper = record helper for TType
- function GetComponentCount: TPasGLTFSizeInt; inline;
- end;
- TRawType = TPasGLTFUInt8;
- PRawType = ^TRawType;
- TMinMaxDynamicArray = TPasGLTFDynamicArray<TPasGLTFFloat>;
- TSparse = class(TBaseExtensionsExtrasObject)
- public type
- TIndices = class(TBaseExtensionsExtrasObject)
- private
- fComponentType: TComponentType;
- fBufferView: TPasGLTFSizeInt;
- fByteOffset: TPasGLTFSizeUInt;
- fEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property ComponentType: TComponentType read fComponentType
- write fComponentType default TComponentType.None;
- property BufferView: TPasGLTFSizeInt read fBufferView write fBufferView
- default 0;
- property ByteOffset: TPasGLTFSizeUInt read fByteOffset write fByteOffset
- default 0;
- property Empty: boolean read fEmpty write fEmpty;
- end;
- TValues = class(TBaseExtensionsExtrasObject)
- private
- fBufferView: TPasGLTFSizeInt;
- fByteOffset: TPasGLTFSizeUInt;
- fEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property BufferView: TPasGLTFSizeInt read fBufferView write fBufferView
- default 0;
- property ByteOffset: TPasGLTFSizeUInt read fByteOffset write fByteOffset
- default 0;
- property Empty: boolean read fEmpty write fEmpty;
- end;
- private
- fCount: TPasGLTFSizeInt;
- fIndices: TIndices;
- fValues: TValues;
- function GetEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Count: TPasGLTFSizeInt read fCount write fCount default 0;
- property Indices: TIndices read fIndices;
- property Values: TValues read fValues;
- property Empty: boolean read GetEmpty;
- end;
- const
- TypeComponentCountTable: array [TType] of TPasGLTFSizeInt = (0, 1, 2, 3, 4,
- 4, 9, 16);
- private
- fName: TPasGLTFUTF8String;
- fComponentType: TComponentType;
- fType: TType;
- fBufferView: TPasGLTFSizeInt;
- fByteOffset: TPasGLTFSizeUInt;
- fCount: TPasGLTFSizeUInt;
- fNormalized: boolean;
- fMinArray: TMinMaxDynamicArray;
- fMaxArray: TMinMaxDynamicArray;
- fSparse: TSparse;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- function DecodeAsDoubleArray(const aForVertex: boolean = true)
- : TPasGLTFDoubleDynamicArray;
- function DecodeAsInt32Array(const aForVertex: boolean = true)
- : TPasGLTFInt32DynamicArray;
- function DecodeAsUInt32Array(const aForVertex: boolean = true)
- : TPasGLTFUInt32DynamicArray;
- function DecodeAsInt64Array(const aForVertex: boolean = true)
- : TPasGLTFInt64DynamicArray;
- function DecodeAsUInt64Array(const aForVertex: boolean = true)
- : TPasGLTFUInt64DynamicArray;
- function DecodeAsFloatArray(const aForVertex: boolean = true)
- : TPasGLTFFloatDynamicArray;
- function DecodeAsVector2Array(const aForVertex: boolean = true)
- : TVector2DynamicArray;
- function DecodeAsVector3Array(const aForVertex: boolean = true)
- : TVector3DynamicArray;
- function DecodeAsVector4Array(const aForVertex: boolean = true)
- : TVector4DynamicArray;
- function DecodeAsInt32Vector4Array(const aForVertex: boolean = true)
- : TInt32Vector4DynamicArray;
- function DecodeAsUInt32Vector4Array(const aForVertex: boolean = true)
- : TUInt32Vector4DynamicArray;
- function DecodeAsColorArray(const aForVertex: boolean = true)
- : TVector4DynamicArray;
- function DecodeAsMatrix2x2Array(const aForVertex: boolean = true)
- : TMatrix2x2DynamicArray;
- function DecodeAsMatrix3x3Array(const aForVertex: boolean = true)
- : TMatrix3x3DynamicArray;
- function DecodeAsMatrix4x4Array(const aForVertex: boolean = true)
- : TMatrix4x4DynamicArray;
- published
- property ComponentType: TComponentType read fComponentType
- write fComponentType default TComponentType.None;
- property Type_: TType read fType write fType default TType.None;
- property BufferView: TPasGLTFSizeInt read fBufferView write fBufferView
- default -1;
- property ByteOffset: TPasGLTFSizeUInt read fByteOffset write fByteOffset
- default 0;
- property Count: TPasGLTFSizeUInt read fCount write fCount default 0;
- property MinArray: TMinMaxDynamicArray read fMinArray;
- property MaxArray: TMinMaxDynamicArray read fMaxArray;
- property Normalized: boolean read fNormalized write fNormalized
- default false;
- property Sparse: TSparse read fSparse;
- end;
- TAccessors = TPasGLTFObjectList<TAccessor>;
- TAnimation = class(TBaseExtensionsExtrasObject)
- public type
- TChannel = class(TBaseExtensionsExtrasObject)
- public type
- TTarget = class(TBaseExtensionsExtrasObject)
- private
- fNode: TPasGLTFSizeInt;
- fPath: TPasGLTFUTF8String;
- fEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Node: TPasGLTFSizeInt read fNode write fNode default -1;
- property Path: TPasGLTFUTF8String read fPath write fPath;
- property Empty: boolean read fEmpty write fEmpty;
- end;
- private
- fSampler: TPasGLTFSizeInt;
- fTarget: TChannel.TTarget;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Sampler: TPasGLTFSizeInt read fSampler write fSampler default -1;
- property Target: TChannel.TTarget read fTarget;
- end;
- TChannels = TPasGLTFObjectList<TChannel>;
- TSampler = class(TBaseExtensionsExtrasObject)
- public type
- TType = (Linear = 0, Step = 1, CubicSpline = 2);
- PType = ^TType;
- private
- fInput: TPasGLTFSizeInt;
- fOutput: TPasGLTFSizeInt;
- fInterpolation: TType;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Input: TPasGLTFSizeInt read fInput write fInput default -1;
- property Output: TPasGLTFSizeInt read fOutput write fOutput default -1;
- property Interpolation: TType read fInterpolation write fInterpolation
- default TType.Linear;
- end;
- TSamplers = TPasGLTFObjectList<TSampler>;
- private
- fName: TPasGLTFUTF8String;
- fChannels: TChannels;
- fSamplers: TSamplers;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Name: TPasGLTFUTF8String read fName write fName;
- property Channels: TChannels read fChannels;
- property Samplers: TSamplers read fSamplers;
- end;
- TAnimations = TPasGLTFObjectList<TAnimation>;
- TAsset = class(TBaseExtensionsExtrasObject)
- private
- fCopyright: TPasGLTFUTF8String;
- fGenerator: TPasGLTFUTF8String;
- fMinVersion: TPasGLTFUTF8String;
- fVersion: TPasGLTFUTF8String;
- fEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Copyright: TPasGLTFUTF8String read fCopyright write fCopyright;
- property Generator: TPasGLTFUTF8String read fGenerator write fGenerator;
- property MinVersion: TPasGLTFUTF8String read fMinVersion write fMinVersion;
- property Version: TPasGLTFUTF8String read fVersion write fVersion;
- property Empty: boolean read fEmpty write fEmpty;
- end;
- TBuffer = class(TBaseExtensionsExtrasObject)
- private
- fByteLength: TPasGLTFSizeUInt;
- fName: TPasGLTFUTF8String;
- fURI: TPasGLTFUTF8String;
- fData: TMemoryStream;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- procedure SetEmbeddedResourceData;
- published
- property ByteLength: TPasGLTFSizeUInt read fByteLength write fByteLength;
- property Name: TPasGLTFUTF8String read fName write fName;
- property URI: TPasGLTFUTF8String read fURI write fURI;
- property Data: TMemoryStream read fData write fData;
- end;
- TBuffers = TPasGLTFObjectList<TBuffer>;
- TBufferView = class(TBaseExtensionsExtrasObject)
- public type
- TTargetType = (None = 0, ArrayBuffer = 34962, ElementArrayBuffer = 34963);
- PTargetType = ^TTargetType;
- private
- fName: TPasGLTFUTF8String;
- fBuffer: TPasGLTFSizeInt;
- fByteOffset: TPasGLTFSizeUInt;
- fByteLength: TPasGLTFSizeUInt;
- fByteStride: TPasGLTFSizeUInt;
- fTarget: TTargetType;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- function Decode(const aSkipEvery: TPasGLTFSizeUInt;
- const aSkipBytes: TPasGLTFSizeUInt; const aElementSize: TPasGLTFSizeUInt;
- const aCount: TPasGLTFSizeUInt; const aType: TPasGLTF.TAccessor.TType;
- const aComponentCount: TPasGLTFSizeUInt;
- const aComponentType: TPasGLTF.TAccessor.TComponentType;
- const aComponentSize: TPasGLTFSizeUInt;
- const aByteOffset: TPasGLTFSizeUInt; const aNormalized: boolean;
- const aForVertex: boolean): TPasGLTFDoubleDynamicArray;
- published
- property Name: TPasGLTFUTF8String read fName write fName;
- property Buffer: TPasGLTFSizeInt read fBuffer write fBuffer;
- property ByteOffset: TPasGLTFSizeUInt read fByteOffset write fByteOffset;
- property ByteLength: TPasGLTFSizeUInt read fByteLength write fByteLength;
- property ByteStride: TPasGLTFSizeUInt read fByteStride write fByteStride;
- property Target: TTargetType read fTarget write fTarget
- default TTargetType.None;
- end;
- TBufferViews = TPasGLTFObjectList<TBufferView>;
- TCamera = class(TBaseExtensionsExtrasObject)
- public type
- TType = (None = 0, Orthographic = 1, Perspective = 2);
- TOrthographic = class(TBaseExtensionsExtrasObject)
- private
- fXMag: TPasGLTFFloat;
- fYMag: TPasGLTFFloat;
- fZNear: TPasGLTFFloat;
- fZFar: TPasGLTFFloat;
- fEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property XMag: TPasGLTFFloat read fXMag write fXMag;
- property YMag: TPasGLTFFloat read fYMag write fYMag;
- property ZNear: TPasGLTFFloat read fZNear write fZNear;
- property ZFar: TPasGLTFFloat read fZFar write fZFar;
- property Empty: boolean read fEmpty write fEmpty;
- end;
- TPerspective = class(TBaseExtensionsExtrasObject)
- private
- fAspectRatio: TPasGLTFFloat;
- fYFov: TPasGLTFFloat;
- fZNear: TPasGLTFFloat;
- fZFar: TPasGLTFFloat;
- fEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property AspectRatio: TPasGLTFFloat read fAspectRatio write fAspectRatio;
- property YFov: TPasGLTFFloat read fYFov write fYFov;
- property ZNear: TPasGLTFFloat read fZNear write fZNear;
- property ZFar: TPasGLTFFloat read fZFar write fZFar;
- property Empty: boolean read fEmpty write fEmpty;
- end;
- private
- fType: TType;
- fOrthographic: TOrthographic;
- fPerspective: TPerspective;
- fName: TPasGLTFUTF8String;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Type_: TType read fType write fType;
- property Orthographic: TOrthographic read fOrthographic;
- property Perspective: TPerspective read fPerspective;
- property Name: TPasGLTFUTF8String read fName write fName;
- end;
- TCameras = TPasGLTFObjectList<TCamera>;
- TImage = class(TBaseExtensionsExtrasObject)
- private
- fBufferView: TPasGLTFSizeInt;
- fName: TPasGLTFUTF8String;
- fURI: TPasGLTFUTF8String;
- fMimeType: TPasGLTFUTF8String;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- procedure SetEmbeddedResourceData(const aStream: TStream);
- procedure GetResourceData(const aStream: TStream);
- function IsExternalResource: boolean;
- published
- property BufferView: TPasGLTFSizeInt read fBufferView write fBufferView;
- property Name: TPasGLTFUTF8String read fName write fName;
- property URI: TPasGLTFUTF8String read fURI write fURI;
- property MimeType: TPasGLTFUTF8String read fMimeType write fMimeType;
- end;
- TImages = TPasGLTFObjectList<TImage>;
- TMaterial = class(TBaseExtensionsExtrasObject)
- public type
- TAlphaMode = (Opaque = 0, Mask = 1, Blend = 2);
- PAlphaMode = ^TAlphaMode;
- TAlphaModes = set of TAlphaMode;
- TTexture = class(TBaseExtensionsExtrasObject)
- private
- fIndex: TPasGLTFSizeInt;
- fTexCoord: TPasGLTFSizeInt;
- function GetEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Index: TPasGLTFSizeInt read fIndex write fIndex;
- property TexCoord: TPasGLTFSizeInt read fTexCoord write fTexCoord;
- property Empty: boolean read GetEmpty;
- end;
- TNormalTexture = class(TTexture)
- private
- fScale: TPasGLTFFloat;
- public
- constructor Create(const aDocument: TDocument); override;
- published
- property Scale: TPasGLTFFloat read fScale write fScale;
- end;
- TOcclusionTexture = class(TTexture)
- private
- fStrength: TPasGLTFFloat;
- public
- constructor Create(const aDocument: TDocument); override;
- published
- property Strength: TPasGLTFFloat read fStrength write fStrength;
- end;
- TPBRMetallicRoughness = class(TBaseExtensionsExtrasObject)
- private
- fBaseColorFactor: TVector4;
- fBaseColorTexture: TTexture;
- fRoughnessFactor: TPasGLTFFloat;
- fMetallicFactor: TPasGLTFFloat;
- fMetallicRoughnessTexture: TTexture;
- function GetEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- public
- property BaseColorFactor: TVector4 read fBaseColorFactor
- write fBaseColorFactor;
- published
- property BaseColorTexture: TTexture read fBaseColorTexture;
- property RoughnessFactor: TPasGLTFFloat read fRoughnessFactor
- write fRoughnessFactor;
- property MetallicFactor: TPasGLTFFloat read fMetallicFactor
- write fMetallicFactor;
- property MetallicRoughnessTexture: TTexture
- read fMetallicRoughnessTexture;
- property Empty: boolean read GetEmpty;
- end;
- private
- fName: TPasGLTFUTF8String;
- fAlphaCutOff: TPasGLTFFloat;
- fAlphaMode: TAlphaMode;
- fDoubleSided: boolean;
- fNormalTexture: TNormalTexture;
- fOcclusionTexture: TOcclusionTexture;
- fPBRMetallicRoughness: TPBRMetallicRoughness;
- fEmissiveTexture: TTexture;
- fEmissiveFactor: TVector3;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- public
- property EmissiveFactor: TVector3 read fEmissiveFactor
- write fEmissiveFactor;
- published
- property Name: TPasGLTFUTF8String read fName write fName;
- property AlphaCutOff: TPasGLTFFloat read fAlphaCutOff write fAlphaCutOff;
- property AlphaMode: TAlphaMode read fAlphaMode write fAlphaMode;
- property DoubleSided: boolean read fDoubleSided write fDoubleSided;
- property NormalTexture: TNormalTexture read fNormalTexture;
- property OcclusionTexture: TOcclusionTexture read fOcclusionTexture;
- property PBRMetallicRoughness: TPBRMetallicRoughness
- read fPBRMetallicRoughness;
- property EmissiveTexture: TTexture read fEmissiveTexture;
- end;
- TMaterials = TPasGLTFObjectList<TMaterial>;
- TMesh = class(TBaseExtensionsExtrasObject)
- public type
- TPrimitive = class(TBaseExtensionsExtrasObject)
- public type
- TMode = (Points = 0, Lines = 1, LineLoop = 2, LineStrip = 3,
- Triangles = 4, TriangleStrip = 5, TriangleFan = 6);
- PMode = ^TMode;
- private
- fMode: TMode;
- fIndices: TPasGLTFSizeInt;
- fMaterial: TPasGLTFSizeInt;
- fAttributes: TAttributes;
- fTargets: TAttributesList;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Mode: TMode read fMode write fMode;
- property Indices: TPasGLTFSizeInt read fIndices write fIndices;
- property Material: TPasGLTFSizeInt read fMaterial write fMaterial;
- property Attributes: TAttributes read fAttributes;
- property Targets: TAttributesList read fTargets;
- end;
- TPrimitives = TPasGLTFObjectList<TPrimitive>;
- TWeights = TPasGLTFDynamicArray<TPasGLTFFloat>;
- private
- fName: TPasGLTFUTF8String;
- fWeights: TWeights;
- fPrimitives: TPrimitives;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- public
- published
- property Name: TPasGLTFUTF8String read fName write fName;
- property Weights: TWeights read fWeights;
- property Primitives: TPrimitives read fPrimitives;
- end;
- TMeshes = TPasGLTFObjectList<TMesh>;
- TNode = class(TBaseExtensionsExtrasObject)
- public type
- TChildren = TPasGLTFDynamicArray<TPasGLTFSizeInt>;
- TWeights = TPasGLTFDynamicArray<TPasGLTFFloat>;
- private
- fName: TPasGLTFUTF8String;
- fCamera: TPasGLTFSizeInt;
- fMesh: TPasGLTFSizeInt;
- fSkin: TPasGLTFSizeInt;
- fMatrix: TMatrix4x4;
- fRotation: TVector4;
- fScale: TVector3;
- fTranslation: TVector3;
- fChildren: TChildren;
- fWeights: TWeights;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- public
- property Matrix: TMatrix4x4 read fMatrix write fMatrix;
- property Rotation: TVector4 read fRotation write fRotation;
- property Scale: TVector3 read fScale write fScale;
- property Translation: TVector3 read fTranslation write fTranslation;
- published
- property Name: TPasGLTFUTF8String read fName write fName;
- property Camera: TPasGLTFSizeInt read fCamera write fCamera;
- property Mesh: TPasGLTFSizeInt read fMesh write fMesh;
- property Skin: TPasGLTFSizeInt read fSkin write fSkin;
- property Children: TChildren read fChildren;
- property Weights: TWeights read fWeights;
- end;
- TNodes = TPasGLTFObjectList<TNode>;
- TSampler = class(TBaseExtensionsExtrasObject)
- public type
- TMagFilter = (None = 0, Nearest = 9728, Linear = 9729);
- PMagFilter = ^TMagFilter;
- TMinFilter = (None = 0, Nearest = 9728, Linear = 9729,
- NearestMipMapNearest = 9984, LinearMipMapNearest = 9985,
- NearestMipMapLinear = 9986, LinearMipMapLinear = 9987);
- PMinFilter = ^TMinFilter;
- TWrappingMode = (Repeat_ = 10497, ClampToEdge = 33071,
- MirroredRepeat = 33648);
- PWrappingMode = ^TWrappingMode;
- private
- fName: TPasGLTFUTF8String;
- fMagFilter: TMagFilter;
- fMinFilter: TMinFilter;
- fWrapS: TWrappingMode;
- fWrapT: TWrappingMode;
- function GetEmpty: boolean;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Name: TPasGLTFUTF8String read fName write fName;
- property MagFilter: TMagFilter read fMagFilter write fMagFilter;
- property MinFilter: TMinFilter read fMinFilter write fMinFilter;
- property WrapS: TWrappingMode read fWrapS write fWrapS;
- property WrapT: TWrappingMode read fWrapT write fWrapT;
- property Empty: boolean read GetEmpty;
- end;
- TSamplers = TPasGLTFObjectList<TSampler>;
- TScene = class(TBaseExtensionsExtrasObject)
- public type
- TNodes = TPasGLTFDynamicArray<TPasGLTFSizeUInt>;
- private
- fName: TPasGLTFUTF8String;
- fNodes: TScene.TNodes;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Name: TPasGLTFUTF8String read fName write fName;
- property Nodes: TScene.TNodes read fNodes;
- end;
- TScenes = TPasGLTFObjectList<TScene>;
- TSkin = class(TBaseExtensionsExtrasObject)
- public type
- TJoints = TPasGLTFDynamicArray<TPasGLTFSizeUInt>;
- private
- fName: TPasGLTFUTF8String;
- fInverseBindMatrices: TPasGLTFSizeInt;
- fSkeleton: TPasGLTFSizeInt;
- fJoints: TSkin.TJoints;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Name: TPasGLTFUTF8String read fName write fName;
- property InverseBindMatrices: TPasGLTFSizeInt read fInverseBindMatrices
- write fInverseBindMatrices;
- property Skeleton: TPasGLTFSizeInt read fSkeleton write fSkeleton;
- property Joints: TSkin.TJoints read fJoints;
- end;
- TSkins = TPasGLTFObjectList<TSkin>;
- TTexture = class(TBaseExtensionsExtrasObject)
- private
- fName: TPasGLTFUTF8String;
- fSampler: TPasGLTFSizeInt;
- fSource: TPasGLTFSizeInt;
- public
- constructor Create(const aDocument: TDocument); override;
- destructor Destroy; override;
- published
- property Name: TPasGLTFUTF8String read fName write fName;
- property Sampler: TPasGLTFSizeInt read fSampler write fSampler;
- property Source: TPasGLTFSizeInt read fSource write fSource;
- end;
- TTextures = TPasGLTFObjectList<TTexture>;
- TDocument = class(TBaseExtensionsExtrasObject)
- public type
- TGetURI = function(const aURI: TPasGLTFUTF8String): TStream of object;
- private
- fAsset: TAsset;
- fAccessors: TAccessors;
- fAnimations: TAnimations;
- fBuffers: TBuffers;
- fBufferViews: TBufferViews;
- fCameras: TCameras;
- fImages: TImages;
- fMaterials: TMaterials;
- fMeshes: TMeshes;
- fNodes: TNodes;
- fSamplers: TSamplers;
- fScene: TPasGLTFSizeInt;
- fScenes: TScenes;
- fSkins: TSkins;
- fTextures: TTextures;
- fExtensionsUsed: TStringList;
- fExtensionsRequired: TStringList;
- fRootPath: TPasGLTFUTF8String;
- fGetURI: TGetURI;
- function DefaultGetURI(const aURI: TPasGLTFUTF8String): TStream;
- procedure LoadURISource(const aURI: TPasGLTFUTF8String;
- const aStream: TStream);
- procedure LoadURISources;
- public
- constructor Create(const aDocument: TDocument = nil); override;
- destructor Destroy; override;
- procedure LoadFromJSON(const aJSONRootItem: TPasJSONItem);
- procedure LoadFromBinary(const aStream: TStream);
- procedure LoadFromStream(const aStream: TStream);
- function SaveToJSON(const aFormatted: boolean = false)
- : TPasJSONRawByteString;
- procedure SaveToBinary(const aStream: TStream);
- procedure SaveToStream(const aStream: TStream;
- const aBinary: boolean = false; const aFormatted: boolean = false);
- published
- property Asset: TAsset read fAsset;
- property Accessors: TAccessors read fAccessors;
- property Animations: TAnimations read fAnimations;
- property Buffers: TBuffers read fBuffers;
- property BufferViews: TBufferViews read fBufferViews;
- property Cameras: TCameras read fCameras;
- property Images: TImages read fImages;
- property Materials: TMaterials read fMaterials;
- property Meshes: TMeshes read fMeshes;
- property Nodes: TNodes read fNodes;
- property Samplers: TSamplers read fSamplers;
- property Scene: TPasGLTFSizeInt read fScene write fScene;
- property Scenes: TScenes read fScenes;
- property Skins: TSkins read fSkins;
- property Textures: TTextures read fTextures;
- property ExtensionsUsed: TStringList read fExtensionsUsed;
- property ExtensionsRequired: TStringList read fExtensionsRequired;
- property RootPath: TPasGLTFUTF8String read fRootPath write fRootPath;
- property GetURI: TGetURI read fGetURI write fGetURI;
- end;
- public
- class function ResolveURIToPath(const aURI: TPasGLTFUTF8String): TPasGLTFUTF8String; static;
- end;
- implementation
- {$IFNDEF fpc}
- class function TPasGLTFTypedSort<T>.BSRDWord(aValue: TPasGLTFUInt32)
- : TPasGLTFInt32;
- const
- BSRDebruijn32Multiplicator = TPasGLTFUInt32($07C4ACDD);
- BSRDebruijn32Shift = 27;
- BSRDebruijn32Mask = 31;
- BSRDebruijn32Table: array [0 .. 31] of TPasGLTFInt32 = (0, 9, 1, 10, 13, 21,
- 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27,
- 23, 6, 26, 5, 4, 31);
- var
- Value: TPasGLTFUInt32;
- begin
- if aValue = 0 then
- begin
- result := 255;
- end
- else
- begin
- Value := aValue or (aValue shr 1);
- Value := Value or (Value shr 2);
- Value := Value or (Value shr 4);
- Value := Value or (Value shr 8);
- Value := Value or (Value shr 16);
- result := BSRDebruijn32Table
- [((Value * BSRDebruijn32Multiplicator) shr BSRDebruijn32Shift) and
- BSRDebruijn32Mask];
- end;
- end;
- {$ENDIF}
- class procedure TPasGLTFTypedSort<T>.IntroSort(const pItems: TPasGLTFPointer;
- const pLeft, pRight: TPasGLTFSizeInt;
- const pCompareFunc: TPasGLTFTypedSortCompareFunction);
- type
- TItem = T;
- pItem = ^TItem;
- TItemArray = array [0 .. 65535] of TItem;
- PItemArray = ^TItemArray;
- var
- Left, Right, i, j, Middle, Size, Parent, Child, Pivot, iA, iB,
- iC: TPasGLTFSizeInt;
- Depth: TPasGLTFInt32;
- StackItem: PStackItem;
- Stack: array [0 .. 31] of TStackItem;
- Temp: T;
- begin
- if pLeft < pRight then
- begin
- StackItem := @Stack[0];
- StackItem^.Left := pLeft;
- StackItem^.Right := pRight;
- if (TPasGLTFInt64(pRight) - TPasGLTFInt64(pLeft)) <=
- TPasGLTFInt64(High(TPasGLTFUInt32)) then
- begin
- StackItem^.Depth := BSRDWord((pRight - pLeft) + 1) shl 1;
- if StackItem^.Depth > 31 then
- begin
- StackItem^.Depth := 31;
- end;
- end
- else
- begin
- StackItem^.Depth := 31;
- end;
- inc(StackItem);
- while {%H-}TPasGLTFPtrUInt(TPasGLTFPointer(StackItem)) >
- TPasGLTFPtrUInt(TPasGLTFPointer(@Stack[0])) do
- begin
- dec(StackItem);
- Left := StackItem^.Left;
- Right := StackItem^.Right;
- Depth := StackItem^.Depth;
- Size := (Right - Left) + 1;
- if Size < 16 then
- begin
- // Insertion sort
- iA := Left;
- iB := iA + 1;
- while iB <= Right do
- begin
- iC := iB;
- while (iA >= Left) and (iC >= Left) and
- (pCompareFunc(PItemArray(pItems)^[iA],
- PItemArray(pItems)^[iC]) > 0) do
- begin
- Temp := PItemArray(pItems)^[iA];
- PItemArray(pItems)^[iA] := PItemArray(pItems)^[iC];
- PItemArray(pItems)^[iC] := Temp;
- dec(iA);
- dec(iC);
- end;
- iA := iB;
- inc(iB);
- end;
- end
- else
- begin
- if (Depth = 0) or ({%H-}TPasGLTFPtrUInt(TPasGLTFPointer(StackItem)) >=
- TPasGLTFPtrUInt(TPasGLTFPointer(@Stack[high(Stack) - 1]))) then
- begin
- // Heap sort
- i := Size div 2;
- repeat
- if i > 0 then
- begin
- dec(i);
- end
- else
- begin
- dec(Size);
- if Size > 0 then
- begin
- Temp := PItemArray(pItems)^[Left + Size];
- PItemArray(pItems)^[Left + Size] := PItemArray(pItems)^[Left];
- PItemArray(pItems)^[Left] := Temp;
- end
- else
- begin
- break;
- end;
- end;
- Parent := i;
- repeat
- Child := (Parent * 2) + 1;
- if Child < Size then
- begin
- if (Child < (Size - 1)) and
- (pCompareFunc(PItemArray(pItems)^[Left + Child],
- PItemArray(pItems)^[Left + Child + 1]) < 0) then
- begin
- inc(Child);
- end;
- if pCompareFunc(PItemArray(pItems)^[Left + Parent],
- PItemArray(pItems)^[Left + Child]) < 0 then
- begin
- Temp := PItemArray(pItems)^[Left + Parent];
- PItemArray(pItems)^[Left + Parent] := PItemArray(pItems)
- ^[Left + Child];
- PItemArray(pItems)^[Left + Child] := Temp;
- Parent := Child;
- continue;
- end;
- end;
- break;
- until false;
- until false;
- end
- else
- begin
- // Quick sort width median-of-three optimization
- Middle := Left + ((Right - Left) shr 1);
- if (Right - Left) > 3 then
- begin
- if pCompareFunc(PItemArray(pItems)^[Left],
- PItemArray(pItems)^[Middle]) > 0 then
- begin
- Temp := PItemArray(pItems)^[Left];
- PItemArray(pItems)^[Left] := PItemArray(pItems)^[Middle];
- PItemArray(pItems)^[Middle] := Temp;
- end;
- if pCompareFunc(PItemArray(pItems)^[Left],
- PItemArray(pItems)^[Right]) > 0 then
- begin
- Temp := PItemArray(pItems)^[Left];
- PItemArray(pItems)^[Left] := PItemArray(pItems)^[Right];
- PItemArray(pItems)^[Right] := Temp;
- end;
- if pCompareFunc(PItemArray(pItems)^[Middle],
- PItemArray(pItems)^[Right]) > 0 then
- begin
- Temp := PItemArray(pItems)^[Middle];
- PItemArray(pItems)^[Middle] := PItemArray(pItems)^[Right];
- PItemArray(pItems)^[Right] := Temp;
- end;
- end;
- Pivot := Middle;
- i := Left;
- j := Right;
- repeat
- while (i < Right) and
- (pCompareFunc(PItemArray(pItems)^[i],
- PItemArray(pItems)^[Pivot]) < 0) do
- begin
- inc(i);
- end;
- while (j >= i) and
- (pCompareFunc(PItemArray(pItems)^[j],
- PItemArray(pItems)^[Pivot]) > 0) do
- begin
- dec(j);
- end;
- if i > j then
- begin
- break;
- end
- else
- begin
- if i <> j then
- begin
- Temp := PItemArray(pItems)^[i];
- PItemArray(pItems)^[i] := PItemArray(pItems)^[j];
- PItemArray(pItems)^[j] := Temp;
- if Pivot = i then
- begin
- Pivot := j;
- end
- else if Pivot = j then
- begin
- Pivot := i;
- end;
- end;
- inc(i);
- dec(j);
- end;
- until false;
- if i < Right then
- begin
- StackItem^.Left := i;
- StackItem^.Right := Right;
- StackItem^.Depth := Depth - 1;
- inc(StackItem);
- end;
- if Left < j then
- begin
- StackItem^.Left := Left;
- StackItem^.Right := j;
- StackItem^.Depth := Depth - 1;
- inc(StackItem);
- end;
- end;
- end;
- end;
- end;
- end;
- constructor TPasGLTFDynamicArray<T>.TValueEnumerator.Create(const aDynamicArray
- : TPasGLTFDynamicArray<T>);
- begin
- fDynamicArray := aDynamicArray;
- fIndex := -1;
- end;
- function TPasGLTFDynamicArray<T>.TValueEnumerator.MoveNext: boolean;
- begin
- inc(fIndex);
- result := fIndex < fDynamicArray.fCount;
- end;
- function TPasGLTFDynamicArray<T>.TValueEnumerator.GetCurrent: T;
- begin
- result := fDynamicArray.fItems[fIndex];
- end;
- constructor TPasGLTFDynamicArray<T>.Create;
- begin
- fItems := nil;
- fCount := 0;
- fAllocated := 0;
- inherited Create;
- end;
- destructor TPasGLTFDynamicArray<T>.Destroy;
- begin
- SetLength(fItems, 0);
- fCount := 0;
- fAllocated := 0;
- inherited Destroy;
- end;
- procedure TPasGLTFDynamicArray<T>.Clear;
- begin
- SetLength(fItems, 0);
- fCount := 0;
- fAllocated := 0;
- end;
- procedure TPasGLTFDynamicArray<T>.SetCount(const pNewCount: TPasGLTFSizeInt);
- begin
- if pNewCount <= 0 then
- begin
- SetLength(fItems, 0);
- fCount := 0;
- fAllocated := 0;
- end
- else
- begin
- if pNewCount < fCount then
- begin
- fCount := pNewCount;
- if (fCount + fCount) < fAllocated then
- begin
- fAllocated := fCount + fCount;
- SetLength(fItems, fAllocated);
- end;
- end
- else
- begin
- fCount := pNewCount;
- if fAllocated < fCount then
- begin
- fAllocated := fCount + fCount;
- SetLength(fItems, fAllocated);
- end;
- end;
- end;
- end;
- function TPasGLTFDynamicArray<T>.GetItem(const pIndex: TPasGLTFSizeInt): T;
- begin
- result := fItems[pIndex];
- end;
- procedure TPasGLTFDynamicArray<T>.SetItem(const pIndex: TPasGLTFSizeInt;
- const pItem: T);
- begin
- fItems[pIndex] := pItem;
- end;
- function TPasGLTFDynamicArray<T>.Add(const pItem: T): TPasGLTFSizeInt;
- begin
- result := fCount;
- inc(fCount);
- if fAllocated < fCount then
- begin
- fAllocated := fCount + fCount;
- SetLength(fItems, fAllocated);
- end;
- fItems[result] := pItem;
- end;
- function TPasGLTFDynamicArray<T>.Add(const pItems: array of T): TPasGLTFSizeInt;
- var
- Index: TPasGLTFSizeInt;
- begin
- result := fCount;
- if Length(pItems) > 0 then
- begin
- inc(fCount, Length(pItems));
- if fAllocated < fCount then
- begin
- fAllocated := fCount + fCount;
- SetLength(fItems, fAllocated);
- end;
- for Index := 0 to Length(pItems) - 1 do
- begin
- fItems[result + Index] := pItems[Index];
- end;
- end;
- end;
- procedure TPasGLTFDynamicArray<T>.Insert(const pIndex: TPasGLTFSizeInt;
- const pItem: T);
- begin
- if pIndex >= 0 then
- begin
- if pIndex < fCount then
- begin
- inc(fCount);
- if fCount < fAllocated then
- begin
- fAllocated := fCount shl 1;
- SetLength(fItems, fAllocated);
- end;
- Move(fItems[pIndex], fItems[pIndex + 1], (fCount - pIndex) * SizeOf(T));
- FillChar(fItems[pIndex], SizeOf(T), #0);
- end
- else
- begin
- fCount := pIndex + 1;
- if fCount < fAllocated then
- begin
- fAllocated := fCount shl 1;
- SetLength(fItems, fAllocated);
- end;
- end;
- fItems[pIndex] := pItem;
- end;
- end;
- procedure TPasGLTFDynamicArray<T>.Delete(const pIndex: TPasGLTFSizeInt);
- begin
- Finalize(fItems[pIndex]);
- Move(fItems[pIndex + 1], fItems[pIndex], (fCount - pIndex) * SizeOf(T));
- dec(fCount);
- FillChar(fItems[fCount], SizeOf(T), #0);
- if fCount < (fAllocated shr 1) then
- begin
- fAllocated := fAllocated shr 1;
- SetLength(fItems, fAllocated);
- end;
- end;
- procedure TPasGLTFDynamicArray<T>.Exchange(const pIndex,
- pWithIndex: TPasGLTFSizeInt);
- var
- Temporary: T;
- begin
- Temporary := fItems[pIndex];
- fItems[pIndex] := fItems[pWithIndex];
- fItems[pWithIndex] := Temporary;
- end;
- function TPasGLTFDynamicArray<T>.Memory: TPasGLTFPointer;
- begin
- result := @fItems[0];
- end;
- function TPasGLTFDynamicArray<T>.GetEnumerator
- : TPasGLTFDynamicArray<T>.TValueEnumerator;
- begin
- result := TValueEnumerator.Create(self);
- end;
- constructor TPasGLTFObjectList<T>.TValueEnumerator.Create(const aObjectList
- : TPasGLTFObjectList<T>);
- begin
- fObjectList := aObjectList;
- fIndex := -1;
- end;
- function TPasGLTFObjectList<T>.TValueEnumerator.MoveNext: boolean;
- begin
- inc(fIndex);
- result := fIndex < fObjectList.fCount;
- end;
- function TPasGLTFObjectList<T>.TValueEnumerator.GetCurrent: T;
- begin
- result := fObjectList.fItems[fIndex];
- end;
- constructor TPasGLTFObjectList<T>.Create;
- begin
- inherited Create;
- fItems := nil;
- fCount := 0;
- fAllocated := 0;
- fOwnsObjects := true;
- end;
- destructor TPasGLTFObjectList<T>.Destroy;
- begin
- Clear;
- inherited Destroy;
- end;
- function TPasGLTFObjectList<T>.RoundUpToPowerOfTwoSizeUInt(x: TPasGLTFSizeUInt)
- : TPasGLTFSizeUInt;
- begin
- dec(x);
- x := x or (x shr 1);
- x := x or (x shr 2);
- x := x or (x shr 4);
- x := x or (x shr 8);
- x := x or (x shr 16);
- {$IFDEF CPU64}
- x := x or (x shr 32);
- {$ENDIF}
- result := x + 1;
- end;
- procedure TPasGLTFObjectList<T>.Clear;
- var
- Index: TPasGLTFSizeInt;
- begin
- if fOwnsObjects then
- begin
- for Index := fCount - 1 downto 0 do
- begin
- FreeAndNil(fItems[Index]);
- end;
- end;
- fItems := nil;
- fCount := 0;
- fAllocated := 0;
- end;
- procedure TPasGLTFObjectList<T>.SetCount(const pNewCount: TPasGLTFSizeInt);
- var
- Index, NewAllocated: TPasGLTFSizeInt;
- begin
- if fCount < pNewCount then
- begin
- NewAllocated := RoundUpToPowerOfTwoSizeUInt(pNewCount);
- if fAllocated < NewAllocated then
- begin
- SetLength(fItems, NewAllocated);
- FillChar(fItems[fAllocated], (NewAllocated - fAllocated) * SizeOf(T), #0);
- fAllocated := NewAllocated;
- end;
- FillChar(fItems[fCount], (pNewCount - fCount) * SizeOf(T), #0);
- fCount := pNewCount;
- end
- else if fCount > pNewCount then
- begin
- if fOwnsObjects then
- begin
- for Index := fCount - 1 downto pNewCount do
- begin
- FreeAndNil(fItems[Index]);
- end;
- end;
- fCount := pNewCount;
- if pNewCount < (fAllocated shr 2) then
- begin
- if pNewCount = 0 then
- begin
- fItems := nil;
- fAllocated := 0;
- end
- else
- begin
- NewAllocated := fAllocated shr 1;
- SetLength(fItems, NewAllocated);
- fAllocated := NewAllocated;
- end;
- end;
- end;
- end;
- function TPasGLTFObjectList<T>.GetItem(const pIndex: TPasGLTFSizeInt): T;
- begin
- if (pIndex < 0) or (pIndex >= fCount) then
- begin
- raise ERangeError.Create('Out of index range');
- end;
- result := fItems[pIndex];
- end;
- procedure TPasGLTFObjectList<T>.SetItem(const pIndex: TPasGLTFSizeInt;
- const pItem: T);
- begin
- if (pIndex < 0) or (pIndex >= fCount) then
- begin
- raise ERangeError.Create('Out of index range');
- end;
- fItems[pIndex] := pItem;
- end;
- function TPasGLTFObjectList<T>.IndexOf(const pItem: T): TPasGLTFSizeInt;
- var
- Index: TPasGLTFSizeInt;
- begin
- for Index := 0 to fCount - 1 do
- begin
- if fItems[Index] = pItem then
- begin
- result := Index;
- exit;
- end;
- end;
- result := -1;
- end;
- function TPasGLTFObjectList<T>.Add(const pItem: T): TPasGLTFSizeInt;
- begin
- result := fCount;
- inc(fCount);
- if fAllocated < fCount then
- begin
- fAllocated := fCount + fCount;
- SetLength(fItems, fAllocated);
- end;
- fItems[result] := pItem;
- end;
- procedure TPasGLTFObjectList<T>.Insert(const pIndex: TPasGLTFSizeInt;
- const pItem: T);
- var
- OldCount: TPasGLTFSizeInt;
- begin
- if pIndex >= 0 then
- begin
- OldCount := fCount;
- if fCount < pIndex then
- begin
- fCount := pIndex + 1;
- end
- else
- begin
- inc(fCount);
- end;
- if fAllocated < fCount then
- begin
- fAllocated := fCount shl 1;
- SetLength(fItems, fAllocated);
- end;
- if OldCount < fCount then
- begin
- FillChar(fItems[OldCount], (fCount - OldCount) * SizeOf(T), #0);
- end;
- if pIndex < OldCount then
- begin
- System.Move(fItems[pIndex], fItems[pIndex + 1],
- (OldCount - pIndex) * SizeOf(T));
- FillChar(fItems[pIndex], SizeOf(T), #0);
- end;
- fItems[pIndex] := pItem;
- end;
- end;
- procedure TPasGLTFObjectList<T>.Delete(const pIndex: TPasGLTFSizeInt);
- var
- Old: T;
- begin
- if (pIndex < 0) or (pIndex >= fCount) then
- begin
- raise ERangeError.Create('Out of index range');
- end;
- Old := fItems[pIndex];
- dec(fCount);
- FillChar(fItems[pIndex], SizeOf(T), #0);
- if pIndex <> fCount then
- begin
- System.Move(fItems[pIndex + 1], fItems[pIndex],
- (fCount - pIndex) * SizeOf(T));
- FillChar(fItems[fCount], SizeOf(T), #0);
- end;
- if fCount < (fAllocated shr 1) then
- begin
- fAllocated := fAllocated shr 1;
- SetLength(fItems, fAllocated);
- end;
- if fOwnsObjects then
- begin
- FreeAndNil(Old);
- end;
- end;
- procedure TPasGLTFObjectList<T>.Remove(const pItem: T);
- var
- Index: TPasGLTFSizeInt;
- begin
- Index := IndexOf(pItem);
- if Index >= 0 then
- begin
- Delete(Index);
- end;
- end;
- procedure TPasGLTFObjectList<T>.Exchange(const pIndex,
- pWithIndex: TPasGLTFSizeInt);
- var
- Temporary: T;
- begin
- if ((pIndex < 0) or (pIndex >= fCount)) or
- ((pWithIndex < 0) or (pWithIndex >= fCount)) then
- begin
- raise ERangeError.Create('Out of index range');
- end;
- Temporary := fItems[pIndex];
- fItems[pIndex] := fItems[pWithIndex];
- fItems[pWithIndex] := Temporary;
- end;
- function TPasGLTFObjectList<T>.GetEnumerator
- : TPasGLTFObjectList<T>.TValueEnumerator;
- begin
- result := TValueEnumerator.Create(self);
- end;
- constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapEntityEnumerator.Create(const aHashMap
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- begin
- fHashMap := aHashMap;
- fIndex := -1;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapEntityEnumerator.GetCurrent: TPasGLTFHashMapEntity;
- begin
- result := fHashMap.fEntities[fIndex];
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapEntityEnumerator.MoveNext: boolean;
- begin
- repeat
- inc(fIndex);
- if fIndex < fHashMap.fSize then
- begin
- if fHashMap.fEntityToCellIndex[fIndex] >= 0 then
- begin
- result := true;
- exit;
- end;
- end
- else
- begin
- break;
- end;
- until false;
- result := false;
- end;
- constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapKeyEnumerator.Create(const aHashMap
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- begin
- fHashMap := aHashMap;
- fIndex := -1;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapKeyEnumerator.GetCurrent: TPasGLTFHashMapKey;
- begin
- result := fHashMap.fEntities[fIndex].Key;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapKeyEnumerator.MoveNext: boolean;
- begin
- repeat
- inc(fIndex);
- if fIndex < fHashMap.fSize then
- begin
- if fHashMap.fEntityToCellIndex[fIndex] >= 0 then
- begin
- result := true;
- exit;
- end;
- end
- else
- begin
- break;
- end;
- until false;
- result := false;
- end;
- constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapValueEnumerator.Create(const aHashMap
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- begin
- fHashMap := aHashMap;
- fIndex := -1;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapValueEnumerator.GetCurrent: TPasGLTFHashMapValue;
- begin
- result := fHashMap.fEntities[fIndex].Value;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapValueEnumerator.MoveNext: boolean;
- begin
- repeat
- inc(fIndex);
- if fIndex < fHashMap.fSize then
- begin
- if fHashMap.fEntityToCellIndex[fIndex] >= 0 then
- begin
- result := true;
- exit;
- end;
- end
- else
- begin
- break;
- end;
- until false;
- result := false;
- end;
- constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapEntitiesObject.Create(const aOwner
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- begin
- inherited Create;
- fOwner := aOwner;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapEntitiesObject.GetEnumerator: TPasGLTFHashMapEntityEnumerator;
- begin
- result := TPasGLTFHashMapEntityEnumerator.Create(fOwner);
- end;
- constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapKeysObject.Create(const aOwner
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- begin
- inherited Create;
- fOwner := aOwner;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapKeysObject.GetEnumerator: TPasGLTFHashMapKeyEnumerator;
- begin
- result := TPasGLTFHashMapKeyEnumerator.Create(fOwner);
- end;
- constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapValuesObject.Create(const aOwner
- : TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>);
- begin
- inherited Create;
- fOwner := aOwner;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapValuesObject.GetEnumerator: TPasGLTFHashMapValueEnumerator;
- begin
- result := TPasGLTFHashMapValueEnumerator.Create(fOwner);
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapValuesObject.GetValue(const Key: TPasGLTFHashMapKey)
- : TPasGLTFHashMapValue;
- begin
- result := fOwner.GetValue(Key);
- end;
- procedure TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.
- TPasGLTFHashMapValuesObject.SetValue(const Key: TPasGLTFHashMapKey;
- const aValue: TPasGLTFHashMapValue);
- begin
- fOwner.SetValue(Key, aValue);
- end;
- constructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Create
- (const DefaultValue: TPasGLTFHashMapValue);
- begin
- inherited Create;
- fRealSize := 0;
- fLogSize := 0;
- fSize := 0;
- fEntities := nil;
- fEntityToCellIndex := nil;
- fCellToEntityIndex := nil;
- fDefaultValue := DefaultValue;
- fCanShrink := true;
- fEntitiesObject := TPasGLTFHashMapEntitiesObject.Create(self);
- fKeysObject := TPasGLTFHashMapKeysObject.Create(self);
- fValuesObject := TPasGLTFHashMapValuesObject.Create(self);
- Resize;
- end;
- destructor TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Destroy;
- var
- Counter: TPasGLTFSizeInt;
- begin
- Clear;
- for Counter := 0 to Length(fEntities) - 1 do
- begin
- Finalize(fEntities[Counter].Key);
- Finalize(fEntities[Counter].Value);
- end;
- SetLength(fEntities, 0);
- SetLength(fEntityToCellIndex, 0);
- SetLength(fCellToEntityIndex, 0);
- FreeAndNil(fEntitiesObject);
- FreeAndNil(fKeysObject);
- FreeAndNil(fValuesObject);
- inherited Destroy;
- end;
- procedure TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Clear;
- var
- Counter: TPasGLTFSizeInt;
- begin
- for Counter := 0 to Length(fEntities) - 1 do
- begin
- Finalize(fEntities[Counter].Key);
- Finalize(fEntities[Counter].Value);
- end;
- if fCanShrink then
- begin
- fRealSize := 0;
- fLogSize := 0;
- fSize := 0;
- SetLength(fEntities, 0);
- SetLength(fEntityToCellIndex, 0);
- SetLength(fCellToEntityIndex, 0);
- Resize;
- end
- else
- begin
- for Counter := 0 to Length(fCellToEntityIndex) - 1 do
- begin
- fCellToEntityIndex[Counter] := ENT_EMPTY;
- end;
- for Counter := 0 to Length(fEntityToCellIndex) - 1 do
- begin
- fEntityToCellIndex[Counter] := CELL_EMPTY;
- end;
- end;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.HashData
- (const Data: TPasGLTFPointer; const DataLength: TPasGLTFSizeUInt)
- : TPasGLTFUInt32;
- // xxHash32
- const
- PRIME32_1 = TPasGLTFUInt32(2654435761);
- PRIME32_2 = TPasGLTFUInt32(2246822519);
- PRIME32_3 = TPasGLTFUInt32(3266489917);
- PRIME32_4 = TPasGLTFUInt32(668265263);
- PRIME32_5 = TPasGLTFUInt32(374761393);
- Seed = TPasGLTFUInt32($1337C0D3);
- v1Initialization = TPasGLTFUInt32
- (TPasGLTFUInt64(TPasGLTFUInt64(Seed) + TPasGLTFUInt64(PRIME32_1) +
- TPasGLTFUInt64(PRIME32_2)));
- v2Initialization = TPasGLTFUInt32
- (TPasGLTFUInt64(TPasGLTFUInt64(Seed) + TPasGLTFUInt64(PRIME32_2)));
- v3Initialization = TPasGLTFUInt32
- (TPasGLTFUInt64(TPasGLTFUInt64(Seed) + TPasGLTFUInt64(0)));
- v4Initialization = TPasGLTFUInt32
- (TPasGLTFUInt64(TPasGLTFInt64(TPasGLTFInt64(Seed) -
- TPasGLTFInt64(PRIME32_1))));
- HashInitialization = TPasGLTFUInt32
- (TPasGLTFUInt64(TPasGLTFUInt64(Seed) + TPasGLTFUInt64(PRIME32_5)));
- var
- v1, v2, v3, v4: TPasGLTFUInt32;
- p, e: PPasGLTFUInt8;
- begin
- p := Data;
- if DataLength >= 16 then
- begin
- v1 := v1Initialization;
- v2 := v2Initialization;
- v3 := v3Initialization;
- v4 := v4Initialization;
- e := @PPasGLTFUInt8Array(Data)^[DataLength - 16];
- repeat
- {$IF defined(fpc) or declared(ROLDWord)}
- v1 := ROLDWord(v1 + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
- TPasGLTFUInt32(PRIME32_2)), 13) * TPasGLTFUInt32(PRIME32_1);
- {$ELSE}
- inc(v1, TPasGLTFUInt32(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_2));
- v1 := ((v1 shl 13) or (v1 shr 19)) * TPasGLTFUInt32(PRIME32_1);
- {$IFEND}
- inc(p, SizeOf(TPasGLTFUInt32));
- {$IF defined(fpc) or declared(ROLDWord)}
- v2 := ROLDWord(v2 + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
- TPasGLTFUInt32(PRIME32_2)), 13) * TPasGLTFUInt32(PRIME32_1);
- {$ELSE}
- inc(v2, TPasGLTFUInt32(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_2));
- v2 := ((v2 shl 13) or (v2 shr 19)) * TPasGLTFUInt32(PRIME32_1);
- {$IFEND}
- inc(p, SizeOf(TPasGLTFUInt32));
- {$IF defined(fpc) or declared(ROLDWord)}
- v3 := ROLDWord(v3 + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
- TPasGLTFUInt32(PRIME32_2)), 13) * TPasGLTFUInt32(PRIME32_1);
- {$ELSE}
- inc(v3, TPasGLTFUInt32(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_2));
- v3 := ((v3 shl 13) or (v3 shr 19)) * TPasGLTFUInt32(PRIME32_1);
- {$IFEND}
- inc(p, SizeOf(TPasGLTFUInt32));
- {$IF defined(fpc) or declared(ROLDWord)}
- v4 := ROLDWord(v4 + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
- TPasGLTFUInt32(PRIME32_2)), 13) * TPasGLTFUInt32(PRIME32_1);
- {$ELSE}
- inc(v4, TPasGLTFUInt32(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_2));
- v4 := ((v4 shl 13) or (v4 shr 19)) * TPasGLTFUInt32(PRIME32_1);
- {$IFEND}
- inc(p, SizeOf(TPasGLTFUInt32));
- until {%H-}TPasGLTFPtrUInt(p) > {%H-}TPasGLTFPtrUInt(e);
- {$IF defined(fpc) or declared(ROLDWord)}
- result := ROLDWord(v1, 1) + ROLDWord(v2, 7) + ROLDWord(v3, 12) +
- ROLDWord(v4, 18);
- {$ELSE}
- result := ((v1 shl 1) or (v1 shr 31)) + ((v2 shl 7) or (v2 shr 25)) +
- ((v3 shl 12) or (v3 shr 20)) + ((v4 shl 18) or (v4 shr 14));
- {$IFEND}
- end
- else
- begin
- result := HashInitialization;
- end;
- inc(result, DataLength);
- e := @PPasGLTFUInt8Array(Data)^[DataLength];
- while ({%H-}TPasGLTFPtrUInt(p) + SizeOf(TPasGLTFUInt32)) <=
- {%H-}TPasGLTFPtrUInt(e) do
- begin
- {$IF defined(fpc) or declared(ROLDWord)}
- result := ROLDWord(result + (TPasGLTFUInt32(TPasGLTFPointer(p)^) *
- TPasGLTFUInt32(PRIME32_3)), 17) * TPasGLTFUInt32(PRIME32_4);
- {$ELSE}
- inc(result, TPasGLTFUInt32(TPasGLTFPointer(p)^) *
- TPasGLTFUInt32(PRIME32_3));
- result := ((result shl 17) or (result shr 15)) * TPasGLTFUInt32(PRIME32_4);
- {$IFEND}
- inc(p, SizeOf(TPasGLTFUInt32));
- end;
- while {%H-}TPasGLTFPtrUInt(p) < {%H-}TPasGLTFPtrUInt(e) do
- begin
- {$IF defined(fpc) or declared(ROLDWord)}
- result := ROLDWord(result + (TPasGLTFUInt8(TPasGLTFPointer(p)^) *
- TPasGLTFUInt32(PRIME32_5)), 11) * TPasGLTFUInt32(PRIME32_1);
- {$ELSE}
- inc(result, TPasGLTFUInt8(TPasGLTFPointer(p)^) * TPasGLTFUInt32(PRIME32_5));
- result := ((result shl 11) or (result shr 21)) * TPasGLTFUInt32(PRIME32_1);
- {$IFEND}
- inc(p, SizeOf(TPasGLTFUInt8));
- end;
- result := (result xor (result shr 15)) * TPasGLTFUInt32(PRIME32_2);
- result := (result xor (result shr 13)) * TPasGLTFUInt32(PRIME32_3);
- result := result xor (result shr 16);
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.HashKey
- (const Key: TPasGLTFHashMapKey): TPasGLTFUInt32;
- begin
- result := HashData(PPasGLTFUInt8(@Key[1]),
- Length(Key) * SizeOf(TPasGLTFRawByteChar));
- {$IF defined(CPU386) or defined(CPUAMD64)}
- // Special case: The hash value may be never zero
- result := result or (-TPasGLTFUInt32(ord(result = 0) and 1));
- {$ELSE}
- if result = 0 then
- begin
- // Special case: The hash value may be never zero
- result := $FFFFFFFF;
- end;
- {$IFEND}
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.CompareKey(const KeyA,
- KeyB: TPasGLTFHashMapKey): boolean;
- begin
- result := KeyA = KeyB;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.FindCell
- (const Key: TPasGLTFHashMapKey): TPasGLTFUInt32;
- var
- HashCode, Mask, Step: TPasGLTFUInt32;
- Entity: TPasGLTFInt32;
- begin
- HashCode := HashKey(Key);
- Mask := (2 shl fLogSize) - 1;
- Step := ((HashCode shl 1) + 1) and Mask;
- if fLogSize <> 0 then
- begin
- result := HashCode shr (32 - fLogSize);
- end
- else
- begin
- result := 0;
- end;
- repeat
- Entity := fCellToEntityIndex[result];
- if (Entity = ENT_EMPTY) or
- ((Entity <> ENT_DELETED) and CompareKey(fEntities[Entity].Key, Key)) then
- begin
- exit;
- end;
- result := (result + Step) and Mask;
- until false;
- end;
- procedure TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Resize;
- var
- NewLogSize, NewSize, Cell, Entity: TPasGLTFInt32;
- Counter: TPasGLTFSizeInt;
- OldEntities: TPasGLTFHashMapEntities;
- OldCellToEntityIndex: TPasGLTFHashMapEntityIndices;
- OldEntityToCellIndex: TPasGLTFHashMapEntityIndices;
- begin
- NewLogSize := 0;
- NewSize := fRealSize;
- while NewSize <> 0 do
- begin
- NewSize := NewSize shr 1;
- inc(NewLogSize);
- end;
- if NewLogSize < 1 then
- begin
- NewLogSize := 1;
- end;
- fSize := 0;
- fRealSize := 0;
- fLogSize := NewLogSize;
- OldEntities := fEntities;
- OldCellToEntityIndex := fCellToEntityIndex;
- OldEntityToCellIndex := fEntityToCellIndex;
- fEntities := nil;
- fCellToEntityIndex := nil;
- fEntityToCellIndex := nil;
- SetLength(fEntities, 2 shl fLogSize);
- SetLength(fCellToEntityIndex, 2 shl fLogSize);
- SetLength(fEntityToCellIndex, 2 shl fLogSize);
- for Counter := 0 to Length(fCellToEntityIndex) - 1 do
- begin
- fCellToEntityIndex[Counter] := ENT_EMPTY;
- end;
- for Counter := 0 to Length(fEntityToCellIndex) - 1 do
- begin
- fEntityToCellIndex[Counter] := CELL_EMPTY;
- end;
- for Counter := 0 to Length(OldEntityToCellIndex) - 1 do
- begin
- Cell := OldEntityToCellIndex[Counter];
- if Cell >= 0 then
- begin
- Entity := OldCellToEntityIndex[Cell];
- if Entity >= 0 then
- begin
- Add(OldEntities[Counter].Key, OldEntities[Counter].Value);
- end;
- end;
- end;
- for Counter := 0 to Length(OldEntities) - 1 do
- begin
- Finalize(OldEntities[Counter].Key);
- Finalize(OldEntities[Counter].Value);
- end;
- SetLength(OldEntities, 0);
- SetLength(OldCellToEntityIndex, 0);
- SetLength(OldEntityToCellIndex, 0);
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Add
- (const Key: TPasGLTFHashMapKey; const Value: TPasGLTFHashMapValue)
- : PPasGLTFHashMapEntity;
- var
- Entity: TPasGLTFInt32;
- Cell: TPasGLTFUInt32;
- begin
- result := nil;
- while fRealSize >= (1 shl fLogSize) do
- begin
- Resize;
- end;
- Cell := FindCell(Key);
- Entity := fCellToEntityIndex[Cell];
- if Entity >= 0 then
- begin
- result := @fEntities[Entity];
- result^.Key := Key;
- result^.Value := Value;
- exit;
- end;
- Entity := fSize;
- inc(fSize);
- if Entity < (2 shl fLogSize) then
- begin
- fCellToEntityIndex[Cell] := Entity;
- fEntityToCellIndex[Entity] := Cell;
- inc(fRealSize);
- result := @fEntities[Entity];
- result^.Key := Key;
- result^.Value := Value;
- end;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Get
- (const Key: TPasGLTFHashMapKey; const CreateIfNotExist: boolean = false)
- : PPasGLTFHashMapEntity;
- var
- Entity: TPasGLTFInt32;
- Cell: TPasGLTFUInt32;
- Value: TPasGLTFHashMapValue;
- begin
- result := nil;
- Cell := FindCell(Key);
- Entity := fCellToEntityIndex[Cell];
- if Entity >= 0 then
- begin
- result := @fEntities[Entity];
- end
- else if CreateIfNotExist then
- begin
- Initialize(Value);
- result := Add(Key, Value);
- end;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.TryGet
- (const Key: TPasGLTFHashMapKey; out Value: TPasGLTFHashMapValue): boolean;
- var
- Entity: TPasGLTFInt32;
- begin
- Entity := fCellToEntityIndex[FindCell(Key)];
- result := Entity >= 0;
- if result then
- begin
- Value := fEntities[Entity].Value;
- end
- else
- begin
- Initialize(Value);
- end;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.ExistKey
- (const Key: TPasGLTFHashMapKey): boolean;
- begin
- result := fCellToEntityIndex[FindCell(Key)] >= 0;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.Delete
- (const Key: TPasGLTFHashMapKey): boolean;
- var
- Entity: TPasGLTFInt32;
- Cell: TPasGLTFUInt32;
- begin
- result := false;
- Cell := FindCell(Key);
- Entity := fCellToEntityIndex[Cell];
- if Entity >= 0 then
- begin
- Finalize(fEntities[Entity].Key);
- Finalize(fEntities[Entity].Value);
- fEntityToCellIndex[Entity] := CELL_DELETED;
- fCellToEntityIndex[Cell] := ENT_DELETED;
- result := true;
- end;
- end;
- function TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.GetValue
- (const Key: TPasGLTFHashMapKey): TPasGLTFHashMapValue;
- var
- Entity: TPasGLTFInt32;
- Cell: TPasGLTFUInt32;
- begin
- Cell := FindCell(Key);
- Entity := fCellToEntityIndex[Cell];
- if Entity >= 0 then
- begin
- result := fEntities[Entity].Value;
- end
- else
- begin
- result := fDefaultValue;
- end;
- end;
- procedure TPasGLTFUTF8StringHashMap<TPasGLTFHashMapValue>.SetValue
- (const Key: TPasGLTFHashMapKey; const Value: TPasGLTFHashMapValue);
- begin
- Add(Key, Value);
- end;
- { TPasGLTF }
- class function TPasGLTF.ResolveURIToPath(const aURI: TPasGLTFUTF8String)
- : TPasGLTFUTF8String;
- begin
- result := TPasGLTFUTF8String(StringReplace(String(aURI),
- {$IFDEF Windows}'/', '\'{$ELSE}'\', '/'{$ENDIF}, [rfReplaceAll]));
- end;
- { TPasGLTF.TBase64 }
- class function TPasGLTF.TBase64.Encode(const aData;
- const aDataLength: TPasGLTFSizeInt): TPasGLTFRawByteString;
- var
- Index, BitCount, OutputIndex: TPasGLTFSizeInt;
- Value: TPasGLTFUInt32;
- begin
- result := '';
- if aDataLength > 0 then
- begin
- SetLength(result, (((aDataLength * 4) div 3) + 3) and not 3);
- OutputIndex := 0;
- Value := 0;
- BitCount := -6;
- for Index := 0 to aDataLength - 1 do
- begin
- Value := (Value shl 8) or PPasGLTFUInt8Array(@aData)^[Index];
- inc(BitCount, 8);
- while BitCount >= 0 do
- begin
- result[Low(result) + OutputIndex] := EncodingLookUpTable
- [(Value shr BitCount) and 63];
- inc(OutputIndex);
- dec(BitCount, 6);
- end;
- end;
- if BitCount > -6 then
- begin
- result[Low(result) + OutputIndex] := EncodingLookUpTable
- [((Value shl 8) shr (BitCount + 8)) and 63];
- inc(OutputIndex);
- end;
- while (OutputIndex and 3) <> 0 do
- begin
- result[Low(result) + OutputIndex] := '=';
- inc(OutputIndex);
- end;
- SetLength(result, OutputIndex);
- end;
- end;
- class function TPasGLTF.TBase64.Encode(const aData: array of TPasGLTFUInt8)
- : TPasGLTFRawByteString;
- begin
- result := Encode(aData[0], Length(aData));
- end;
- class function TPasGLTF.TBase64.Encode(const aData: TPasGLTFRawByteString)
- : TPasGLTFRawByteString;
- begin
- result := Encode(aData[Low(aData)], Length(aData));
- end;
- class function TPasGLTF.TBase64.Encode(const aData: TStream)
- : TPasGLTFRawByteString;
- var
- Bytes: TPasGLTFUInt8DynamicArray;
- begin
- Bytes := nil;
- try
- SetLength(Bytes, aData.Size);
- aData.Seek(0, soBeginning);
- aData.ReadBuffer(Bytes[0], aData.Size);
- result := Encode(Bytes[0], Length(Bytes));
- finally
- Bytes := nil;
- end;
- end;
- class function TPasGLTF.TBase64.Decode(const aInput: TPasGLTFRawByteString;
- const aOutput: TStream): boolean;
- var
- Index, Size, BitCount, OutputIndex, LookUpTableValue,
- Remaining: TPasGLTFSizeInt;
- Value: TPasGLTFUInt32;
- Buffer: TPasGLTFUInt8DynamicArray;
- begin
- result := false;
- Buffer := nil;
- try
- Size := Length(aInput);
- if Size > 0 then
- begin
- if (Size and 3) = 0 then
- begin
- result := true;
- SetLength(Buffer, (Size * 3) shr 2);
- Value := 0;
- BitCount := -8;
- OutputIndex := 0;
- try
- for Index := 1 to Size do
- begin
- LookUpTableValue := DecodingLookUpTable[aInput[Index]];
- if LookUpTableValue >= 0 then
- begin
- Value := (Value shl 6) or LookUpTableValue;
- inc(BitCount, 6);
- while BitCount >= 0 do
- begin
- Buffer[OutputIndex] := (Value shr BitCount) and $FF;
- inc(OutputIndex);
- dec(BitCount, 8);
- end;
- end
- else
- begin
- case aInput[Index] of
- '=':
- begin
- Remaining := Size - Index;
- if (Remaining > 1) or
- ((Remaining = 1) and (aInput[Index + 1] <> '=')) then
- begin
- result := false;
- end;
- end;
- else
- begin
- result := false;
- end;
- end;
- break;
- end;
- end;
- finally
- SetLength(Buffer, OutputIndex);
- end;
- if result then
- begin
- aOutput.WriteBuffer(Buffer[0], OutputIndex);
- end;
- end;
- end
- else
- begin
- result := true;
- end;
- finally
- Buffer := nil;
- end;
- end;
- { TPasGLTF.TBaseObject }
- constructor TPasGLTF.TBaseObject.Create(const aDocument: TDocument);
- begin
- inherited Create;
- fDocument := aDocument;
- end;
- destructor TPasGLTF.TBaseObject.Destroy;
- begin
- inherited Destroy;
- end;
- { TPasGLTF.TBaseExtensionsExtrasObject }
- constructor TPasGLTF.TBaseExtensionsExtrasObject.Create(const aDocument
- : TDocument);
- begin
- inherited Create(aDocument);
- fExtensions := TPasJSONItemObject.Create;
- fExtras := TPasJSONItemObject.Create;
- end;
- destructor TPasGLTF.TBaseExtensionsExtrasObject.Destroy;
- begin
- FreeAndNil(fExtensions);
- FreeAndNil(fExtras);
- inherited Destroy;
- end;
- { TPasGLTF.TAccessor.TComponentTypeHelper }
- function TPasGLTF.TAccessor.TComponentTypeHelper.GetSize: TPasGLTFSizeInt;
- begin
- case self of
- TPasGLTF.TAccessor.TComponentType.SignedByte:
- begin
- result := SizeOf(TPasGLTFInt8);
- end;
- TPasGLTF.TAccessor.TComponentType.UnsignedByte:
- begin
- result := SizeOf(TPasGLTFUInt8);
- end;
- TPasGLTF.TAccessor.TComponentType.SignedShort:
- begin
- result := SizeOf(TPasGLTFInt16);
- end;
- TPasGLTF.TAccessor.TComponentType.UnsignedShort:
- begin
- result := SizeOf(TPasGLTFUInt16);
- end;
- TPasGLTF.TAccessor.TComponentType.UnsignedInt:
- begin
- result := SizeOf(TPasGLTFUInt32);
- end;
- TPasGLTF.TAccessor.TComponentType.Float:
- begin
- result := SizeOf(TPasGLTFFloat);
- end;
- else { TPasGLTF.TAccessor.TComponentType.None: }
- begin
- result := 0;
- Assert(false);
- end;
- end;
- end;
- { TPasGLTF.TAccessor.TTypeHelper }
- function TPasGLTF.TAccessor.TTypeHelper.GetComponentCount: TPasGLTFSizeInt;
- begin
- result := TPasGLTF.TAccessor.TypeComponentCountTable[self];
- end;
- { TPasGLTF.TAccessor.TSparse.TIndices }
- constructor TPasGLTF.TAccessor.TSparse.TIndices.Create(const aDocument
- : TDocument);
- begin
- inherited Create(aDocument);
- fComponentType := TComponentType.None;
- fBufferView := 0;
- fByteOffset := 0;
- fEmpty := false;
- end;
- destructor TPasGLTF.TAccessor.TSparse.TIndices.Destroy;
- begin
- inherited Destroy;
- end;
- { TPasGLTF.TAccessor.TSparse.TValues }
- constructor TPasGLTF.TAccessor.TSparse.TValues.Create(const aDocument
- : TDocument);
- begin
- inherited Create(aDocument);
- fBufferView := 0;
- fByteOffset := 0;
- fEmpty := false;
- end;
- destructor TPasGLTF.TAccessor.TSparse.TValues.Destroy;
- begin
- inherited Destroy;
- end;
- { TPasGLTF.TAccessor.TSparse }
- constructor TPasGLTF.TAccessor.TSparse.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fCount := 0;
- fIndices := TIndices.Create(fDocument);
- fValues := TValues.Create(fDocument);
- end;
- destructor TPasGLTF.TAccessor.TSparse.Destroy;
- begin
- FreeAndNil(fIndices);
- FreeAndNil(fValues);
- inherited Destroy;
- end;
- function TPasGLTF.TAccessor.TSparse.GetEmpty: boolean;
- begin
- result := fCount = 0;
- end;
- { TPasGLTF.TAccessor }
- constructor TPasGLTF.TAccessor.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fComponentType := TComponentType.None;
- fType := TType.None;
- fBufferView := -1;
- fByteOffset := 0;
- fCount := 0;
- fNormalized := TDefaults.AccessorNormalized;
- fMinArray := TMinMaxDynamicArray.Create;
- fMaxArray := TMinMaxDynamicArray.Create;
- fSparse := TSparse.Create(fDocument);
- end;
- destructor TPasGLTF.TAccessor.Destroy;
- begin
- FreeAndNil(fMinArray);
- FreeAndNil(fMaxArray);
- FreeAndNil(fSparse);
- inherited Destroy;
- end;
- function TPasGLTF.TAccessor.DecodeAsDoubleArray(const aForVertex
- : boolean = true): TPasGLTFDoubleDynamicArray;
- var
- Index, ComponentIndex, ComponentCount, ComponentSize, ElementSize, SkipEvery,
- SkipBytes, IndicesComponentSize, Base: TPasGLTFSizeInt;
- Indices, Values: TPasGLTFDoubleDynamicArray;
- begin
- ComponentCount := fType.GetComponentCount;
- ComponentSize := fComponentType.GetSize;
- ElementSize := ComponentSize * ComponentCount;
- SkipEvery := 0;
- SkipBytes := 0;
- case fComponentType of
- TPasGLTF.TAccessor.TComponentType.SignedByte,
- TPasGLTF.TAccessor.TComponentType.UnsignedByte:
- begin
- case fType of
- TPasGLTF.TAccessor.TType.Mat2:
- begin
- SkipEvery := 2;
- SkipBytes := 2;
- ElementSize := 8;
- end;
- TPasGLTF.TAccessor.TType.Mat3:
- begin
- SkipEvery := 3;
- SkipBytes := 1;
- ElementSize := 12;
- end;
- end;
- end;
- TPasGLTF.TAccessor.TComponentType.SignedShort,
- TPasGLTF.TAccessor.TComponentType.UnsignedShort:
- begin
- case fType of
- TPasGLTF.TAccessor.TType.Mat3:
- begin
- SkipEvery := 6;
- SkipBytes := 4;
- ElementSize := 16;
- end;
- end;
- end;
- end;
- result := nil;
- if fBufferView >= 0 then
- begin
- if fBufferView < fDocument.fBufferViews.Count then
- begin
- result := fDocument.fBufferViews[fBufferView].Decode(SkipEvery, SkipBytes,
- ElementSize, fCount, fType, ComponentCount, fComponentType,
- ComponentSize, fByteOffset, fNormalized, aForVertex);
- end
- else
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- end
- else
- begin
- SetLength(result, ComponentCount * fCount);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index] := 0;
- end;
- end;
- if fSparse.fCount > 0 then
- begin
- if (fSparse.fIndices.fBufferView >= 0) and
- (fSparse.fIndices.fBufferView < fDocument.fBufferViews.Count) then
- begin
- IndicesComponentSize := fSparse.fIndices.fComponentType.GetSize;
- Indices := fDocument.fBufferViews[fSparse.fIndices.fBufferView]
- .Decode(0, 0, IndicesComponentSize, fSparse.fCount, TType.Scalar, 1,
- fSparse.fIndices.fComponentType, IndicesComponentSize,
- fSparse.fIndices.fByteOffset, false, false);
- if (fSparse.fValues.fBufferView >= 0) and
- (fSparse.fValues.fBufferView < fDocument.fBufferViews.Count) then
- begin
- Values := fDocument.fBufferViews[fSparse.fValues.fBufferView]
- .Decode(SkipEvery, SkipBytes, ElementSize, fSparse.fCount, fType,
- ComponentCount, fComponentType, ComponentSize,
- fSparse.fValues.fByteOffset, fNormalized, aForVertex);
- for Index := 0 to Length(Indices) - 1 do
- begin
- Base := trunc(Indices[Index]) * ComponentCount;
- for ComponentIndex := 0 to ComponentCount - 1 do
- begin
- result[Base + ComponentIndex] :=
- Values[(Index * ComponentCount) + ComponentIndex];
- end;
- end;
- end
- else
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- end
- else
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsInt32Array(const aForVertex: boolean)
- : TPasGLTFInt32DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- SetLength(result, Length(DoubleArray));
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index] := trunc(DoubleArray[Index]);
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsUInt32Array(const aForVertex: boolean)
- : TPasGLTFUInt32DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- SetLength(result, Length(DoubleArray));
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index] := trunc(DoubleArray[Index]);
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsInt64Array(const aForVertex: boolean)
- : TPasGLTFInt64DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- SetLength(result, Length(DoubleArray));
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index] := trunc(DoubleArray[Index]);
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsUInt64Array(const aForVertex: boolean)
- : TPasGLTFUInt64DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- SetLength(result, Length(DoubleArray));
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index] := trunc(DoubleArray[Index]);
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsFloatArray(const aForVertex: boolean)
- : TPasGLTFFloatDynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- SetLength(result, Length(DoubleArray));
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index] := DoubleArray[Index];
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsVector2Array(const aForVertex: boolean)
- : TVector2DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- Assert((Length(DoubleArray) and 1) = 0);
- SetLength(result, Length(DoubleArray) shr 1);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := DoubleArray[(Index shl 1) or 0];
- result[Index, 1] := DoubleArray[(Index shl 1) or 1];
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsVector3Array(const aForVertex: boolean)
- : TVector3DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- Assert((Length(DoubleArray) mod 3) = 0);
- SetLength(result, Length(DoubleArray) div 3);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := DoubleArray[(Index * 3) + 0];
- result[Index, 1] := DoubleArray[(Index * 3) + 1];
- result[Index, 2] := DoubleArray[(Index * 3) + 2];
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsVector4Array(const aForVertex: boolean)
- : TVector4DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- Assert((Length(DoubleArray) and 3) = 0);
- SetLength(result, Length(DoubleArray) shr 2);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := DoubleArray[(Index shl 2) or 0];
- result[Index, 1] := DoubleArray[(Index shl 2) or 1];
- result[Index, 2] := DoubleArray[(Index shl 2) or 2];
- result[Index, 3] := DoubleArray[(Index shl 2) or 3];
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsInt32Vector4Array(const aForVertex: boolean)
- : TInt32Vector4DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- Assert((Length(DoubleArray) and 3) = 0);
- SetLength(result, Length(DoubleArray) shr 2);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := trunc(DoubleArray[(Index shl 2) or 0]);
- result[Index, 1] := trunc(DoubleArray[(Index shl 2) or 1]);
- result[Index, 2] := trunc(DoubleArray[(Index shl 2) or 2]);
- result[Index, 3] := trunc(DoubleArray[(Index shl 2) or 3]);
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsUInt32Vector4Array(const aForVertex
- : boolean): TUInt32Vector4DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- Assert((Length(DoubleArray) and 3) = 0);
- SetLength(result, Length(DoubleArray) shr 2);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := trunc(DoubleArray[(Index shl 2) or 0]);
- result[Index, 1] := trunc(DoubleArray[(Index shl 2) or 1]);
- result[Index, 2] := trunc(DoubleArray[(Index shl 2) or 2]);
- result[Index, 3] := trunc(DoubleArray[(Index shl 2) or 3]);
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsColorArray(const aForVertex: boolean = true)
- : TVector4DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- if fType = TType.Vec3 then
- begin
- Assert((Length(DoubleArray) mod 3) = 0);
- SetLength(result, Length(DoubleArray) div 3);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := DoubleArray[(Index * 3) + 0];
- result[Index, 1] := DoubleArray[(Index * 3) + 1];
- result[Index, 2] := DoubleArray[(Index * 3) + 2];
- result[Index, 3] := 1.0;
- end;
- end
- else
- begin
- Assert((Length(DoubleArray) and 3) = 0);
- SetLength(result, Length(DoubleArray) shr 2);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := DoubleArray[(Index shl 2) or 0];
- result[Index, 1] := DoubleArray[(Index shl 2) or 1];
- result[Index, 2] := DoubleArray[(Index shl 2) or 2];
- result[Index, 3] := DoubleArray[(Index shl 2) or 3];
- end;
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsMatrix2x2Array(const aForVertex
- : boolean = true): TMatrix2x2DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- Assert((Length(DoubleArray) and 3) = 0);
- SetLength(result, Length(DoubleArray) shr 2);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := DoubleArray[(Index shl 2) or 0];
- result[Index, 1] := DoubleArray[(Index shl 2) or 1];
- result[Index, 2] := DoubleArray[(Index shl 2) or 2];
- result[Index, 3] := DoubleArray[(Index shl 2) or 3];
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsMatrix3x3Array(const aForVertex
- : boolean = true): TMatrix3x3DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- Assert((Length(DoubleArray) mod 9) = 0);
- SetLength(result, Length(DoubleArray) div 9);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := DoubleArray[(Index * 9) + 0];
- result[Index, 1] := DoubleArray[(Index * 9) + 1];
- result[Index, 2] := DoubleArray[(Index * 9) + 2];
- result[Index, 3] := DoubleArray[(Index * 9) + 3];
- result[Index, 4] := DoubleArray[(Index * 9) + 4];
- result[Index, 5] := DoubleArray[(Index * 9) + 5];
- result[Index, 6] := DoubleArray[(Index * 9) + 6];
- result[Index, 7] := DoubleArray[(Index * 9) + 7];
- result[Index, 8] := DoubleArray[(Index * 9) + 8];
- end;
- end;
- function TPasGLTF.TAccessor.DecodeAsMatrix4x4Array(const aForVertex
- : boolean = true): TMatrix4x4DynamicArray;
- var
- Index: TPasGLTFSizeInt;
- DoubleArray: TPasGLTFDoubleDynamicArray;
- begin
- result := nil;
- DoubleArray := DecodeAsDoubleArray(aForVertex);
- Assert((Length(DoubleArray) and 15) = 0);
- SetLength(result, Length(DoubleArray) shr 4);
- for Index := 0 to Length(result) - 1 do
- begin
- result[Index, 0] := DoubleArray[(Index shl 4) or 0];
- result[Index, 1] := DoubleArray[(Index shl 4) or 1];
- result[Index, 2] := DoubleArray[(Index shl 4) or 2];
- result[Index, 3] := DoubleArray[(Index shl 4) or 3];
- result[Index, 4] := DoubleArray[(Index shl 4) or 4];
- result[Index, 5] := DoubleArray[(Index shl 4) or 5];
- result[Index, 6] := DoubleArray[(Index shl 4) or 6];
- result[Index, 7] := DoubleArray[(Index shl 4) or 7];
- result[Index, 8] := DoubleArray[(Index shl 4) or 8];
- result[Index, 9] := DoubleArray[(Index shl 4) or 9];
- result[Index, 10] := DoubleArray[(Index shl 4) or 10];
- result[Index, 11] := DoubleArray[(Index shl 4) or 11];
- result[Index, 12] := DoubleArray[(Index shl 4) or 12];
- result[Index, 13] := DoubleArray[(Index shl 4) or 13];
- result[Index, 14] := DoubleArray[(Index shl 4) or 14];
- result[Index, 15] := DoubleArray[(Index shl 4) or 15];
- end;
- end;
- { TPasGLTF.TAnimation.TChannel.TTarget }
- constructor TPasGLTF.TAnimation.TChannel.TTarget.Create(const aDocument
- : TDocument);
- begin
- inherited Create(aDocument);
- fNode := -1;
- fPath := '';
- fEmpty := false;
- end;
- destructor TPasGLTF.TAnimation.TChannel.TTarget.Destroy;
- begin
- inherited Destroy;
- end;
- { TPasGLTF.TAnimation.TChannel }
- constructor TPasGLTF.TAnimation.TChannel.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fSampler := -1;
- fTarget := TTarget.Create(aDocument);
- end;
- destructor TPasGLTF.TAnimation.TChannel.Destroy;
- begin
- FreeAndNil(fTarget);
- inherited Destroy;
- end;
- { TPasGLTF.TAnimation.TSampler }
- constructor TPasGLTF.TAnimation.TSampler.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fInput := -1;
- fOutput := -1;
- fInterpolation := TType.Linear;
- end;
- destructor TPasGLTF.TAnimation.TSampler.Destroy;
- begin
- inherited Destroy;
- end;
- { TPasGLTF.TAnimation }
- constructor TPasGLTF.TAnimation.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fName := '';
- fChannels := TChannels.Create;
- fSamplers := TSamplers.Create;
- end;
- destructor TPasGLTF.TAnimation.Destroy;
- begin
- FreeAndNil(fChannels);
- FreeAndNil(fSamplers);
- inherited Destroy;
- end;
- { TPasGLTF.TAsset }
- constructor TPasGLTF.TAsset.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fCopyright := '';
- fGenerator := '';
- fMinVersion := '';
- fVersion := '2.0';
- fEmpty := false;
- end;
- destructor TPasGLTF.TAsset.Destroy;
- begin
- inherited Destroy;
- end;
- { TPasGLTF.TBuffer }
- constructor TPasGLTF.TBuffer.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fByteLength := 0;
- fName := '';
- fURI := '';
- fData := TMemoryStream.Create;
- end;
- destructor TPasGLTF.TBuffer.Destroy;
- begin
- FreeAndNil(fData);
- inherited Destroy;
- end;
- procedure TPasGLTF.TBuffer.SetEmbeddedResourceData;
- begin
- fURI := 'data:' + MimeTypeApplicationOctet + ';base64,' +
- TBase64.Encode(fData);
- end;
- { TPasGLTF.TBufferView }
- constructor TPasGLTF.TBufferView.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fName := '';
- fBuffer := -1;
- fByteOffset := 0;
- fByteLength := 0;
- fByteStride := 0;
- fTarget := TTargetType.None;
- end;
- destructor TPasGLTF.TBufferView.Destroy;
- begin
- inherited Destroy;
- end;
- function TPasGLTF.TBufferView.Decode(const aSkipEvery: TPasGLTFSizeUInt;
- const aSkipBytes: TPasGLTFSizeUInt; const aElementSize: TPasGLTFSizeUInt;
- const aCount: TPasGLTFSizeUInt; const aType: TPasGLTF.TAccessor.TType;
- const aComponentCount: TPasGLTFSizeUInt;
- const aComponentType: TPasGLTF.TAccessor.TComponentType;
- const aComponentSize: TPasGLTFSizeUInt; const aByteOffset: TPasGLTFSizeUInt;
- const aNormalized: boolean; const aForVertex: boolean)
- : TPasGLTFDoubleDynamicArray;
- var
- Stride, Offset, Index, ComponentIndex, OutputIndex: TPasGLTFSizeUInt;
- Buffer: TPasGLTF.TBuffer;
- BufferData, Source: PPasGLTFUInt8Array;
- Value: TPasGLTFDouble;
- begin
- result := nil;
- Buffer := fDocument.fBuffers[fBuffer];
- if fByteStride <> 0 then
- begin
- Stride := fByteStride;
- end
- else
- begin
- Stride := aElementSize;
- end;
- if aForVertex and ((Stride and 3) <> 0) then
- begin
- inc(Stride, 4 - (Stride and 3));
- end;
- SetLength(result, aCount * aComponentCount);
- Offset := fByteOffset + aByteOffset;
- BufferData := Buffer.fData.Memory;
- if (((Stride * (aCount - 1)) + aElementSize) > fByteLength) or
- ((Offset + ((Stride * (aCount - 1)) + aElementSize)) >
- TPasGLTFSizeUInt(Buffer.fData.Size)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid document');
- end;
- OutputIndex := 0;
- for Index := 1 to aCount do
- begin
- Source := @BufferData^[Offset + ((Index - 1) * Stride)];
- for ComponentIndex := 1 to aComponentCount do
- begin
- if (aSkipEvery > 0) and (ComponentIndex > 1) and
- (((ComponentIndex - 1) mod aSkipEvery) = 0) then
- begin
- Source := @Source^[aSkipBytes];
- end;
- Value := 0.0;
- case aComponentType of
- TPasGLTF.TAccessor.TComponentType.SignedByte:
- begin
- if aNormalized then
- begin
- Value := TPasGLTFInt8(TPasGLTFPointer(@Source^[0])^) / 128.0;
- end
- else
- begin
- Value := TPasGLTFInt8(TPasGLTFPointer(@Source^[0])^);
- end;
- end;
- TPasGLTF.TAccessor.TComponentType.UnsignedByte:
- begin
- if aNormalized then
- begin
- Value := TPasGLTFUInt8(TPasGLTFPointer(@Source^[0])^) / 255.0;
- end
- else
- begin
- Value := TPasGLTFUInt8(TPasGLTFPointer(@Source^[0])^);
- end;
- end;
- TPasGLTF.TAccessor.TComponentType.SignedShort:
- begin
- if aNormalized then
- begin
- Value := TPasGLTFInt16(TPasGLTFPointer(@Source^[0])^) / 32768.0;
- end
- else
- begin
- Value := TPasGLTFInt16(TPasGLTFPointer(@Source^[0])^);
- end;
- end;
- TPasGLTF.TAccessor.TComponentType.UnsignedShort:
- begin
- if aNormalized then
- begin
- Value := TPasGLTFUInt16(TPasGLTFPointer(@Source^[0])^) / 65535.0;
- end
- else
- begin
- Value := TPasGLTFUInt16(TPasGLTFPointer(@Source^[0])^);
- end;
- end;
- TPasGLTF.TAccessor.TComponentType.UnsignedInt:
- begin
- if aNormalized then
- begin
- Value := TPasGLTFUInt32(TPasGLTFPointer(@Source^[0])^) /
- 4294967295.0;
- end
- else
- begin
- Value := TPasGLTFUInt32(TPasGLTFPointer(@Source^[0])^);
- end;
- end;
- TPasGLTF.TAccessor.TComponentType.Float:
- begin
- Value := TPasGLTFFloat(TPasGLTFPointer(@Source^[0])^);
- end;
- else { TPasGLTF.TAccessor.TComponentType.None: }
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid document');
- end;
- end;
- result[OutputIndex] := Value;
- inc(OutputIndex);
- Source := @Source^[aComponentSize];
- end;
- end;
- end;
- { TPasGLTF.TCamera.TOrthographic }
- constructor TPasGLTF.TCamera.TOrthographic.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fXMag := TDefaults.FloatSentinel;
- fYMag := TDefaults.FloatSentinel;
- fZNear := -TDefaults.FloatSentinel;
- fZFar := -TDefaults.FloatSentinel;
- fEmpty := false;
- end;
- destructor TPasGLTF.TCamera.TOrthographic.Destroy;
- begin
- inherited Destroy;
- end;
- { TPasGLTF.TCamera.TPerspective }
- constructor TPasGLTF.TCamera.TPerspective.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fAspectRatio := 1.778;
- fYFov := 0.252;
- fZNear := 0.1;
- fZFar := 1000.0;
- fEmpty := false;
- end;
- destructor TPasGLTF.TCamera.TPerspective.Destroy;
- begin
- inherited Destroy;
- end;
- { TPasGLTF.TCamera }
- constructor TPasGLTF.TCamera.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fType := TType.None;
- fOrthographic := TOrthographic.Create(fDocument);
- fPerspective := TPerspective.Create(fDocument);
- end;
- destructor TPasGLTF.TCamera.Destroy;
- begin
- FreeAndNil(fOrthographic);
- FreeAndNil(fPerspective);
- inherited Destroy;
- end;
- { TPasGLTF.TImage }
- constructor TPasGLTF.TImage.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fBufferView := -1;
- fName := '';
- fURI := '';
- fMimeType := '';
- end;
- destructor TPasGLTF.TImage.Destroy;
- begin
- inherited Destroy;
- end;
- procedure TPasGLTF.TImage.SetEmbeddedResourceData(const aStream: TStream);
- begin
- fURI := 'data:' + fMimeType + ';base64,' + TBase64.Encode(aStream);
- end;
- procedure TPasGLTF.TImage.GetResourceData(const aStream: TStream);
- var
- BufferView: TBufferView;
- Buffer: TBuffer;
- begin
- if fBufferView >= 0 then
- begin
- if fBufferView < fDocument.fBufferViews.Count then
- begin
- BufferView := fDocument.fBufferViews[fBufferView];
- if (BufferView.fBuffer >= 0) and
- (BufferView.fBuffer < fDocument.fBuffers.Count) then
- begin
- Buffer := fDocument.fBuffers[BufferView.fBuffer];
- if (BufferView.fByteOffset + BufferView.fByteLength) <= Buffer.fData.Size
- then
- begin
- aStream.WriteBuffer(PPasGLTFUInt8Array(Buffer.fData.Memory)
- ^[BufferView.fByteOffset], BufferView.fByteLength);
- aStream.Seek(-BufferView.fByteLength, soCurrent);
- end
- else
- begin
- raise EInOutError.Create('I/O error');
- end;
- end
- else
- begin
- raise EInOutError.Create('I/O error');
- end;
- end
- else
- begin
- raise EInOutError.Create('I/O error');
- end;
- end
- else
- begin
- fDocument.LoadURISource(fURI, aStream);
- end;
- end;
- function TPasGLTF.TImage.IsExternalResource: boolean;
- begin
- result := not((fBufferView >= 0) or (pos('data:', fURI) = 1));
- end;
- { TPasGLTF.TMaterial.TTexture }
- constructor TPasGLTF.TMaterial.TTexture.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fIndex := -1;
- fTexCoord := 0;
- end;
- destructor TPasGLTF.TMaterial.TTexture.Destroy;
- begin
- inherited Destroy;
- end;
- function TPasGLTF.TMaterial.TTexture.GetEmpty: boolean;
- begin
- result := fIndex < 0;
- end;
- { TPasGLTF.TMaterial.TNormalTexture }
- constructor TPasGLTF.TMaterial.TNormalTexture.Create(const aDocument
- : TDocument);
- begin
- inherited Create(aDocument);
- fScale := TDefaults.IdentityScalar;
- end;
- { TPasGLTF.TMaterial.TOcclusionTexture }
- constructor TPasGLTF.TMaterial.TOcclusionTexture.Create(const aDocument
- : TDocument);
- begin
- inherited Create(aDocument);
- fStrength := TDefaults.IdentityScalar;
- end;
- { TPasGLTF.TMaterial.TPBRMetallicRoughness }
- constructor TPasGLTF.TMaterial.TPBRMetallicRoughness.Create(const aDocument
- : TDocument);
- begin
- inherited Create(aDocument);
- fBaseColorFactor := TDefaults.IdentityVector4;
- fBaseColorTexture := TTexture.Create(fDocument);
- fRoughnessFactor := TDefaults.IdentityScalar;
- fMetallicFactor := TDefaults.IdentityScalar;
- fMetallicRoughnessTexture := TTexture.Create(fDocument);
- end;
- destructor TPasGLTF.TMaterial.TPBRMetallicRoughness.Destroy;
- begin
- FreeAndNil(fBaseColorTexture);
- FreeAndNil(fMetallicRoughnessTexture);
- inherited Destroy;
- end;
- function TPasGLTF.TMaterial.TPBRMetallicRoughness.GetEmpty: boolean;
- begin
- result := fBaseColorTexture.Empty and fMetallicRoughnessTexture.Empty and
- SameValue(fRoughnessFactor, TDefaults.IdentityScalar) and
- SameValue(fMetallicFactor, TDefaults.IdentityScalar);
- end;
- { TPasGLTF.TMaterial }
- constructor TPasGLTF.TMaterial.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fName := '';
- fAlphaCutOff := TDefaults.MaterialAlphaCutoff;
- fAlphaMode := TAlphaMode.Opaque;
- fDoubleSided := TDefaults.MaterialDoubleSided;
- fNormalTexture := TNormalTexture.Create(fDocument);
- fOcclusionTexture := TOcclusionTexture.Create(fDocument);
- fPBRMetallicRoughness := TPBRMetallicRoughness.Create(fDocument);
- fEmissiveTexture := TTexture.Create(fDocument);
- fEmissiveFactor := TDefaults.NullVector3;
- end;
- destructor TPasGLTF.TMaterial.Destroy;
- begin
- FreeAndNil(fNormalTexture);
- FreeAndNil(fOcclusionTexture);
- FreeAndNil(fPBRMetallicRoughness);
- FreeAndNil(fEmissiveTexture);
- inherited Destroy;
- end;
- { TPasGLTF.TMesh.TPrimitive }
- constructor TPasGLTF.TMesh.TPrimitive.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fMode := TMode.Triangles;
- fIndices := -1;
- fMaterial := -1;
- fAttributes := TAttributes.Create(-1);
- fTargets := TAttributesList.Create;
- end;
- destructor TPasGLTF.TMesh.TPrimitive.Destroy;
- begin
- FreeAndNil(fAttributes);
- FreeAndNil(fTargets);
- inherited Destroy;
- end;
- { TPasGLTF.TMesh }
- constructor TPasGLTF.TMesh.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fName := '';
- fWeights := TWeights.Create;
- fPrimitives := TPrimitives.Create;
- end;
- destructor TPasGLTF.TMesh.Destroy;
- begin
- FreeAndNil(fWeights);
- FreeAndNil(fPrimitives);
- inherited Destroy;
- end;
- { TPasGLTF.TNode }
- constructor TPasGLTF.TNode.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fName := '';
- fCamera := -1;
- fMesh := -1;
- fSkin := -1;
- fMatrix := TDefaults.IdentityMatrix4x4;
- fRotation := TDefaults.IdentityQuaternion;
- fScale := TDefaults.IdentityVector3;
- fTranslation := TDefaults.NullVector3;
- fChildren := TChildren.Create;
- fWeights := TWeights.Create;
- end;
- destructor TPasGLTF.TNode.Destroy;
- begin
- FreeAndNil(fChildren);
- FreeAndNil(fWeights);
- inherited Destroy;
- end;
- { TPasGLTF.TSampler }
- constructor TPasGLTF.TSampler.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fName := '';
- fMagFilter := TMagFilter.None;
- fMinFilter := TMinFilter.None;
- fWrapS := TWrappingMode.Repeat_;
- fWrapT := TWrappingMode.Repeat_;
- end;
- destructor TPasGLTF.TSampler.Destroy;
- begin
- inherited Destroy;
- end;
- function TPasGLTF.TSampler.GetEmpty: boolean;
- begin
- result := (Length(fName) = 0) and (fMagFilter = TMagFilter.None) and
- (fMinFilter = TMinFilter.None) and (fWrapS = TWrappingMode.Repeat_) and
- (fWrapT = TWrappingMode.Repeat_);
- end;
- { TPasGLTF.TScene }
- constructor TPasGLTF.TScene.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fName := '';
- fNodes := TPasGLTF.TScene.TNodes.Create;
- end;
- destructor TPasGLTF.TScene.Destroy;
- begin
- FreeAndNil(fNodes);
- inherited Destroy;
- end;
- { TPasGLTF.TSkin }
- constructor TPasGLTF.TSkin.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fName := '';
- fInverseBindMatrices := -1;
- fSkeleton := -1;
- fJoints := TPasGLTF.TSkin.TJoints.Create;
- end;
- destructor TPasGLTF.TSkin.Destroy;
- begin
- FreeAndNil(fJoints);
- inherited Destroy;
- end;
- { TPasGLTF.TTexture }
- constructor TPasGLTF.TTexture.Create(const aDocument: TDocument);
- begin
- inherited Create(aDocument);
- fName := '';
- fSampler := -1;
- fSource := -1;
- end;
- destructor TPasGLTF.TTexture.Destroy;
- begin
- inherited Destroy;
- end;
- { TPasGLTF.TDocument }
- constructor TPasGLTF.TDocument.Create(const aDocument: TDocument = nil);
- begin
- inherited Create(aDocument);
- fAsset := TAsset.Create(fDocument);
- fAccessors := TAccessors.Create;
- fAnimations := TAnimations.Create;
- fBuffers := TBuffers.Create;
- fBufferViews := TBufferViews.Create;
- fCameras := TCameras.Create;
- fImages := TImages.Create;
- fMaterials := TMaterials.Create;
- fMeshes := TMeshes.Create;
- fNodes := TNodes.Create;
- fSamplers := TSamplers.Create;
- fScene := -1;
- fScenes := TScenes.Create;
- fSkins := TSkins.Create;
- fTextures := TTextures.Create;
- fExtensionsUsed := TStringList.Create;
- fExtensionsRequired := TStringList.Create;
- fRootPath := '';
- fGetURI := DefaultGetURI;
- end;
- destructor TPasGLTF.TDocument.Destroy;
- begin
- FreeAndNil(fAsset);
- FreeAndNil(fAccessors);
- FreeAndNil(fAnimations);
- FreeAndNil(fBuffers);
- FreeAndNil(fBufferViews);
- FreeAndNil(fCameras);
- FreeAndNil(fImages);
- FreeAndNil(fMaterials);
- FreeAndNil(fMeshes);
- FreeAndNil(fNodes);
- FreeAndNil(fSamplers);
- FreeAndNil(fScenes);
- FreeAndNil(fSkins);
- FreeAndNil(fTextures);
- FreeAndNil(fExtensionsUsed);
- FreeAndNil(fExtensionsRequired);
- inherited Destroy;
- end;
- function TPasGLTF.TDocument.DefaultGetURI(const aURI
- : TPasGLTFUTF8String): TStream;
- var
- FileName: String;
- begin
- FileName := ExpandFileName(IncludeTrailingPathDelimiter(fRootPath) +
- String(TPasGLTF.ResolveURIToPath(aURI)));
- result := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
- end;
- procedure TPasGLTF.TDocument.LoadURISource(const aURI: TPasGLTFUTF8String;
- const aStream: TStream);
- const
- Base64Signature = ';base64,';
- var
- Stream: TStream;
- Base64Position: TPasGLTFSizeInt;
- begin
- if Length(trim(aURI)) > 0 then
- begin
- if (Length(aURI) > 5) and (aURI[1] = 'd') and (aURI[2] = 'a') and
- (aURI[3] = 't') and (aURI[4] = 'a') and (aURI[5] = ':') then
- begin
- Base64Position := pos(Base64Signature, aURI);
- if Base64Position > 0 then
- begin
- TBase64.Decode(copy(aURI, Base64Position + Length(Base64Signature),
- (Length(aURI) - (Base64Position + Length(Base64Signature))) +
- 1), aStream);
- end;
- end
- else if assigned(fGetURI) then
- begin
- Stream := fGetURI(aURI);
- if assigned(Stream) then
- begin
- try
- Stream.Seek(0, soBeginning);
- if aStream.CopyFrom(Stream, Stream.Size) <> Stream.Size then
- begin
- raise EInOutError.Create('I/O error');
- end;
- finally
- FreeAndNil(Stream);
- end;
- end;
- end;
- aStream.Seek(0, soBeginning);
- end;
- end;
- procedure TPasGLTF.TDocument.LoadURISources;
- var
- Buffer: TBuffer;
- begin
- for Buffer in fBuffers do
- begin
- if Length(trim(Buffer.fURI)) > 0 then
- begin
- LoadURISource(Buffer.fURI, Buffer.fData);
- end;
- end;
- end;
- procedure TPasGLTF.TDocument.LoadFromJSON(const aJSONRootItem: TPasJSONItem);
- function Required(const aJSONItem: TPasJSONItem;
- const aName: TPasGLTFUTF8String = ''): TPasJSONItem;
- begin
- result := aJSONItem;
- if not assigned(result) then
- begin
- if Length(aName) > 0 then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document, missing "'
- + String(aName) + '" field');
- end
- else
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- end;
- end;
- procedure ProcessExtensionsAndExtras(const aJSONItem: TPasJSONItem;
- const aBaseExtensionsExtrasObject: TBaseExtensionsExtrasObject);
- var
- JSONObject: TPasJSONItemObject;
- JSONObjectItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- begin
- JSONObjectItem := JSONObject.Properties['extensions'];
- if assigned(JSONObjectItem) and (JSONObjectItem is TPasJSONItemObject)
- then
- begin
- aBaseExtensionsExtrasObject.fExtensions.Merge(JSONObjectItem);
- end;
- end;
- begin
- JSONObjectItem := JSONObject.Properties['extras'];
- if assigned(JSONObjectItem) and (JSONObjectItem is TPasJSONItemObject)
- then
- begin
- aBaseExtensionsExtrasObject.fExtras.Merge(JSONObjectItem);
- end;
- end;
- end;
- procedure ProcessAccessors(const aJSONItem: TPasJSONItem);
- function ProcessAccessor(const aJSONItem: TPasJSONItem): TAccessor;
- procedure ProcessSparse(const aJSONItem: TPasJSONItem;
- const aSparse: TAccessor.TSparse);
- var
- JSONObject: TPasJSONItemObject;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- ProcessExtensionsAndExtras(JSONObject, aSparse);
- aSparse.fCount := TPasJSON.GetInt64
- (Required(JSONObject.Properties['count'], 'count'), aSparse.fCount);
- begin
- JSONItem := JSONObject.Properties['indices'];
- if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
- aSparse.fIndices);
- aSparse.fIndices.fBufferView :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
- .Properties['bufferView'], 'bufferView'),
- aSparse.fIndices.fBufferView);
- aSparse.fIndices.fComponentType :=
- TAccessor.TComponentType
- (TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
- .Properties['componentType'], 'componentType'),
- TPasGLTFInt64(TAccessor.TComponentType.None)));
- aSparse.fIndices.fByteOffset :=
- TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
- ['byteOffset'], aSparse.fIndices.fByteOffset);
- end;
- begin
- JSONItem := JSONObject.Properties['values'];
- if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
- aSparse.fValues);
- aSparse.fValues.fBufferView :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
- .Properties['bufferView'], 'bufferView'),
- aSparse.fValues.fBufferView);
- aSparse.fValues.fByteOffset :=
- TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
- ['byteOffset'], aSparse.fValues.fByteOffset);
- end;
- end;
- var
- JSONObject: TPasJSONItemObject;
- JSONItem, JSONArrayItem: TPasJSONItem;
- Type_: TPasGLTFUTF8String;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TAccessor.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fComponentType := TAccessor.TComponentType
- (TPasJSON.GetInt64(Required(JSONObject.Properties['componentType'],
- 'componentType'), TPasGLTFInt64(TAccessor.TComponentType.None)));
- result.fCount := TPasJSON.GetInt64
- (Required(JSONObject.Properties['count'], 'count'), result.fCount);
- begin
- Type_ := TPasJSON.GetString(Required(JSONObject.Properties['type'],
- 'type'), 'NONE');
- if Type_ = 'SCALAR' then
- begin
- result.fType := TAccessor.TType.Scalar;
- end
- else if Type_ = 'VEC2' then
- begin
- result.fType := TAccessor.TType.Vec2;
- end
- else if Type_ = 'VEC3' then
- begin
- result.fType := TAccessor.TType.Vec3;
- end
- else if Type_ = 'VEC4' then
- begin
- result.fType := TAccessor.TType.Vec4;
- end
- else if Type_ = 'MAT2' then
- begin
- result.fType := TAccessor.TType.Mat2;
- end
- else if Type_ = 'MAT3' then
- begin
- result.fType := TAccessor.TType.Mat3;
- end
- else if Type_ = 'MAT4' then
- begin
- result.fType := TAccessor.TType.Mat4;
- end
- else
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- end;
- result.fBufferView := TPasJSON.GetInt64
- (JSONObject.Properties['bufferView'], result.fBufferView);
- result.fByteOffset := TPasJSON.GetInt64
- (JSONObject.Properties['byteOffset'], result.fByteOffset);
- begin
- JSONItem := JSONObject.Properties['min'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemArray) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- if not(assigned(JSONArrayItem) and
- (JSONArrayItem is TPasJSONItemNumber)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- result.fMinArray.Add(TPasJSON.GetNumber(JSONArrayItem, 0.0));
- end;
- end;
- end;
- begin
- JSONItem := JSONObject.Properties['max'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemArray) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- if not(assigned(JSONArrayItem) and
- (JSONArrayItem is TPasJSONItemNumber)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- result.fMaxArray.Add(TPasJSON.GetNumber(JSONArrayItem, 0.0));
- end;
- end;
- end;
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- result.fNormalized := TPasJSON.GetBoolean
- (JSONObject.Properties['normalized'], result.fNormalized);
- begin
- JSONItem := JSONObject.Properties['sparse'];
- if assigned(JSONItem) then
- begin
- ProcessSparse(JSONItem, result.fSparse);
- end;
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fAccessors.Add(ProcessAccessor(JSONItem));
- end;
- end;
- procedure ProcessAnimations(const aJSONItem: TPasJSONItem);
- function ProcessAnimation(const aJSONItem: TPasJSONItem): TAnimation;
- var
- JSONObject: TPasJSONItemObject;
- JSONItem, JSONArrayItem, TargetItem, InterpolationItem: TPasJSONItem;
- Interpolation: TPasGLTFUTF8String;
- Channel: TAnimation.TChannel;
- Sampler: TAnimation.TSampler;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TAnimation.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- begin
- JSONItem := JSONObject.Properties['channels'];
- if not(assigned(JSONItem) and (JSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- if not(assigned(JSONArrayItem) and
- (JSONArrayItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- Channel := TAnimation.TChannel.Create(self);
- try
- ProcessExtensionsAndExtras
- (TPasJSONItemObject(JSONArrayItem), Channel);
- Channel.fSampler :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONArrayItem)
- .Properties['sampler'], 'sampler'), Channel.fSampler);
- begin
- TargetItem := Required(TPasJSONItemObject(JSONArrayItem)
- .Properties['target'], 'target');
- if not(assigned(TargetItem) and
- (TargetItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(TargetItem),
- Channel.fTarget);
- Channel.fTarget.fPath :=
- TPasJSON.GetString
- (Required(TPasJSONItemObject(TargetItem).Properties['path'],
- 'path'), Channel.fTarget.fPath);
- Channel.fTarget.fNode :=
- TPasJSON.GetInt64(TPasJSONItemObject(TargetItem).Properties
- ['node'], Channel.fTarget.fNode);
- end;
- finally
- result.fChannels.Add(Channel);
- end;
- end;
- end;
- begin
- JSONItem := JSONObject.Properties['samplers'];
- if not(assigned(JSONItem) and (JSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- if not(assigned(JSONArrayItem) and
- (JSONArrayItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- Sampler := TAnimation.TSampler.Create(self);
- try
- ProcessExtensionsAndExtras
- (TPasJSONItemObject(JSONArrayItem), Sampler);
- Sampler.fInput :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONArrayItem)
- .Properties['input'], 'input'), Sampler.fInput);
- Sampler.fOutput :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONArrayItem)
- .Properties['output'], 'output'), Sampler.fOutput);
- begin
- InterpolationItem := TPasJSONItemObject(JSONArrayItem)
- .Properties['interpolation'];
- if assigned(InterpolationItem) then
- begin
- if not(InterpolationItem is TPasJSONItemString) then
- begin
- raise EPasGLTFInvalidDocument.Create
- ('Invalid GLTF document');
- end;
- Interpolation :=
- TPasJSON.GetString(InterpolationItem, 'NONE');
- if Interpolation = 'LINEAR' then
- begin
- Sampler.fInterpolation := TAnimation.TSampler.TType.Linear;
- end
- else if Interpolation = 'STEP' then
- begin
- Sampler.fInterpolation := TAnimation.TSampler.TType.Step;
- end
- else if Interpolation = 'CUBICSPLINE' then
- begin
- Sampler.fInterpolation :=
- TAnimation.TSampler.TType.CubicSpline;
- end
- else
- begin
- raise EPasGLTFInvalidDocument.Create
- ('Invalid GLTF document');
- end;
- end;
- end;
- finally
- result.fSamplers.Add(Sampler);
- end;
- end;
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fAnimations.Add(ProcessAnimation(JSONItem));
- end;
- end;
- procedure ProcessAsset(const aJSONItem: TPasJSONItem);
- var
- JSONObject: TPasJSONItemObject;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- ProcessExtensionsAndExtras(JSONObject, fAsset);
- fAsset.fCopyright := TPasJSON.GetString(JSONObject.Properties['copyright'],
- fAsset.fCopyright);
- fAsset.fGenerator := TPasJSON.GetString(JSONObject.Properties['generator'],
- fAsset.fGenerator);
- fAsset.fMinVersion := TPasJSON.GetString
- (JSONObject.Properties['minVersion'], fAsset.fMinVersion);
- fAsset.fVersion := TPasJSON.GetString
- (Required(JSONObject.Properties['version'], 'version'), fAsset.fVersion);
- end;
- procedure ProcessBuffers(const aJSONItem: TPasJSONItem);
- function ProcessBuffer(const aJSONItem: TPasJSONItem): TBuffer;
- var
- JSONObject: TPasJSONItemObject;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TBuffer.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- result.fURI := TPasJSON.GetString(JSONObject.Properties['uri'],
- result.fURI);
- result.fByteLength := TPasJSON.GetInt64
- (Required(JSONObject.Properties['byteLength'], 'byteLength'),
- result.fByteLength);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fBuffers.Add(ProcessBuffer(JSONItem));
- end;
- end;
- procedure ProcessBufferViews(const aJSONItem: TPasJSONItem);
- function ProcessBufferView(const aJSONItem: TPasJSONItem): TBufferView;
- var
- JSONObject: TPasJSONItemObject;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TBufferView.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fBuffer := TPasJSON.GetInt64
- (Required(JSONObject.Properties['buffer'], 'buffer'), result.fBuffer);
- result.fByteLength := TPasJSON.GetInt64
- (Required(JSONObject.Properties['byteLength'], 'byteLength'),
- result.fByteLength);
- result.fByteOffset := TPasJSON.GetInt64
- (JSONObject.Properties['byteOffset'], result.fByteOffset);
- result.fByteStride := TPasJSON.GetInt64
- (JSONObject.Properties['byteStride'], result.fByteStride);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- result.fTarget := TBufferView.TTargetType
- (TPasJSON.GetInt64(JSONObject.Properties['target'],
- TPasGLTFInt64(result.fTarget)));
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fBufferViews.Add(ProcessBufferView(JSONItem));
- end;
- end;
- procedure ProcessCameras(const aJSONItem: TPasJSONItem);
- function ProcessCamera(const aJSONItem: TPasJSONItem): TCamera;
- var
- JSONObject: TPasJSONItemObject;
- JSONItem: TPasJSONItem;
- Type_: TPasGLTFUTF8String;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TCamera.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- begin
- Type_ := TPasJSON.GetString(Required(JSONObject.Properties['type'],
- 'type'), 'none');
- if Type_ = 'orthographic' then
- begin
- result.fType := TCamera.TType.Orthographic;
- end
- else if Type_ = 'perspective' then
- begin
- result.fType := TCamera.TType.Perspective;
- end
- else
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- end;
- case result.fType of
- TCamera.TType.Orthographic:
- begin
- JSONItem := JSONObject.Properties['orthographic'];
- if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject))
- then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
- result.fOrthographic);
- result.fOrthographic.fXMag :=
- TPasJSON.GetNumber
- (Required(TPasJSONItemObject(JSONItem).Properties['xmag'],
- 'xmag'), result.fOrthographic.fXMag);
- result.fOrthographic.fYMag :=
- TPasJSON.GetNumber
- (Required(TPasJSONItemObject(JSONItem).Properties['ymag'],
- 'ymag'), result.fOrthographic.fYMag);
- result.fOrthographic.fZNear :=
- TPasJSON.GetNumber
- (Required(TPasJSONItemObject(JSONItem).Properties['znear'],
- 'znear'), result.fOrthographic.fZNear);
- result.fOrthographic.fZFar :=
- TPasJSON.GetNumber
- (Required(TPasJSONItemObject(JSONItem).Properties['zfar'],
- 'zfar'), result.fOrthographic.fZFar);
- end;
- TCamera.TType.Perspective:
- begin
- JSONItem := JSONObject.Properties['perspective'];
- if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject))
- then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
- result.fPerspective);
- result.fPerspective.fAspectRatio :=
- TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
- ['aspectRatio'], result.fPerspective.fAspectRatio);
- result.fPerspective.fYFov :=
- TPasJSON.GetNumber
- (Required(TPasJSONItemObject(JSONItem).Properties['yfov'],
- 'yfov'), result.fPerspective.fYFov);
- result.fPerspective.fZNear :=
- TPasJSON.GetNumber
- (Required(TPasJSONItemObject(JSONItem).Properties['znear'],
- 'znear'), result.fPerspective.fZNear);
- result.fPerspective.fZFar :=
- TPasJSON.GetNumber
- (Required(TPasJSONItemObject(JSONItem).Properties['zfar'],
- 'zfar'), result.fPerspective.fZFar);
- end;
- else
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fCameras.Add(ProcessCamera(JSONItem));
- end;
- end;
- procedure ProcessImages(const aJSONItem: TPasJSONItem);
- function ProcessImage(const aJSONItem: TPasJSONItem): TImage;
- var
- JSONObject: TPasJSONItemObject;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TImage.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fBufferView := TPasJSON.GetInt64
- (JSONObject.Properties['bufferView'], result.fBufferView);
- result.fMimeType := TPasJSON.GetString
- (JSONObject.Properties['mimeType'], result.fMimeType);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- result.fURI := TPasJSON.GetString(JSONObject.Properties['uri'],
- result.fURI);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fImages.Add(ProcessImage(JSONItem));
- end;
- end;
- procedure ProcessMaterials(const aJSONItem: TPasJSONItem);
- function ProcessMaterial(const aJSONItem: TPasJSONItem): TMaterial;
- var
- JSONObject: TPasJSONItemObject;
- JSONItem, JSONSubItem: TPasJSONItem;
- Mode: TPasGLTFUTF8String;
- Index: TPasGLTFSizeInt;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TMaterial.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fAlphaCutOff := TPasJSON.GetNumber
- (JSONObject.Properties['alphaCutoff'], result.fAlphaCutOff);
- begin
- JSONItem := JSONObject.Properties['alphaMode'];
- if assigned(JSONItem) then
- begin
- Mode := TPasJSON.GetString(JSONItem, 'NONE');
- if Mode = 'OPAQUE' then
- begin
- result.fAlphaMode := TMaterial.TAlphaMode.Opaque;
- end
- else if Mode = 'MASK' then
- begin
- result.fAlphaMode := TMaterial.TAlphaMode.Mask;
- end
- else if Mode = 'BLEND' then
- begin
- result.fAlphaMode := TMaterial.TAlphaMode.Blend;
- end
- else
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- end;
- end;
- result.fDoubleSided := TPasJSON.GetBoolean
- (JSONObject.Properties['doubleSided'], result.fDoubleSided);
- begin
- JSONItem := JSONObject.Properties['emissiveFactor'];
- if assigned(JSONItem) then
- begin
- if not((JSONItem is TPasJSONItemArray) and
- (TPasJSONItemArray(JSONItem).Count = 3)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for Index := 0 to 2 do
- begin
- result.fEmissiveFactor[Index] :=
- TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
- result.fEmissiveFactor[Index]);
- end;
- end;
- end;
- begin
- JSONItem := JSONObject.Properties['emissiveTexture'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemObject) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
- result.fEmissiveTexture);
- result.fEmissiveTexture.fIndex :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
- .Properties['index'], 'index'), result.fEmissiveTexture.fIndex);
- result.fEmissiveTexture.fTexCoord :=
- TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
- ['texCoord'], result.fEmissiveTexture.fTexCoord);
- end;
- end;
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- begin
- JSONItem := JSONObject.Properties['normalTexture'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemObject) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
- result.fNormalTexture);
- result.fNormalTexture.fIndex :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
- .Properties['index'], 'index'), result.fNormalTexture.fIndex);
- result.fNormalTexture.fTexCoord :=
- TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
- ['texCoord'], result.fNormalTexture.fTexCoord);
- result.fNormalTexture.fScale :=
- TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
- ['scale'], result.fNormalTexture.fScale);
- end;
- end;
- begin
- JSONItem := JSONObject.Properties['occlusionTexture'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemObject) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
- result.fOcclusionTexture);
- result.fOcclusionTexture.fIndex :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONItem)
- .Properties['index'], 'index'), result.fOcclusionTexture.fIndex);
- result.fOcclusionTexture.fTexCoord :=
- TPasJSON.GetInt64(TPasJSONItemObject(JSONItem).Properties
- ['texCoord'], result.fOcclusionTexture.fTexCoord);
- result.fOcclusionTexture.fStrength :=
- TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
- ['scale'], result.fOcclusionTexture.fStrength);
- end;
- end;
- begin
- JSONItem := JSONObject.Properties['pbrMetallicRoughness'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemObject) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONItem),
- result.fPBRMetallicRoughness);
- begin
- JSONSubItem := TPasJSONItemObject(JSONItem).Properties
- ['baseColorFactor'];
- if assigned(JSONSubItem) then
- begin
- if not((JSONSubItem is TPasJSONItemArray) and
- (TPasJSONItemArray(JSONSubItem).Count = 4)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for Index := 0 to 3 do
- begin
- result.fPBRMetallicRoughness.fBaseColorFactor[Index] :=
- TPasJSON.GetNumber(TPasJSONItemArray(JSONSubItem)
- .Items[Index],
- result.fPBRMetallicRoughness.fBaseColorFactor[Index]);
- end;
- end;
- end;
- begin
- JSONSubItem := TPasJSONItemObject(JSONItem).Properties
- ['baseColorTexture'];
- if assigned(JSONSubItem) then
- begin
- if not(JSONSubItem is TPasJSONItemObject) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONSubItem),
- result.fPBRMetallicRoughness.fBaseColorTexture);
- result.fPBRMetallicRoughness.fBaseColorTexture.fIndex :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONSubItem)
- .Properties['index'], 'index'),
- result.fPBRMetallicRoughness.fBaseColorTexture.fIndex);
- result.fPBRMetallicRoughness.fBaseColorTexture.fTexCoord :=
- TPasJSON.GetInt64(TPasJSONItemObject(JSONSubItem)
- .Properties['texCoord'],
- result.fPBRMetallicRoughness.fBaseColorTexture.fTexCoord);
- end;
- end;
- result.fPBRMetallicRoughness.fMetallicFactor :=
- TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
- ['metallicFactor'], result.fPBRMetallicRoughness.fMetallicFactor);
- begin
- JSONSubItem := TPasJSONItemObject(JSONItem).Properties
- ['metallicRoughnessTexture'];
- if assigned(JSONSubItem) then
- begin
- if not(JSONSubItem is TPasJSONItemObject) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- ProcessExtensionsAndExtras(TPasJSONItemObject(JSONSubItem),
- result.fPBRMetallicRoughness.fMetallicRoughnessTexture);
- result.fPBRMetallicRoughness.fMetallicRoughnessTexture.fIndex :=
- TPasJSON.GetInt64(Required(TPasJSONItemObject(JSONSubItem)
- .Properties['index'], 'index'),
- result.fPBRMetallicRoughness.
- fMetallicRoughnessTexture.fIndex);
- result.fPBRMetallicRoughness.fMetallicRoughnessTexture.fTexCoord
- := TPasJSON.GetInt64(TPasJSONItemObject(JSONSubItem)
- .Properties['texCoord'],
- result.fPBRMetallicRoughness.fMetallicRoughnessTexture.
- fTexCoord);
- end;
- end;
- result.fPBRMetallicRoughness.fRoughnessFactor :=
- TPasJSON.GetNumber(TPasJSONItemObject(JSONItem).Properties
- ['roughnessFactor'],
- result.fPBRMetallicRoughness.fRoughnessFactor);
- end;
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fMaterials.Add(ProcessMaterial(JSONItem));
- end;
- end;
- procedure ProcessMeshes(const aJSONItem: TPasJSONItem);
- function ProcessMesh(const aJSONItem: TPasJSONItem): TMesh;
- function ProcessPrimitive(const aJSONItem: TPasJSONItem)
- : TMesh.TPrimitive;
- var
- JSONObject: TPasJSONItemObject;
- JSONItem, JSONArrayItem: TPasJSONItem;
- JSONObjectProperty: TPasJSONItemObjectProperty;
- Attributes: TAttributes;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TMesh.TPrimitive.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- begin
- JSONItem := Required(JSONObject.Properties['attributes'],
- 'attributes');
- if not(assigned(JSONItem) and (JSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONObjectProperty in TPasJSONItemObject(JSONItem) do
- begin
- result.fAttributes.Add(JSONObjectProperty.Key,
- TPasJSON.GetInt64(JSONObjectProperty.Value, 0));
- end;
- end;
- result.fIndices := TPasJSON.GetInt64(JSONObject.Properties['indices'],
- result.fIndices);
- result.fMaterial := TPasJSON.GetInt64
- (JSONObject.Properties['material'], result.fMaterial);
- result.fMode := TMesh.TPrimitive.TMode
- (TPasJSON.GetInt64(JSONObject.Properties['mode'],
- TPasGLTFInt64(result.fMode)));
- begin
- JSONItem := JSONObject.Properties['targets'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemArray) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- if not(assigned(JSONArrayItem) and
- (JSONArrayItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- Attributes := TAttributes.Create(-1);
- try
- for JSONObjectProperty in TPasJSONItemObject(JSONArrayItem) do
- begin
- Attributes.Add(JSONObjectProperty.Key,
- TPasJSON.GetInt64(JSONObjectProperty.Value, 0));
- end;
- finally
- result.fTargets.Add(Attributes);
- end;
- end;
- end;
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONObject: TPasJSONItemObject;
- JSONItem, JSONArrayItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TMesh.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- begin
- JSONItem := Required(JSONObject.Properties['primitives'],
- 'primitives');
- if not(assigned(JSONItem) and (JSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- result.fPrimitives.Add(ProcessPrimitive(JSONArrayItem));
- end;
- end;
- begin
- JSONItem := JSONObject.Properties['weights'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemArray) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- result.fWeights.Add(TPasJSON.GetNumber(JSONArrayItem, 0.0));
- end;
- end;
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fMeshes.Add(ProcessMesh(JSONItem));
- end;
- end;
- procedure ProcessNodes(const aJSONItem: TPasJSONItem);
- function ProcessNode(const aJSONItem: TPasJSONItem): TNode;
- var
- JSONObject: TPasJSONItemObject;
- JSONItem, JSONArrayItem: TPasJSONItem;
- Index: TPasGLTFSizeInt;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TNode.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fCamera := TPasJSON.GetInt64(JSONObject.Properties['camera'],
- result.fCamera);
- begin
- JSONItem := JSONObject.Properties['children'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemArray) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- result.fChildren.Add(TPasJSON.GetInt64(JSONArrayItem));
- end;
- end;
- end;
- begin
- JSONItem := JSONObject.Properties['matrix'];
- if assigned(JSONItem) then
- begin
- if not((JSONItem is TPasJSONItemArray) and
- (TPasJSONItemArray(JSONItem).Count = 16)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for Index := 0 to 15 do
- begin
- result.fMatrix[Index] :=
- TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
- result.fMatrix[Index]);
- end;
- end;
- end;
- result.fMesh := TPasJSON.GetInt64(JSONObject.Properties['mesh'],
- result.fMesh);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- begin
- JSONItem := JSONObject.Properties['rotation'];
- if assigned(JSONItem) then
- begin
- if not((JSONItem is TPasJSONItemArray) and
- (TPasJSONItemArray(JSONItem).Count = 4)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for Index := 0 to 3 do
- begin
- result.fRotation[Index] :=
- TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
- result.fRotation[Index]);
- end;
- end;
- end;
- begin
- JSONItem := JSONObject.Properties['scale'];
- if assigned(JSONItem) then
- begin
- if not((JSONItem is TPasJSONItemArray) and
- (TPasJSONItemArray(JSONItem).Count = 3)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for Index := 0 to 2 do
- begin
- result.fScale[Index] :=
- TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
- result.fScale[Index]);
- end;
- end;
- end;
- result.fSkin := TPasJSON.GetInt64(JSONObject.Properties['skin'],
- result.fSkin);
- begin
- JSONItem := JSONObject.Properties['translation'];
- if assigned(JSONItem) then
- begin
- if not((JSONItem is TPasJSONItemArray) and
- (TPasJSONItemArray(JSONItem).Count = 3)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for Index := 0 to 2 do
- begin
- result.fTranslation[Index] :=
- TPasJSON.GetNumber(TPasJSONItemArray(JSONItem).Items[Index],
- result.fTranslation[Index]);
- end;
- end;
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fNodes.Add(ProcessNode(JSONItem));
- end;
- end;
- procedure ProcessSamplers(const aJSONItem: TPasJSONItem);
- function ProcessSampler(const aJSONItem: TPasJSONItem): TSampler;
- var
- JSONObject: TPasJSONItemObject;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TSampler.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fMagFilter := TSampler.TMagFilter
- (TPasJSON.GetInt64(JSONObject.Properties['magFilter'],
- TPasGLTFInt64(result.fMagFilter)));
- result.fMinFilter := TSampler.TMinFilter
- (TPasJSON.GetInt64(JSONObject.Properties['minFilter'],
- TPasGLTFInt64(result.fMinFilter)));
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- result.fWrapS := TSampler.TWrappingMode
- (TPasJSON.GetInt64(JSONObject.Properties['wrapS'],
- TPasGLTFInt64(result.fWrapS)));
- result.fWrapT := TSampler.TWrappingMode
- (TPasJSON.GetInt64(JSONObject.Properties['wrapT'],
- TPasGLTFInt64(result.fWrapT)));
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fSamplers.Add(ProcessSampler(JSONItem));
- end;
- end;
- procedure ProcessScenes(const aJSONItem: TPasJSONItem);
- function ProcessScene(const aJSONItem: TPasJSONItem): TScene;
- var
- JSONObject: TPasJSONItemObject;
- JSONItem, JSONArrayItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TScene.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- begin
- JSONItem := JSONObject.Properties['nodes'];
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemArray) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- result.fNodes.Add(TPasJSON.GetInt64(JSONArrayItem));
- end;
- end;
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fScenes.Add(ProcessScene(JSONItem));
- end;
- end;
- procedure ProcessSkins(const aJSONItem: TPasJSONItem);
- function ProcessSkin(const aJSONItem: TPasJSONItem): TSkin;
- var
- JSONObject: TPasJSONItemObject;
- JSONItem, JSONArrayItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TSkin.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- begin
- JSONItem := Required(JSONObject.Properties['joints']);
- if assigned(JSONItem) then
- begin
- if not(JSONItem is TPasJSONItemArray) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- for JSONArrayItem in TPasJSONItemArray(JSONItem) do
- begin
- result.fJoints.Add(TPasJSON.GetInt64(JSONArrayItem));
- end;
- end;
- end;
- result.fInverseBindMatrices :=
- TPasJSON.GetInt64(JSONObject.Properties['inverseBindMatrices'],
- result.fInverseBindMatrices);
- result.fSkeleton := TPasJSON.GetInt64(JSONObject.Properties['skeleton'],
- result.fSkeleton);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fSkins.Add(ProcessSkin(JSONItem));
- end;
- end;
- procedure ProcessTextures(const aJSONItem: TPasJSONItem);
- function ProcessTexture(const aJSONItem: TPasJSONItem): TTexture;
- var
- JSONObject: TPasJSONItemObject;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONItem);
- result := TTexture.Create(self);
- try
- ProcessExtensionsAndExtras(JSONObject, result);
- result.fName := TPasJSON.GetString(JSONObject.Properties['name'],
- result.fName);
- result.fSampler := TPasJSON.GetInt64(JSONObject.Properties['sampler'],
- result.fSampler);
- result.fSource := TPasJSON.GetInt64(JSONObject.Properties['source'],
- result.fSource);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- fTextures.Add(ProcessTexture(JSONItem));
- end;
- end;
- procedure ProcessStringList(const aJSONItem: TPasJSONItem;
- const aStrings: TStrings);
- var
- JSONArray: TPasJSONItemArray;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aJSONItem) and (aJSONItem is TPasJSONItemArray)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONArray := TPasJSONItemArray(aJSONItem);
- for JSONItem in JSONArray do
- begin
- aStrings.Add(TPasJSON.GetString(JSONItem, ''));
- end;
- end;
- var
- JSONObject: TPasJSONItemObject;
- JSONObjectProperty: TPasJSONItemObjectProperty;
- HasAsset: boolean;
- begin
- if not(assigned(aJSONRootItem) and (aJSONRootItem is TPasJSONItemObject)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- JSONObject := TPasJSONItemObject(aJSONRootItem);
- ProcessExtensionsAndExtras(JSONObject, self);
- HasAsset := false;
- for JSONObjectProperty in JSONObject do
- begin
- if JSONObjectProperty.Key = 'accessors' then
- begin
- ProcessAccessors(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'animations' then
- begin
- ProcessAnimations(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'asset' then
- begin
- HasAsset := true;
- ProcessAsset(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'buffers' then
- begin
- ProcessBuffers(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'bufferViews' then
- begin
- ProcessBufferViews(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'cameras' then
- begin
- ProcessCameras(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'images' then
- begin
- ProcessImages(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'materials' then
- begin
- ProcessMaterials(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'meshes' then
- begin
- ProcessMeshes(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'nodes' then
- begin
- ProcessNodes(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'samplers' then
- begin
- ProcessSamplers(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'scene' then
- begin
- fScene := TPasJSON.GetInt64(JSONObjectProperty.Value, fScene);
- end
- else if JSONObjectProperty.Key = 'scenes' then
- begin
- ProcessScenes(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'skins' then
- begin
- ProcessSkins(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'textures' then
- begin
- ProcessTextures(JSONObjectProperty.Value);
- end
- else if JSONObjectProperty.Key = 'extensionsUsed' then
- begin
- ProcessStringList(JSONObjectProperty.Value, fExtensionsUsed);
- end
- else if JSONObjectProperty.Key = 'extensionsRequired' then
- begin
- ProcessStringList(JSONObjectProperty.Value, fExtensionsRequired);
- end;
- end;
- if not HasAsset then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLTF document');
- end;
- LoadURISources;
- end;
- procedure TPasGLTF.TDocument.LoadFromBinary(const aStream: TStream);
- var
- GLBHeader: TGLBHeader;
- OtherEndianness: boolean;
- CountBuffers: TPasGLTFSizeInt;
- function SwapEndianness32(const aValue: TPasGLTFUInt32): TPasGLTFUInt32;
- begin
- if OtherEndianness then
- begin
- result := ((aValue and $000000FF) shl 24) or
- ((aValue and $0000FF00) shl 8) or ((aValue and $00FF0000) shr 8) or
- ((aValue and $FF000000) shr 24);
- end
- else
- begin
- result := aValue;
- end;
- end;
- var
- RawJSONRawByteString: TPasJSONRawByteString;
- ChunkHeader: TChunkHeader;
- Stream: TMemoryStream;
- JSONItem: TPasJSONItem;
- begin
- if not(assigned(aStream) and (aStream.Size >= GLBHeaderSize)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
- end;
- if aStream.Read(GLBHeader, SizeOf(TGLBHeader)) <> SizeOf(TGLBHeader) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
- end;
- if (GLBHeader.Magic <> GLBHeaderMagicNativeEndianness) and
- (GLBHeader.Magic <> GLBHeaderMagicOtherEndianness) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
- end;
- OtherEndianness := GLBHeader.Magic = GLBHeaderMagicOtherEndianness;
- if not((not OtherEndianness) and
- (GLBHeader.JSONChunkHeader.ChunkType = GLBChunkJSONNativeEndianness)) or
- (OtherEndianness and
- (GLBHeader.JSONChunkHeader.ChunkType = GLBChunkJSONOtherEndianness)) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
- end;
- GLBHeader.Magic := SwapEndianness32(GLBHeader.Magic);
- GLBHeader.Version := SwapEndianness32(GLBHeader.Version);
- GLBHeader.Length := SwapEndianness32(GLBHeader.Length);
- GLBHeader.JSONChunkHeader.ChunkLength :=
- SwapEndianness32(GLBHeader.JSONChunkHeader.ChunkLength);
- GLBHeader.JSONChunkHeader.ChunkType :=
- SwapEndianness32(GLBHeader.JSONChunkHeader.ChunkType);
- if ((GLBHeader.JSONChunkHeader.ChunkLength + GLBHeaderSize) >
- GLBHeader.Length) or (GLBHeader.JSONChunkHeader.ChunkLength < 2) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
- end;
- RawJSONRawByteString := '';
- SetLength(RawJSONRawByteString, GLBHeader.JSONChunkHeader.ChunkLength);
- aStream.ReadBuffer(RawJSONRawByteString[1], Length(RawJSONRawByteString));
- JSONItem := TPasJSON.Parse(RawJSONRawByteString, [], TPasJSONEncoding.UTF8);
- if assigned(JSONItem) then
- begin
- try
- LoadFromJSON(JSONItem);
- finally
- FreeAndNil(JSONItem);
- end;
- end;
- CountBuffers := 0;
- while aStream.Position < aStream.Size do
- begin
- if aStream.Read(ChunkHeader, SizeOf(TChunkHeader)) <> SizeOf(ChunkHeader)
- then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
- end;
- ChunkHeader.ChunkLength := SwapEndianness32(ChunkHeader.ChunkLength);
- ChunkHeader.ChunkType := SwapEndianness32(ChunkHeader.ChunkType);
- if ChunkHeader.ChunkType = GLBChunkBinaryNativeEndianness then
- begin
- if (ChunkHeader.ChunkType <> GLBChunkBinaryNativeEndianness) or
- ((ChunkHeader.ChunkLength + aStream.Position) > GLBHeader.Length) then
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
- end;
- inc(CountBuffers);
- if fBuffers.Count < CountBuffers then
- begin
- fBuffers.Add(TBuffer.Create(self));
- end;
- Stream := fBuffers[CountBuffers - 1].fData;
- Stream.Clear;
- Stream.CopyFrom(aStream, ChunkHeader.ChunkLength);
- end
- else
- begin
- if (ChunkHeader.ChunkLength + aStream.Position) <= GLBHeader.Length then
- begin
- Stream.Seek(ChunkHeader.ChunkLength, soCurrent);
- end
- else
- begin
- raise EPasGLTFInvalidDocument.Create('Invalid GLB document');
- end;
- end;
- end;
- end;
- procedure TPasGLTF.TDocument.LoadFromStream(const aStream: TStream);
- var
- FirstFourBytes: array [0 .. 3] of TPasGLTFUInt8;
- JSONItem: TPasJSONItem;
- begin
- aStream.ReadBuffer(FirstFourBytes, SizeOf(FirstFourBytes));
- aStream.Seek(-SizeOf(FirstFourBytes), soCurrent);
- if (FirstFourBytes[0] = ord('g')) and (FirstFourBytes[1] = ord('l')) and
- (FirstFourBytes[2] = ord('T')) and (FirstFourBytes[3] = ord('F')) then
- begin
- LoadFromBinary(aStream);
- end
- else
- begin
- JSONItem := TPasJSON.Parse(aStream, [],
- TPasJSONEncoding.AutomaticDetection);
- if assigned(JSONItem) then
- begin
- try
- LoadFromJSON(JSONItem);
- finally
- FreeAndNil(JSONItem);
- end;
- end;
- end;
- end;
- function TPasGLTF.TDocument.SaveToJSON(const aFormatted: boolean = false)
- : TPasJSONRawByteString;
- procedure ProcessExtensionsAndExtras(const aJSONObject: TPasJSONItemObject;
- const aBaseExtensionsExtrasObject: TBaseExtensionsExtrasObject);
- var
- TemporaryObject, TemporarySubObject: TPasJSONItemObject;
- begin
- TemporaryObject := TPasJSONItemObject.Create;
- try
- if aBaseExtensionsExtrasObject.fExtensions.Count > 0 then
- begin
- TemporarySubObject := TPasJSONItemObject.Create;
- try
- TemporarySubObject.Merge(aBaseExtensionsExtrasObject.fExtensions);
- finally
- TemporaryObject.Add('extensions', TemporarySubObject);
- end;
- end;
- if aBaseExtensionsExtrasObject.fExtras.Count > 0 then
- begin
- TemporarySubObject := TPasJSONItemObject.Create;
- try
- TemporarySubObject.Merge(aBaseExtensionsExtrasObject.fExtras);
- finally
- TemporaryObject.Add('extras', TemporarySubObject);
- end;
- end;
- aJSONObject.Merge(TemporaryObject);
- finally
- FreeAndNil(TemporaryObject);
- end;
- end;
- function ProcessAccessors: TPasJSONItemArray;
- function ProcessAccessor(const aObject: TAccessor): TPasJSONItemObject;
- var
- Index: TPasJSONSizeInt;
- JSONArray: TPasJSONItemArray;
- JSONObject, JSONSubObject: TPasJSONItemObject;
- begin
- result := TPasJSONItemObject.Create;
- try
- if aObject.fBufferView >= 0 then
- begin
- result.Add('bufferView',
- TPasJSONItemNumber.Create(aObject.fBufferView));
- end;
- result.Add('byteOffset',
- TPasJSONItemNumber.Create(aObject.fByteOffset));
- if aObject.fComponentType <> TAccessor.TComponentType.None then
- begin
- result.Add('componentType',
- TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fComponentType)));
- end;
- result.Add('count', TPasJSONItemNumber.Create(aObject.fCount));
- if aObject.fMinArray.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to aObject.fMinArray.Count - 1 do
- begin
- JSONArray.Add
- (TPasJSONItemNumber.Create(aObject.fMinArray.Items[Index]));
- end;
- finally
- result.Add('min', JSONArray);
- end;
- end;
- if aObject.fMaxArray.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to aObject.fMaxArray.Count - 1 do
- begin
- JSONArray.Add
- (TPasJSONItemNumber.Create(aObject.fMaxArray.Items[Index]));
- end;
- finally
- result.Add('max', JSONArray);
- end;
- end;
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if aObject.Normalized then
- begin
- result.Add('normalized',
- TPasJSONItemBoolean.Create(aObject.Normalized));
- end;
- if not aObject.fSparse.Empty then
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- if aObject.fSparse.fCount >= 0 then
- begin
- JSONObject.Add('count',
- TPasJSONItemNumber.Create(aObject.fSparse.fCount));
- end;
- if not aObject.fSparse.fIndices.Empty then
- begin
- JSONSubObject := TPasJSONItemObject.Create;
- try
- if aObject.fSparse.fIndices.fComponentType <>
- TAccessor.TComponentType.None then
- begin
- JSONSubObject.Add('componentType',
- TPasJSONItemNumber.Create
- (TPasGLTFInt64(aObject.fSparse.fIndices.fComponentType)));
- end;
- if aObject.fSparse.fIndices.fBufferView >= 0 then
- begin
- JSONSubObject.Add('bufferView',
- TPasJSONItemNumber.Create
- (aObject.fSparse.fIndices.fBufferView));
- end;
- JSONSubObject.Add('byteOffset',
- TPasJSONItemNumber.Create
- (aObject.fSparse.fIndices.fByteOffset));
- finally
- JSONObject.Add('indices', JSONSubObject);
- end;
- end;
- if not aObject.fSparse.fValues.Empty then
- begin
- JSONSubObject := TPasJSONItemObject.Create;
- try
- if aObject.fSparse.fValues.fBufferView >= 0 then
- begin
- JSONSubObject.Add('bufferView',
- TPasJSONItemNumber.Create
- (aObject.fSparse.fValues.fBufferView));
- end;
- JSONSubObject.Add('byteOffset',
- TPasJSONItemNumber.Create
- (aObject.fSparse.fValues.fByteOffset));
- finally
- JSONObject.Add('values', JSONSubObject);
- end;
- end;
- finally
- result.Add('sparse', JSONObject);
- end;
- end;
- case aObject.fType of
- TPasGLTF.TAccessor.TType.Scalar:
- begin
- result.Add('type', TPasJSONItemString.Create('SCALAR'));
- end;
- TPasGLTF.TAccessor.TType.Vec2:
- begin
- result.Add('type', TPasJSONItemString.Create('VEC2'));
- end;
- TPasGLTF.TAccessor.TType.Vec3:
- begin
- result.Add('type', TPasJSONItemString.Create('VEC3'));
- end;
- TPasGLTF.TAccessor.TType.Vec4:
- begin
- result.Add('type', TPasJSONItemString.Create('VEC4'));
- end;
- TPasGLTF.TAccessor.TType.Mat2:
- begin
- result.Add('type', TPasJSONItemString.Create('MAT2'));
- end;
- TPasGLTF.TAccessor.TType.Mat3:
- begin
- result.Add('type', TPasJSONItemString.Create('MAT3'));
- end;
- TPasGLTF.TAccessor.TType.Mat4:
- begin
- result.Add('type', TPasJSONItemString.Create('MAT4'));
- end;
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Accessor: TAccessor;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Accessor in fAccessors do
- begin
- result.Add(ProcessAccessor(Accessor));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessAnimations: TPasJSONItemArray;
- function ProcessAnimation(const aObject: TAnimation): TPasJSONItemObject;
- var
- JSONArray: TPasJSONItemArray;
- JSONObject, JSONSubObject: TPasJSONItemObject;
- Channel: TAnimation.TChannel;
- Sampler: TAnimation.TSampler;
- begin
- result := TPasJSONItemObject.Create;
- try
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if aObject.fChannels.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Channel in aObject.fChannels do
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- if Channel.fSampler >= 0 then
- begin
- JSONObject.Add('sampler',
- TPasJSONItemNumber.Create(Channel.fSampler));
- end;
- if not Channel.fTarget.Empty then
- begin
- JSONSubObject := TPasJSONItemObject.Create;
- try
- if Channel.fTarget.fNode >= 0 then
- begin
- JSONSubObject.Add('node',
- TPasJSONItemNumber.Create(Channel.fTarget.fNode));
- end;
- if Length(Channel.fTarget.fPath) > 0 then
- begin
- JSONSubObject.Add('path',
- TPasJSONItemString.Create(Channel.fTarget.fPath));
- end;
- ProcessExtensionsAndExtras(JSONSubObject, Channel.fTarget);
- finally
- JSONObject.Add('target', JSONSubObject);
- end;
- end;
- ProcessExtensionsAndExtras(JSONObject, Channel);
- finally
- JSONArray.Add(JSONObject);
- end;
- end;
- finally
- result.Add('channels', JSONArray);
- end;
- end;
- if aObject.fSamplers.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Sampler in aObject.fSamplers do
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- if Sampler.fInput >= 0 then
- begin
- JSONObject.Add('input',
- TPasJSONItemNumber.Create(Sampler.fInput));
- end;
- if Sampler.fOutput >= 0 then
- begin
- JSONObject.Add('output',
- TPasJSONItemNumber.Create(Sampler.fOutput));
- end;
- case Sampler.fInterpolation of
- TPasGLTF.TAnimation.TSampler.TType.Linear:
- begin
- JSONObject.Add('interpolation',
- TPasJSONItemString.Create('LINEAR'));
- end;
- TPasGLTF.TAnimation.TSampler.TType.Step:
- begin
- JSONObject.Add('interpolation',
- TPasJSONItemString.Create('STEP'));
- end;
- TPasGLTF.TAnimation.TSampler.TType.CubicSpline:
- begin
- JSONObject.Add('interpolation',
- TPasJSONItemString.Create('CUBICSPLINE'));
- end;
- else
- begin
- Assert(false);
- end;
- end;
- finally
- JSONArray.Add(JSONObject);
- end;
- end;
- finally
- result.Add('samplers', JSONArray);
- end;
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Animation: TAnimation;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Animation in fAnimations do
- begin
- result.Add(ProcessAnimation(Animation));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessAsset: TPasJSONItemObject;
- begin
- result := TPasJSONItemObject.Create;
- try
- if Length(fAsset.fCopyright) > 0 then
- begin
- result.Add('copyright', TPasJSONItemString.Create(fAsset.fCopyright));
- end;
- if Length(fAsset.fGenerator) > 0 then
- begin
- result.Add('generator', TPasJSONItemString.Create(fAsset.fGenerator));
- end;
- if Length(fAsset.fMinVersion) > 0 then
- begin
- result.Add('minVersion', TPasJSONItemString.Create(fAsset.fMinVersion));
- end;
- result.Add('version', TPasJSONItemString.Create(fAsset.fVersion));
- ProcessExtensionsAndExtras(result, fAsset);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessBuffers: TPasJSONItemArray;
- function ProcessBuffer(const aObject: TBuffer): TPasJSONItemObject;
- begin
- result := TPasJSONItemObject.Create;
- try
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if Length(aObject.fURI) > 0 then
- begin
- result.Add('uri', TPasJSONItemString.Create(aObject.fURI));
- end;
- result.Add('byteLength',
- TPasJSONItemNumber.Create(aObject.fByteLength));
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Buffer: TBuffer;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Buffer in fBuffers do
- begin
- result.Add(ProcessBuffer(Buffer));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessBufferViews: TPasJSONItemArray;
- function ProcessBufferView(const aObject: TBufferView): TPasJSONItemObject;
- begin
- result := TPasJSONItemObject.Create;
- try
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if aObject.fBuffer >= 0 then
- begin
- result.Add('buffer', TPasJSONItemNumber.Create(aObject.fBuffer));
- end;
- result.Add('byteLength',
- TPasJSONItemNumber.Create(aObject.fByteLength));
- result.Add('byteOffset',
- TPasJSONItemNumber.Create(aObject.fByteOffset));
- if aObject.fByteStride > 0 then
- begin
- result.Add('byteStride',
- TPasJSONItemNumber.Create(aObject.fByteStride));
- end;
- if aObject.fTarget <> TBufferView.TTargetType.None then
- begin
- result.Add('target',
- TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fTarget)));
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- BufferView: TBufferView;
- begin
- result := TPasJSONItemArray.Create;
- try
- for BufferView in fBufferViews do
- begin
- result.Add(ProcessBufferView(BufferView));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessCameras: TPasJSONItemArray;
- function ProcessCamera(const aObject: TCamera): TPasJSONItemObject;
- var
- JSONObject: TPasJSONItemObject;
- begin
- result := TPasJSONItemObject.Create;
- try
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- case aObject.Type_ of
- TPasGLTF.TCamera.TType.Orthographic:
- begin
- result.Add('type', TPasJSONItemString.Create('orthographic'));
- if not aObject.Orthographic.Empty then
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- if aObject.Orthographic.fXMag <> TDefaults.FloatSentinel then
- begin
- JSONObject.Add('xmag',
- TPasJSONItemNumber.Create(aObject.Orthographic.fXMag));
- end;
- if aObject.Orthographic.fYMag <> TDefaults.FloatSentinel then
- begin
- JSONObject.Add('ymag',
- TPasJSONItemNumber.Create(aObject.Orthographic.fYMag));
- end;
- if aObject.Orthographic.fZNear <> -TDefaults.FloatSentinel
- then
- begin
- JSONObject.Add('znear',
- TPasJSONItemNumber.Create(aObject.Orthographic.fZNear));
- end;
- if aObject.Orthographic.fZFar <> -TDefaults.FloatSentinel then
- begin
- JSONObject.Add('zfar',
- TPasJSONItemNumber.Create(aObject.Orthographic.fZFar));
- end;
- ProcessExtensionsAndExtras(JSONObject, aObject.Orthographic);
- finally
- result.Add('orthographic', JSONObject);
- end;
- end;
- end;
- TPasGLTF.TCamera.TType.Perspective:
- begin
- result.Add('type', TPasJSONItemString.Create('perspective'));
- if not aObject.Perspective.Empty then
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- JSONObject.Add('aspectRatio',
- TPasJSONItemNumber.Create
- (aObject.Perspective.fAspectRatio));
- JSONObject.Add('yfov',
- TPasJSONItemNumber.Create(aObject.Perspective.fYFov));
- JSONObject.Add('znear',
- TPasJSONItemNumber.Create(aObject.Perspective.fZNear));
- JSONObject.Add('zfar',
- TPasJSONItemNumber.Create(aObject.Perspective.fZFar));
- ProcessExtensionsAndExtras(JSONObject, aObject.Perspective);
- finally
- result.Add('perspective', JSONObject);
- end;
- end;
- end;
- else
- begin
- Assert(false);
- end;
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Camera: TCamera;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Camera in fCameras do
- begin
- result.Add(ProcessCamera(Camera));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessImages: TPasJSONItemArray;
- function ProcessImage(const aObject: TImage): TPasJSONItemObject;
- begin
- result := TPasJSONItemObject.Create;
- try
- if ((aObject.fBufferView >= 0) and (Length(aObject.fURI) = 0)) or
- ((aObject.fBufferView > 0) and (Length(aObject.fURI) > 0)) then
- begin
- result.Add('bufferView',
- TPasJSONItemNumber.Create(aObject.fBufferView));
- end;
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if Length(aObject.fMimeType) > 0 then
- begin
- result.Add('mimeType', TPasJSONItemString.Create(aObject.fMimeType));
- end;
- if Length(aObject.fURI) > 0 then
- begin
- result.Add('uri', TPasJSONItemString.Create(aObject.fURI));
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Image: TImage;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Image in fImages do
- begin
- result.Add(ProcessImage(Image));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessMaterials: TPasJSONItemArray;
- function ProcessMaterial(const aObject: TMaterial): TPasJSONItemObject;
- var
- JSONArray: TPasJSONItemArray;
- JSONObject, JSONSubObject: TPasJSONItemObject;
- begin
- result := TPasJSONItemObject.Create;
- try
- if aObject.fAlphaCutOff <> TDefaults.MaterialAlphaCutoff then
- begin
- result.Add('alphaCutoff',
- TPasJSONItemNumber.Create(aObject.fAlphaCutOff));
- end;
- case aObject.fAlphaMode of
- TPasGLTF.TMaterial.TAlphaMode.Opaque:
- begin
- // Default value
- // result.Add('alphaMode',TPasJSONItemString.Create('OPAQUE'));
- end;
- TPasGLTF.TMaterial.TAlphaMode.Mask:
- begin
- result.Add('alphaMode', TPasJSONItemString.Create('MASK'));
- end;
- TPasGLTF.TMaterial.TAlphaMode.Blend:
- begin
- result.Add('alphaMode', TPasJSONItemString.Create('BLEND'));
- end;
- else
- begin
- Assert(false);
- end;
- end;
- if aObject.fDoubleSided <> TDefaults.MaterialDoubleSided then
- begin
- result.Add('doubleSided',
- TPasJSONItemBoolean.Create(aObject.fDoubleSided));
- end;
- if not CompareMem(@aObject.EmissiveFactor, @TDefaults.NullVector3,
- SizeOf(TVector3)) then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- JSONArray.Add(TPasJSONItemNumber.Create(aObject.EmissiveFactor[0]));
- JSONArray.Add(TPasJSONItemNumber.Create(aObject.EmissiveFactor[1]));
- JSONArray.Add(TPasJSONItemNumber.Create(aObject.EmissiveFactor[2]));
- finally
- result.Add('emissiveFactor', JSONArray);
- end;
- end;
- if not aObject.fEmissiveTexture.Empty then
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- if aObject.fEmissiveTexture.fIndex >= 0 then
- begin
- JSONObject.Add('index',
- TPasJSONItemNumber.Create(aObject.fEmissiveTexture.fIndex));
- end;
- if aObject.fEmissiveTexture.fTexCoord > 0 then
- begin
- JSONObject.Add('texCoord',
- TPasJSONItemNumber.Create(aObject.fEmissiveTexture.fTexCoord));
- end;
- ProcessExtensionsAndExtras(JSONObject, aObject.fEmissiveTexture);
- finally
- result.Add('emissiveTexture', JSONObject);
- end;
- end;
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if not aObject.fNormalTexture.Empty then
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- if aObject.fNormalTexture.fIndex >= 0 then
- begin
- JSONObject.Add('index',
- TPasJSONItemNumber.Create(aObject.fNormalTexture.fIndex));
- end;
- if aObject.fNormalTexture.fTexCoord > 0 then
- begin
- JSONObject.Add('texCoord',
- TPasJSONItemNumber.Create(aObject.fNormalTexture.fTexCoord));
- end;
- if aObject.fNormalTexture.fScale <> TDefaults.IdentityScalar then
- begin
- JSONObject.Add('scale',
- TPasJSONItemNumber.Create(aObject.fNormalTexture.fScale));
- end;
- ProcessExtensionsAndExtras(JSONObject, aObject.fNormalTexture);
- finally
- result.Add('normalTexture', JSONObject);
- end;
- end;
- if not aObject.fOcclusionTexture.Empty then
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- if aObject.fOcclusionTexture.fIndex >= 0 then
- begin
- JSONObject.Add('index',
- TPasJSONItemNumber.Create(aObject.fOcclusionTexture.fIndex));
- end;
- if aObject.fOcclusionTexture.fTexCoord > 0 then
- begin
- JSONObject.Add('texCoord',
- TPasJSONItemNumber.Create(aObject.fOcclusionTexture.fTexCoord));
- end;
- if aObject.fOcclusionTexture.fStrength <> TDefaults.IdentityScalar
- then
- begin
- JSONObject.Add('strength',
- TPasJSONItemNumber.Create(aObject.fOcclusionTexture.fStrength));
- end;
- ProcessExtensionsAndExtras(JSONObject, aObject.fOcclusionTexture);
- finally
- result.Add('occlusionTexture', JSONObject);
- end;
- end;
- if not aObject.PBRMetallicRoughness.Empty then
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- if not CompareMem(@aObject.PBRMetallicRoughness.fBaseColorFactor,
- @TDefaults.IdentityVector4, SizeOf(TVector4)) then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- JSONArray.Add
- (TPasJSONItemNumber.Create
- (aObject.PBRMetallicRoughness.fBaseColorFactor[0]));
- JSONArray.Add
- (TPasJSONItemNumber.Create
- (aObject.PBRMetallicRoughness.fBaseColorFactor[1]));
- JSONArray.Add
- (TPasJSONItemNumber.Create
- (aObject.PBRMetallicRoughness.fBaseColorFactor[2]));
- JSONArray.Add
- (TPasJSONItemNumber.Create
- (aObject.PBRMetallicRoughness.fBaseColorFactor[3]));
- finally
- JSONObject.Add('baseColorFactor', JSONArray);
- end;
- end;
- if not aObject.fPBRMetallicRoughness.fBaseColorTexture.Empty then
- begin
- JSONSubObject := TPasJSONItemObject.Create;
- try
- if aObject.fPBRMetallicRoughness.fBaseColorTexture.fIndex >= 0
- then
- begin
- JSONSubObject.Add('index',
- TPasJSONItemNumber.Create
- (aObject.fPBRMetallicRoughness.fBaseColorTexture.fIndex));
- end;
- if aObject.fPBRMetallicRoughness.fBaseColorTexture.fTexCoord > 0
- then
- begin
- JSONSubObject.Add('texCoord',
- TPasJSONItemNumber.Create
- (aObject.fPBRMetallicRoughness.fBaseColorTexture.
- fTexCoord));
- end;
- ProcessExtensionsAndExtras(JSONSubObject,
- aObject.fPBRMetallicRoughness.fBaseColorTexture);
- finally
- JSONObject.Add('baseColorTexture', JSONSubObject);
- end;
- end;
- if aObject.fPBRMetallicRoughness.fMetallicFactor <> TDefaults.IdentityScalar
- then
- begin
- JSONObject.Add('metallicFactor',
- TPasJSONItemNumber.Create
- (aObject.fPBRMetallicRoughness.fMetallicFactor));
- end;
- if not aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture.Empty
- then
- begin
- JSONSubObject := TPasJSONItemObject.Create;
- try
- if aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture.
- fIndex >= 0 then
- begin
- JSONSubObject.Add('index',
- TPasJSONItemNumber.Create
- (aObject.fPBRMetallicRoughness.
- fMetallicRoughnessTexture.fIndex));
- end;
- if aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture.
- fTexCoord > 0 then
- begin
- JSONSubObject.Add('texCoord',
- TPasJSONItemNumber.Create
- (aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture.
- fTexCoord));
- end;
- ProcessExtensionsAndExtras(JSONSubObject,
- aObject.fPBRMetallicRoughness.fMetallicRoughnessTexture);
- finally
- JSONObject.Add('metallicRoughnessTexture', JSONSubObject);
- end;
- end;
- if aObject.fPBRMetallicRoughness.fRoughnessFactor <> TDefaults.IdentityScalar
- then
- begin
- JSONObject.Add('roughnessFactor',
- TPasJSONItemNumber.Create
- (aObject.fPBRMetallicRoughness.fRoughnessFactor));
- end;
- ProcessExtensionsAndExtras(JSONObject,
- aObject.fPBRMetallicRoughness);
- finally
- result.Add('pbrMetallicRoughness', JSONObject);
- end;
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Material: TMaterial;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Material in fMaterials do
- begin
- result.Add(ProcessMaterial(Material));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessMeshes: TPasJSONItemArray;
- function ProcessMesh(const aObject: TMesh): TPasJSONItemObject;
- var
- Index: TPasJSONSizeInt;
- JSONArray: TPasJSONItemArray;
- JSONObject, JSONSubObject: TPasJSONItemObject;
- Primitive: TMesh.TPrimitive;
- Attributes: TAttributes;
- Used: boolean;
- begin
- result := TPasJSONItemObject.Create;
- try
- if aObject.fPrimitives.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Primitive in aObject.fPrimitives do
- begin
- JSONObject := TPasJSONItemObject.Create;
- try
- begin
- Used := false;
- for Index := 0 to Primitive.fAttributes.fSize - 1 do
- begin
- if Primitive.fAttributes.fEntityToCellIndex[Index] >= 0 then
- begin
- Used := true;
- break;
- end;
- end;
- if Used then
- begin
- JSONSubObject := TPasJSONItemObject.Create;
- try
- for Index := 0 to Primitive.fAttributes.fSize - 1 do
- begin
- if Primitive.fAttributes.fEntityToCellIndex[Index] >= 0
- then
- begin
- JSONSubObject.Add(Primitive.fAttributes.fEntities
- [Index].Key,
- TPasJSONItemNumber.Create
- (Primitive.fAttributes.fEntities[Index].Value));
- end;
- end;
- finally
- JSONObject.Add('attributes', JSONSubObject);
- end;
- end;
- end;
- if Primitive.fIndices >= 0 then
- begin
- JSONObject.Add('indices',
- TPasJSONItemNumber.Create(Primitive.fIndices));
- end;
- if Primitive.fMaterial >= 0 then
- begin
- JSONObject.Add('material',
- TPasJSONItemNumber.Create(Primitive.fMaterial));
- end;
- if Primitive.fMode <> TMesh.TPrimitive.TMode.Triangles then
- begin
- JSONObject.Add('mode',
- TPasJSONItemNumber.Create(TPasGLTFInt64(Primitive.fMode)));
- end;
- if Primitive.fTargets.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Attributes in Primitive.fTargets do
- begin
- JSONSubObject := TPasJSONItemObject.Create;
- try
- for Index := 0 to Attributes.fSize - 1 do
- begin
- if Attributes.fEntityToCellIndex[Index] >= 0 then
- begin
- JSONSubObject.Add(Attributes.fEntities[Index].Key,
- TPasJSONItemNumber.Create(Attributes.fEntities[
- Index].Value));
- end;
- end;
- finally
- JSONArray.Add(JSONSubObject);
- end;
- end;
- finally
- JSONObject.Add('targets', JSONArray);
- end;
- end;
- ProcessExtensionsAndExtras(JSONObject, Primitive);
- finally
- JSONArray.Add(JSONObject);
- end;
- end;
- finally
- result.Add('primitives', JSONArray);
- end;
- end;
- if aObject.fWeights.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to aObject.fWeights.Count - 1 do
- begin
- JSONArray.Add
- (TPasJSONItemNumber.Create(aObject.fWeights.Items[Index]));
- end;
- finally
- result.Add('weights', JSONArray);
- end;
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Mesh: TMesh;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Mesh in fMeshes do
- begin
- result.Add(ProcessMesh(Mesh));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessNodes: TPasJSONItemArray;
- function ProcessNode(const aObject: TNode): TPasJSONItemObject;
- var
- Index: TPasJSONSizeInt;
- JSONArray: TPasJSONItemArray;
- begin
- result := TPasJSONItemObject.Create;
- try
- if aObject.fCamera >= 0 then
- begin
- result.Add('camera', TPasJSONItemNumber.Create(aObject.fCamera));
- end;
- if aObject.fChildren.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to aObject.fChildren.Count - 1 do
- begin
- JSONArray.Add
- (TPasJSONItemNumber.Create(aObject.fChildren.Items[Index]));
- end;
- finally
- result.Add('children', JSONArray);
- end;
- end;
- if not CompareMem(@aObject.fMatrix, @TDefaults.IdentityMatrix4x4,
- SizeOf(TMatrix4x4)) then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to 15 do
- begin
- JSONArray.Add(TPasJSONItemNumber.Create(aObject.fMatrix[Index]));
- end;
- finally
- result.Add('matrix', JSONArray);
- end;
- end;
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if aObject.fMesh >= 0 then
- begin
- result.Add('mesh', TPasJSONItemNumber.Create(aObject.fMesh));
- end;
- if not CompareMem(@aObject.fRotation, @TDefaults.IdentityQuaternion,
- SizeOf(TVector4)) then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to 3 do
- begin
- JSONArray.Add(TPasJSONItemNumber.Create(aObject.fRotation
- [Index]));
- end;
- finally
- result.Add('rotation', JSONArray);
- end;
- end;
- if not CompareMem(@aObject.fScale, @TDefaults.IdentityVector3,
- SizeOf(TVector3)) then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to 2 do
- begin
- JSONArray.Add(TPasJSONItemNumber.Create(aObject.fScale[Index]));
- end;
- finally
- result.Add('scale', JSONArray);
- end;
- end;
- if aObject.fSkin >= 0 then
- begin
- result.Add('skin', TPasJSONItemNumber.Create(aObject.fSkin));
- end;
- if not CompareMem(@aObject.fTranslation, @TDefaults.NullVector3,
- SizeOf(TVector3)) then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to 2 do
- begin
- JSONArray.Add
- (TPasJSONItemNumber.Create(aObject.fTranslation[Index]));
- end;
- finally
- result.Add('translation', JSONArray);
- end;
- end;
- if aObject.fWeights.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to aObject.fWeights.Count - 1 do
- begin
- JSONArray.Add
- (TPasJSONItemNumber.Create(aObject.fWeights.Items[Index]));
- end;
- finally
- result.Add('weights', JSONArray);
- end;
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Node: TNode;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Node in fNodes do
- begin
- result.Add(ProcessNode(Node));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessSamplers: TPasJSONItemArray;
- function ProcessSampler(const aObject: TSampler): TPasJSONItemObject;
- begin
- result := TPasJSONItemObject.Create;
- try
- if not aObject.Empty then
- begin
- if aObject.fMinFilter <> TSampler.TMinFilter.None then
- begin
- result.Add('minFilter',
- TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fMinFilter)));
- end;
- if aObject.fMagFilter <> TSampler.TMagFilter.None then
- begin
- result.Add('magFilter',
- TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fMagFilter)));
- end;
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if aObject.fWrapS <> TSampler.TWrappingMode.Repeat_ then
- begin
- result.Add('wrapS',
- TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fWrapS)));
- end;
- if aObject.fWrapT <> TSampler.TWrappingMode.Repeat_ then
- begin
- result.Add('wrapS',
- TPasJSONItemNumber.Create(TPasGLTFInt64(aObject.fWrapT)));
- end;
- ProcessExtensionsAndExtras(result, aObject);
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Sampler: TSampler;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Sampler in fSamplers do
- begin
- result.Add(ProcessSampler(Sampler));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessScenes: TPasJSONItemArray;
- function ProcessScene(const aObject: TScene): TPasJSONItemObject;
- var
- Index: TPasJSONSizeInt;
- JSONArray: TPasJSONItemArray;
- begin
- result := TPasJSONItemObject.Create;
- try
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if aObject.fNodes.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to aObject.fNodes.Count - 1 do
- begin
- JSONArray.Add
- (TPasJSONItemNumber.Create(aObject.fNodes.Items[Index]));
- end;
- finally
- result.Add('nodes', JSONArray);
- end;
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Scene: TScene;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Scene in fScenes do
- begin
- result.Add(ProcessScene(Scene));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessSkins: TPasJSONItemArray;
- function ProcessSkin(const aObject: TSkin): TPasJSONItemObject;
- var
- Index: TPasJSONSizeInt;
- JSONArray: TPasJSONItemArray;
- begin
- result := TPasJSONItemObject.Create;
- try
- if aObject.fInverseBindMatrices >= 0 then
- begin
- result.Add('inverseBindMatrices',
- TPasJSONItemNumber.Create(aObject.fInverseBindMatrices));
- end;
- if aObject.fJoints.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Index := 0 to aObject.fJoints.Count - 1 do
- begin
- JSONArray.Add
- (TPasJSONItemNumber.Create(aObject.fJoints.Items[Index]));
- end;
- finally
- result.Add('joints', JSONArray);
- end;
- end;
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if aObject.fSkeleton >= 0 then
- begin
- result.Add('skeleton', TPasJSONItemNumber.Create(aObject.fSkeleton));
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Skin: TSkin;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Skin in fSkins do
- begin
- result.Add(ProcessSkin(Skin));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- function ProcessTextures: TPasJSONItemArray;
- function ProcessTexture(const aObject: TTexture): TPasJSONItemObject;
- begin
- result := TPasJSONItemObject.Create;
- try
- if Length(aObject.fName) > 0 then
- begin
- result.Add('name', TPasJSONItemString.Create(aObject.fName));
- end;
- if aObject.fSampler >= 0 then
- begin
- result.Add('sampler', TPasJSONItemNumber.Create(aObject.fSampler));
- end;
- if aObject.fSource >= 0 then
- begin
- result.Add('source', TPasJSONItemNumber.Create(aObject.fSource));
- end;
- ProcessExtensionsAndExtras(result, aObject);
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- Texture: TTexture;
- begin
- result := TPasJSONItemArray.Create;
- try
- for Texture in fTextures do
- begin
- result.Add(ProcessTexture(Texture));
- end;
- except
- FreeAndNil(result);
- raise;
- end;
- end;
- var
- JSONRootItem: TPasJSONItemObject;
- JSONArray: TPasJSONItemArray;
- Extension: String;
- begin
- JSONRootItem := TPasJSONItemObject.Create;
- try
- if fAccessors.Count > 0 then
- begin
- JSONRootItem.Add('accessors', ProcessAccessors);
- end;
- if fAnimations.Count > 0 then
- begin
- JSONRootItem.Add('animations', ProcessAnimations);
- end;
- JSONRootItem.Add('asset', ProcessAsset);
- if fBuffers.Count > 0 then
- begin
- JSONRootItem.Add('buffers', ProcessBuffers);
- end;
- if fBufferViews.Count > 0 then
- begin
- JSONRootItem.Add('bufferViews', ProcessBufferViews);
- end;
- if fCameras.Count > 0 then
- begin
- JSONRootItem.Add('cameras', ProcessCameras);
- end;
- if fImages.Count > 0 then
- begin
- JSONRootItem.Add('images', ProcessImages);
- end;
- if fMaterials.Count > 0 then
- begin
- JSONRootItem.Add('materials', ProcessMaterials);
- end;
- if fMeshes.Count > 0 then
- begin
- JSONRootItem.Add('meshes', ProcessMeshes);
- end;
- if fNodes.Count > 0 then
- begin
- JSONRootItem.Add('nodes', ProcessNodes);
- end;
- if fSamplers.Count > 0 then
- begin
- JSONRootItem.Add('samplers', ProcessSamplers);
- end;
- if fScene >= 0 then
- begin
- JSONRootItem.Add('scene', TPasJSONItemNumber.Create(fScene));
- end;
- if fScenes.Count > 0 then
- begin
- JSONRootItem.Add('scenes', ProcessScenes);
- end;
- if fSkins.Count > 0 then
- begin
- JSONRootItem.Add('skins', ProcessSkins);
- end;
- if fTextures.Count > 0 then
- begin
- JSONRootItem.Add('textures', ProcessTextures);
- end;
- if fExtensionsUsed.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Extension in fExtensionsUsed do
- begin
- JSONArray.Add(TPasJSONItemString.Create
- (TPasJSONUTF8String(Extension)));
- end;
- finally
- JSONRootItem.Add('extensionsUsed', JSONArray);
- end;
- end;
- if fExtensionsRequired.Count > 0 then
- begin
- JSONArray := TPasJSONItemArray.Create;
- try
- for Extension in fExtensionsRequired do
- begin
- JSONArray.Add(TPasJSONItemString.Create
- (TPasJSONUTF8String(Extension)));
- end;
- finally
- JSONRootItem.Add('extensionsRequired', JSONArray);
- end;
- end;
- ProcessExtensionsAndExtras(JSONRootItem, self);
- result := TPasJSON.Stringify(JSONRootItem, aFormatted, []);
- finally
- FreeAndNil(JSONRootItem);
- end;
- end;
- procedure TPasGLTF.TDocument.SaveToBinary(const aStream: TStream);
- var
- Index: TPasGLTFSizeInt;
- JSONRawByteString: TPasJSONRawByteString;
- GLBHeader: TGLBHeader;
- ChunkHeader: TChunkHeader;
- Buffer: TPasGLTF.TBuffer;
- begin
- JSONRawByteString := SaveToJSON(false);
- while (Length(JSONRawByteString) = 0) or
- ((Length(JSONRawByteString) and 3) <> 0) do
- begin
- JSONRawByteString := JSONRawByteString + #32;
- end;
- GLBHeader.Magic := GLBHeaderMagicNativeEndianness;
- GLBHeader.Version := $00000002;
- GLBHeader.Length := SizeOf(TGLBHeader) + Length(JSONRawByteString);
- if (fBuffers.Count > 0) and (fBuffers[0].fData.Size > 0) then
- begin
- inc(GLBHeader.Length, SizeOf(TChunkHeader) + fBuffers[0].fData.Size);
- end;
- GLBHeader.JSONChunkHeader.ChunkLength := Length(JSONRawByteString);
- GLBHeader.JSONChunkHeader.ChunkType := GLBChunkJSONNativeEndianness;
- aStream.WriteBuffer(GLBHeader, SizeOf(TGLBHeader));
- aStream.WriteBuffer(JSONRawByteString[1], Length(JSONRawByteString));
- for Index := 0 to fBuffers.Count - 1 do
- begin
- Buffer := fBuffers[Index];
- ChunkHeader.ChunkLength := Buffer.fData.Size;
- ChunkHeader.ChunkType := GLBChunkBinaryNativeEndianness;
- aStream.WriteBuffer(ChunkHeader, SizeOf(TChunkHeader));
- if ChunkHeader.ChunkLength > 0 then
- begin
- aStream.WriteBuffer(Buffer.fData.Memory^, Buffer.fData.Size);
- end;
- end;
- end;
- procedure TPasGLTF.TDocument.SaveToStream(const aStream: TStream;
- const aBinary: boolean = false; const aFormatted: boolean = false);
- var
- JSONRawByteString: TPasJSONRawByteString;
- begin
- if aBinary then
- begin
- SaveToBinary(aStream);
- end
- else
- begin
- JSONRawByteString := SaveToJSON(aFormatted);
- if Length(JSONRawByteString) > 0 then
- begin
- aStream.WriteBuffer(JSONRawByteString[1], Length(JSONRawByteString));
- end;
- end;
- end;
- end.
|