tiny_gltf.h 273 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725
  1. //
  2. // Header-only tiny glTF 2.0 loader and serializer.
  3. //
  4. //
  5. // The MIT License (MIT)
  6. //
  7. // Copyright (c) 2015 - Present Syoyo Fujita, Aurélien Chatelain and many
  8. // contributors.
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining a copy
  11. // of this software and associated documentation files (the "Software"), to deal
  12. // in the Software without restriction, including without limitation the rights
  13. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. // copies of the Software, and to permit persons to whom the Software is
  15. // furnished to do so, subject to the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be included in
  18. // all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  23. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  25. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  26. // THE SOFTWARE.
  27. // Version: - v2.9.*
  28. // See https://github.com/syoyo/tinygltf/releases for release history.
  29. //
  30. // Tiny glTF loader is using following third party libraries:
  31. //
  32. // - jsonhpp: C++ JSON library.
  33. // - base64: base64 decode/encode library.
  34. // - stb_image: Image loading library.
  35. //
  36. #ifndef TINY_GLTF_H_
  37. #define TINY_GLTF_H_
  38. #include <array>
  39. #include <cassert>
  40. #include <cmath> // std::fabs
  41. #include <cstdint>
  42. #include <cstdlib>
  43. #include <cstring>
  44. #include <functional>
  45. #include <limits>
  46. #include <map>
  47. #include <string>
  48. #include <utility>
  49. #include <vector>
  50. // Auto-detect C++14 standard version
  51. #if !defined(TINYGLTF_USE_CPP14) && defined(__cplusplus) && \
  52. (__cplusplus >= 201402L)
  53. #define TINYGLTF_USE_CPP14
  54. #endif
  55. #ifdef __ANDROID__
  56. #ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
  57. #include <android/asset_manager.h>
  58. #endif
  59. #endif
  60. #ifdef __GNUC__
  61. #if (__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ <= 8))
  62. #define TINYGLTF_NOEXCEPT
  63. #else
  64. #define TINYGLTF_NOEXCEPT noexcept
  65. #endif
  66. #else
  67. #define TINYGLTF_NOEXCEPT noexcept
  68. #endif
  69. #define DEFAULT_METHODS(x) \
  70. ~x() = default; \
  71. x(const x &) = default; \
  72. x(x &&) TINYGLTF_NOEXCEPT = default; \
  73. x &operator=(const x &) = default; \
  74. x &operator=(x &&) TINYGLTF_NOEXCEPT = default;
  75. namespace tinygltf {
  76. #define TINYGLTF_MODE_POINTS (0)
  77. #define TINYGLTF_MODE_LINE (1)
  78. #define TINYGLTF_MODE_LINE_LOOP (2)
  79. #define TINYGLTF_MODE_LINE_STRIP (3)
  80. #define TINYGLTF_MODE_TRIANGLES (4)
  81. #define TINYGLTF_MODE_TRIANGLE_STRIP (5)
  82. #define TINYGLTF_MODE_TRIANGLE_FAN (6)
  83. #define TINYGLTF_COMPONENT_TYPE_BYTE (5120)
  84. #define TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE (5121)
  85. #define TINYGLTF_COMPONENT_TYPE_SHORT (5122)
  86. #define TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT (5123)
  87. #define TINYGLTF_COMPONENT_TYPE_INT (5124)
  88. #define TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT (5125)
  89. #define TINYGLTF_COMPONENT_TYPE_FLOAT (5126)
  90. #define TINYGLTF_COMPONENT_TYPE_DOUBLE \
  91. (5130) // OpenGL double type. Note that some of glTF 2.0 validator does not
  92. // support double type even the schema seems allow any value of
  93. // integer:
  94. // https://github.com/KhronosGroup/glTF/blob/b9884a2fd45130b4d673dd6c8a706ee21ee5c5f7/specification/2.0/schema/accessor.schema.json#L22
  95. #define TINYGLTF_TEXTURE_FILTER_NEAREST (9728)
  96. #define TINYGLTF_TEXTURE_FILTER_LINEAR (9729)
  97. #define TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST (9984)
  98. #define TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST (9985)
  99. #define TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR (9986)
  100. #define TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR (9987)
  101. #define TINYGLTF_TEXTURE_WRAP_REPEAT (10497)
  102. #define TINYGLTF_TEXTURE_WRAP_CLAMP_TO_EDGE (33071)
  103. #define TINYGLTF_TEXTURE_WRAP_MIRRORED_REPEAT (33648)
  104. // Redeclarations of the above for technique.parameters.
  105. #define TINYGLTF_PARAMETER_TYPE_BYTE (5120)
  106. #define TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE (5121)
  107. #define TINYGLTF_PARAMETER_TYPE_SHORT (5122)
  108. #define TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT (5123)
  109. #define TINYGLTF_PARAMETER_TYPE_INT (5124)
  110. #define TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT (5125)
  111. #define TINYGLTF_PARAMETER_TYPE_FLOAT (5126)
  112. #define TINYGLTF_PARAMETER_TYPE_FLOAT_VEC2 (35664)
  113. #define TINYGLTF_PARAMETER_TYPE_FLOAT_VEC3 (35665)
  114. #define TINYGLTF_PARAMETER_TYPE_FLOAT_VEC4 (35666)
  115. #define TINYGLTF_PARAMETER_TYPE_INT_VEC2 (35667)
  116. #define TINYGLTF_PARAMETER_TYPE_INT_VEC3 (35668)
  117. #define TINYGLTF_PARAMETER_TYPE_INT_VEC4 (35669)
  118. #define TINYGLTF_PARAMETER_TYPE_BOOL (35670)
  119. #define TINYGLTF_PARAMETER_TYPE_BOOL_VEC2 (35671)
  120. #define TINYGLTF_PARAMETER_TYPE_BOOL_VEC3 (35672)
  121. #define TINYGLTF_PARAMETER_TYPE_BOOL_VEC4 (35673)
  122. #define TINYGLTF_PARAMETER_TYPE_FLOAT_MAT2 (35674)
  123. #define TINYGLTF_PARAMETER_TYPE_FLOAT_MAT3 (35675)
  124. #define TINYGLTF_PARAMETER_TYPE_FLOAT_MAT4 (35676)
  125. #define TINYGLTF_PARAMETER_TYPE_SAMPLER_2D (35678)
  126. // End parameter types
  127. #define TINYGLTF_TYPE_VEC2 (2)
  128. #define TINYGLTF_TYPE_VEC3 (3)
  129. #define TINYGLTF_TYPE_VEC4 (4)
  130. #define TINYGLTF_TYPE_MAT2 (32 + 2)
  131. #define TINYGLTF_TYPE_MAT3 (32 + 3)
  132. #define TINYGLTF_TYPE_MAT4 (32 + 4)
  133. #define TINYGLTF_TYPE_SCALAR (64 + 1)
  134. #define TINYGLTF_TYPE_VECTOR (64 + 4)
  135. #define TINYGLTF_TYPE_MATRIX (64 + 16)
  136. #define TINYGLTF_IMAGE_FORMAT_JPEG (0)
  137. #define TINYGLTF_IMAGE_FORMAT_PNG (1)
  138. #define TINYGLTF_IMAGE_FORMAT_BMP (2)
  139. #define TINYGLTF_IMAGE_FORMAT_GIF (3)
  140. #define TINYGLTF_TEXTURE_FORMAT_ALPHA (6406)
  141. #define TINYGLTF_TEXTURE_FORMAT_RGB (6407)
  142. #define TINYGLTF_TEXTURE_FORMAT_RGBA (6408)
  143. #define TINYGLTF_TEXTURE_FORMAT_LUMINANCE (6409)
  144. #define TINYGLTF_TEXTURE_FORMAT_LUMINANCE_ALPHA (6410)
  145. #define TINYGLTF_TEXTURE_TARGET_TEXTURE2D (3553)
  146. #define TINYGLTF_TEXTURE_TYPE_UNSIGNED_BYTE (5121)
  147. #define TINYGLTF_TARGET_ARRAY_BUFFER (34962)
  148. #define TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER (34963)
  149. #define TINYGLTF_SHADER_TYPE_VERTEX_SHADER (35633)
  150. #define TINYGLTF_SHADER_TYPE_FRAGMENT_SHADER (35632)
  151. #define TINYGLTF_DOUBLE_EPS (1.e-12)
  152. #define TINYGLTF_DOUBLE_EQUAL(a, b) (std::fabs((b) - (a)) < TINYGLTF_DOUBLE_EPS)
  153. #ifdef __ANDROID__
  154. #ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
  155. #ifdef TINYGLTF_IMPLEMENTATION
  156. AAssetManager *asset_manager = nullptr;
  157. #else
  158. extern AAssetManager *asset_manager;
  159. #endif
  160. #endif
  161. #endif
  162. typedef enum {
  163. NULL_TYPE,
  164. REAL_TYPE,
  165. INT_TYPE,
  166. BOOL_TYPE,
  167. STRING_TYPE,
  168. ARRAY_TYPE,
  169. BINARY_TYPE,
  170. OBJECT_TYPE
  171. } Type;
  172. typedef enum {
  173. Permissive,
  174. Strict
  175. } ParseStrictness;
  176. static inline int32_t GetComponentSizeInBytes(uint32_t componentType) {
  177. if (componentType == TINYGLTF_COMPONENT_TYPE_BYTE) {
  178. return 1;
  179. } else if (componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
  180. return 1;
  181. } else if (componentType == TINYGLTF_COMPONENT_TYPE_SHORT) {
  182. return 2;
  183. } else if (componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
  184. return 2;
  185. } else if (componentType == TINYGLTF_COMPONENT_TYPE_INT) {
  186. return 4;
  187. } else if (componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) {
  188. return 4;
  189. } else if (componentType == TINYGLTF_COMPONENT_TYPE_FLOAT) {
  190. return 4;
  191. } else if (componentType == TINYGLTF_COMPONENT_TYPE_DOUBLE) {
  192. return 8;
  193. } else {
  194. // Unknown component type
  195. return -1;
  196. }
  197. }
  198. static inline int32_t GetNumComponentsInType(uint32_t ty) {
  199. if (ty == TINYGLTF_TYPE_SCALAR) {
  200. return 1;
  201. } else if (ty == TINYGLTF_TYPE_VEC2) {
  202. return 2;
  203. } else if (ty == TINYGLTF_TYPE_VEC3) {
  204. return 3;
  205. } else if (ty == TINYGLTF_TYPE_VEC4) {
  206. return 4;
  207. } else if (ty == TINYGLTF_TYPE_MAT2) {
  208. return 4;
  209. } else if (ty == TINYGLTF_TYPE_MAT3) {
  210. return 9;
  211. } else if (ty == TINYGLTF_TYPE_MAT4) {
  212. return 16;
  213. } else {
  214. // Unknown component type
  215. return -1;
  216. }
  217. }
  218. // TODO(syoyo): Move these functions to TinyGLTF class
  219. bool IsDataURI(const std::string &in);
  220. bool DecodeDataURI(std::vector<unsigned char> *out, std::string &mime_type,
  221. const std::string &in, size_t reqBytes, bool checkSize);
  222. #ifdef __clang__
  223. #pragma clang diagnostic push
  224. // Suppress warning for : static Value null_value
  225. #pragma clang diagnostic ignored "-Wexit-time-destructors"
  226. #pragma clang diagnostic ignored "-Wpadded"
  227. #endif
  228. // Simple class to represent JSON object
  229. class Value {
  230. public:
  231. typedef std::vector<Value> Array;
  232. typedef std::map<std::string, Value> Object;
  233. Value() = default;
  234. explicit Value(bool b) : type_(BOOL_TYPE) { boolean_value_ = b; }
  235. explicit Value(int i) : type_(INT_TYPE) {
  236. int_value_ = i;
  237. real_value_ = i;
  238. }
  239. explicit Value(double n) : type_(REAL_TYPE) { real_value_ = n; }
  240. explicit Value(const std::string &s) : type_(STRING_TYPE) {
  241. string_value_ = s;
  242. }
  243. explicit Value(std::string &&s)
  244. : type_(STRING_TYPE), string_value_(std::move(s)) {}
  245. explicit Value(const char *s) : type_(STRING_TYPE) { string_value_ = s; }
  246. explicit Value(const unsigned char *p, size_t n) : type_(BINARY_TYPE) {
  247. binary_value_.resize(n);
  248. memcpy(binary_value_.data(), p, n);
  249. }
  250. explicit Value(std::vector<unsigned char> &&v) noexcept
  251. : type_(BINARY_TYPE),
  252. binary_value_(std::move(v)) {}
  253. explicit Value(const Array &a) : type_(ARRAY_TYPE) { array_value_ = a; }
  254. explicit Value(Array &&a) noexcept : type_(ARRAY_TYPE),
  255. array_value_(std::move(a)) {}
  256. explicit Value(const Object &o) : type_(OBJECT_TYPE) { object_value_ = o; }
  257. explicit Value(Object &&o) noexcept : type_(OBJECT_TYPE),
  258. object_value_(std::move(o)) {}
  259. DEFAULT_METHODS(Value)
  260. char Type() const { return static_cast<char>(type_); }
  261. bool IsBool() const { return (type_ == BOOL_TYPE); }
  262. bool IsInt() const { return (type_ == INT_TYPE); }
  263. bool IsNumber() const { return (type_ == REAL_TYPE) || (type_ == INT_TYPE); }
  264. bool IsReal() const { return (type_ == REAL_TYPE); }
  265. bool IsString() const { return (type_ == STRING_TYPE); }
  266. bool IsBinary() const { return (type_ == BINARY_TYPE); }
  267. bool IsArray() const { return (type_ == ARRAY_TYPE); }
  268. bool IsObject() const { return (type_ == OBJECT_TYPE); }
  269. // Use this function if you want to have number value as double.
  270. double GetNumberAsDouble() const {
  271. if (type_ == INT_TYPE) {
  272. return double(int_value_);
  273. } else {
  274. return real_value_;
  275. }
  276. }
  277. // Use this function if you want to have number value as int.
  278. // TODO(syoyo): Support int value larger than 32 bits
  279. int GetNumberAsInt() const {
  280. if (type_ == REAL_TYPE) {
  281. return int(real_value_);
  282. } else {
  283. return int_value_;
  284. }
  285. }
  286. // Accessor
  287. template <typename T>
  288. const T &Get() const;
  289. template <typename T>
  290. T &Get();
  291. // Lookup value from an array
  292. const Value &Get(size_t idx) const {
  293. static Value null_value;
  294. assert(IsArray());
  295. return (idx < array_value_.size())
  296. ? array_value_[idx]
  297. : null_value;
  298. }
  299. // Lookup value from a key-value pair
  300. const Value &Get(const std::string &key) const {
  301. static Value null_value;
  302. assert(IsObject());
  303. Object::const_iterator it = object_value_.find(key);
  304. return (it != object_value_.end()) ? it->second : null_value;
  305. }
  306. size_t ArrayLen() const {
  307. if (!IsArray()) return 0;
  308. return array_value_.size();
  309. }
  310. // Valid only for object type.
  311. bool Has(const std::string &key) const {
  312. if (!IsObject()) return false;
  313. Object::const_iterator it = object_value_.find(key);
  314. return (it != object_value_.end()) ? true : false;
  315. }
  316. // List keys
  317. std::vector<std::string> Keys() const {
  318. std::vector<std::string> keys;
  319. if (!IsObject()) return keys; // empty
  320. for (Object::const_iterator it = object_value_.begin();
  321. it != object_value_.end(); ++it) {
  322. keys.push_back(it->first);
  323. }
  324. return keys;
  325. }
  326. size_t Size() const { return (IsArray() ? ArrayLen() : Keys().size()); }
  327. bool operator==(const tinygltf::Value &other) const;
  328. protected:
  329. int type_ = NULL_TYPE;
  330. int int_value_ = 0;
  331. double real_value_ = 0.0;
  332. std::string string_value_;
  333. std::vector<unsigned char> binary_value_;
  334. Array array_value_;
  335. Object object_value_;
  336. bool boolean_value_ = false;
  337. };
  338. #ifdef __clang__
  339. #pragma clang diagnostic pop
  340. #endif
  341. #define TINYGLTF_VALUE_GET(ctype, var) \
  342. template <> \
  343. inline const ctype &Value::Get<ctype>() const { \
  344. return var; \
  345. } \
  346. template <> \
  347. inline ctype &Value::Get<ctype>() { \
  348. return var; \
  349. }
  350. TINYGLTF_VALUE_GET(bool, boolean_value_)
  351. TINYGLTF_VALUE_GET(double, real_value_)
  352. TINYGLTF_VALUE_GET(int, int_value_)
  353. TINYGLTF_VALUE_GET(std::string, string_value_)
  354. TINYGLTF_VALUE_GET(std::vector<unsigned char>, binary_value_)
  355. TINYGLTF_VALUE_GET(Value::Array, array_value_)
  356. TINYGLTF_VALUE_GET(Value::Object, object_value_)
  357. #undef TINYGLTF_VALUE_GET
  358. #ifdef __clang__
  359. #pragma clang diagnostic push
  360. #pragma clang diagnostic ignored "-Wc++98-compat"
  361. #pragma clang diagnostic ignored "-Wpadded"
  362. #endif
  363. /// Aggregate object for representing a color
  364. using ColorValue = std::array<double, 4>;
  365. // === legacy interface ====
  366. // TODO(syoyo): Deprecate `Parameter` class.
  367. struct Parameter {
  368. bool bool_value = false;
  369. bool has_number_value = false;
  370. std::string string_value;
  371. std::vector<double> number_array;
  372. std::map<std::string, double> json_double_value;
  373. double number_value = 0.0;
  374. // context sensitive methods. depending the type of the Parameter you are
  375. // accessing, these are either valid or not
  376. // If this parameter represent a texture map in a material, will return the
  377. // texture index
  378. /// Return the index of a texture if this Parameter is a texture map.
  379. /// Returned value is only valid if the parameter represent a texture from a
  380. /// material
  381. int TextureIndex() const {
  382. const auto it = json_double_value.find("index");
  383. if (it != std::end(json_double_value)) {
  384. return int(it->second);
  385. }
  386. return -1;
  387. }
  388. /// Return the index of a texture coordinate set if this Parameter is a
  389. /// texture map. Returned value is only valid if the parameter represent a
  390. /// texture from a material
  391. int TextureTexCoord() const {
  392. const auto it = json_double_value.find("texCoord");
  393. if (it != std::end(json_double_value)) {
  394. return int(it->second);
  395. }
  396. // As per the spec, if texCoord is omitted, this parameter is 0
  397. return 0;
  398. }
  399. /// Return the scale of a texture if this Parameter is a normal texture map.
  400. /// Returned value is only valid if the parameter represent a normal texture
  401. /// from a material
  402. double TextureScale() const {
  403. const auto it = json_double_value.find("scale");
  404. if (it != std::end(json_double_value)) {
  405. return it->second;
  406. }
  407. // As per the spec, if scale is omitted, this parameter is 1
  408. return 1;
  409. }
  410. /// Return the strength of a texture if this Parameter is a an occlusion map.
  411. /// Returned value is only valid if the parameter represent an occlusion map
  412. /// from a material
  413. double TextureStrength() const {
  414. const auto it = json_double_value.find("strength");
  415. if (it != std::end(json_double_value)) {
  416. return it->second;
  417. }
  418. // As per the spec, if strength is omitted, this parameter is 1
  419. return 1;
  420. }
  421. /// Material factor, like the roughness or metalness of a material
  422. /// Returned value is only valid if the parameter represent a texture from a
  423. /// material
  424. double Factor() const { return number_value; }
  425. /// Return the color of a material
  426. /// Returned value is only valid if the parameter represent a texture from a
  427. /// material
  428. ColorValue ColorFactor() const {
  429. return {
  430. {// this aggregate initialize the std::array object, and uses C++11 RVO.
  431. number_array[0], number_array[1], number_array[2],
  432. (number_array.size() > 3 ? number_array[3] : 1.0)}};
  433. }
  434. Parameter() = default;
  435. DEFAULT_METHODS(Parameter)
  436. bool operator==(const Parameter &) const;
  437. };
  438. #ifdef __clang__
  439. #pragma clang diagnostic pop
  440. #endif
  441. #ifdef __clang__
  442. #pragma clang diagnostic push
  443. #pragma clang diagnostic ignored "-Wpadded"
  444. #endif
  445. typedef std::map<std::string, Parameter> ParameterMap;
  446. typedef std::map<std::string, Value> ExtensionMap;
  447. struct AnimationChannel {
  448. int sampler{-1}; // required
  449. int target_node{-1}; // optional index of the node to target (alternative
  450. // target should be provided by extension)
  451. std::string target_path; // required with standard values of ["translation",
  452. // "rotation", "scale", "weights"]
  453. Value extras;
  454. ExtensionMap extensions;
  455. Value target_extras;
  456. ExtensionMap target_extensions;
  457. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  458. std::string extras_json_string;
  459. std::string extensions_json_string;
  460. std::string target_extras_json_string;
  461. std::string target_extensions_json_string;
  462. AnimationChannel() = default;
  463. DEFAULT_METHODS(AnimationChannel)
  464. bool operator==(const AnimationChannel &) const;
  465. };
  466. struct AnimationSampler {
  467. int input{-1}; // required
  468. int output{-1}; // required
  469. std::string interpolation; // "LINEAR", "STEP","CUBICSPLINE" or user defined
  470. // string. default "LINEAR"
  471. Value extras;
  472. ExtensionMap extensions;
  473. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  474. std::string extras_json_string;
  475. std::string extensions_json_string;
  476. AnimationSampler() : interpolation("LINEAR") {}
  477. DEFAULT_METHODS(AnimationSampler)
  478. bool operator==(const AnimationSampler &) const;
  479. };
  480. struct Animation {
  481. std::string name;
  482. std::vector<AnimationChannel> channels;
  483. std::vector<AnimationSampler> samplers;
  484. Value extras;
  485. ExtensionMap extensions;
  486. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  487. std::string extras_json_string;
  488. std::string extensions_json_string;
  489. Animation() = default;
  490. DEFAULT_METHODS(Animation)
  491. bool operator==(const Animation &) const;
  492. };
  493. struct Skin {
  494. std::string name;
  495. int inverseBindMatrices{-1}; // required here but not in the spec
  496. int skeleton{-1}; // The index of the node used as a skeleton root
  497. std::vector<int> joints; // Indices of skeleton nodes
  498. Value extras;
  499. ExtensionMap extensions;
  500. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  501. std::string extras_json_string;
  502. std::string extensions_json_string;
  503. Skin() = default;
  504. DEFAULT_METHODS(Skin)
  505. bool operator==(const Skin &) const;
  506. };
  507. struct Sampler {
  508. std::string name;
  509. // glTF 2.0 spec does not define default value for `minFilter` and
  510. // `magFilter`. Set -1 in TinyGLTF(issue #186)
  511. int minFilter =
  512. -1; // optional. -1 = no filter defined. ["NEAREST", "LINEAR",
  513. // "NEAREST_MIPMAP_NEAREST", "LINEAR_MIPMAP_NEAREST",
  514. // "NEAREST_MIPMAP_LINEAR", "LINEAR_MIPMAP_LINEAR"]
  515. int magFilter =
  516. -1; // optional. -1 = no filter defined. ["NEAREST", "LINEAR"]
  517. int wrapS =
  518. TINYGLTF_TEXTURE_WRAP_REPEAT; // ["CLAMP_TO_EDGE", "MIRRORED_REPEAT",
  519. // "REPEAT"], default "REPEAT"
  520. int wrapT =
  521. TINYGLTF_TEXTURE_WRAP_REPEAT; // ["CLAMP_TO_EDGE", "MIRRORED_REPEAT",
  522. // "REPEAT"], default "REPEAT"
  523. // int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT; // TinyGLTF extension. currently
  524. // not used.
  525. Value extras;
  526. ExtensionMap extensions;
  527. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  528. std::string extras_json_string;
  529. std::string extensions_json_string;
  530. Sampler() = default;
  531. DEFAULT_METHODS(Sampler)
  532. bool operator==(const Sampler &) const;
  533. };
  534. struct Image {
  535. std::string name;
  536. int width{-1};
  537. int height{-1};
  538. int component{-1};
  539. int bits{-1}; // bit depth per channel. 8(byte), 16 or 32.
  540. int pixel_type{-1}; // pixel type(TINYGLTF_COMPONENT_TYPE_***). usually
  541. // UBYTE(bits = 8) or USHORT(bits = 16)
  542. std::vector<unsigned char> image;
  543. int bufferView{-1}; // (required if no uri)
  544. std::string mimeType; // (required if no uri) ["image/jpeg", "image/png",
  545. // "image/bmp", "image/gif"]
  546. std::string uri; // (required if no mimeType) uri is not decoded(e.g.
  547. // whitespace may be represented as %20)
  548. Value extras;
  549. ExtensionMap extensions;
  550. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  551. std::string extras_json_string;
  552. std::string extensions_json_string;
  553. // When this flag is true, data is stored to `image` in as-is format(e.g. jpeg
  554. // compressed for "image/jpeg" mime) This feature is good if you use custom
  555. // image loader function. (e.g. delayed decoding of images for faster glTF
  556. // parsing).
  557. bool as_is{false};
  558. Image() = default;
  559. DEFAULT_METHODS(Image)
  560. bool operator==(const Image &) const;
  561. };
  562. struct Texture {
  563. std::string name;
  564. int sampler{-1};
  565. int source{-1};
  566. Value extras;
  567. ExtensionMap extensions;
  568. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  569. std::string extras_json_string;
  570. std::string extensions_json_string;
  571. Texture() = default;
  572. DEFAULT_METHODS(Texture)
  573. bool operator==(const Texture &) const;
  574. };
  575. struct TextureInfo {
  576. int index{-1}; // required.
  577. int texCoord{0}; // The set index of texture's TEXCOORD attribute used for
  578. // texture coordinate mapping.
  579. Value extras;
  580. ExtensionMap extensions;
  581. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  582. std::string extras_json_string;
  583. std::string extensions_json_string;
  584. TextureInfo() = default;
  585. DEFAULT_METHODS(TextureInfo)
  586. bool operator==(const TextureInfo &) const;
  587. };
  588. struct NormalTextureInfo {
  589. int index{-1}; // required
  590. int texCoord{0}; // The set index of texture's TEXCOORD attribute used for
  591. // texture coordinate mapping.
  592. double scale{
  593. 1.0}; // scaledNormal = normalize((<sampled normal texture value>
  594. // * 2.0 - 1.0) * vec3(<normal scale>, <normal scale>, 1.0))
  595. Value extras;
  596. ExtensionMap extensions;
  597. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  598. std::string extras_json_string;
  599. std::string extensions_json_string;
  600. NormalTextureInfo() = default;
  601. DEFAULT_METHODS(NormalTextureInfo)
  602. bool operator==(const NormalTextureInfo &) const;
  603. };
  604. struct OcclusionTextureInfo {
  605. int index{-1}; // required
  606. int texCoord{0}; // The set index of texture's TEXCOORD attribute used for
  607. // texture coordinate mapping.
  608. double strength{1.0}; // occludedColor = lerp(color, color * <sampled
  609. // occlusion texture value>, <occlusion strength>)
  610. Value extras;
  611. ExtensionMap extensions;
  612. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  613. std::string extras_json_string;
  614. std::string extensions_json_string;
  615. OcclusionTextureInfo() = default;
  616. DEFAULT_METHODS(OcclusionTextureInfo)
  617. bool operator==(const OcclusionTextureInfo &) const;
  618. };
  619. // pbrMetallicRoughness class defined in glTF 2.0 spec.
  620. struct PbrMetallicRoughness {
  621. std::vector<double> baseColorFactor{1.0, 1.0, 1.0, 1.0}; // len = 4. default [1,1,1,1]
  622. TextureInfo baseColorTexture;
  623. double metallicFactor{1.0}; // default 1
  624. double roughnessFactor{1.0}; // default 1
  625. TextureInfo metallicRoughnessTexture;
  626. Value extras;
  627. ExtensionMap extensions;
  628. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  629. std::string extras_json_string;
  630. std::string extensions_json_string;
  631. PbrMetallicRoughness() = default;
  632. DEFAULT_METHODS(PbrMetallicRoughness)
  633. bool operator==(const PbrMetallicRoughness &) const;
  634. };
  635. // Each extension should be stored in a ParameterMap.
  636. // members not in the values could be included in the ParameterMap
  637. // to keep a single material model
  638. struct Material {
  639. std::string name;
  640. std::vector<double> emissiveFactor{0.0, 0.0, 0.0}; // length 3. default [0, 0, 0]
  641. std::string alphaMode{"OPAQUE"}; // default "OPAQUE"
  642. double alphaCutoff{0.5}; // default 0.5
  643. bool doubleSided{false}; // default false
  644. std::vector<int> lods; // level of detail materials (MSFT_lod)
  645. PbrMetallicRoughness pbrMetallicRoughness;
  646. NormalTextureInfo normalTexture;
  647. OcclusionTextureInfo occlusionTexture;
  648. TextureInfo emissiveTexture;
  649. // For backward compatibility
  650. // TODO(syoyo): Remove `values` and `additionalValues` in the next release.
  651. ParameterMap values;
  652. ParameterMap additionalValues;
  653. ExtensionMap extensions;
  654. Value extras;
  655. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  656. std::string extras_json_string;
  657. std::string extensions_json_string;
  658. Material() = default;
  659. DEFAULT_METHODS(Material)
  660. bool operator==(const Material &) const;
  661. };
  662. struct BufferView {
  663. std::string name;
  664. int buffer{-1}; // Required
  665. size_t byteOffset{0}; // minimum 0, default 0
  666. size_t byteLength{0}; // required, minimum 1. 0 = invalid
  667. size_t byteStride{0}; // minimum 4, maximum 252 (multiple of 4), default 0 =
  668. // understood to be tightly packed
  669. int target{0}; // ["ARRAY_BUFFER", "ELEMENT_ARRAY_BUFFER"] for vertex indices
  670. // or attribs. Could be 0 for other data
  671. Value extras;
  672. ExtensionMap extensions;
  673. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  674. std::string extras_json_string;
  675. std::string extensions_json_string;
  676. bool dracoDecoded{false}; // Flag indicating this has been draco decoded
  677. BufferView() = default;
  678. DEFAULT_METHODS(BufferView)
  679. bool operator==(const BufferView &) const;
  680. };
  681. struct Accessor {
  682. int bufferView{-1}; // optional in spec but required here since sparse
  683. // accessor are not supported
  684. std::string name;
  685. size_t byteOffset{0};
  686. bool normalized{false}; // optional.
  687. int componentType{-1}; // (required) One of TINYGLTF_COMPONENT_TYPE_***
  688. size_t count{0}; // required
  689. int type{-1}; // (required) One of TINYGLTF_TYPE_*** ..
  690. Value extras;
  691. ExtensionMap extensions;
  692. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  693. std::string extras_json_string;
  694. std::string extensions_json_string;
  695. std::vector<double>
  696. minValues; // optional. integer value is promoted to double
  697. std::vector<double>
  698. maxValues; // optional. integer value is promoted to double
  699. struct Sparse {
  700. int count;
  701. bool isSparse;
  702. struct {
  703. size_t byteOffset;
  704. int bufferView;
  705. int componentType; // a TINYGLTF_COMPONENT_TYPE_ value
  706. Value extras;
  707. ExtensionMap extensions;
  708. std::string extras_json_string;
  709. std::string extensions_json_string;
  710. } indices;
  711. struct {
  712. int bufferView;
  713. size_t byteOffset;
  714. Value extras;
  715. ExtensionMap extensions;
  716. std::string extras_json_string;
  717. std::string extensions_json_string;
  718. } values;
  719. Value extras;
  720. ExtensionMap extensions;
  721. std::string extras_json_string;
  722. std::string extensions_json_string;
  723. };
  724. Sparse sparse;
  725. ///
  726. /// Utility function to compute byteStride for a given bufferView object.
  727. /// Returns -1 upon invalid glTF value or parameter configuration.
  728. ///
  729. int ByteStride(const BufferView &bufferViewObject) const {
  730. if (bufferViewObject.byteStride == 0) {
  731. // Assume data is tightly packed.
  732. int componentSizeInBytes =
  733. GetComponentSizeInBytes(static_cast<uint32_t>(componentType));
  734. if (componentSizeInBytes <= 0) {
  735. return -1;
  736. }
  737. int numComponents = GetNumComponentsInType(static_cast<uint32_t>(type));
  738. if (numComponents <= 0) {
  739. return -1;
  740. }
  741. return componentSizeInBytes * numComponents;
  742. } else {
  743. // Check if byteStride is a multiple of the size of the accessor's
  744. // component type.
  745. int componentSizeInBytes =
  746. GetComponentSizeInBytes(static_cast<uint32_t>(componentType));
  747. if (componentSizeInBytes <= 0) {
  748. return -1;
  749. }
  750. if ((bufferViewObject.byteStride % uint32_t(componentSizeInBytes)) != 0) {
  751. return -1;
  752. }
  753. return static_cast<int>(bufferViewObject.byteStride);
  754. }
  755. // unreachable return 0;
  756. }
  757. Accessor()
  758. {
  759. sparse.isSparse = false;
  760. }
  761. DEFAULT_METHODS(Accessor)
  762. bool operator==(const tinygltf::Accessor &) const;
  763. };
  764. struct PerspectiveCamera {
  765. double aspectRatio{0.0}; // min > 0
  766. double yfov{0.0}; // required. min > 0
  767. double zfar{0.0}; // min > 0
  768. double znear{0.0}; // required. min > 0
  769. PerspectiveCamera() = default;
  770. DEFAULT_METHODS(PerspectiveCamera)
  771. bool operator==(const PerspectiveCamera &) const;
  772. ExtensionMap extensions;
  773. Value extras;
  774. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  775. std::string extras_json_string;
  776. std::string extensions_json_string;
  777. };
  778. struct OrthographicCamera {
  779. double xmag{0.0}; // required. must not be zero.
  780. double ymag{0.0}; // required. must not be zero.
  781. double zfar{0.0}; // required. `zfar` must be greater than `znear`.
  782. double znear{0.0}; // required
  783. OrthographicCamera() = default;
  784. DEFAULT_METHODS(OrthographicCamera)
  785. bool operator==(const OrthographicCamera &) const;
  786. ExtensionMap extensions;
  787. Value extras;
  788. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  789. std::string extras_json_string;
  790. std::string extensions_json_string;
  791. };
  792. struct Camera {
  793. std::string type; // required. "perspective" or "orthographic"
  794. std::string name;
  795. PerspectiveCamera perspective;
  796. OrthographicCamera orthographic;
  797. Camera() = default;
  798. DEFAULT_METHODS(Camera)
  799. bool operator==(const Camera &) const;
  800. ExtensionMap extensions;
  801. Value extras;
  802. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  803. std::string extras_json_string;
  804. std::string extensions_json_string;
  805. };
  806. struct Primitive {
  807. std::map<std::string, int> attributes; // (required) A dictionary object of
  808. // integer, where each integer
  809. // is the index of the accessor
  810. // containing an attribute.
  811. int material{-1}; // The index of the material to apply to this primitive
  812. // when rendering.
  813. int indices{-1}; // The index of the accessor that contains the indices.
  814. int mode{-1}; // one of TINYGLTF_MODE_***
  815. std::vector<std::map<std::string, int> > targets; // array of morph targets,
  816. // where each target is a dict with attributes in ["POSITION, "NORMAL",
  817. // "TANGENT"] pointing
  818. // to their corresponding accessors
  819. ExtensionMap extensions;
  820. Value extras;
  821. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  822. std::string extras_json_string;
  823. std::string extensions_json_string;
  824. Primitive() = default;
  825. DEFAULT_METHODS(Primitive)
  826. bool operator==(const Primitive &) const;
  827. };
  828. struct Mesh {
  829. std::string name;
  830. std::vector<Primitive> primitives;
  831. std::vector<double> weights; // weights to be applied to the Morph Targets
  832. ExtensionMap extensions;
  833. Value extras;
  834. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  835. std::string extras_json_string;
  836. std::string extensions_json_string;
  837. Mesh() = default;
  838. DEFAULT_METHODS(Mesh)
  839. bool operator==(const Mesh &) const;
  840. };
  841. class Node {
  842. public:
  843. Node() = default;
  844. DEFAULT_METHODS(Node)
  845. bool operator==(const Node &) const;
  846. int camera{-1}; // the index of the camera referenced by this node
  847. std::string name;
  848. int skin{-1};
  849. int mesh{-1};
  850. int light{-1}; // light source index (KHR_lights_punctual)
  851. int emitter{-1}; // audio emitter index (KHR_audio)
  852. std::vector<int> lods; // level of detail nodes (MSFT_lod)
  853. std::vector<int> children;
  854. std::vector<double> rotation; // length must be 0 or 4
  855. std::vector<double> scale; // length must be 0 or 3
  856. std::vector<double> translation; // length must be 0 or 3
  857. std::vector<double> matrix; // length must be 0 or 16
  858. std::vector<double> weights; // The weights of the instantiated Morph Target
  859. ExtensionMap extensions;
  860. Value extras;
  861. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  862. std::string extras_json_string;
  863. std::string extensions_json_string;
  864. };
  865. struct Buffer {
  866. std::string name;
  867. std::vector<unsigned char> data;
  868. std::string
  869. uri; // considered as required here but not in the spec (need to clarify)
  870. // uri is not decoded(e.g. whitespace may be represented as %20)
  871. Value extras;
  872. ExtensionMap extensions;
  873. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  874. std::string extras_json_string;
  875. std::string extensions_json_string;
  876. Buffer() = default;
  877. DEFAULT_METHODS(Buffer)
  878. bool operator==(const Buffer &) const;
  879. };
  880. struct Asset {
  881. std::string version = "2.0"; // required
  882. std::string generator;
  883. std::string minVersion;
  884. std::string copyright;
  885. ExtensionMap extensions;
  886. Value extras;
  887. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  888. std::string extras_json_string;
  889. std::string extensions_json_string;
  890. Asset() = default;
  891. DEFAULT_METHODS(Asset)
  892. bool operator==(const Asset &) const;
  893. };
  894. struct Scene {
  895. std::string name;
  896. std::vector<int> nodes;
  897. std::vector<int> audioEmitters; // KHR_audio global emitters
  898. ExtensionMap extensions;
  899. Value extras;
  900. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  901. std::string extras_json_string;
  902. std::string extensions_json_string;
  903. Scene() = default;
  904. DEFAULT_METHODS(Scene)
  905. bool operator==(const Scene &) const;
  906. };
  907. struct SpotLight {
  908. double innerConeAngle{0.0};
  909. double outerConeAngle{0.7853981634};
  910. SpotLight() = default;
  911. DEFAULT_METHODS(SpotLight)
  912. bool operator==(const SpotLight &) const;
  913. ExtensionMap extensions;
  914. Value extras;
  915. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  916. std::string extras_json_string;
  917. std::string extensions_json_string;
  918. };
  919. struct Light {
  920. std::string name;
  921. std::vector<double> color;
  922. double intensity{1.0};
  923. std::string type;
  924. double range{0.0}; // 0.0 = infinite
  925. SpotLight spot;
  926. Light() = default;
  927. DEFAULT_METHODS(Light)
  928. bool operator==(const Light &) const;
  929. ExtensionMap extensions;
  930. Value extras;
  931. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  932. std::string extras_json_string;
  933. std::string extensions_json_string;
  934. };
  935. struct PositionalEmitter {
  936. double coneInnerAngle{6.283185307179586};
  937. double coneOuterAngle{6.283185307179586};
  938. double coneOuterGain{0.0};
  939. double maxDistance{100.0};
  940. double refDistance{1.0};
  941. double rolloffFactor{1.0};
  942. PositionalEmitter() = default;
  943. DEFAULT_METHODS(PositionalEmitter)
  944. bool operator==(const PositionalEmitter &) const;
  945. ExtensionMap extensions;
  946. Value extras;
  947. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  948. std::string extras_json_string;
  949. std::string extensions_json_string;
  950. };
  951. struct AudioEmitter {
  952. std::string name;
  953. double gain{1.0};
  954. bool loop{false};
  955. bool playing{false};
  956. std::string
  957. type; // positional - Positional audio emitters. Using sound cones, the
  958. // orientation is +Z having the same front side for a glTF asset.
  959. // global - Global audio emitters are not affected by the position
  960. // of audio listeners. coneInnerAngle, coneOuterAngle,
  961. // coneOuterGain, distanceModel, maxDistance, refDistance, and
  962. // rolloffFactor should all be ignored when set.
  963. std::string
  964. distanceModel; // linear - A linear distance model calculating the
  965. // gain induced by the distance according to: 1.0
  966. // - rolloffFactor * (distance - refDistance) /
  967. // (maxDistance - refDistance)
  968. // inverse - (default) An inverse distance model
  969. // calculating the gain induced by the distance according
  970. // to: refDistance / (refDistance + rolloffFactor *
  971. // (Math.max(distance, refDistance) - refDistance))
  972. // exponential - An exponential distance model calculating
  973. // the gain induced by the distance according to:
  974. // pow((Math.max(distance, refDistance) / refDistance,
  975. // -rolloffFactor))
  976. PositionalEmitter positional;
  977. int source{-1};
  978. AudioEmitter() : type("global"), distanceModel("inverse") {}
  979. DEFAULT_METHODS(AudioEmitter)
  980. bool operator==(const AudioEmitter &) const;
  981. ExtensionMap extensions;
  982. Value extras;
  983. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  984. std::string extras_json_string;
  985. std::string extensions_json_string;
  986. };
  987. struct AudioSource {
  988. std::string name;
  989. std::string uri;
  990. int bufferView{-1}; // (required if no uri)
  991. std::string
  992. mimeType; // (required if no uri) The audio's MIME type. Required if
  993. // bufferView is defined. Unless specified by another
  994. // extension, the only supported mimeType is audio/mpeg.
  995. AudioSource() = default;
  996. DEFAULT_METHODS(AudioSource)
  997. bool operator==(const AudioSource &) const;
  998. Value extras;
  999. ExtensionMap extensions;
  1000. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  1001. std::string extras_json_string;
  1002. std::string extensions_json_string;
  1003. };
  1004. class Model {
  1005. public:
  1006. Model() = default;
  1007. DEFAULT_METHODS(Model)
  1008. bool operator==(const Model &) const;
  1009. std::vector<Accessor> accessors;
  1010. std::vector<Animation> animations;
  1011. std::vector<Buffer> buffers;
  1012. std::vector<BufferView> bufferViews;
  1013. std::vector<Material> materials;
  1014. std::vector<Mesh> meshes;
  1015. std::vector<Node> nodes;
  1016. std::vector<Texture> textures;
  1017. std::vector<Image> images;
  1018. std::vector<Skin> skins;
  1019. std::vector<Sampler> samplers;
  1020. std::vector<Camera> cameras;
  1021. std::vector<Scene> scenes;
  1022. std::vector<Light> lights;
  1023. std::vector<AudioEmitter> audioEmitters;
  1024. std::vector<AudioSource> audioSources;
  1025. int defaultScene{-1};
  1026. std::vector<std::string> extensionsUsed;
  1027. std::vector<std::string> extensionsRequired;
  1028. Asset asset;
  1029. Value extras;
  1030. ExtensionMap extensions;
  1031. // Filled when SetStoreOriginalJSONForExtrasAndExtensions is enabled.
  1032. std::string extras_json_string;
  1033. std::string extensions_json_string;
  1034. };
  1035. enum SectionCheck {
  1036. NO_REQUIRE = 0x00,
  1037. REQUIRE_VERSION = 0x01,
  1038. REQUIRE_SCENE = 0x02,
  1039. REQUIRE_SCENES = 0x04,
  1040. REQUIRE_NODES = 0x08,
  1041. REQUIRE_ACCESSORS = 0x10,
  1042. REQUIRE_BUFFERS = 0x20,
  1043. REQUIRE_BUFFER_VIEWS = 0x40,
  1044. REQUIRE_ALL = 0x7f
  1045. };
  1046. ///
  1047. /// URIEncodeFunction type. Signature for custom URI encoding of external
  1048. /// resources such as .bin and image files. Used by tinygltf to re-encode the
  1049. /// final location of saved files. object_type may be used to encode buffer and
  1050. /// image URIs differently, for example. See
  1051. /// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#uris
  1052. ///
  1053. using URIEncodeFunction = std::function<bool(
  1054. const std::string & /* in_uri */, const std::string & /* object_type */,
  1055. std::string * /* out_uri */, void * /* user_data */)>;
  1056. ///
  1057. /// URIDecodeFunction type. Signature for custom URI decoding of external
  1058. /// resources such as .bin and image files. Used by tinygltf when computing
  1059. /// filenames to write resources.
  1060. ///
  1061. using URIDecodeFunction =
  1062. std::function<bool(const std::string & /* in_uri */,
  1063. std::string * /* out_uri */, void * /* user_data */)>;
  1064. // Declaration of default uri decode function
  1065. bool URIDecode(const std::string &in_uri, std::string *out_uri,
  1066. void *user_data);
  1067. ///
  1068. /// A structure containing URI callbacks and a pointer to their user data.
  1069. ///
  1070. struct URICallbacks {
  1071. URIEncodeFunction encode; // Optional encode method
  1072. URIDecodeFunction decode; // Required decode method
  1073. void *user_data; // An argument that is passed to all uri callbacks
  1074. };
  1075. ///
  1076. /// FileExistsFunction type. Signature for custom filesystem callbacks.
  1077. ///
  1078. using FileExistsFunction = std::function<bool(
  1079. const std::string & /* abs_filename */, void * /* user_data */)>;
  1080. ///
  1081. /// ExpandFilePathFunction type. Signature for custom filesystem callbacks.
  1082. ///
  1083. using ExpandFilePathFunction =
  1084. std::function<std::string(const std::string &, void *)>;
  1085. ///
  1086. /// ReadWholeFileFunction type. Signature for custom filesystem callbacks.
  1087. ///
  1088. using ReadWholeFileFunction = std::function<bool(
  1089. std::vector<unsigned char> *, std::string *, const std::string &, void *)>;
  1090. ///
  1091. /// WriteWholeFileFunction type. Signature for custom filesystem callbacks.
  1092. ///
  1093. using WriteWholeFileFunction =
  1094. std::function<bool(std::string *, const std::string &,
  1095. const std::vector<unsigned char> &, void *)>;
  1096. ///
  1097. /// GetFileSizeFunction type. Signature for custom filesystem callbacks.
  1098. ///
  1099. using GetFileSizeFunction =
  1100. std::function<bool(size_t *filesize_out, std::string *err,
  1101. const std::string &abs_filename, void *userdata)>;
  1102. ///
  1103. /// A structure containing all required filesystem callbacks and a pointer to
  1104. /// their user data.
  1105. ///
  1106. struct FsCallbacks {
  1107. FileExistsFunction FileExists;
  1108. ExpandFilePathFunction ExpandFilePath;
  1109. ReadWholeFileFunction ReadWholeFile;
  1110. WriteWholeFileFunction WriteWholeFile;
  1111. GetFileSizeFunction GetFileSizeInBytes; // To avoid GetFileSize Win32 API,
  1112. // add `InBytes` suffix.
  1113. void *user_data; // An argument that is passed to all fs callbacks
  1114. };
  1115. #ifndef TINYGLTF_NO_FS
  1116. // Declaration of default filesystem callbacks
  1117. bool FileExists(const std::string &abs_filename, void *);
  1118. ///
  1119. /// Expand file path(e.g. `~` to home directory on posix, `%APPDATA%` to
  1120. /// `C:\\Users\\tinygltf\\AppData`)
  1121. ///
  1122. /// @param[in] filepath File path string. Assume UTF-8
  1123. /// @param[in] userdata User data. Set to `nullptr` if you don't need it.
  1124. ///
  1125. std::string ExpandFilePath(const std::string &filepath, void *userdata);
  1126. bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
  1127. const std::string &filepath, void *);
  1128. bool WriteWholeFile(std::string *err, const std::string &filepath,
  1129. const std::vector<unsigned char> &contents, void *);
  1130. bool GetFileSizeInBytes(size_t *filesize_out, std::string *err,
  1131. const std::string &filepath, void *);
  1132. #endif
  1133. ///
  1134. /// LoadImageDataFunction type. Signature for custom image loading callbacks.
  1135. ///
  1136. using LoadImageDataFunction = std::function<bool(
  1137. Image * /* image */, const int /* image_idx */, std::string * /* err */,
  1138. std::string * /* warn */, int /* req_width */, int /* req_height */,
  1139. const unsigned char * /* bytes */, int /* size */, void * /*user_data */)>;
  1140. ///
  1141. /// WriteImageDataFunction type. Signature for custom image writing callbacks.
  1142. /// The out_uri parameter becomes the URI written to the gltf and may reference
  1143. /// a file or contain a data URI.
  1144. ///
  1145. using WriteImageDataFunction = std::function<bool(
  1146. const std::string * /* basepath */, const std::string * /* filename */,
  1147. const Image *image, bool /* embedImages */,
  1148. const FsCallbacks * /* fs_cb */, const URICallbacks * /* uri_cb */,
  1149. std::string * /* out_uri */, void * /* user_pointer */)>;
  1150. #ifndef TINYGLTF_NO_STB_IMAGE
  1151. // Declaration of default image loader callback
  1152. bool LoadImageData(Image *image, const int image_idx, std::string *err,
  1153. std::string *warn, int req_width, int req_height,
  1154. const unsigned char *bytes, int size, void *);
  1155. #endif
  1156. #ifndef TINYGLTF_NO_STB_IMAGE_WRITE
  1157. // Declaration of default image writer callback
  1158. bool WriteImageData(const std::string *basepath, const std::string *filename,
  1159. const Image *image, bool embedImages,
  1160. const FsCallbacks* fs_cb, const URICallbacks *uri_cb,
  1161. std::string *out_uri, void *);
  1162. #endif
  1163. ///
  1164. /// glTF Parser/Serializer context.
  1165. ///
  1166. class TinyGLTF {
  1167. public:
  1168. #ifdef __clang__
  1169. #pragma clang diagnostic push
  1170. #pragma clang diagnostic ignored "-Wc++98-compat"
  1171. #endif
  1172. TinyGLTF() = default;
  1173. #ifdef __clang__
  1174. #pragma clang diagnostic pop
  1175. #endif
  1176. ~TinyGLTF() = default;
  1177. ///
  1178. /// Loads glTF ASCII asset from a file.
  1179. /// Set warning message to `warn` for example it fails to load asserts.
  1180. /// Returns false and set error string to `err` if there's an error.
  1181. ///
  1182. bool LoadASCIIFromFile(Model *model, std::string *err, std::string *warn,
  1183. const std::string &filename,
  1184. unsigned int check_sections = REQUIRE_VERSION);
  1185. ///
  1186. /// Loads glTF ASCII asset from string(memory).
  1187. /// `length` = strlen(str);
  1188. /// `base_dir` is a search path of glTF asset(e.g. images). Path Must be an
  1189. /// expanded path (e.g. no tilde(`~`), no environment variables). Set warning
  1190. /// message to `warn` for example it fails to load asserts. Returns false and
  1191. /// set error string to `err` if there's an error.
  1192. ///
  1193. bool LoadASCIIFromString(Model *model, std::string *err, std::string *warn,
  1194. const char *str, const unsigned int length,
  1195. const std::string &base_dir,
  1196. unsigned int check_sections = REQUIRE_VERSION);
  1197. ///
  1198. /// Loads glTF binary asset from a file.
  1199. /// Set warning message to `warn` for example it fails to load asserts.
  1200. /// Returns false and set error string to `err` if there's an error.
  1201. ///
  1202. bool LoadBinaryFromFile(Model *model, std::string *err, std::string *warn,
  1203. const std::string &filename,
  1204. unsigned int check_sections = REQUIRE_VERSION);
  1205. ///
  1206. /// Loads glTF binary asset from memory.
  1207. /// `length` = strlen(str);
  1208. /// `base_dir` is a search path of glTF asset(e.g. images). Path Must be an
  1209. /// expanded path (e.g. no tilde(`~`), no environment variables).
  1210. /// Set warning message to `warn` for example it fails to load asserts.
  1211. /// Returns false and set error string to `err` if there's an error.
  1212. ///
  1213. bool LoadBinaryFromMemory(Model *model, std::string *err, std::string *warn,
  1214. const unsigned char *bytes,
  1215. const unsigned int length,
  1216. const std::string &base_dir = "",
  1217. unsigned int check_sections = REQUIRE_VERSION);
  1218. ///
  1219. /// Write glTF to stream, buffers and images will be embedded
  1220. ///
  1221. bool WriteGltfSceneToStream(const Model *model, std::ostream &stream,
  1222. bool prettyPrint, bool writeBinary);
  1223. ///
  1224. /// Write glTF to file.
  1225. ///
  1226. bool WriteGltfSceneToFile(const Model *model, const std::string &filename,
  1227. bool embedImages, bool embedBuffers,
  1228. bool prettyPrint, bool writeBinary);
  1229. ///
  1230. /// Sets the parsing strictness.
  1231. ///
  1232. void SetParseStrictness(ParseStrictness strictness);
  1233. ///
  1234. /// Set callback to use for loading image data. Passing the nullptr is akin to
  1235. /// calling RemoveImageLoader().
  1236. ///
  1237. void SetImageLoader(LoadImageDataFunction LoadImageData, void *user_data);
  1238. ///
  1239. /// Unset(remove) callback of loading image data
  1240. ///
  1241. void RemoveImageLoader();
  1242. ///
  1243. /// Set callback to use for writing image data
  1244. ///
  1245. void SetImageWriter(WriteImageDataFunction WriteImageData, void *user_data);
  1246. ///
  1247. /// Set callbacks to use for URI encoding and decoding and their user data.
  1248. /// Returns false if there is an error with the callbacks. If err is not
  1249. /// nullptr, explanation will be written there.
  1250. ///
  1251. bool SetURICallbacks(URICallbacks callbacks, std::string* err = nullptr);
  1252. ///
  1253. /// Set callbacks to use for filesystem (fs) access and their user data.
  1254. /// Returns false if there is an error with the callbacks. If err is not
  1255. /// nullptr, explanation will be written there.
  1256. ///
  1257. bool SetFsCallbacks(FsCallbacks callbacks, std::string* err = nullptr);
  1258. ///
  1259. /// Set serializing default values(default = false).
  1260. /// When true, default values are force serialized to .glTF.
  1261. /// This may be helpful if you want to serialize a full description of glTF
  1262. /// data.
  1263. ///
  1264. /// TODO(LTE): Supply parsing option as function arguments to
  1265. /// `LoadASCIIFromFile()` and others, not by a class method
  1266. ///
  1267. void SetSerializeDefaultValues(const bool enabled) {
  1268. serialize_default_values_ = enabled;
  1269. }
  1270. bool GetSerializeDefaultValues() const { return serialize_default_values_; }
  1271. ///
  1272. /// Store original JSON string for `extras` and `extensions`.
  1273. /// This feature will be useful when the user want to reconstruct custom data
  1274. /// structure from JSON string.
  1275. ///
  1276. void SetStoreOriginalJSONForExtrasAndExtensions(const bool enabled) {
  1277. store_original_json_for_extras_and_extensions_ = enabled;
  1278. }
  1279. bool GetStoreOriginalJSONForExtrasAndExtensions() const {
  1280. return store_original_json_for_extras_and_extensions_;
  1281. }
  1282. ///
  1283. /// Specify whether preserve image channels when loading images or not.
  1284. /// (Not effective when the user supplies their own LoadImageData callbacks)
  1285. ///
  1286. void SetPreserveImageChannels(bool onoff) {
  1287. preserve_image_channels_ = onoff;
  1288. }
  1289. bool GetPreserveImageChannels() const { return preserve_image_channels_; }
  1290. ///
  1291. /// Specifiy whether image data is decoded/decompressed during load, or left as is
  1292. ///
  1293. void SetImagesAsIs(bool onoff) {
  1294. images_as_is_ = onoff;
  1295. }
  1296. bool GetImagesAsIs() const { return images_as_is_; }
  1297. ///
  1298. /// Set maximum allowed external file size in bytes.
  1299. /// Default: 2GB
  1300. /// Only effective for built-in ReadWholeFileFunction FS function.
  1301. ///
  1302. void SetMaxExternalFileSize(size_t max_bytes) {
  1303. max_external_file_size_ = max_bytes;
  1304. }
  1305. size_t GetMaxExternalFileSize() const { return max_external_file_size_; }
  1306. private:
  1307. ///
  1308. /// Loads glTF asset from string(memory).
  1309. /// `length` = strlen(str);
  1310. /// Set warning message to `warn` for example it fails to load asserts
  1311. /// Returns false and set error string to `err` if there's an error.
  1312. ///
  1313. bool LoadFromString(Model *model, std::string *err, std::string *warn,
  1314. const char *str, const unsigned int length,
  1315. const std::string &base_dir, unsigned int check_sections);
  1316. const unsigned char *bin_data_ = nullptr;
  1317. size_t bin_size_ = 0;
  1318. bool is_binary_ = false;
  1319. ParseStrictness strictness_ = ParseStrictness::Strict;
  1320. bool serialize_default_values_ = false; ///< Serialize default values?
  1321. bool store_original_json_for_extras_and_extensions_ = false;
  1322. bool preserve_image_channels_ = false; /// Default false(expand channels to
  1323. /// RGBA) for backward compatibility.
  1324. bool images_as_is_ = false; /// Default false (decode/decompress images)
  1325. size_t max_external_file_size_{
  1326. size_t((std::numeric_limits<int32_t>::max)())}; // Default 2GB
  1327. // Warning & error messages
  1328. std::string warn_;
  1329. std::string err_;
  1330. FsCallbacks fs = {
  1331. #ifndef TINYGLTF_NO_FS
  1332. &tinygltf::FileExists,
  1333. &tinygltf::ExpandFilePath,
  1334. &tinygltf::ReadWholeFile,
  1335. &tinygltf::WriteWholeFile,
  1336. &tinygltf::GetFileSizeInBytes,
  1337. nullptr // Fs callback user data
  1338. #else
  1339. nullptr, nullptr, nullptr, nullptr, nullptr,
  1340. nullptr // Fs callback user data
  1341. #endif
  1342. };
  1343. URICallbacks uri_cb = {
  1344. // Use paths as-is by default. This will use JSON string escaping.
  1345. nullptr,
  1346. // Decode all URIs before using them as paths as the application may have
  1347. // percent encoded them.
  1348. &tinygltf::URIDecode,
  1349. // URI callback user data
  1350. nullptr};
  1351. LoadImageDataFunction LoadImageData =
  1352. #ifndef TINYGLTF_NO_STB_IMAGE
  1353. &tinygltf::LoadImageData;
  1354. #else
  1355. nullptr;
  1356. #endif
  1357. void *load_image_user_data_{nullptr};
  1358. bool user_image_loader_{false};
  1359. WriteImageDataFunction WriteImageData =
  1360. #ifndef TINYGLTF_NO_STB_IMAGE_WRITE
  1361. &tinygltf::WriteImageData;
  1362. #else
  1363. nullptr;
  1364. #endif
  1365. void *write_image_user_data_{nullptr};
  1366. };
  1367. #ifdef __clang__
  1368. #pragma clang diagnostic pop // -Wpadded
  1369. #endif
  1370. } // namespace tinygltf
  1371. #endif // TINY_GLTF_H_
  1372. #if defined(TINYGLTF_IMPLEMENTATION) || defined(__INTELLISENSE__)
  1373. #include <algorithm>
  1374. // #include <cassert>
  1375. #ifndef TINYGLTF_NO_FS
  1376. #include <sys/stat.h> // for is_directory check
  1377. #include <cstdio>
  1378. #include <fstream>
  1379. #endif
  1380. #include <sstream>
  1381. #ifdef __clang__
  1382. // Disable some warnings for external files.
  1383. #pragma clang diagnostic push
  1384. #pragma clang diagnostic ignored "-Wfloat-equal"
  1385. #pragma clang diagnostic ignored "-Wexit-time-destructors"
  1386. #pragma clang diagnostic ignored "-Wconversion"
  1387. #pragma clang diagnostic ignored "-Wold-style-cast"
  1388. #pragma clang diagnostic ignored "-Wglobal-constructors"
  1389. #if __has_warning("-Wreserved-id-macro")
  1390. #pragma clang diagnostic ignored "-Wreserved-id-macro"
  1391. #endif
  1392. #pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
  1393. #pragma clang diagnostic ignored "-Wpadded"
  1394. #pragma clang diagnostic ignored "-Wc++98-compat"
  1395. #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
  1396. #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
  1397. #pragma clang diagnostic ignored "-Wswitch-enum"
  1398. #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
  1399. #pragma clang diagnostic ignored "-Wweak-vtables"
  1400. #pragma clang diagnostic ignored "-Wcovered-switch-default"
  1401. #if __has_warning("-Wdouble-promotion")
  1402. #pragma clang diagnostic ignored "-Wdouble-promotion"
  1403. #endif
  1404. #if __has_warning("-Wcomma")
  1405. #pragma clang diagnostic ignored "-Wcomma"
  1406. #endif
  1407. #if __has_warning("-Wzero-as-null-pointer-constant")
  1408. #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
  1409. #endif
  1410. #if __has_warning("-Wcast-qual")
  1411. #pragma clang diagnostic ignored "-Wcast-qual"
  1412. #endif
  1413. #if __has_warning("-Wmissing-variable-declarations")
  1414. #pragma clang diagnostic ignored "-Wmissing-variable-declarations"
  1415. #endif
  1416. #if __has_warning("-Wmissing-prototypes")
  1417. #pragma clang diagnostic ignored "-Wmissing-prototypes"
  1418. #endif
  1419. #if __has_warning("-Wcast-align")
  1420. #pragma clang diagnostic ignored "-Wcast-align"
  1421. #endif
  1422. #if __has_warning("-Wnewline-eof")
  1423. #pragma clang diagnostic ignored "-Wnewline-eof"
  1424. #endif
  1425. #if __has_warning("-Wunused-parameter")
  1426. #pragma clang diagnostic ignored "-Wunused-parameter"
  1427. #endif
  1428. #if __has_warning("-Wmismatched-tags")
  1429. #pragma clang diagnostic ignored "-Wmismatched-tags"
  1430. #endif
  1431. #if __has_warning("-Wextra-semi-stmt")
  1432. #pragma clang diagnostic ignored "-Wextra-semi-stmt"
  1433. #endif
  1434. #endif
  1435. // Disable GCC warnings
  1436. #ifdef __GNUC__
  1437. #pragma GCC diagnostic push
  1438. #pragma GCC diagnostic ignored "-Wtype-limits"
  1439. #endif // __GNUC__
  1440. #ifndef TINYGLTF_NO_INCLUDE_JSON
  1441. #ifndef TINYGLTF_USE_RAPIDJSON
  1442. #include "json.hpp"
  1443. #else
  1444. #ifndef TINYGLTF_NO_INCLUDE_RAPIDJSON
  1445. #include "document.h"
  1446. #include "prettywriter.h"
  1447. #include "rapidjson.h"
  1448. #include "stringbuffer.h"
  1449. #include "writer.h"
  1450. #endif
  1451. #endif
  1452. #endif
  1453. #ifdef TINYGLTF_ENABLE_DRACO
  1454. #include "draco/compression/decode.h"
  1455. #include "draco/core/decoder_buffer.h"
  1456. #endif
  1457. #ifndef TINYGLTF_NO_STB_IMAGE
  1458. #ifndef TINYGLTF_NO_INCLUDE_STB_IMAGE
  1459. #include "stb_image.h"
  1460. #endif
  1461. #endif
  1462. #ifndef TINYGLTF_NO_STB_IMAGE_WRITE
  1463. #ifndef TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE
  1464. #include "stb_image_write.h"
  1465. #endif
  1466. #endif
  1467. #ifdef __clang__
  1468. #pragma clang diagnostic pop
  1469. #endif
  1470. #ifdef __GNUC__
  1471. #pragma GCC diagnostic pop
  1472. #endif
  1473. #ifdef _WIN32
  1474. // issue 143.
  1475. // Define NOMINMAX to avoid min/max defines,
  1476. // but undef it after included Windows.h
  1477. #ifndef NOMINMAX
  1478. #define TINYGLTF_INTERNAL_NOMINMAX
  1479. #define NOMINMAX
  1480. #endif
  1481. #ifndef WIN32_LEAN_AND_MEAN
  1482. #define WIN32_LEAN_AND_MEAN
  1483. #define TINYGLTF_INTERNAL_WIN32_LEAN_AND_MEAN
  1484. #endif
  1485. #ifndef __MINGW32__
  1486. #include <Windows.h> // include API for expanding a file path
  1487. #else
  1488. #include <windows.h>
  1489. #endif
  1490. #ifdef TINYGLTF_INTERNAL_WIN32_LEAN_AND_MEAN
  1491. #undef WIN32_LEAN_AND_MEAN
  1492. #endif
  1493. #if defined(TINYGLTF_INTERNAL_NOMINMAX)
  1494. #undef NOMINMAX
  1495. #endif
  1496. #if defined(__GLIBCXX__) // mingw
  1497. #include <fcntl.h> // _O_RDONLY
  1498. #include <ext/stdio_filebuf.h> // fstream (all sorts of IO stuff) + stdio_filebuf (=streambuf)
  1499. #endif
  1500. #elif !defined(__ANDROID__) && !defined(__OpenBSD__)
  1501. // #include <wordexp.h>
  1502. #endif
  1503. #if defined(__sparcv9) || defined(__powerpc__)
  1504. // Big endian
  1505. #else
  1506. #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
  1507. #define TINYGLTF_LITTLE_ENDIAN 1
  1508. #endif
  1509. #endif
  1510. namespace tinygltf {
  1511. namespace detail {
  1512. #ifdef TINYGLTF_USE_RAPIDJSON
  1513. #ifdef TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR
  1514. // This uses the RapidJSON CRTAllocator. It is thread safe and multiple
  1515. // documents may be active at once.
  1516. using json =
  1517. rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator>;
  1518. using json_iterator = json::MemberIterator;
  1519. using json_const_iterator = json::ConstMemberIterator;
  1520. using json_const_array_iterator = json const *;
  1521. using JsonDocument =
  1522. rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>;
  1523. rapidjson::CrtAllocator s_CrtAllocator; // stateless and thread safe
  1524. rapidjson::CrtAllocator &GetAllocator() { return s_CrtAllocator; }
  1525. #else
  1526. // This uses the default RapidJSON MemoryPoolAllocator. It is very fast, but
  1527. // not thread safe. Only a single JsonDocument may be active at any one time,
  1528. // meaning only a single gltf load/save can be active any one time.
  1529. using json = rapidjson::Value;
  1530. using json_iterator = json::MemberIterator;
  1531. using json_const_iterator = json::ConstMemberIterator;
  1532. using json_const_array_iterator = json const *;
  1533. rapidjson::Document *s_pActiveDocument = nullptr;
  1534. rapidjson::Document::AllocatorType &GetAllocator() {
  1535. assert(s_pActiveDocument); // Root json node must be JsonDocument type
  1536. return s_pActiveDocument->GetAllocator();
  1537. }
  1538. #ifdef __clang__
  1539. #pragma clang diagnostic push
  1540. // Suppress JsonDocument(JsonDocument &&rhs) noexcept
  1541. #pragma clang diagnostic ignored "-Wunused-member-function"
  1542. #endif
  1543. struct JsonDocument : public rapidjson::Document {
  1544. JsonDocument() {
  1545. assert(s_pActiveDocument ==
  1546. nullptr); // When using default allocator, only one document can be
  1547. // active at a time, if you need multiple active at once,
  1548. // define TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR
  1549. s_pActiveDocument = this;
  1550. }
  1551. JsonDocument(const JsonDocument &) = delete;
  1552. JsonDocument(JsonDocument &&rhs) noexcept
  1553. : rapidjson::Document(std::move(rhs)) {
  1554. s_pActiveDocument = this;
  1555. rhs.isNil = true;
  1556. }
  1557. ~JsonDocument() {
  1558. if (!isNil) {
  1559. s_pActiveDocument = nullptr;
  1560. }
  1561. }
  1562. private:
  1563. bool isNil = false;
  1564. };
  1565. #ifdef __clang__
  1566. #pragma clang diagnostic pop
  1567. #endif
  1568. #endif // TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR
  1569. #else
  1570. using nlohmann::json;
  1571. using json_iterator = json::iterator;
  1572. using json_const_iterator = json::const_iterator;
  1573. using json_const_array_iterator = json_const_iterator;
  1574. using JsonDocument = json;
  1575. #endif
  1576. void JsonParse(JsonDocument &doc, const char *str, size_t length,
  1577. bool throwExc = false) {
  1578. #ifdef TINYGLTF_USE_RAPIDJSON
  1579. (void)throwExc;
  1580. doc.Parse(str, length);
  1581. #else
  1582. doc = detail::json::parse(str, str + length, nullptr, throwExc);
  1583. #endif
  1584. }
  1585. } // namespace detail
  1586. } // namespace tinygltf
  1587. #ifdef __APPLE__
  1588. #include "TargetConditionals.h"
  1589. #endif
  1590. #ifdef __clang__
  1591. #pragma clang diagnostic push
  1592. #pragma clang diagnostic ignored "-Wc++98-compat"
  1593. #endif
  1594. namespace tinygltf {
  1595. ///
  1596. /// Internal LoadImageDataOption struct.
  1597. /// This struct is passed through `user_pointer` in LoadImageData.
  1598. /// The struct is not passed when the user supply their own LoadImageData
  1599. /// callbacks.
  1600. ///
  1601. struct LoadImageDataOption {
  1602. // true: preserve image channels(e.g. load as RGB image if the image has RGB
  1603. // channels) default `false`(channels are expanded to RGBA for backward
  1604. // compatibility).
  1605. bool preserve_channels{false};
  1606. // true: do not decode/decompress image data.
  1607. // default `false`: decode/decompress image data.
  1608. bool as_is{false};
  1609. };
  1610. // Equals function for Value, for recursivity
  1611. static bool Equals(const tinygltf::Value &one, const tinygltf::Value &other) {
  1612. if (one.Type() != other.Type()) return false;
  1613. switch (one.Type()) {
  1614. case NULL_TYPE:
  1615. return true;
  1616. case BOOL_TYPE:
  1617. return one.Get<bool>() == other.Get<bool>();
  1618. case REAL_TYPE:
  1619. return TINYGLTF_DOUBLE_EQUAL(one.Get<double>(), other.Get<double>());
  1620. case INT_TYPE:
  1621. return one.Get<int>() == other.Get<int>();
  1622. case OBJECT_TYPE: {
  1623. auto oneObj = one.Get<tinygltf::Value::Object>();
  1624. auto otherObj = other.Get<tinygltf::Value::Object>();
  1625. if (oneObj.size() != otherObj.size()) return false;
  1626. for (auto &it : oneObj) {
  1627. auto otherIt = otherObj.find(it.first);
  1628. if (otherIt == otherObj.end()) return false;
  1629. if (!Equals(it.second, otherIt->second)) return false;
  1630. }
  1631. return true;
  1632. }
  1633. case ARRAY_TYPE: {
  1634. if (one.Size() != other.Size()) return false;
  1635. for (size_t i = 0; i < one.Size(); ++i)
  1636. if (!Equals(one.Get(i), other.Get(i))) return false;
  1637. return true;
  1638. }
  1639. case STRING_TYPE:
  1640. return one.Get<std::string>() == other.Get<std::string>();
  1641. case BINARY_TYPE:
  1642. return one.Get<std::vector<unsigned char> >() ==
  1643. other.Get<std::vector<unsigned char> >();
  1644. default: {
  1645. // unhandled type
  1646. return false;
  1647. }
  1648. }
  1649. }
  1650. // Equals function for std::vector<double> using TINYGLTF_DOUBLE_EPSILON
  1651. static bool Equals(const std::vector<double> &one,
  1652. const std::vector<double> &other) {
  1653. if (one.size() != other.size()) return false;
  1654. for (int i = 0; i < int(one.size()); ++i) {
  1655. if (!TINYGLTF_DOUBLE_EQUAL(one[size_t(i)], other[size_t(i)])) return false;
  1656. }
  1657. return true;
  1658. }
  1659. bool Accessor::operator==(const Accessor &other) const {
  1660. return this->bufferView == other.bufferView &&
  1661. this->byteOffset == other.byteOffset &&
  1662. this->componentType == other.componentType &&
  1663. this->count == other.count && this->extensions == other.extensions &&
  1664. this->extras == other.extras &&
  1665. Equals(this->maxValues, other.maxValues) &&
  1666. Equals(this->minValues, other.minValues) && this->name == other.name &&
  1667. this->normalized == other.normalized && this->type == other.type;
  1668. }
  1669. bool Animation::operator==(const Animation &other) const {
  1670. return this->channels == other.channels &&
  1671. this->extensions == other.extensions && this->extras == other.extras &&
  1672. this->name == other.name && this->samplers == other.samplers;
  1673. }
  1674. bool AnimationChannel::operator==(const AnimationChannel &other) const {
  1675. return this->extensions == other.extensions && this->extras == other.extras &&
  1676. this->target_node == other.target_node &&
  1677. this->target_path == other.target_path &&
  1678. this->sampler == other.sampler;
  1679. }
  1680. bool AnimationSampler::operator==(const AnimationSampler &other) const {
  1681. return this->extras == other.extras && this->extensions == other.extensions &&
  1682. this->input == other.input &&
  1683. this->interpolation == other.interpolation &&
  1684. this->output == other.output;
  1685. }
  1686. bool Asset::operator==(const Asset &other) const {
  1687. return this->copyright == other.copyright &&
  1688. this->extensions == other.extensions && this->extras == other.extras &&
  1689. this->generator == other.generator &&
  1690. this->minVersion == other.minVersion && this->version == other.version;
  1691. }
  1692. bool Buffer::operator==(const Buffer &other) const {
  1693. return this->data == other.data && this->extensions == other.extensions &&
  1694. this->extras == other.extras && this->name == other.name &&
  1695. this->uri == other.uri;
  1696. }
  1697. bool BufferView::operator==(const BufferView &other) const {
  1698. return this->buffer == other.buffer && this->byteLength == other.byteLength &&
  1699. this->byteOffset == other.byteOffset &&
  1700. this->byteStride == other.byteStride && this->name == other.name &&
  1701. this->target == other.target && this->extensions == other.extensions &&
  1702. this->extras == other.extras &&
  1703. this->dracoDecoded == other.dracoDecoded;
  1704. }
  1705. bool Camera::operator==(const Camera &other) const {
  1706. return this->name == other.name && this->extensions == other.extensions &&
  1707. this->extras == other.extras &&
  1708. this->orthographic == other.orthographic &&
  1709. this->perspective == other.perspective && this->type == other.type;
  1710. }
  1711. bool Image::operator==(const Image &other) const {
  1712. return this->bufferView == other.bufferView &&
  1713. this->component == other.component &&
  1714. this->extensions == other.extensions && this->extras == other.extras &&
  1715. this->height == other.height && this->image == other.image &&
  1716. this->mimeType == other.mimeType && this->name == other.name &&
  1717. this->uri == other.uri && this->width == other.width;
  1718. }
  1719. bool Light::operator==(const Light &other) const {
  1720. return Equals(this->color, other.color) && this->name == other.name &&
  1721. this->type == other.type;
  1722. }
  1723. bool AudioEmitter::operator==(const AudioEmitter &other) const {
  1724. return this->name == other.name &&
  1725. TINYGLTF_DOUBLE_EQUAL(this->gain, other.gain) &&
  1726. this->loop == other.loop && this->playing == other.playing &&
  1727. this->type == other.type &&
  1728. this->distanceModel == other.distanceModel &&
  1729. this->source == other.source;
  1730. }
  1731. bool AudioSource::operator==(const AudioSource &other) const {
  1732. return this->name == other.name && this->uri == other.uri;
  1733. }
  1734. bool Material::operator==(const Material &other) const {
  1735. return (this->pbrMetallicRoughness == other.pbrMetallicRoughness) &&
  1736. (this->normalTexture == other.normalTexture) &&
  1737. (this->occlusionTexture == other.occlusionTexture) &&
  1738. (this->emissiveTexture == other.emissiveTexture) &&
  1739. Equals(this->emissiveFactor, other.emissiveFactor) &&
  1740. (this->alphaMode == other.alphaMode) &&
  1741. TINYGLTF_DOUBLE_EQUAL(this->alphaCutoff, other.alphaCutoff) &&
  1742. (this->doubleSided == other.doubleSided) &&
  1743. (this->extensions == other.extensions) &&
  1744. (this->extras == other.extras) && (this->values == other.values) &&
  1745. (this->additionalValues == other.additionalValues) &&
  1746. (this->name == other.name);
  1747. }
  1748. bool Mesh::operator==(const Mesh &other) const {
  1749. return this->extensions == other.extensions && this->extras == other.extras &&
  1750. this->name == other.name && Equals(this->weights, other.weights) &&
  1751. this->primitives == other.primitives;
  1752. }
  1753. bool Model::operator==(const Model &other) const {
  1754. return this->accessors == other.accessors &&
  1755. this->animations == other.animations && this->asset == other.asset &&
  1756. this->buffers == other.buffers &&
  1757. this->bufferViews == other.bufferViews &&
  1758. this->cameras == other.cameras &&
  1759. this->defaultScene == other.defaultScene &&
  1760. this->extensions == other.extensions &&
  1761. this->extensionsRequired == other.extensionsRequired &&
  1762. this->extensionsUsed == other.extensionsUsed &&
  1763. this->extras == other.extras && this->images == other.images &&
  1764. this->lights == other.lights && this->materials == other.materials &&
  1765. this->meshes == other.meshes && this->nodes == other.nodes &&
  1766. this->samplers == other.samplers && this->scenes == other.scenes &&
  1767. this->skins == other.skins && this->textures == other.textures;
  1768. }
  1769. bool Node::operator==(const Node &other) const {
  1770. return this->camera == other.camera && this->children == other.children &&
  1771. this->extensions == other.extensions && this->extras == other.extras &&
  1772. Equals(this->matrix, other.matrix) && this->mesh == other.mesh &&
  1773. (this->light == other.light) && (this->emitter == other.emitter) &&
  1774. this->name == other.name && Equals(this->rotation, other.rotation) &&
  1775. Equals(this->scale, other.scale) && this->skin == other.skin &&
  1776. Equals(this->translation, other.translation) &&
  1777. Equals(this->weights, other.weights);
  1778. }
  1779. bool SpotLight::operator==(const SpotLight &other) const {
  1780. return this->extensions == other.extensions && this->extras == other.extras &&
  1781. TINYGLTF_DOUBLE_EQUAL(this->innerConeAngle, other.innerConeAngle) &&
  1782. TINYGLTF_DOUBLE_EQUAL(this->outerConeAngle, other.outerConeAngle);
  1783. }
  1784. bool PositionalEmitter::operator==(const PositionalEmitter &other) const {
  1785. return this->extensions == other.extensions && this->extras == other.extras &&
  1786. TINYGLTF_DOUBLE_EQUAL(this->coneInnerAngle, other.coneInnerAngle) &&
  1787. TINYGLTF_DOUBLE_EQUAL(this->coneOuterAngle, other.coneOuterAngle) &&
  1788. TINYGLTF_DOUBLE_EQUAL(this->coneOuterGain, other.coneOuterGain) &&
  1789. TINYGLTF_DOUBLE_EQUAL(this->maxDistance, other.maxDistance) &&
  1790. TINYGLTF_DOUBLE_EQUAL(this->refDistance, other.refDistance) &&
  1791. TINYGLTF_DOUBLE_EQUAL(this->rolloffFactor, other.rolloffFactor);
  1792. }
  1793. bool OrthographicCamera::operator==(const OrthographicCamera &other) const {
  1794. return this->extensions == other.extensions && this->extras == other.extras &&
  1795. TINYGLTF_DOUBLE_EQUAL(this->xmag, other.xmag) &&
  1796. TINYGLTF_DOUBLE_EQUAL(this->ymag, other.ymag) &&
  1797. TINYGLTF_DOUBLE_EQUAL(this->zfar, other.zfar) &&
  1798. TINYGLTF_DOUBLE_EQUAL(this->znear, other.znear);
  1799. }
  1800. bool Parameter::operator==(const Parameter &other) const {
  1801. if (this->bool_value != other.bool_value ||
  1802. this->has_number_value != other.has_number_value)
  1803. return false;
  1804. if (!TINYGLTF_DOUBLE_EQUAL(this->number_value, other.number_value))
  1805. return false;
  1806. if (this->json_double_value.size() != other.json_double_value.size())
  1807. return false;
  1808. for (auto &it : this->json_double_value) {
  1809. auto otherIt = other.json_double_value.find(it.first);
  1810. if (otherIt == other.json_double_value.end()) return false;
  1811. if (!TINYGLTF_DOUBLE_EQUAL(it.second, otherIt->second)) return false;
  1812. }
  1813. if (!Equals(this->number_array, other.number_array)) return false;
  1814. if (this->string_value != other.string_value) return false;
  1815. return true;
  1816. }
  1817. bool PerspectiveCamera::operator==(const PerspectiveCamera &other) const {
  1818. return TINYGLTF_DOUBLE_EQUAL(this->aspectRatio, other.aspectRatio) &&
  1819. this->extensions == other.extensions && this->extras == other.extras &&
  1820. TINYGLTF_DOUBLE_EQUAL(this->yfov, other.yfov) &&
  1821. TINYGLTF_DOUBLE_EQUAL(this->zfar, other.zfar) &&
  1822. TINYGLTF_DOUBLE_EQUAL(this->znear, other.znear);
  1823. }
  1824. bool Primitive::operator==(const Primitive &other) const {
  1825. return this->attributes == other.attributes && this->extras == other.extras &&
  1826. this->indices == other.indices && this->material == other.material &&
  1827. this->mode == other.mode && this->targets == other.targets;
  1828. }
  1829. bool Sampler::operator==(const Sampler &other) const {
  1830. return this->extensions == other.extensions && this->extras == other.extras &&
  1831. this->magFilter == other.magFilter &&
  1832. this->minFilter == other.minFilter && this->name == other.name &&
  1833. this->wrapS == other.wrapS && this->wrapT == other.wrapT;
  1834. // this->wrapR == other.wrapR
  1835. }
  1836. bool Scene::operator==(const Scene &other) const {
  1837. return this->extensions == other.extensions && this->extras == other.extras &&
  1838. this->name == other.name && this->nodes == other.nodes;
  1839. }
  1840. bool Skin::operator==(const Skin &other) const {
  1841. return this->extensions == other.extensions && this->extras == other.extras &&
  1842. this->inverseBindMatrices == other.inverseBindMatrices &&
  1843. this->joints == other.joints && this->name == other.name &&
  1844. this->skeleton == other.skeleton;
  1845. }
  1846. bool Texture::operator==(const Texture &other) const {
  1847. return this->extensions == other.extensions && this->extras == other.extras &&
  1848. this->name == other.name && this->sampler == other.sampler &&
  1849. this->source == other.source;
  1850. }
  1851. bool TextureInfo::operator==(const TextureInfo &other) const {
  1852. return this->extensions == other.extensions && this->extras == other.extras &&
  1853. this->index == other.index && this->texCoord == other.texCoord;
  1854. }
  1855. bool NormalTextureInfo::operator==(const NormalTextureInfo &other) const {
  1856. return this->extensions == other.extensions && this->extras == other.extras &&
  1857. this->index == other.index && this->texCoord == other.texCoord &&
  1858. TINYGLTF_DOUBLE_EQUAL(this->scale, other.scale);
  1859. }
  1860. bool OcclusionTextureInfo::operator==(const OcclusionTextureInfo &other) const {
  1861. return this->extensions == other.extensions && this->extras == other.extras &&
  1862. this->index == other.index && this->texCoord == other.texCoord &&
  1863. TINYGLTF_DOUBLE_EQUAL(this->strength, other.strength);
  1864. }
  1865. bool PbrMetallicRoughness::operator==(const PbrMetallicRoughness &other) const {
  1866. return this->extensions == other.extensions && this->extras == other.extras &&
  1867. (this->baseColorTexture == other.baseColorTexture) &&
  1868. (this->metallicRoughnessTexture == other.metallicRoughnessTexture) &&
  1869. Equals(this->baseColorFactor, other.baseColorFactor) &&
  1870. TINYGLTF_DOUBLE_EQUAL(this->metallicFactor, other.metallicFactor) &&
  1871. TINYGLTF_DOUBLE_EQUAL(this->roughnessFactor, other.roughnessFactor);
  1872. }
  1873. bool Value::operator==(const Value &other) const {
  1874. return Equals(*this, other);
  1875. }
  1876. static void swap4(unsigned int *val) {
  1877. #ifdef TINYGLTF_LITTLE_ENDIAN
  1878. (void)val;
  1879. #else
  1880. unsigned int tmp = *val;
  1881. unsigned char *dst = reinterpret_cast<unsigned char *>(val);
  1882. unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
  1883. dst[0] = src[3];
  1884. dst[1] = src[2];
  1885. dst[2] = src[1];
  1886. dst[3] = src[0];
  1887. #endif
  1888. }
  1889. static std::string JoinPath(const std::string &path0,
  1890. const std::string &path1) {
  1891. if (path0.empty()) {
  1892. return path1;
  1893. } else {
  1894. // check '/'
  1895. char lastChar = *path0.rbegin();
  1896. if (lastChar != '/') {
  1897. return path0 + std::string("/") + path1;
  1898. } else {
  1899. return path0 + path1;
  1900. }
  1901. }
  1902. }
  1903. static std::string FindFile(const std::vector<std::string> &paths,
  1904. const std::string &filepath, FsCallbacks *fs) {
  1905. if (fs == nullptr || fs->ExpandFilePath == nullptr ||
  1906. fs->FileExists == nullptr) {
  1907. // Error, fs callback[s] missing
  1908. return std::string();
  1909. }
  1910. // https://github.com/syoyo/tinygltf/issues/416
  1911. // Use strlen() since std::string's size/length reports the number of elements
  1912. // in the buffer, not the length of string(null-terminated) strip
  1913. // null-character in the middle of string.
  1914. size_t slength = strlen(filepath.c_str());
  1915. if (slength == 0) {
  1916. return std::string();
  1917. }
  1918. std::string cleaned_filepath = std::string(filepath.c_str());
  1919. for (size_t i = 0; i < paths.size(); i++) {
  1920. std::string absPath =
  1921. fs->ExpandFilePath(JoinPath(paths[i], cleaned_filepath), fs->user_data);
  1922. if (fs->FileExists(absPath, fs->user_data)) {
  1923. return absPath;
  1924. }
  1925. }
  1926. return std::string();
  1927. }
  1928. static std::string GetFilePathExtension(const std::string &FileName) {
  1929. if (FileName.find_last_of(".") != std::string::npos)
  1930. return FileName.substr(FileName.find_last_of(".") + 1);
  1931. return "";
  1932. }
  1933. static std::string GetBaseDir(const std::string &filepath) {
  1934. if (filepath.find_last_of("/\\") != std::string::npos)
  1935. return filepath.substr(0, filepath.find_last_of("/\\") + 1);
  1936. return "";
  1937. }
  1938. static std::string GetBaseFilename(const std::string &filepath) {
  1939. auto idx = filepath.find_last_of("/\\");
  1940. if (idx != std::string::npos) return filepath.substr(idx + 1);
  1941. return filepath;
  1942. }
  1943. std::string base64_encode(unsigned char const *, unsigned int len);
  1944. std::string base64_decode(std::string const &s);
  1945. /*
  1946. base64.cpp and base64.h
  1947. Copyright (C) 2004-2008 René Nyffenegger
  1948. This source code is provided 'as-is', without any express or implied
  1949. warranty. In no event will the author be held liable for any damages
  1950. arising from the use of this software.
  1951. Permission is granted to anyone to use this software for any purpose,
  1952. including commercial applications, and to alter it and redistribute it
  1953. freely, subject to the following restrictions:
  1954. 1. The origin of this source code must not be misrepresented; you must not
  1955. claim that you wrote the original source code. If you use this source code
  1956. in a product, an acknowledgment in the product documentation would be
  1957. appreciated but is not required.
  1958. 2. Altered source versions must be plainly marked as such, and must not be
  1959. misrepresented as being the original source code.
  1960. 3. This notice may not be removed or altered from any source distribution.
  1961. René Nyffenegger [email protected]
  1962. */
  1963. #ifdef __clang__
  1964. #pragma clang diagnostic push
  1965. #pragma clang diagnostic ignored "-Wsign-conversion"
  1966. #pragma clang diagnostic ignored "-Wconversion"
  1967. #endif
  1968. static inline bool is_base64(unsigned char c) {
  1969. return (isalnum(c) || (c == '+') || (c == '/'));
  1970. }
  1971. std::string base64_encode(unsigned char const *bytes_to_encode,
  1972. unsigned int in_len) {
  1973. std::string ret;
  1974. int i = 0;
  1975. int j = 0;
  1976. unsigned char char_array_3[3];
  1977. unsigned char char_array_4[4];
  1978. const char *base64_chars =
  1979. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  1980. "abcdefghijklmnopqrstuvwxyz"
  1981. "0123456789+/";
  1982. while (in_len--) {
  1983. char_array_3[i++] = *(bytes_to_encode++);
  1984. if (i == 3) {
  1985. char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
  1986. char_array_4[1] =
  1987. ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
  1988. char_array_4[2] =
  1989. ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
  1990. char_array_4[3] = char_array_3[2] & 0x3f;
  1991. for (i = 0; (i < 4); i++) ret += base64_chars[char_array_4[i]];
  1992. i = 0;
  1993. }
  1994. }
  1995. if (i) {
  1996. for (j = i; j < 3; j++) char_array_3[j] = '\0';
  1997. char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
  1998. char_array_4[1] =
  1999. ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
  2000. char_array_4[2] =
  2001. ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
  2002. for (j = 0; (j < i + 1); j++) ret += base64_chars[char_array_4[j]];
  2003. while ((i++ < 3)) ret += '=';
  2004. }
  2005. return ret;
  2006. }
  2007. std::string base64_decode(std::string const &encoded_string) {
  2008. int in_len = static_cast<int>(encoded_string.size());
  2009. int i = 0;
  2010. int j = 0;
  2011. int in_ = 0;
  2012. unsigned char char_array_4[4], char_array_3[3];
  2013. std::string ret;
  2014. const std::string base64_chars =
  2015. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  2016. "abcdefghijklmnopqrstuvwxyz"
  2017. "0123456789+/";
  2018. while (in_len-- && (encoded_string[in_] != '=') &&
  2019. is_base64(encoded_string[in_])) {
  2020. char_array_4[i++] = encoded_string[in_];
  2021. in_++;
  2022. if (i == 4) {
  2023. for (i = 0; i < 4; i++)
  2024. char_array_4[i] =
  2025. static_cast<unsigned char>(base64_chars.find(char_array_4[i]));
  2026. char_array_3[0] =
  2027. (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
  2028. char_array_3[1] =
  2029. ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
  2030. char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
  2031. for (i = 0; (i < 3); i++) ret += char_array_3[i];
  2032. i = 0;
  2033. }
  2034. }
  2035. if (i) {
  2036. for (j = i; j < 4; j++) char_array_4[j] = 0;
  2037. for (j = 0; j < 4; j++)
  2038. char_array_4[j] =
  2039. static_cast<unsigned char>(base64_chars.find(char_array_4[j]));
  2040. char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
  2041. char_array_3[1] =
  2042. ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
  2043. char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
  2044. for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
  2045. }
  2046. return ret;
  2047. }
  2048. #ifdef __clang__
  2049. #pragma clang diagnostic pop
  2050. #endif
  2051. // https://github.com/syoyo/tinygltf/issues/228
  2052. // TODO(syoyo): Use uriparser https://uriparser.github.io/ for stricter Uri
  2053. // decoding?
  2054. //
  2055. // Uri Decoding from DLIB
  2056. // http://dlib.net/dlib/server/server_http.cpp.html
  2057. // --- dlib begin ------------------------------------------------------------
  2058. // Copyright (C) 2003 Davis E. King ([email protected])
  2059. // License: Boost Software License
  2060. // Boost Software License - Version 1.0 - August 17th, 2003
  2061. // Permission is hereby granted, free of charge, to any person or organization
  2062. // obtaining a copy of the software and accompanying documentation covered by
  2063. // this license (the "Software") to use, reproduce, display, distribute,
  2064. // execute, and transmit the Software, and to prepare derivative works of the
  2065. // Software, and to permit third-parties to whom the Software is furnished to
  2066. // do so, all subject to the following:
  2067. // The copyright notices in the Software and this entire statement, including
  2068. // the above license grant, this restriction and the following disclaimer,
  2069. // must be included in all copies of the Software, in whole or in part, and
  2070. // all derivative works of the Software, unless such copies or derivative
  2071. // works are solely in the form of machine-executable object code generated by
  2072. // a source language processor.
  2073. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  2074. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  2075. // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
  2076. // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
  2077. // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
  2078. // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  2079. // DEALINGS IN THE SOFTWARE.
  2080. //
  2081. namespace dlib {
  2082. inline unsigned char from_hex(unsigned char ch) {
  2083. if (ch <= '9' && ch >= '0')
  2084. ch -= '0';
  2085. else if (ch <= 'f' && ch >= 'a')
  2086. ch -= 'a' - 10;
  2087. else if (ch <= 'F' && ch >= 'A')
  2088. ch -= 'A' - 10;
  2089. else
  2090. ch = 0;
  2091. return ch;
  2092. }
  2093. static const std::string urldecode(const std::string &str) {
  2094. using namespace std;
  2095. string result;
  2096. string::size_type i;
  2097. for (i = 0; i < str.size(); ++i) {
  2098. if (str[i] == '+') {
  2099. result += ' ';
  2100. } else if (str[i] == '%' && str.size() > i + 2) {
  2101. const unsigned char ch1 =
  2102. from_hex(static_cast<unsigned char>(str[i + 1]));
  2103. const unsigned char ch2 =
  2104. from_hex(static_cast<unsigned char>(str[i + 2]));
  2105. const unsigned char ch = static_cast<unsigned char>((ch1 << 4) | ch2);
  2106. result += static_cast<char>(ch);
  2107. i += 2;
  2108. } else {
  2109. result += str[i];
  2110. }
  2111. }
  2112. return result;
  2113. }
  2114. } // namespace dlib
  2115. // --- dlib end --------------------------------------------------------------
  2116. bool URIDecode(const std::string &in_uri, std::string *out_uri,
  2117. void *user_data) {
  2118. (void)user_data;
  2119. *out_uri = dlib::urldecode(in_uri);
  2120. return true;
  2121. }
  2122. static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
  2123. std::string *warn, const std::string &filename,
  2124. const std::string &basedir, bool required,
  2125. size_t reqBytes, bool checkSize,
  2126. size_t maxFileSize, FsCallbacks *fs) {
  2127. if (fs == nullptr || fs->FileExists == nullptr ||
  2128. fs->ExpandFilePath == nullptr || fs->ReadWholeFile == nullptr) {
  2129. // This is a developer error, assert() ?
  2130. if (err) {
  2131. (*err) += "FS callback[s] not set\n";
  2132. }
  2133. return false;
  2134. }
  2135. std::string *failMsgOut = required ? err : warn;
  2136. out->clear();
  2137. std::vector<std::string> paths;
  2138. paths.push_back(basedir);
  2139. paths.push_back(".");
  2140. std::string filepath = FindFile(paths, filename, fs);
  2141. if (filepath.empty() || filename.empty()) {
  2142. if (failMsgOut) {
  2143. (*failMsgOut) += "File not found : " + filename + "\n";
  2144. }
  2145. return false;
  2146. }
  2147. // Check file size
  2148. if (fs->GetFileSizeInBytes) {
  2149. size_t file_size{0};
  2150. std::string _err;
  2151. bool ok =
  2152. fs->GetFileSizeInBytes(&file_size, &_err, filepath, fs->user_data);
  2153. if (!ok) {
  2154. if (_err.size()) {
  2155. if (failMsgOut) {
  2156. (*failMsgOut) += "Getting file size failed : " + filename +
  2157. ", err = " + _err + "\n";
  2158. }
  2159. }
  2160. return false;
  2161. }
  2162. if (file_size > maxFileSize) {
  2163. if (failMsgOut) {
  2164. (*failMsgOut) += "File size " + std::to_string(file_size) +
  2165. " exceeds maximum allowed file size " +
  2166. std::to_string(maxFileSize) + " : " + filepath + "\n";
  2167. }
  2168. return false;
  2169. }
  2170. }
  2171. std::vector<unsigned char> buf;
  2172. std::string fileReadErr;
  2173. bool fileRead =
  2174. fs->ReadWholeFile(&buf, &fileReadErr, filepath, fs->user_data);
  2175. if (!fileRead) {
  2176. if (failMsgOut) {
  2177. (*failMsgOut) +=
  2178. "File read error : " + filepath + " : " + fileReadErr + "\n";
  2179. }
  2180. return false;
  2181. }
  2182. size_t sz = buf.size();
  2183. if (sz == 0) {
  2184. if (failMsgOut) {
  2185. (*failMsgOut) += "File is empty : " + filepath + "\n";
  2186. }
  2187. return false;
  2188. }
  2189. if (checkSize) {
  2190. if (reqBytes == sz) {
  2191. out->swap(buf);
  2192. return true;
  2193. } else {
  2194. std::stringstream ss;
  2195. ss << "File size mismatch : " << filepath << ", requestedBytes "
  2196. << reqBytes << ", but got " << sz << std::endl;
  2197. if (failMsgOut) {
  2198. (*failMsgOut) += ss.str();
  2199. }
  2200. return false;
  2201. }
  2202. }
  2203. out->swap(buf);
  2204. return true;
  2205. }
  2206. void TinyGLTF::SetParseStrictness(ParseStrictness strictness) {
  2207. strictness_ = strictness;
  2208. }
  2209. void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) {
  2210. if (func == nullptr) {
  2211. RemoveImageLoader();
  2212. return;
  2213. }
  2214. LoadImageData = std::move(func);
  2215. load_image_user_data_ = user_data;
  2216. user_image_loader_ = true;
  2217. }
  2218. void TinyGLTF::RemoveImageLoader() {
  2219. LoadImageData =
  2220. #ifndef TINYGLTF_NO_STB_IMAGE
  2221. &tinygltf::LoadImageData;
  2222. #else
  2223. nullptr;
  2224. #endif
  2225. load_image_user_data_ = nullptr;
  2226. user_image_loader_ = false;
  2227. }
  2228. #ifndef TINYGLTF_NO_STB_IMAGE
  2229. bool LoadImageData(Image *image, const int image_idx, std::string *err,
  2230. std::string *warn, int req_width, int req_height,
  2231. const unsigned char *bytes, int size, void *user_data) {
  2232. (void)warn;
  2233. LoadImageDataOption option;
  2234. if (user_data) {
  2235. option = *reinterpret_cast<LoadImageDataOption *>(user_data);
  2236. }
  2237. int w = 0, h = 0, comp = 0, req_comp = 0;
  2238. // Try to decode image header
  2239. if (!stbi_info_from_memory(bytes, size, &w, &h, &comp)) {
  2240. // On failure, if we load images as is, we just warn.
  2241. std::string* msgOut = option.as_is ? warn : err;
  2242. if (msgOut) {
  2243. (*msgOut) +=
  2244. "Unknown image format. STB cannot decode image header for image[" +
  2245. std::to_string(image_idx) + "] name = \"" + image->name + "\".\n";
  2246. }
  2247. if (!option.as_is) {
  2248. // If we decode images, error out.
  2249. return false;
  2250. } else {
  2251. // If we load images as is, we copy the image data,
  2252. // set all image properties to invalid, and report success.
  2253. image->width = image->height = image->component = -1;
  2254. image->bits = image->pixel_type = -1;
  2255. image->image.resize(static_cast<size_t>(size));
  2256. std::copy(bytes, bytes + size, image->image.begin());
  2257. return true;
  2258. }
  2259. }
  2260. int bits = 8;
  2261. int pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
  2262. if (stbi_is_16_bit_from_memory(bytes, size)) {
  2263. bits = 16;
  2264. pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT;
  2265. }
  2266. // preserve_channels true: Use channels stored in the image file.
  2267. // false: force 32-bit textures for common Vulkan compatibility. It appears
  2268. // that some GPU drivers do not support 24-bit images for Vulkan
  2269. req_comp = (option.preserve_channels || option.as_is) ? 0 : 4;
  2270. unsigned char* data = nullptr;
  2271. // Perform image decoding if requested
  2272. if (!option.as_is) {
  2273. // If the image is marked as 16 bit per channel, attempt to decode it as such first.
  2274. // If that fails, we are going to attempt to load it as 8 bit per channel image.
  2275. if (bits == 16) {
  2276. data = reinterpret_cast<unsigned char *>(stbi_load_16_from_memory(bytes, size, &w, &h, &comp, req_comp));
  2277. }
  2278. // Load as 8 bit per channel data
  2279. if (!data) {
  2280. data = stbi_load_from_memory(bytes, size, &w, &h, &comp, req_comp);
  2281. if (!data) {
  2282. if (err) {
  2283. (*err) +=
  2284. "Unknown image format. STB cannot decode image data for image[" +
  2285. std::to_string(image_idx) + "] name = \"" + image->name + "\".\n";
  2286. }
  2287. return false;
  2288. }
  2289. // If we were succesful, mark as 8 bit
  2290. bits = 8;
  2291. pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
  2292. }
  2293. }
  2294. if ((w < 1) || (h < 1)) {
  2295. stbi_image_free(data);
  2296. if (err) {
  2297. (*err) += "Invalid image data for image[" + std::to_string(image_idx) +
  2298. "] name = \"" + image->name + "\"\n";
  2299. }
  2300. return false;
  2301. }
  2302. if (req_width > 0) {
  2303. if (req_width != w) {
  2304. stbi_image_free(data);
  2305. if (err) {
  2306. (*err) += "Image width mismatch for image[" +
  2307. std::to_string(image_idx) + "] name = \"" + image->name +
  2308. "\"\n";
  2309. }
  2310. return false;
  2311. }
  2312. }
  2313. if (req_height > 0) {
  2314. if (req_height != h) {
  2315. stbi_image_free(data);
  2316. if (err) {
  2317. (*err) += "Image height mismatch. for image[" +
  2318. std::to_string(image_idx) + "] name = \"" + image->name +
  2319. "\"\n";
  2320. }
  2321. return false;
  2322. }
  2323. }
  2324. if (req_comp != 0) {
  2325. // loaded data has `req_comp` channels(components)
  2326. comp = req_comp;
  2327. }
  2328. image->width = w;
  2329. image->height = h;
  2330. image->component = comp;
  2331. image->bits = bits;
  2332. image->pixel_type = pixel_type;
  2333. image->as_is = option.as_is;
  2334. if (option.as_is) {
  2335. // Store the original image data
  2336. image->image.resize(static_cast<size_t>(size));
  2337. std::copy(bytes, bytes + size, image->image.begin());
  2338. }
  2339. else {
  2340. // Store the decoded image data
  2341. image->image.resize(static_cast<size_t>(w * h * comp) * size_t(bits / 8));
  2342. std::copy(data, data + w * h * comp * (bits / 8), image->image.begin());
  2343. }
  2344. stbi_image_free(data);
  2345. return true;
  2346. }
  2347. #endif
  2348. void TinyGLTF::SetImageWriter(WriteImageDataFunction func, void *user_data) {
  2349. WriteImageData = std::move(func);
  2350. write_image_user_data_ = user_data;
  2351. }
  2352. #ifndef TINYGLTF_NO_STB_IMAGE_WRITE
  2353. static void WriteToMemory_stbi(void *context, void *data, int size) {
  2354. std::vector<unsigned char> *buffer =
  2355. reinterpret_cast<std::vector<unsigned char> *>(context);
  2356. unsigned char *pData = reinterpret_cast<unsigned char *>(data);
  2357. buffer->insert(buffer->end(), pData, pData + size);
  2358. }
  2359. bool WriteImageData(const std::string *basepath, const std::string *filename,
  2360. const Image *image, bool embedImages,
  2361. const FsCallbacks* fs_cb, const URICallbacks *uri_cb,
  2362. std::string *out_uri, void *) {
  2363. const std::string ext = GetFilePathExtension(*filename);
  2364. // Write image to temporary buffer
  2365. std::string header;
  2366. std::vector<unsigned char> data;
  2367. // If the image data is already encoded, take it as is
  2368. if (image->as_is) {
  2369. data = image->image;
  2370. }
  2371. if (ext == "png") {
  2372. if (!image->as_is) {
  2373. if ((image->bits != 8) ||
  2374. (image->pixel_type != TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)) {
  2375. // Unsupported pixel format
  2376. return false;
  2377. }
  2378. if (!stbi_write_png_to_func(WriteToMemory_stbi, &data, image->width,
  2379. image->height, image->component,
  2380. &image->image[0], 0)) {
  2381. return false;
  2382. }
  2383. }
  2384. header = "data:image/png;base64,";
  2385. } else if (ext == "jpg") {
  2386. if (!image->as_is &&
  2387. !stbi_write_jpg_to_func(WriteToMemory_stbi, &data, image->width,
  2388. image->height, image->component,
  2389. &image->image[0], 100)) {
  2390. return false;
  2391. }
  2392. header = "data:image/jpeg;base64,";
  2393. } else if (ext == "bmp") {
  2394. if (!image->as_is &&
  2395. !stbi_write_bmp_to_func(WriteToMemory_stbi, &data, image->width,
  2396. image->height, image->component,
  2397. &image->image[0])) {
  2398. return false;
  2399. }
  2400. header = "data:image/bmp;base64,";
  2401. } else if (!embedImages) {
  2402. // Error: can't output requested format to file
  2403. return false;
  2404. }
  2405. if (embedImages) {
  2406. // Embed base64-encoded image into URI
  2407. if (data.size()) {
  2408. *out_uri = header + base64_encode(&data[0],
  2409. static_cast<unsigned int>(data.size()));
  2410. } else {
  2411. // Throw error?
  2412. }
  2413. } else {
  2414. // Write image to disc
  2415. if ((fs_cb != nullptr) && (fs_cb->WriteWholeFile != nullptr)) {
  2416. const std::string imagefilepath = JoinPath(*basepath, *filename);
  2417. std::string writeError;
  2418. if (!fs_cb->WriteWholeFile(&writeError, imagefilepath, data,
  2419. fs_cb->user_data)) {
  2420. // Could not write image file to disc; Throw error ?
  2421. return false;
  2422. }
  2423. } else {
  2424. // Throw error?
  2425. }
  2426. if (uri_cb->encode) {
  2427. if (!uri_cb->encode(*filename, "image", out_uri, uri_cb->user_data)) {
  2428. return false;
  2429. }
  2430. } else {
  2431. *out_uri = *filename;
  2432. }
  2433. }
  2434. return true;
  2435. }
  2436. #endif
  2437. bool TinyGLTF::SetURICallbacks(URICallbacks callbacks, std::string* err) {
  2438. if (callbacks.decode == nullptr) {
  2439. if (err != nullptr) {
  2440. *err = "URI Callback require a non-null decode function.";
  2441. }
  2442. return false;
  2443. }
  2444. if (callbacks.decode) {
  2445. uri_cb = std::move(callbacks);
  2446. }
  2447. return true;
  2448. }
  2449. bool TinyGLTF::SetFsCallbacks(FsCallbacks callbacks, std::string *err) {
  2450. // If callbacks are defined at all, they must all be defined.
  2451. if (callbacks.FileExists == nullptr || callbacks.ExpandFilePath == nullptr ||
  2452. callbacks.ReadWholeFile == nullptr ||
  2453. callbacks.WriteWholeFile == nullptr ||
  2454. callbacks.GetFileSizeInBytes == nullptr) {
  2455. if (err != nullptr) {
  2456. *err =
  2457. "FS Callbacks must be completely defined. At least one callback is "
  2458. "null.";
  2459. }
  2460. return false;
  2461. }
  2462. fs = std::move(callbacks);
  2463. return true;
  2464. }
  2465. #ifdef _WIN32
  2466. static inline std::wstring UTF8ToWchar(const std::string &str) {
  2467. int wstr_size =
  2468. MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0);
  2469. std::wstring wstr((size_t)wstr_size, 0);
  2470. MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &wstr[0],
  2471. (int)wstr.size());
  2472. return wstr;
  2473. }
  2474. static inline std::string WcharToUTF8(const std::wstring &wstr) {
  2475. int str_size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(),
  2476. nullptr, 0, nullptr, nullptr);
  2477. std::string str((size_t)str_size, 0);
  2478. WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), &str[0],
  2479. (int)str.size(), nullptr, nullptr);
  2480. return str;
  2481. }
  2482. #endif
  2483. #ifndef TINYGLTF_NO_FS
  2484. // Default implementations of filesystem functions
  2485. bool FileExists(const std::string &abs_filename, void *) {
  2486. bool ret;
  2487. #ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
  2488. if (asset_manager) {
  2489. AAsset *asset = AAssetManager_open(asset_manager, abs_filename.c_str(),
  2490. AASSET_MODE_STREAMING);
  2491. if (!asset) {
  2492. return false;
  2493. }
  2494. AAsset_close(asset);
  2495. ret = true;
  2496. } else {
  2497. return false;
  2498. }
  2499. #else
  2500. #ifdef _WIN32
  2501. #if defined(_MSC_VER) || defined(_LIBCPP_VERSION)
  2502. // First check if a file is a directory.
  2503. DWORD result = GetFileAttributesW(UTF8ToWchar(abs_filename).c_str());
  2504. if (result == INVALID_FILE_ATTRIBUTES) {
  2505. return false;
  2506. }
  2507. if (result & FILE_ATTRIBUTE_DIRECTORY) {
  2508. return false;
  2509. }
  2510. FILE *fp = nullptr;
  2511. errno_t err = _wfopen_s(&fp, UTF8ToWchar(abs_filename).c_str(), L"rb");
  2512. if (err != 0) {
  2513. return false;
  2514. }
  2515. #elif defined(__GLIBCXX__)
  2516. FILE *fp = fopen(abs_filename.c_str(), "rb");
  2517. if (!fp) {
  2518. return false;
  2519. }
  2520. #else
  2521. // TODO: is_directory check
  2522. FILE *fp = nullptr;
  2523. errno_t err = fopen_s(&fp, abs_filename.c_str(), "rb");
  2524. if (err != 0) {
  2525. return false;
  2526. }
  2527. #endif
  2528. #else
  2529. struct stat sb;
  2530. if (stat(abs_filename.c_str(), &sb)) {
  2531. return false;
  2532. }
  2533. if (S_ISDIR(sb.st_mode)) {
  2534. return false;
  2535. }
  2536. FILE *fp = fopen(abs_filename.c_str(), "rb");
  2537. #endif
  2538. if (fp) {
  2539. ret = true;
  2540. fclose(fp);
  2541. } else {
  2542. ret = false;
  2543. }
  2544. #endif
  2545. return ret;
  2546. }
  2547. std::string ExpandFilePath(const std::string &filepath, void *) {
  2548. // https://github.com/syoyo/tinygltf/issues/368
  2549. //
  2550. // No file path expansion in built-in FS function anymore, since glTF URI
  2551. // should not contain tilde('~') and environment variables, and for security
  2552. // reason(`wordexp`).
  2553. //
  2554. // Users need to supply `base_dir`(in `LoadASCIIFromString`,
  2555. // `LoadBinaryFromMemory`) in expanded absolute path.
  2556. return filepath;
  2557. #if 0
  2558. #ifdef _WIN32
  2559. // Assume input `filepath` is encoded in UTF-8
  2560. std::wstring wfilepath = UTF8ToWchar(filepath);
  2561. DWORD wlen = ExpandEnvironmentStringsW(wfilepath.c_str(), nullptr, 0);
  2562. wchar_t *wstr = new wchar_t[wlen];
  2563. ExpandEnvironmentStringsW(wfilepath.c_str(), wstr, wlen);
  2564. std::wstring ws(wstr);
  2565. delete[] wstr;
  2566. return WcharToUTF8(ws);
  2567. #else
  2568. #if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || \
  2569. defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__OpenBSD__)
  2570. // no expansion
  2571. std::string s = filepath;
  2572. #else
  2573. std::string s;
  2574. wordexp_t p;
  2575. if (filepath.empty()) {
  2576. return "";
  2577. }
  2578. // Quote the string to keep any spaces in filepath intact.
  2579. std::string quoted_path = "\"" + filepath + "\"";
  2580. // char** w;
  2581. int ret = wordexp(quoted_path.c_str(), &p, 0);
  2582. if (ret) {
  2583. // err
  2584. s = filepath;
  2585. return s;
  2586. }
  2587. // Use first element only.
  2588. if (p.we_wordv) {
  2589. s = std::string(p.we_wordv[0]);
  2590. wordfree(&p);
  2591. } else {
  2592. s = filepath;
  2593. }
  2594. #endif
  2595. return s;
  2596. #endif
  2597. #endif
  2598. }
  2599. bool GetFileSizeInBytes(size_t *filesize_out, std::string *err,
  2600. const std::string &filepath, void *userdata) {
  2601. (void)userdata;
  2602. #ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
  2603. if (asset_manager) {
  2604. AAsset *asset = AAssetManager_open(asset_manager, filepath.c_str(),
  2605. AASSET_MODE_STREAMING);
  2606. if (!asset) {
  2607. if (err) {
  2608. (*err) += "File open error : " + filepath + "\n";
  2609. }
  2610. return false;
  2611. }
  2612. size_t size = AAsset_getLength(asset);
  2613. if (size == 0) {
  2614. if (err) {
  2615. (*err) += "Invalid file size : " + filepath +
  2616. " (does the path point to a directory?)";
  2617. }
  2618. return false;
  2619. }
  2620. return true;
  2621. } else {
  2622. if (err) {
  2623. (*err) += "No asset manager specified : " + filepath + "\n";
  2624. }
  2625. return false;
  2626. }
  2627. #else
  2628. #ifdef _WIN32
  2629. #if defined(__GLIBCXX__) // mingw
  2630. int file_descriptor =
  2631. _wopen(UTF8ToWchar(filepath).c_str(), _O_RDONLY | _O_BINARY);
  2632. __gnu_cxx::stdio_filebuf<char> wfile_buf(file_descriptor, std::ios_base::in);
  2633. std::istream f(&wfile_buf);
  2634. #elif defined(_MSC_VER) || defined(_LIBCPP_VERSION)
  2635. // For libcxx, assume _LIBCPP_HAS_OPEN_WITH_WCHAR is defined to accept
  2636. // `wchar_t *`
  2637. std::ifstream f(UTF8ToWchar(filepath).c_str(), std::ifstream::binary);
  2638. #else
  2639. // Unknown compiler/runtime
  2640. std::ifstream f(filepath.c_str(), std::ifstream::binary);
  2641. #endif
  2642. #else
  2643. std::ifstream f(filepath.c_str(), std::ifstream::binary);
  2644. #endif
  2645. if (!f) {
  2646. if (err) {
  2647. (*err) += "File open error : " + filepath + "\n";
  2648. }
  2649. return false;
  2650. }
  2651. // For directory(and pipe?), peek() will fail(Posix gnustl/libc++ only)
  2652. f.peek();
  2653. if (!f) {
  2654. if (err) {
  2655. (*err) +=
  2656. "File read error. Maybe empty file or invalid file : " + filepath +
  2657. "\n";
  2658. }
  2659. return false;
  2660. }
  2661. f.seekg(0, f.end);
  2662. const auto sz = f.tellg();
  2663. // std::cout << "sz = " << sz << "\n";
  2664. f.seekg(0, f.beg);
  2665. if (sz < 0) {
  2666. if (err) {
  2667. (*err) += "Invalid file size : " + filepath +
  2668. " (does the path point to a directory?)";
  2669. }
  2670. return false;
  2671. } else if (sz == std::streamoff(0)) {
  2672. if (err) {
  2673. (*err) += "File is empty : " + filepath + "\n";
  2674. }
  2675. return false;
  2676. } else if (sz >= (std::numeric_limits<std::streamoff>::max)()) {
  2677. if (err) {
  2678. (*err) += "Invalid file size : " + filepath + "\n";
  2679. }
  2680. return false;
  2681. }
  2682. (*filesize_out) = static_cast<size_t>(sz);
  2683. return true;
  2684. #endif
  2685. }
  2686. bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
  2687. const std::string &filepath, void *) {
  2688. #ifdef TINYGLTF_ANDROID_LOAD_FROM_ASSETS
  2689. if (asset_manager) {
  2690. AAsset *asset = AAssetManager_open(asset_manager, filepath.c_str(),
  2691. AASSET_MODE_STREAMING);
  2692. if (!asset) {
  2693. if (err) {
  2694. (*err) += "File open error : " + filepath + "\n";
  2695. }
  2696. return false;
  2697. }
  2698. size_t size = AAsset_getLength(asset);
  2699. if (size == 0) {
  2700. if (err) {
  2701. (*err) += "Invalid file size : " + filepath +
  2702. " (does the path point to a directory?)";
  2703. }
  2704. return false;
  2705. }
  2706. out->resize(static_cast<size_t>(size));
  2707. AAsset_read(asset, reinterpret_cast<char *>(&out->at(0)), size);
  2708. AAsset_close(asset);
  2709. return true;
  2710. } else {
  2711. if (err) {
  2712. (*err) += "No asset manager specified : " + filepath + "\n";
  2713. }
  2714. return false;
  2715. }
  2716. #else
  2717. #ifdef _WIN32
  2718. #if defined(__GLIBCXX__) // mingw
  2719. int file_descriptor =
  2720. _wopen(UTF8ToWchar(filepath).c_str(), _O_RDONLY | _O_BINARY);
  2721. __gnu_cxx::stdio_filebuf<char> wfile_buf(file_descriptor, std::ios_base::in);
  2722. std::istream f(&wfile_buf);
  2723. #elif defined(_MSC_VER) || defined(_LIBCPP_VERSION)
  2724. // For libcxx, assume _LIBCPP_HAS_OPEN_WITH_WCHAR is defined to accept
  2725. // `wchar_t *`
  2726. std::ifstream f(UTF8ToWchar(filepath).c_str(), std::ifstream::binary);
  2727. #else
  2728. // Unknown compiler/runtime
  2729. std::ifstream f(filepath.c_str(), std::ifstream::binary);
  2730. #endif
  2731. #else
  2732. std::ifstream f(filepath.c_str(), std::ifstream::binary);
  2733. #endif
  2734. if (!f) {
  2735. if (err) {
  2736. (*err) += "File open error : " + filepath + "\n";
  2737. }
  2738. return false;
  2739. }
  2740. // For directory(and pipe?), peek() will fail(Posix gnustl/libc++ only)
  2741. f.peek();
  2742. if (!f) {
  2743. if (err) {
  2744. (*err) +=
  2745. "File read error. Maybe empty file or invalid file : " + filepath +
  2746. "\n";
  2747. }
  2748. return false;
  2749. }
  2750. f.seekg(0, f.end);
  2751. const auto sz = f.tellg();
  2752. // std::cout << "sz = " << sz << "\n";
  2753. f.seekg(0, f.beg);
  2754. if (sz < 0) {
  2755. if (err) {
  2756. (*err) += "Invalid file size : " + filepath +
  2757. " (does the path point to a directory?)";
  2758. }
  2759. return false;
  2760. } else if (sz == std::streamoff(0)) {
  2761. if (err) {
  2762. (*err) += "File is empty : " + filepath + "\n";
  2763. }
  2764. return false;
  2765. } else if (sz >= (std::numeric_limits<std::streamoff>::max)()) {
  2766. if (err) {
  2767. (*err) += "Invalid file size : " + filepath + "\n";
  2768. }
  2769. return false;
  2770. }
  2771. out->resize(sz);
  2772. f.read(reinterpret_cast<char *>(&out->at(0)),
  2773. static_cast<std::streamsize>(sz));
  2774. return true;
  2775. #endif
  2776. }
  2777. bool WriteWholeFile(std::string *err, const std::string &filepath,
  2778. const std::vector<unsigned char> &contents, void *) {
  2779. #ifdef _WIN32
  2780. #if defined(__GLIBCXX__) // mingw
  2781. int file_descriptor = _wopen(UTF8ToWchar(filepath).c_str(),
  2782. _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY, _S_IWRITE);
  2783. __gnu_cxx::stdio_filebuf<char> wfile_buf(
  2784. file_descriptor, std::ios_base::out | std::ios_base::binary);
  2785. std::ostream f(&wfile_buf);
  2786. #elif defined(_MSC_VER)
  2787. std::ofstream f(UTF8ToWchar(filepath).c_str(), std::ofstream::binary);
  2788. #else // clang?
  2789. std::ofstream f(filepath.c_str(), std::ofstream::binary);
  2790. #endif
  2791. #else
  2792. std::ofstream f(filepath.c_str(), std::ofstream::binary);
  2793. #endif
  2794. if (!f) {
  2795. if (err) {
  2796. (*err) += "File open error for writing : " + filepath + "\n";
  2797. }
  2798. return false;
  2799. }
  2800. f.write(reinterpret_cast<const char *>(&contents.at(0)),
  2801. static_cast<std::streamsize>(contents.size()));
  2802. if (!f) {
  2803. if (err) {
  2804. (*err) += "File write error: " + filepath + "\n";
  2805. }
  2806. return false;
  2807. }
  2808. return true;
  2809. }
  2810. #endif // TINYGLTF_NO_FS
  2811. static std::string MimeToExt(const std::string &mimeType) {
  2812. if (mimeType == "image/jpeg") {
  2813. return "jpg";
  2814. } else if (mimeType == "image/png") {
  2815. return "png";
  2816. } else if (mimeType == "image/bmp") {
  2817. return "bmp";
  2818. } else if (mimeType == "image/gif") {
  2819. return "gif";
  2820. }
  2821. return "";
  2822. }
  2823. static bool UpdateImageObject(const Image &image, std::string &baseDir,
  2824. int index, bool embedImages,
  2825. const FsCallbacks *fs_cb,
  2826. const URICallbacks *uri_cb,
  2827. const WriteImageDataFunction& WriteImageData,
  2828. void *user_data, std::string *out_uri) {
  2829. std::string filename;
  2830. std::string ext;
  2831. // If image has uri, use it as a filename
  2832. if (image.uri.size()) {
  2833. std::string decoded_uri;
  2834. if (!uri_cb->decode(image.uri, &decoded_uri, uri_cb->user_data)) {
  2835. // A decode failure results in a failure to write the gltf.
  2836. return false;
  2837. }
  2838. filename = GetBaseFilename(decoded_uri);
  2839. ext = GetFilePathExtension(filename);
  2840. } else if (image.bufferView != -1) {
  2841. // If there's no URI and the data exists in a buffer,
  2842. // don't change properties or write images
  2843. } else if (image.name.size()) {
  2844. ext = MimeToExt(image.mimeType);
  2845. // Otherwise use name as filename
  2846. filename = image.name + "." + ext;
  2847. } else {
  2848. ext = MimeToExt(image.mimeType);
  2849. // Fallback to index of image as filename
  2850. filename = std::to_string(index) + "." + ext;
  2851. }
  2852. // If callback is set and image data exists, modify image data object. If
  2853. // image data does not exist, this is not considered a failure and the
  2854. // original uri should be maintained.
  2855. bool imageWritten = false;
  2856. if (WriteImageData != nullptr && !filename.empty() && !image.image.empty()) {
  2857. imageWritten = WriteImageData(&baseDir, &filename, &image, embedImages,
  2858. fs_cb, uri_cb, out_uri, user_data);
  2859. if (!imageWritten) {
  2860. return false;
  2861. }
  2862. }
  2863. // Use the original uri if the image was not written.
  2864. if (!imageWritten) {
  2865. *out_uri = image.uri;
  2866. }
  2867. return true;
  2868. }
  2869. bool IsDataURI(const std::string &in) {
  2870. std::string header = "data:application/octet-stream;base64,";
  2871. if (in.find(header) == 0) {
  2872. return true;
  2873. }
  2874. header = "data:image/jpeg;base64,";
  2875. if (in.find(header) == 0) {
  2876. return true;
  2877. }
  2878. header = "data:image/png;base64,";
  2879. if (in.find(header) == 0) {
  2880. return true;
  2881. }
  2882. header = "data:image/bmp;base64,";
  2883. if (in.find(header) == 0) {
  2884. return true;
  2885. }
  2886. header = "data:image/gif;base64,";
  2887. if (in.find(header) == 0) {
  2888. return true;
  2889. }
  2890. header = "data:text/plain;base64,";
  2891. if (in.find(header) == 0) {
  2892. return true;
  2893. }
  2894. header = "data:application/gltf-buffer;base64,";
  2895. if (in.find(header) == 0) {
  2896. return true;
  2897. }
  2898. return false;
  2899. }
  2900. bool DecodeDataURI(std::vector<unsigned char> *out, std::string &mime_type,
  2901. const std::string &in, size_t reqBytes, bool checkSize) {
  2902. std::string header = "data:application/octet-stream;base64,";
  2903. std::string data;
  2904. if (in.find(header) == 0) {
  2905. data = base64_decode(in.substr(header.size())); // cut mime string.
  2906. }
  2907. if (data.empty()) {
  2908. header = "data:image/jpeg;base64,";
  2909. if (in.find(header) == 0) {
  2910. mime_type = "image/jpeg";
  2911. data = base64_decode(in.substr(header.size())); // cut mime string.
  2912. }
  2913. }
  2914. if (data.empty()) {
  2915. header = "data:image/png;base64,";
  2916. if (in.find(header) == 0) {
  2917. mime_type = "image/png";
  2918. data = base64_decode(in.substr(header.size())); // cut mime string.
  2919. }
  2920. }
  2921. if (data.empty()) {
  2922. header = "data:image/bmp;base64,";
  2923. if (in.find(header) == 0) {
  2924. mime_type = "image/bmp";
  2925. data = base64_decode(in.substr(header.size())); // cut mime string.
  2926. }
  2927. }
  2928. if (data.empty()) {
  2929. header = "data:image/gif;base64,";
  2930. if (in.find(header) == 0) {
  2931. mime_type = "image/gif";
  2932. data = base64_decode(in.substr(header.size())); // cut mime string.
  2933. }
  2934. }
  2935. if (data.empty()) {
  2936. header = "data:text/plain;base64,";
  2937. if (in.find(header) == 0) {
  2938. mime_type = "text/plain";
  2939. data = base64_decode(in.substr(header.size()));
  2940. }
  2941. }
  2942. if (data.empty()) {
  2943. header = "data:application/gltf-buffer;base64,";
  2944. if (in.find(header) == 0) {
  2945. data = base64_decode(in.substr(header.size()));
  2946. }
  2947. }
  2948. // TODO(syoyo): Allow empty buffer? #229
  2949. if (data.empty()) {
  2950. return false;
  2951. }
  2952. if (checkSize) {
  2953. if (data.size() != reqBytes) {
  2954. return false;
  2955. }
  2956. out->resize(reqBytes);
  2957. } else {
  2958. out->resize(data.size());
  2959. }
  2960. std::copy(data.begin(), data.end(), out->begin());
  2961. return true;
  2962. }
  2963. namespace detail {
  2964. bool GetInt(const detail::json &o, int &val) {
  2965. #ifdef TINYGLTF_USE_RAPIDJSON
  2966. if (!o.IsDouble()) {
  2967. if (o.IsInt()) {
  2968. val = o.GetInt();
  2969. return true;
  2970. } else if (o.IsUint()) {
  2971. val = static_cast<int>(o.GetUint());
  2972. return true;
  2973. } else if (o.IsInt64()) {
  2974. val = static_cast<int>(o.GetInt64());
  2975. return true;
  2976. } else if (o.IsUint64()) {
  2977. val = static_cast<int>(o.GetUint64());
  2978. return true;
  2979. }
  2980. }
  2981. return false;
  2982. #else
  2983. auto type = o.type();
  2984. if ((type == detail::json::value_t::number_integer) ||
  2985. (type == detail::json::value_t::number_unsigned)) {
  2986. val = static_cast<int>(o.get<int64_t>());
  2987. return true;
  2988. }
  2989. return false;
  2990. #endif
  2991. }
  2992. #ifdef TINYGLTF_USE_RAPIDJSON
  2993. bool GetDouble(const detail::json &o, double &val) {
  2994. if (o.IsDouble()) {
  2995. val = o.GetDouble();
  2996. return true;
  2997. }
  2998. return false;
  2999. }
  3000. #endif
  3001. bool GetNumber(const detail::json &o, double &val) {
  3002. #ifdef TINYGLTF_USE_RAPIDJSON
  3003. if (o.IsNumber()) {
  3004. val = o.GetDouble();
  3005. return true;
  3006. }
  3007. return false;
  3008. #else
  3009. if (o.is_number()) {
  3010. val = o.get<double>();
  3011. return true;
  3012. }
  3013. return false;
  3014. #endif
  3015. }
  3016. bool GetString(const detail::json &o, std::string &val) {
  3017. #ifdef TINYGLTF_USE_RAPIDJSON
  3018. if (o.IsString()) {
  3019. val = o.GetString();
  3020. return true;
  3021. }
  3022. return false;
  3023. #else
  3024. if (o.type() == detail::json::value_t::string) {
  3025. val = o.get<std::string>();
  3026. return true;
  3027. }
  3028. return false;
  3029. #endif
  3030. }
  3031. bool IsArray(const detail::json &o) {
  3032. #ifdef TINYGLTF_USE_RAPIDJSON
  3033. return o.IsArray();
  3034. #else
  3035. return o.is_array();
  3036. #endif
  3037. }
  3038. detail::json_const_array_iterator ArrayBegin(const detail::json &o) {
  3039. #ifdef TINYGLTF_USE_RAPIDJSON
  3040. return o.Begin();
  3041. #else
  3042. return o.begin();
  3043. #endif
  3044. }
  3045. detail::json_const_array_iterator ArrayEnd(const detail::json &o) {
  3046. #ifdef TINYGLTF_USE_RAPIDJSON
  3047. return o.End();
  3048. #else
  3049. return o.end();
  3050. #endif
  3051. }
  3052. bool IsObject(const detail::json &o) {
  3053. #ifdef TINYGLTF_USE_RAPIDJSON
  3054. return o.IsObject();
  3055. #else
  3056. return o.is_object();
  3057. #endif
  3058. }
  3059. detail::json_const_iterator ObjectBegin(const detail::json &o) {
  3060. #ifdef TINYGLTF_USE_RAPIDJSON
  3061. return o.MemberBegin();
  3062. #else
  3063. return o.begin();
  3064. #endif
  3065. }
  3066. detail::json_const_iterator ObjectEnd(const detail::json &o) {
  3067. #ifdef TINYGLTF_USE_RAPIDJSON
  3068. return o.MemberEnd();
  3069. #else
  3070. return o.end();
  3071. #endif
  3072. }
  3073. // Making this a const char* results in a pointer to a temporary when
  3074. // TINYGLTF_USE_RAPIDJSON is off.
  3075. std::string GetKey(detail::json_const_iterator &it) {
  3076. #ifdef TINYGLTF_USE_RAPIDJSON
  3077. return it->name.GetString();
  3078. #else
  3079. return it.key().c_str();
  3080. #endif
  3081. }
  3082. bool FindMember(const detail::json &o, const char *member,
  3083. detail::json_const_iterator &it) {
  3084. #ifdef TINYGLTF_USE_RAPIDJSON
  3085. if (!o.IsObject()) {
  3086. return false;
  3087. }
  3088. it = o.FindMember(member);
  3089. return it != o.MemberEnd();
  3090. #else
  3091. it = o.find(member);
  3092. return it != o.end();
  3093. #endif
  3094. }
  3095. bool FindMember(detail::json &o, const char *member,
  3096. detail::json_iterator &it) {
  3097. #ifdef TINYGLTF_USE_RAPIDJSON
  3098. if (!o.IsObject()) {
  3099. return false;
  3100. }
  3101. it = o.FindMember(member);
  3102. return it != o.MemberEnd();
  3103. #else
  3104. it = o.find(member);
  3105. return it != o.end();
  3106. #endif
  3107. }
  3108. void Erase(detail::json &o, detail::json_iterator &it) {
  3109. #ifdef TINYGLTF_USE_RAPIDJSON
  3110. o.EraseMember(it);
  3111. #else
  3112. o.erase(it);
  3113. #endif
  3114. }
  3115. bool IsEmpty(const detail::json &o) {
  3116. #ifdef TINYGLTF_USE_RAPIDJSON
  3117. return o.ObjectEmpty();
  3118. #else
  3119. return o.empty();
  3120. #endif
  3121. }
  3122. const detail::json &GetValue(detail::json_const_iterator &it) {
  3123. #ifdef TINYGLTF_USE_RAPIDJSON
  3124. return it->value;
  3125. #else
  3126. return it.value();
  3127. #endif
  3128. }
  3129. detail::json &GetValue(detail::json_iterator &it) {
  3130. #ifdef TINYGLTF_USE_RAPIDJSON
  3131. return it->value;
  3132. #else
  3133. return it.value();
  3134. #endif
  3135. }
  3136. std::string JsonToString(const detail::json &o, int spacing = -1) {
  3137. #ifdef TINYGLTF_USE_RAPIDJSON
  3138. using namespace rapidjson;
  3139. StringBuffer buffer;
  3140. if (spacing == -1) {
  3141. Writer<StringBuffer> writer(buffer);
  3142. // TODO: Better error handling.
  3143. // https://github.com/syoyo/tinygltf/issues/332
  3144. if (!o.Accept(writer)) {
  3145. return "tiny_gltf::JsonToString() failed rapidjson conversion";
  3146. }
  3147. } else {
  3148. PrettyWriter<StringBuffer> writer(buffer);
  3149. writer.SetIndent(' ', uint32_t(spacing));
  3150. if (!o.Accept(writer)) {
  3151. return "tiny_gltf::JsonToString() failed rapidjson conversion";
  3152. }
  3153. }
  3154. return buffer.GetString();
  3155. #else
  3156. return o.dump(spacing);
  3157. #endif
  3158. }
  3159. } // namespace detail
  3160. static bool ParseJsonAsValue(Value *ret, const detail::json &o) {
  3161. Value val{};
  3162. #ifdef TINYGLTF_USE_RAPIDJSON
  3163. using rapidjson::Type;
  3164. switch (o.GetType()) {
  3165. case Type::kObjectType: {
  3166. Value::Object value_object;
  3167. for (auto it = o.MemberBegin(); it != o.MemberEnd(); ++it) {
  3168. Value entry;
  3169. ParseJsonAsValue(&entry, it->value);
  3170. if (entry.Type() != NULL_TYPE)
  3171. value_object.emplace(detail::GetKey(it), std::move(entry));
  3172. }
  3173. if (value_object.size() > 0) val = Value(std::move(value_object));
  3174. } break;
  3175. case Type::kArrayType: {
  3176. Value::Array value_array;
  3177. value_array.reserve(o.Size());
  3178. for (auto it = o.Begin(); it != o.End(); ++it) {
  3179. Value entry;
  3180. ParseJsonAsValue(&entry, *it);
  3181. if (entry.Type() != NULL_TYPE)
  3182. value_array.emplace_back(std::move(entry));
  3183. }
  3184. if (value_array.size() > 0) val = Value(std::move(value_array));
  3185. } break;
  3186. case Type::kStringType:
  3187. val = Value(std::string(o.GetString()));
  3188. break;
  3189. case Type::kFalseType:
  3190. case Type::kTrueType:
  3191. val = Value(o.GetBool());
  3192. break;
  3193. case Type::kNumberType:
  3194. if (!o.IsDouble()) {
  3195. int i = 0;
  3196. detail::GetInt(o, i);
  3197. val = Value(i);
  3198. } else {
  3199. double d = 0.0;
  3200. detail::GetDouble(o, d);
  3201. val = Value(d);
  3202. }
  3203. break;
  3204. case Type::kNullType:
  3205. break;
  3206. // all types are covered, so no `case default`
  3207. }
  3208. #else
  3209. switch (o.type()) {
  3210. case detail::json::value_t::object: {
  3211. Value::Object value_object;
  3212. for (auto it = o.begin(); it != o.end(); it++) {
  3213. Value entry;
  3214. ParseJsonAsValue(&entry, it.value());
  3215. if (entry.Type() != NULL_TYPE)
  3216. value_object.emplace(it.key(), std::move(entry));
  3217. }
  3218. if (value_object.size() > 0) val = Value(std::move(value_object));
  3219. } break;
  3220. case detail::json::value_t::array: {
  3221. Value::Array value_array;
  3222. value_array.reserve(o.size());
  3223. for (auto it = o.begin(); it != o.end(); it++) {
  3224. Value entry;
  3225. ParseJsonAsValue(&entry, it.value());
  3226. if (entry.Type() != NULL_TYPE)
  3227. value_array.emplace_back(std::move(entry));
  3228. }
  3229. if (value_array.size() > 0) val = Value(std::move(value_array));
  3230. } break;
  3231. case detail::json::value_t::string:
  3232. val = Value(o.get<std::string>());
  3233. break;
  3234. case detail::json::value_t::boolean:
  3235. val = Value(o.get<bool>());
  3236. break;
  3237. case detail::json::value_t::number_integer:
  3238. case detail::json::value_t::number_unsigned:
  3239. val = Value(static_cast<int>(o.get<int64_t>()));
  3240. break;
  3241. case detail::json::value_t::number_float:
  3242. val = Value(o.get<double>());
  3243. break;
  3244. case detail::json::value_t::null:
  3245. case detail::json::value_t::discarded:
  3246. case detail::json::value_t::binary:
  3247. // default:
  3248. break;
  3249. }
  3250. #endif
  3251. const bool isNotNull = val.Type() != NULL_TYPE;
  3252. if (ret) *ret = std::move(val);
  3253. return isNotNull;
  3254. }
  3255. static bool ParseExtrasProperty(Value *ret, const detail::json &o) {
  3256. detail::json_const_iterator it;
  3257. if (!detail::FindMember(o, "extras", it)) {
  3258. return false;
  3259. }
  3260. return ParseJsonAsValue(ret, detail::GetValue(it));
  3261. }
  3262. static bool ParseBooleanProperty(bool *ret, std::string *err,
  3263. const detail::json &o,
  3264. const std::string &property,
  3265. const bool required,
  3266. const std::string &parent_node = "") {
  3267. detail::json_const_iterator it;
  3268. if (!detail::FindMember(o, property.c_str(), it)) {
  3269. if (required) {
  3270. if (err) {
  3271. (*err) += "'" + property + "' property is missing";
  3272. if (!parent_node.empty()) {
  3273. (*err) += " in " + parent_node;
  3274. }
  3275. (*err) += ".\n";
  3276. }
  3277. }
  3278. return false;
  3279. }
  3280. auto &value = detail::GetValue(it);
  3281. bool isBoolean;
  3282. bool boolValue = false;
  3283. #ifdef TINYGLTF_USE_RAPIDJSON
  3284. isBoolean = value.IsBool();
  3285. if (isBoolean) {
  3286. boolValue = value.GetBool();
  3287. }
  3288. #else
  3289. isBoolean = value.is_boolean();
  3290. if (isBoolean) {
  3291. boolValue = value.get<bool>();
  3292. }
  3293. #endif
  3294. if (!isBoolean) {
  3295. if (required) {
  3296. if (err) {
  3297. (*err) += "'" + property + "' property is not a bool type.\n";
  3298. }
  3299. }
  3300. return false;
  3301. }
  3302. if (ret) {
  3303. (*ret) = boolValue;
  3304. }
  3305. return true;
  3306. }
  3307. static bool ParseIntegerProperty(int *ret, std::string *err,
  3308. const detail::json &o,
  3309. const std::string &property,
  3310. const bool required,
  3311. const std::string &parent_node = "") {
  3312. detail::json_const_iterator it;
  3313. if (!detail::FindMember(o, property.c_str(), it)) {
  3314. if (required) {
  3315. if (err) {
  3316. (*err) += "'" + property + "' property is missing";
  3317. if (!parent_node.empty()) {
  3318. (*err) += " in " + parent_node;
  3319. }
  3320. (*err) += ".\n";
  3321. }
  3322. }
  3323. return false;
  3324. }
  3325. int intValue;
  3326. bool isInt = detail::GetInt(detail::GetValue(it), intValue);
  3327. if (!isInt) {
  3328. if (required) {
  3329. if (err) {
  3330. (*err) += "'" + property + "' property is not an integer type.\n";
  3331. }
  3332. }
  3333. return false;
  3334. }
  3335. if (ret) {
  3336. (*ret) = intValue;
  3337. }
  3338. return true;
  3339. }
  3340. static bool ParseUnsignedProperty(size_t *ret, std::string *err,
  3341. const detail::json &o,
  3342. const std::string &property,
  3343. const bool required,
  3344. const std::string &parent_node = "") {
  3345. detail::json_const_iterator it;
  3346. if (!detail::FindMember(o, property.c_str(), it)) {
  3347. if (required) {
  3348. if (err) {
  3349. (*err) += "'" + property + "' property is missing";
  3350. if (!parent_node.empty()) {
  3351. (*err) += " in " + parent_node;
  3352. }
  3353. (*err) += ".\n";
  3354. }
  3355. }
  3356. return false;
  3357. }
  3358. auto &value = detail::GetValue(it);
  3359. size_t uValue = 0;
  3360. bool isUValue;
  3361. #ifdef TINYGLTF_USE_RAPIDJSON
  3362. isUValue = false;
  3363. if (value.IsUint()) {
  3364. uValue = value.GetUint();
  3365. isUValue = true;
  3366. } else if (value.IsUint64()) {
  3367. uValue = value.GetUint64();
  3368. isUValue = true;
  3369. }
  3370. #else
  3371. isUValue = value.is_number_unsigned();
  3372. if (isUValue) {
  3373. uValue = value.get<size_t>();
  3374. }
  3375. #endif
  3376. if (!isUValue) {
  3377. if (required) {
  3378. if (err) {
  3379. (*err) += "'" + property + "' property is not a positive integer.\n";
  3380. }
  3381. }
  3382. return false;
  3383. }
  3384. if (ret) {
  3385. (*ret) = uValue;
  3386. }
  3387. return true;
  3388. }
  3389. static bool ParseNumberProperty(double *ret, std::string *err,
  3390. const detail::json &o,
  3391. const std::string &property,
  3392. const bool required,
  3393. const std::string &parent_node = "") {
  3394. detail::json_const_iterator it;
  3395. if (!detail::FindMember(o, property.c_str(), it)) {
  3396. if (required) {
  3397. if (err) {
  3398. (*err) += "'" + property + "' property is missing";
  3399. if (!parent_node.empty()) {
  3400. (*err) += " in " + parent_node;
  3401. }
  3402. (*err) += ".\n";
  3403. }
  3404. }
  3405. return false;
  3406. }
  3407. double numberValue;
  3408. bool isNumber = detail::GetNumber(detail::GetValue(it), numberValue);
  3409. if (!isNumber) {
  3410. if (required) {
  3411. if (err) {
  3412. (*err) += "'" + property + "' property is not a number type.\n";
  3413. }
  3414. }
  3415. return false;
  3416. }
  3417. if (ret) {
  3418. (*ret) = numberValue;
  3419. }
  3420. return true;
  3421. }
  3422. static bool ParseNumberArrayProperty(std::vector<double> *ret, std::string *err,
  3423. const detail::json &o,
  3424. const std::string &property, bool required,
  3425. const std::string &parent_node = "") {
  3426. detail::json_const_iterator it;
  3427. if (!detail::FindMember(o, property.c_str(), it)) {
  3428. if (required) {
  3429. if (err) {
  3430. (*err) += "'" + property + "' property is missing";
  3431. if (!parent_node.empty()) {
  3432. (*err) += " in " + parent_node;
  3433. }
  3434. (*err) += ".\n";
  3435. }
  3436. }
  3437. return false;
  3438. }
  3439. if (!detail::IsArray(detail::GetValue(it))) {
  3440. if (required) {
  3441. if (err) {
  3442. (*err) += "'" + property + "' property is not an array";
  3443. if (!parent_node.empty()) {
  3444. (*err) += " in " + parent_node;
  3445. }
  3446. (*err) += ".\n";
  3447. }
  3448. }
  3449. return false;
  3450. }
  3451. ret->clear();
  3452. auto end = detail::ArrayEnd(detail::GetValue(it));
  3453. for (auto i = detail::ArrayBegin(detail::GetValue(it)); i != end; ++i) {
  3454. double numberValue;
  3455. const bool isNumber = detail::GetNumber(*i, numberValue);
  3456. if (!isNumber) {
  3457. if (required) {
  3458. if (err) {
  3459. (*err) += "'" + property + "' property is not a number.\n";
  3460. if (!parent_node.empty()) {
  3461. (*err) += " in " + parent_node;
  3462. }
  3463. (*err) += ".\n";
  3464. }
  3465. }
  3466. return false;
  3467. }
  3468. ret->push_back(numberValue);
  3469. }
  3470. return true;
  3471. }
  3472. static bool ParseIntegerArrayProperty(std::vector<int> *ret, std::string *err,
  3473. const detail::json &o,
  3474. const std::string &property,
  3475. bool required,
  3476. const std::string &parent_node = "") {
  3477. detail::json_const_iterator it;
  3478. if (!detail::FindMember(o, property.c_str(), it)) {
  3479. if (required) {
  3480. if (err) {
  3481. (*err) += "'" + property + "' property is missing";
  3482. if (!parent_node.empty()) {
  3483. (*err) += " in " + parent_node;
  3484. }
  3485. (*err) += ".\n";
  3486. }
  3487. }
  3488. return false;
  3489. }
  3490. if (!detail::IsArray(detail::GetValue(it))) {
  3491. if (required) {
  3492. if (err) {
  3493. (*err) += "'" + property + "' property is not an array";
  3494. if (!parent_node.empty()) {
  3495. (*err) += " in " + parent_node;
  3496. }
  3497. (*err) += ".\n";
  3498. }
  3499. }
  3500. return false;
  3501. }
  3502. ret->clear();
  3503. auto end = detail::ArrayEnd(detail::GetValue(it));
  3504. for (auto i = detail::ArrayBegin(detail::GetValue(it)); i != end; ++i) {
  3505. int numberValue;
  3506. bool isNumber = detail::GetInt(*i, numberValue);
  3507. if (!isNumber) {
  3508. if (required) {
  3509. if (err) {
  3510. (*err) += "'" + property + "' property is not an integer type.\n";
  3511. if (!parent_node.empty()) {
  3512. (*err) += " in " + parent_node;
  3513. }
  3514. (*err) += ".\n";
  3515. }
  3516. }
  3517. return false;
  3518. }
  3519. ret->push_back(numberValue);
  3520. }
  3521. return true;
  3522. }
  3523. static bool ParseStringProperty(
  3524. std::string *ret, std::string *err, const detail::json &o,
  3525. const std::string &property, bool required,
  3526. const std::string &parent_node = std::string()) {
  3527. detail::json_const_iterator it;
  3528. if (!detail::FindMember(o, property.c_str(), it)) {
  3529. if (required) {
  3530. if (err) {
  3531. (*err) += "'" + property + "' property is missing";
  3532. if (parent_node.empty()) {
  3533. (*err) += ".\n";
  3534. } else {
  3535. (*err) += " in `" + parent_node + "'.\n";
  3536. }
  3537. }
  3538. }
  3539. return false;
  3540. }
  3541. std::string strValue;
  3542. if (!detail::GetString(detail::GetValue(it), strValue)) {
  3543. if (required) {
  3544. if (err) {
  3545. (*err) += "'" + property + "' property is not a string type.\n";
  3546. }
  3547. }
  3548. return false;
  3549. }
  3550. if (ret) {
  3551. (*ret) = std::move(strValue);
  3552. }
  3553. return true;
  3554. }
  3555. static bool ParseStringIntegerProperty(std::map<std::string, int> *ret,
  3556. std::string *err, const detail::json &o,
  3557. const std::string &property,
  3558. bool required,
  3559. const std::string &parent = "") {
  3560. detail::json_const_iterator it;
  3561. if (!detail::FindMember(o, property.c_str(), it)) {
  3562. if (required) {
  3563. if (err) {
  3564. if (!parent.empty()) {
  3565. (*err) +=
  3566. "'" + property + "' property is missing in " + parent + ".\n";
  3567. } else {
  3568. (*err) += "'" + property + "' property is missing.\n";
  3569. }
  3570. }
  3571. }
  3572. return false;
  3573. }
  3574. const detail::json &dict = detail::GetValue(it);
  3575. // Make sure we are dealing with an object / dictionary.
  3576. if (!detail::IsObject(dict)) {
  3577. if (required) {
  3578. if (err) {
  3579. (*err) += "'" + property + "' property is not an object.\n";
  3580. }
  3581. }
  3582. return false;
  3583. }
  3584. ret->clear();
  3585. detail::json_const_iterator dictIt(detail::ObjectBegin(dict));
  3586. detail::json_const_iterator dictItEnd(detail::ObjectEnd(dict));
  3587. for (; dictIt != dictItEnd; ++dictIt) {
  3588. int intVal;
  3589. if (!detail::GetInt(detail::GetValue(dictIt), intVal)) {
  3590. if (required) {
  3591. if (err) {
  3592. (*err) += "'" + property + "' value is not an integer type.\n";
  3593. }
  3594. }
  3595. return false;
  3596. }
  3597. // Insert into the list.
  3598. (*ret)[detail::GetKey(dictIt)] = intVal;
  3599. }
  3600. return true;
  3601. }
  3602. static bool ParseJSONProperty(std::map<std::string, double> *ret,
  3603. std::string *err, const detail::json &o,
  3604. const std::string &property, bool required) {
  3605. detail::json_const_iterator it;
  3606. if (!detail::FindMember(o, property.c_str(), it)) {
  3607. if (required) {
  3608. if (err) {
  3609. (*err) += "'" + property + "' property is missing. \n'";
  3610. }
  3611. }
  3612. return false;
  3613. }
  3614. const detail::json &obj = detail::GetValue(it);
  3615. if (!detail::IsObject(obj)) {
  3616. if (required) {
  3617. if (err) {
  3618. (*err) += "'" + property + "' property is not a JSON object.\n";
  3619. }
  3620. }
  3621. return false;
  3622. }
  3623. ret->clear();
  3624. detail::json_const_iterator it2(detail::ObjectBegin(obj));
  3625. detail::json_const_iterator itEnd(detail::ObjectEnd(obj));
  3626. for (; it2 != itEnd; ++it2) {
  3627. double numVal;
  3628. if (detail::GetNumber(detail::GetValue(it2), numVal))
  3629. ret->emplace(std::string(detail::GetKey(it2)), numVal);
  3630. }
  3631. return true;
  3632. }
  3633. static bool ParseParameterProperty(Parameter *param, std::string *err,
  3634. const detail::json &o,
  3635. const std::string &prop, bool required) {
  3636. // A parameter value can either be a string or an array of either a boolean or
  3637. // a number. Booleans of any kind aren't supported here. Granted, it
  3638. // complicates the Parameter structure and breaks it semantically in the sense
  3639. // that the client probably works off the assumption that if the string is
  3640. // empty the vector is used, etc. Would a tagged union work?
  3641. if (ParseStringProperty(&param->string_value, err, o, prop, false)) {
  3642. // Found string property.
  3643. return true;
  3644. } else if (ParseNumberArrayProperty(&param->number_array, err, o, prop,
  3645. false)) {
  3646. // Found a number array.
  3647. return true;
  3648. } else if (ParseNumberProperty(&param->number_value, err, o, prop, false)) {
  3649. param->has_number_value = true;
  3650. return true;
  3651. } else if (ParseJSONProperty(&param->json_double_value, err, o, prop,
  3652. false)) {
  3653. return true;
  3654. } else if (ParseBooleanProperty(&param->bool_value, err, o, prop, false)) {
  3655. return true;
  3656. } else {
  3657. if (required) {
  3658. if (err) {
  3659. (*err) += "parameter must be a string or number / number array.\n";
  3660. }
  3661. }
  3662. return false;
  3663. }
  3664. }
  3665. static bool ParseExtensionsProperty(ExtensionMap *ret, std::string *err,
  3666. const detail::json &o) {
  3667. (void)err;
  3668. detail::json_const_iterator it;
  3669. if (!detail::FindMember(o, "extensions", it)) {
  3670. return false;
  3671. }
  3672. auto &obj = detail::GetValue(it);
  3673. if (!detail::IsObject(obj)) {
  3674. return false;
  3675. }
  3676. ExtensionMap extensions;
  3677. detail::json_const_iterator extIt =
  3678. detail::ObjectBegin(obj); // it.value().begin();
  3679. detail::json_const_iterator extEnd = detail::ObjectEnd(obj);
  3680. for (; extIt != extEnd; ++extIt) {
  3681. auto &itObj = detail::GetValue(extIt);
  3682. if (!detail::IsObject(itObj)) continue;
  3683. std::string key(detail::GetKey(extIt));
  3684. if (!ParseJsonAsValue(&extensions[key], itObj)) {
  3685. if (!key.empty()) {
  3686. // create empty object so that an extension object is still of type
  3687. // object
  3688. extensions[key] = Value{Value::Object{}};
  3689. }
  3690. }
  3691. }
  3692. if (ret) {
  3693. (*ret) = std::move(extensions);
  3694. }
  3695. return true;
  3696. }
  3697. template <typename GltfType>
  3698. static bool ParseExtrasAndExtensions(GltfType *target, std::string *err,
  3699. const detail::json &o,
  3700. bool store_json_strings) {
  3701. ParseExtensionsProperty(&target->extensions, err, o);
  3702. ParseExtrasProperty(&target->extras, o);
  3703. if (store_json_strings) {
  3704. {
  3705. detail::json_const_iterator it;
  3706. if (detail::FindMember(o, "extensions", it)) {
  3707. target->extensions_json_string =
  3708. detail::JsonToString(detail::GetValue(it));
  3709. }
  3710. }
  3711. {
  3712. detail::json_const_iterator it;
  3713. if (detail::FindMember(o, "extras", it)) {
  3714. target->extras_json_string = detail::JsonToString(detail::GetValue(it));
  3715. }
  3716. }
  3717. }
  3718. return true;
  3719. }
  3720. static bool ParseAsset(Asset *asset, std::string *err, const detail::json &o,
  3721. bool store_original_json_for_extras_and_extensions) {
  3722. ParseStringProperty(&asset->version, err, o, "version", true, "Asset");
  3723. ParseStringProperty(&asset->generator, err, o, "generator", false, "Asset");
  3724. ParseStringProperty(&asset->minVersion, err, o, "minVersion", false, "Asset");
  3725. ParseStringProperty(&asset->copyright, err, o, "copyright", false, "Asset");
  3726. ParseExtrasAndExtensions(asset, err, o,
  3727. store_original_json_for_extras_and_extensions);
  3728. return true;
  3729. }
  3730. static bool ParseImage(Image *image, const int image_idx, std::string *err,
  3731. std::string *warn, const detail::json &o,
  3732. bool store_original_json_for_extras_and_extensions,
  3733. const std::string &basedir, const size_t max_file_size,
  3734. FsCallbacks *fs, const URICallbacks *uri_cb,
  3735. const LoadImageDataFunction& LoadImageData = nullptr,
  3736. void *load_image_user_data = nullptr) {
  3737. // A glTF image must either reference a bufferView or an image uri
  3738. // schema says oneOf [`bufferView`, `uri`]
  3739. // TODO(syoyo): Check the type of each parameters.
  3740. detail::json_const_iterator it;
  3741. bool hasBufferView = detail::FindMember(o, "bufferView", it);
  3742. bool hasURI = detail::FindMember(o, "uri", it);
  3743. ParseStringProperty(&image->name, err, o, "name", false);
  3744. if (hasBufferView && hasURI) {
  3745. // Should not both defined.
  3746. if (err) {
  3747. (*err) +=
  3748. "Only one of `bufferView` or `uri` should be defined, but both are "
  3749. "defined for image[" +
  3750. std::to_string(image_idx) + "] name = \"" + image->name + "\"\n";
  3751. }
  3752. return false;
  3753. }
  3754. if (!hasBufferView && !hasURI) {
  3755. if (err) {
  3756. (*err) += "Neither required `bufferView` nor `uri` defined for image[" +
  3757. std::to_string(image_idx) + "] name = \"" + image->name +
  3758. "\"\n";
  3759. }
  3760. return false;
  3761. }
  3762. ParseExtrasAndExtensions(image, err, o,
  3763. store_original_json_for_extras_and_extensions);
  3764. if (hasBufferView) {
  3765. int bufferView = -1;
  3766. if (!ParseIntegerProperty(&bufferView, err, o, "bufferView", true)) {
  3767. if (err) {
  3768. (*err) += "Failed to parse `bufferView` for image[" +
  3769. std::to_string(image_idx) + "] name = \"" + image->name +
  3770. "\"\n";
  3771. }
  3772. return false;
  3773. }
  3774. std::string mime_type;
  3775. ParseStringProperty(&mime_type, err, o, "mimeType", false);
  3776. int width = 0;
  3777. ParseIntegerProperty(&width, err, o, "width", false);
  3778. int height = 0;
  3779. ParseIntegerProperty(&height, err, o, "height", false);
  3780. // Just only save some information here. Loading actual image data from
  3781. // bufferView is done after this `ParseImage` function.
  3782. image->bufferView = bufferView;
  3783. image->mimeType = mime_type;
  3784. image->width = width;
  3785. image->height = height;
  3786. return true;
  3787. }
  3788. // Parse URI & Load image data.
  3789. std::string uri;
  3790. std::string tmp_err;
  3791. if (!ParseStringProperty(&uri, &tmp_err, o, "uri", true)) {
  3792. if (err) {
  3793. (*err) += "Failed to parse `uri` for image[" + std::to_string(image_idx) +
  3794. "] name = \"" + image->name + "\".\n";
  3795. }
  3796. return false;
  3797. }
  3798. std::vector<unsigned char> img;
  3799. if (IsDataURI(uri)) {
  3800. if (!DecodeDataURI(&img, image->mimeType, uri, 0, false)) {
  3801. if (err) {
  3802. (*err) += "Failed to decode 'uri' for image[" +
  3803. std::to_string(image_idx) + "] name = \"" + image->name +
  3804. "\"\n";
  3805. }
  3806. return false;
  3807. }
  3808. } else {
  3809. // Assume external file
  3810. // Keep texture path (for textures that cannot be decoded)
  3811. image->uri = uri;
  3812. #ifdef TINYGLTF_NO_EXTERNAL_IMAGE
  3813. return true;
  3814. #else
  3815. std::string decoded_uri;
  3816. if (!uri_cb->decode(uri, &decoded_uri, uri_cb->user_data)) {
  3817. if (warn) {
  3818. (*warn) += "Failed to decode 'uri' for image[" +
  3819. std::to_string(image_idx) + "] name = \"" + image->name +
  3820. "\"\n";
  3821. }
  3822. // Image loading failure is not critical to overall gltf loading.
  3823. return true;
  3824. }
  3825. if (!LoadExternalFile(&img, err, warn, decoded_uri, basedir,
  3826. /* required */ false, /* required bytes */ 0,
  3827. /* checksize */ false,
  3828. /* max file size */ max_file_size, fs)) {
  3829. if (warn) {
  3830. (*warn) += "Failed to load external 'uri' for image[" +
  3831. std::to_string(image_idx) + "] name = \"" + decoded_uri +
  3832. "\"\n";
  3833. }
  3834. // If the image cannot be loaded, keep uri as image->uri.
  3835. return true;
  3836. }
  3837. if (img.empty()) {
  3838. if (warn) {
  3839. (*warn) += "Image data is empty for image[" +
  3840. std::to_string(image_idx) + "] name = \"" + image->name +
  3841. "\" \n";
  3842. }
  3843. return false;
  3844. }
  3845. #endif
  3846. }
  3847. if (LoadImageData == nullptr) {
  3848. if (err) {
  3849. (*err) += "No LoadImageData callback specified.\n";
  3850. }
  3851. return false;
  3852. }
  3853. return LoadImageData(image, image_idx, err, warn, 0, 0, &img.at(0),
  3854. static_cast<int>(img.size()), load_image_user_data);
  3855. }
  3856. static bool ParseTexture(Texture *texture, std::string *err,
  3857. const detail::json &o,
  3858. bool store_original_json_for_extras_and_extensions,
  3859. const std::string &basedir) {
  3860. (void)basedir;
  3861. int sampler = -1;
  3862. int source = -1;
  3863. ParseIntegerProperty(&sampler, err, o, "sampler", false);
  3864. ParseIntegerProperty(&source, err, o, "source", false);
  3865. texture->sampler = sampler;
  3866. texture->source = source;
  3867. ParseExtrasAndExtensions(texture, err, o,
  3868. store_original_json_for_extras_and_extensions);
  3869. ParseStringProperty(&texture->name, err, o, "name", false);
  3870. return true;
  3871. }
  3872. static bool ParseTextureInfo(
  3873. TextureInfo *texinfo, std::string *err, const detail::json &o,
  3874. bool store_original_json_for_extras_and_extensions) {
  3875. if (texinfo == nullptr) {
  3876. return false;
  3877. }
  3878. if (!ParseIntegerProperty(&texinfo->index, err, o, "index",
  3879. /* required */ true, "TextureInfo")) {
  3880. return false;
  3881. }
  3882. ParseIntegerProperty(&texinfo->texCoord, err, o, "texCoord", false);
  3883. ParseExtrasAndExtensions(texinfo, err, o,
  3884. store_original_json_for_extras_and_extensions);
  3885. return true;
  3886. }
  3887. static bool ParseNormalTextureInfo(
  3888. NormalTextureInfo *texinfo, std::string *err, const detail::json &o,
  3889. bool store_original_json_for_extras_and_extensions) {
  3890. if (texinfo == nullptr) {
  3891. return false;
  3892. }
  3893. if (!ParseIntegerProperty(&texinfo->index, err, o, "index",
  3894. /* required */ true, "NormalTextureInfo")) {
  3895. return false;
  3896. }
  3897. ParseIntegerProperty(&texinfo->texCoord, err, o, "texCoord", false);
  3898. ParseNumberProperty(&texinfo->scale, err, o, "scale", false);
  3899. ParseExtrasAndExtensions(texinfo, err, o,
  3900. store_original_json_for_extras_and_extensions);
  3901. return true;
  3902. }
  3903. static bool ParseOcclusionTextureInfo(
  3904. OcclusionTextureInfo *texinfo, std::string *err, const detail::json &o,
  3905. bool store_original_json_for_extras_and_extensions) {
  3906. if (texinfo == nullptr) {
  3907. return false;
  3908. }
  3909. if (!ParseIntegerProperty(&texinfo->index, err, o, "index",
  3910. /* required */ true, "NormalTextureInfo")) {
  3911. return false;
  3912. }
  3913. ParseIntegerProperty(&texinfo->texCoord, err, o, "texCoord", false);
  3914. ParseNumberProperty(&texinfo->strength, err, o, "strength", false);
  3915. ParseExtrasAndExtensions(texinfo, err, o,
  3916. store_original_json_for_extras_and_extensions);
  3917. return true;
  3918. }
  3919. static bool ParseBuffer(Buffer *buffer, std::string *err, const detail::json &o,
  3920. bool store_original_json_for_extras_and_extensions,
  3921. FsCallbacks *fs, const URICallbacks *uri_cb,
  3922. const std::string &basedir,
  3923. const size_t max_buffer_size, bool is_binary = false,
  3924. const unsigned char *bin_data = nullptr,
  3925. size_t bin_size = 0) {
  3926. size_t byteLength;
  3927. if (!ParseUnsignedProperty(&byteLength, err, o, "byteLength", true,
  3928. "Buffer")) {
  3929. return false;
  3930. }
  3931. // In glTF 2.0, uri is not mandatory anymore
  3932. buffer->uri.clear();
  3933. ParseStringProperty(&buffer->uri, err, o, "uri", false, "Buffer");
  3934. // having an empty uri for a non embedded image should not be valid
  3935. if (!is_binary && buffer->uri.empty()) {
  3936. if (err) {
  3937. (*err) += "'uri' is missing from non binary glTF file buffer.\n";
  3938. }
  3939. }
  3940. detail::json_const_iterator type;
  3941. if (detail::FindMember(o, "type", type)) {
  3942. std::string typeStr;
  3943. if (detail::GetString(detail::GetValue(type), typeStr)) {
  3944. if (typeStr.compare("arraybuffer") == 0) {
  3945. // buffer.type = "arraybuffer";
  3946. }
  3947. }
  3948. }
  3949. if (is_binary) {
  3950. // Still binary glTF accepts external dataURI.
  3951. if (!buffer->uri.empty()) {
  3952. // First try embedded data URI.
  3953. if (IsDataURI(buffer->uri)) {
  3954. std::string mime_type;
  3955. if (!DecodeDataURI(&buffer->data, mime_type, buffer->uri, byteLength,
  3956. true)) {
  3957. if (err) {
  3958. (*err) +=
  3959. "Failed to decode 'uri' : " + buffer->uri + " in Buffer\n";
  3960. }
  3961. return false;
  3962. }
  3963. } else {
  3964. // External .bin file.
  3965. std::string decoded_uri;
  3966. if (!uri_cb->decode(buffer->uri, &decoded_uri, uri_cb->user_data)) {
  3967. return false;
  3968. }
  3969. if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr,
  3970. decoded_uri, basedir, /* required */ true,
  3971. byteLength, /* checkSize */ true,
  3972. /* max_file_size */ max_buffer_size, fs)) {
  3973. return false;
  3974. }
  3975. }
  3976. } else {
  3977. // load data from (embedded) binary data
  3978. if ((bin_size == 0) || (bin_data == nullptr)) {
  3979. if (err) {
  3980. (*err) +=
  3981. "Invalid binary data in `Buffer', or GLB with empty BIN chunk.\n";
  3982. }
  3983. return false;
  3984. }
  3985. if (byteLength > bin_size) {
  3986. if (err) {
  3987. std::stringstream ss;
  3988. ss << "Invalid `byteLength'. Must be equal or less than binary size: "
  3989. "`byteLength' = "
  3990. << byteLength << ", binary size = " << bin_size << std::endl;
  3991. (*err) += ss.str();
  3992. }
  3993. return false;
  3994. }
  3995. // Read buffer data
  3996. buffer->data.resize(static_cast<size_t>(byteLength));
  3997. memcpy(&(buffer->data.at(0)), bin_data, static_cast<size_t>(byteLength));
  3998. }
  3999. } else {
  4000. if (IsDataURI(buffer->uri)) {
  4001. std::string mime_type;
  4002. if (!DecodeDataURI(&buffer->data, mime_type, buffer->uri, byteLength,
  4003. true)) {
  4004. if (err) {
  4005. (*err) += "Failed to decode 'uri' : " + buffer->uri + " in Buffer\n";
  4006. }
  4007. return false;
  4008. }
  4009. } else {
  4010. // Assume external .bin file.
  4011. std::string decoded_uri;
  4012. if (!uri_cb->decode(buffer->uri, &decoded_uri, uri_cb->user_data)) {
  4013. return false;
  4014. }
  4015. if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr, decoded_uri,
  4016. basedir, /* required */ true, byteLength,
  4017. /* checkSize */ true,
  4018. /* max file size */ max_buffer_size, fs)) {
  4019. return false;
  4020. }
  4021. }
  4022. }
  4023. ParseStringProperty(&buffer->name, err, o, "name", false);
  4024. ParseExtrasAndExtensions(buffer, err, o,
  4025. store_original_json_for_extras_and_extensions);
  4026. return true;
  4027. }
  4028. static bool ParseBufferView(
  4029. BufferView *bufferView, std::string *err, const detail::json &o,
  4030. bool store_original_json_for_extras_and_extensions) {
  4031. int buffer = -1;
  4032. if (!ParseIntegerProperty(&buffer, err, o, "buffer", true, "BufferView")) {
  4033. return false;
  4034. }
  4035. size_t byteOffset = 0;
  4036. ParseUnsignedProperty(&byteOffset, err, o, "byteOffset", false);
  4037. size_t byteLength = 1;
  4038. if (!ParseUnsignedProperty(&byteLength, err, o, "byteLength", true,
  4039. "BufferView")) {
  4040. return false;
  4041. }
  4042. size_t byteStride = 0;
  4043. if (!ParseUnsignedProperty(&byteStride, err, o, "byteStride", false)) {
  4044. // Spec says: When byteStride of referenced bufferView is not defined, it
  4045. // means that accessor elements are tightly packed, i.e., effective stride
  4046. // equals the size of the element.
  4047. // We cannot determine the actual byteStride until Accessor are parsed, thus
  4048. // set 0(= tightly packed) here(as done in OpenGL's VertexAttribPoiner)
  4049. byteStride = 0;
  4050. }
  4051. if ((byteStride > 252) || ((byteStride % 4) != 0)) {
  4052. if (err) {
  4053. std::stringstream ss;
  4054. ss << "Invalid `byteStride' value. `byteStride' must be the multiple of "
  4055. "4 : "
  4056. << byteStride << std::endl;
  4057. (*err) += ss.str();
  4058. }
  4059. return false;
  4060. }
  4061. int target = 0;
  4062. ParseIntegerProperty(&target, err, o, "target", false);
  4063. if ((target == TINYGLTF_TARGET_ARRAY_BUFFER) ||
  4064. (target == TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER)) {
  4065. // OK
  4066. } else {
  4067. target = 0;
  4068. }
  4069. bufferView->target = target;
  4070. ParseStringProperty(&bufferView->name, err, o, "name", false);
  4071. ParseExtrasAndExtensions(bufferView, err, o,
  4072. store_original_json_for_extras_and_extensions);
  4073. bufferView->buffer = buffer;
  4074. bufferView->byteOffset = byteOffset;
  4075. bufferView->byteLength = byteLength;
  4076. bufferView->byteStride = byteStride;
  4077. return true;
  4078. }
  4079. static bool ParseSparseAccessor(
  4080. Accessor::Sparse *sparse, std::string *err, const detail::json &o,
  4081. bool store_original_json_for_extras_and_extensions) {
  4082. sparse->isSparse = true;
  4083. int count = 0;
  4084. if (!ParseIntegerProperty(&count, err, o, "count", true, "SparseAccessor")) {
  4085. return false;
  4086. }
  4087. ParseExtrasAndExtensions(sparse, err, o,
  4088. store_original_json_for_extras_and_extensions);
  4089. detail::json_const_iterator indices_iterator;
  4090. detail::json_const_iterator values_iterator;
  4091. if (!detail::FindMember(o, "indices", indices_iterator)) {
  4092. (*err) = "the sparse object of this accessor doesn't have indices";
  4093. return false;
  4094. }
  4095. if (!detail::FindMember(o, "values", values_iterator)) {
  4096. (*err) = "the sparse object of this accessor doesn't have values";
  4097. return false;
  4098. }
  4099. const detail::json &indices_obj = detail::GetValue(indices_iterator);
  4100. const detail::json &values_obj = detail::GetValue(values_iterator);
  4101. int indices_buffer_view = 0, component_type = 0;
  4102. size_t indices_byte_offset = 0;
  4103. if (!ParseIntegerProperty(&indices_buffer_view, err, indices_obj,
  4104. "bufferView", true, "SparseAccessor")) {
  4105. return false;
  4106. }
  4107. ParseUnsignedProperty(&indices_byte_offset, err, indices_obj, "byteOffset",
  4108. false);
  4109. if (!ParseIntegerProperty(&component_type, err, indices_obj, "componentType",
  4110. true, "SparseAccessor")) {
  4111. return false;
  4112. }
  4113. int values_buffer_view = 0;
  4114. size_t values_byte_offset = 0;
  4115. if (!ParseIntegerProperty(&values_buffer_view, err, values_obj, "bufferView",
  4116. true, "SparseAccessor")) {
  4117. return false;
  4118. }
  4119. ParseUnsignedProperty(&values_byte_offset, err, values_obj, "byteOffset",
  4120. false);
  4121. sparse->count = count;
  4122. sparse->indices.bufferView = indices_buffer_view;
  4123. sparse->indices.byteOffset = indices_byte_offset;
  4124. sparse->indices.componentType = component_type;
  4125. ParseExtrasAndExtensions(&sparse->indices, err, indices_obj,
  4126. store_original_json_for_extras_and_extensions);
  4127. sparse->values.bufferView = values_buffer_view;
  4128. sparse->values.byteOffset = values_byte_offset;
  4129. ParseExtrasAndExtensions(&sparse->values, err, values_obj,
  4130. store_original_json_for_extras_and_extensions);
  4131. return true;
  4132. }
  4133. static bool ParseAccessor(Accessor *accessor, std::string *err,
  4134. const detail::json &o,
  4135. bool store_original_json_for_extras_and_extensions) {
  4136. int bufferView = -1;
  4137. ParseIntegerProperty(&bufferView, err, o, "bufferView", false, "Accessor");
  4138. size_t byteOffset = 0;
  4139. ParseUnsignedProperty(&byteOffset, err, o, "byteOffset", false, "Accessor");
  4140. bool normalized = false;
  4141. ParseBooleanProperty(&normalized, err, o, "normalized", false, "Accessor");
  4142. size_t componentType = 0;
  4143. if (!ParseUnsignedProperty(&componentType, err, o, "componentType", true,
  4144. "Accessor")) {
  4145. return false;
  4146. }
  4147. size_t count = 0;
  4148. if (!ParseUnsignedProperty(&count, err, o, "count", true, "Accessor")) {
  4149. return false;
  4150. }
  4151. std::string type;
  4152. if (!ParseStringProperty(&type, err, o, "type", true, "Accessor")) {
  4153. return false;
  4154. }
  4155. if (type.compare("SCALAR") == 0) {
  4156. accessor->type = TINYGLTF_TYPE_SCALAR;
  4157. } else if (type.compare("VEC2") == 0) {
  4158. accessor->type = TINYGLTF_TYPE_VEC2;
  4159. } else if (type.compare("VEC3") == 0) {
  4160. accessor->type = TINYGLTF_TYPE_VEC3;
  4161. } else if (type.compare("VEC4") == 0) {
  4162. accessor->type = TINYGLTF_TYPE_VEC4;
  4163. } else if (type.compare("MAT2") == 0) {
  4164. accessor->type = TINYGLTF_TYPE_MAT2;
  4165. } else if (type.compare("MAT3") == 0) {
  4166. accessor->type = TINYGLTF_TYPE_MAT3;
  4167. } else if (type.compare("MAT4") == 0) {
  4168. accessor->type = TINYGLTF_TYPE_MAT4;
  4169. } else {
  4170. std::stringstream ss;
  4171. ss << "Unsupported `type` for accessor object. Got \"" << type << "\"\n";
  4172. if (err) {
  4173. (*err) += ss.str();
  4174. }
  4175. return false;
  4176. }
  4177. ParseStringProperty(&accessor->name, err, o, "name", false);
  4178. accessor->minValues.clear();
  4179. accessor->maxValues.clear();
  4180. ParseNumberArrayProperty(&accessor->minValues, err, o, "min", false,
  4181. "Accessor");
  4182. ParseNumberArrayProperty(&accessor->maxValues, err, o, "max", false,
  4183. "Accessor");
  4184. accessor->count = count;
  4185. accessor->bufferView = bufferView;
  4186. accessor->byteOffset = byteOffset;
  4187. accessor->normalized = normalized;
  4188. {
  4189. if (componentType >= TINYGLTF_COMPONENT_TYPE_BYTE &&
  4190. componentType <= TINYGLTF_COMPONENT_TYPE_DOUBLE) {
  4191. // OK
  4192. accessor->componentType = int(componentType);
  4193. } else {
  4194. std::stringstream ss;
  4195. ss << "Invalid `componentType` in accessor. Got " << componentType
  4196. << "\n";
  4197. if (err) {
  4198. (*err) += ss.str();
  4199. }
  4200. return false;
  4201. }
  4202. }
  4203. ParseExtrasAndExtensions(accessor, err, o,
  4204. store_original_json_for_extras_and_extensions);
  4205. // check if accessor has a "sparse" object:
  4206. detail::json_const_iterator iterator;
  4207. if (detail::FindMember(o, "sparse", iterator)) {
  4208. // here this accessor has a "sparse" subobject
  4209. return ParseSparseAccessor(&accessor->sparse, err,
  4210. detail::GetValue(iterator),
  4211. store_original_json_for_extras_and_extensions);
  4212. }
  4213. return true;
  4214. }
  4215. #ifdef TINYGLTF_ENABLE_DRACO
  4216. static void DecodeIndexBuffer(draco::Mesh *mesh, size_t componentSize,
  4217. std::vector<uint8_t> &outBuffer) {
  4218. if (componentSize == 4) {
  4219. assert(sizeof(mesh->face(draco::FaceIndex(0))[0]) == componentSize);
  4220. memcpy(outBuffer.data(), &mesh->face(draco::FaceIndex(0))[0],
  4221. outBuffer.size());
  4222. } else {
  4223. size_t faceStride = componentSize * 3;
  4224. for (draco::FaceIndex f(0); f < mesh->num_faces(); ++f) {
  4225. const draco::Mesh::Face &face = mesh->face(f);
  4226. if (componentSize == 2) {
  4227. uint16_t indices[3] = {(uint16_t)face[0].value(),
  4228. (uint16_t)face[1].value(),
  4229. (uint16_t)face[2].value()};
  4230. memcpy(outBuffer.data() + f.value() * faceStride, &indices[0],
  4231. faceStride);
  4232. } else {
  4233. uint8_t indices[3] = {(uint8_t)face[0].value(),
  4234. (uint8_t)face[1].value(),
  4235. (uint8_t)face[2].value()};
  4236. memcpy(outBuffer.data() + f.value() * faceStride, &indices[0],
  4237. faceStride);
  4238. }
  4239. }
  4240. }
  4241. }
  4242. template <typename T>
  4243. static bool GetAttributeForAllPoints(draco::Mesh *mesh,
  4244. const draco::PointAttribute *pAttribute,
  4245. std::vector<uint8_t> &outBuffer) {
  4246. size_t byteOffset = 0;
  4247. T values[4] = {0, 0, 0, 0};
  4248. for (draco::PointIndex i(0); i < mesh->num_points(); ++i) {
  4249. const draco::AttributeValueIndex val_index = pAttribute->mapped_index(i);
  4250. if (!pAttribute->ConvertValue<T>(val_index, pAttribute->num_components(),
  4251. values))
  4252. return false;
  4253. memcpy(outBuffer.data() + byteOffset, &values[0],
  4254. sizeof(T) * pAttribute->num_components());
  4255. byteOffset += sizeof(T) * pAttribute->num_components();
  4256. }
  4257. return true;
  4258. }
  4259. static bool GetAttributeForAllPoints(uint32_t componentType, draco::Mesh *mesh,
  4260. const draco::PointAttribute *pAttribute,
  4261. std::vector<uint8_t> &outBuffer) {
  4262. bool decodeResult = false;
  4263. switch (componentType) {
  4264. case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
  4265. decodeResult =
  4266. GetAttributeForAllPoints<uint8_t>(mesh, pAttribute, outBuffer);
  4267. break;
  4268. case TINYGLTF_COMPONENT_TYPE_BYTE:
  4269. decodeResult =
  4270. GetAttributeForAllPoints<int8_t>(mesh, pAttribute, outBuffer);
  4271. break;
  4272. case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
  4273. decodeResult =
  4274. GetAttributeForAllPoints<uint16_t>(mesh, pAttribute, outBuffer);
  4275. break;
  4276. case TINYGLTF_COMPONENT_TYPE_SHORT:
  4277. decodeResult =
  4278. GetAttributeForAllPoints<int16_t>(mesh, pAttribute, outBuffer);
  4279. break;
  4280. case TINYGLTF_COMPONENT_TYPE_INT:
  4281. decodeResult =
  4282. GetAttributeForAllPoints<int32_t>(mesh, pAttribute, outBuffer);
  4283. break;
  4284. case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
  4285. decodeResult =
  4286. GetAttributeForAllPoints<uint32_t>(mesh, pAttribute, outBuffer);
  4287. break;
  4288. case TINYGLTF_COMPONENT_TYPE_FLOAT:
  4289. decodeResult =
  4290. GetAttributeForAllPoints<float>(mesh, pAttribute, outBuffer);
  4291. break;
  4292. case TINYGLTF_COMPONENT_TYPE_DOUBLE:
  4293. decodeResult =
  4294. GetAttributeForAllPoints<double>(mesh, pAttribute, outBuffer);
  4295. break;
  4296. default:
  4297. return false;
  4298. }
  4299. return decodeResult;
  4300. }
  4301. static bool ParseDracoExtension(Primitive *primitive, Model *model,
  4302. std::string *err, std::string *warn,
  4303. const Value &dracoExtensionValue,
  4304. ParseStrictness strictness) {
  4305. (void)err;
  4306. auto bufferViewValue = dracoExtensionValue.Get("bufferView");
  4307. if (!bufferViewValue.IsInt()) return false;
  4308. auto attributesValue = dracoExtensionValue.Get("attributes");
  4309. if (!attributesValue.IsObject()) return false;
  4310. auto attributesObject = attributesValue.Get<Value::Object>();
  4311. int bufferView = bufferViewValue.Get<int>();
  4312. BufferView &view = model->bufferViews[bufferView];
  4313. Buffer &buffer = model->buffers[view.buffer];
  4314. // BufferView has already been decoded
  4315. if (view.dracoDecoded) return true;
  4316. view.dracoDecoded = true;
  4317. const char *bufferViewData =
  4318. reinterpret_cast<const char *>(buffer.data.data() + view.byteOffset);
  4319. size_t bufferViewSize = view.byteLength;
  4320. // decode draco
  4321. draco::DecoderBuffer decoderBuffer;
  4322. decoderBuffer.Init(bufferViewData, bufferViewSize);
  4323. draco::Decoder decoder;
  4324. auto decodeResult = decoder.DecodeMeshFromBuffer(&decoderBuffer);
  4325. if (!decodeResult.ok()) {
  4326. return false;
  4327. }
  4328. const std::unique_ptr<draco::Mesh> &mesh = decodeResult.value();
  4329. // create new bufferView for indices
  4330. if (primitive->indices >= 0) {
  4331. if (strictness == ParseStrictness::Permissive) {
  4332. const draco::PointIndex::ValueType numPoint = mesh->num_points();
  4333. // handle the situation where the stored component type does not match the
  4334. // required type for the actual number of stored points
  4335. int supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
  4336. if (numPoint < static_cast<draco::PointIndex::ValueType>(
  4337. std::numeric_limits<uint8_t>::max())) {
  4338. supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
  4339. } else if (
  4340. numPoint < static_cast<draco::PointIndex::ValueType>(
  4341. std::numeric_limits<uint16_t>::max())) {
  4342. supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT;
  4343. } else {
  4344. supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT;
  4345. }
  4346. if (supposedComponentType > model->accessors[primitive->indices].componentType) {
  4347. if (warn) {
  4348. (*warn) +=
  4349. "GLTF component type " + std::to_string(model->accessors[primitive->indices].componentType) +
  4350. " is not sufficient for number of stored points,"
  4351. " treating as " + std::to_string(supposedComponentType) + "\n";
  4352. }
  4353. model->accessors[primitive->indices].componentType = supposedComponentType;
  4354. }
  4355. }
  4356. int32_t componentSize = GetComponentSizeInBytes(
  4357. model->accessors[primitive->indices].componentType);
  4358. Buffer decodedIndexBuffer;
  4359. decodedIndexBuffer.data.resize(mesh->num_faces() * 3 * componentSize);
  4360. DecodeIndexBuffer(mesh.get(), componentSize, decodedIndexBuffer.data);
  4361. model->buffers.emplace_back(std::move(decodedIndexBuffer));
  4362. BufferView decodedIndexBufferView;
  4363. decodedIndexBufferView.buffer = int(model->buffers.size() - 1);
  4364. decodedIndexBufferView.byteLength =
  4365. int(mesh->num_faces() * 3 * componentSize);
  4366. decodedIndexBufferView.byteOffset = 0;
  4367. decodedIndexBufferView.byteStride = 0;
  4368. decodedIndexBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
  4369. model->bufferViews.emplace_back(std::move(decodedIndexBufferView));
  4370. model->accessors[primitive->indices].bufferView =
  4371. int(model->bufferViews.size() - 1);
  4372. model->accessors[primitive->indices].count = int(mesh->num_faces() * 3);
  4373. }
  4374. for (const auto &attribute : attributesObject) {
  4375. if (!attribute.second.IsInt()) return false;
  4376. auto primitiveAttribute = primitive->attributes.find(attribute.first);
  4377. if (primitiveAttribute == primitive->attributes.end()) return false;
  4378. int dracoAttributeIndex = attribute.second.Get<int>();
  4379. const auto pAttribute = mesh->GetAttributeByUniqueId(dracoAttributeIndex);
  4380. const auto componentType =
  4381. model->accessors[primitiveAttribute->second].componentType;
  4382. // Create a new buffer for this decoded buffer
  4383. Buffer decodedBuffer;
  4384. size_t bufferSize = mesh->num_points() * pAttribute->num_components() *
  4385. GetComponentSizeInBytes(componentType);
  4386. decodedBuffer.data.resize(bufferSize);
  4387. if (!GetAttributeForAllPoints(componentType, mesh.get(), pAttribute,
  4388. decodedBuffer.data))
  4389. return false;
  4390. model->buffers.emplace_back(std::move(decodedBuffer));
  4391. BufferView decodedBufferView;
  4392. decodedBufferView.buffer = int(model->buffers.size() - 1);
  4393. decodedBufferView.byteLength = bufferSize;
  4394. decodedBufferView.byteOffset = pAttribute->byte_offset();
  4395. decodedBufferView.byteStride = pAttribute->byte_stride();
  4396. decodedBufferView.target = primitive->indices >= 0
  4397. ? TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER
  4398. : TINYGLTF_TARGET_ARRAY_BUFFER;
  4399. model->bufferViews.emplace_back(std::move(decodedBufferView));
  4400. model->accessors[primitiveAttribute->second].bufferView =
  4401. int(model->bufferViews.size() - 1);
  4402. model->accessors[primitiveAttribute->second].count =
  4403. int(mesh->num_points());
  4404. }
  4405. return true;
  4406. }
  4407. #endif
  4408. static bool ParsePrimitive(Primitive *primitive, Model *model,
  4409. std::string *err, std::string *warn,
  4410. const detail::json &o,
  4411. bool store_original_json_for_extras_and_extensions,
  4412. ParseStrictness strictness) {
  4413. int material = -1;
  4414. ParseIntegerProperty(&material, err, o, "material", false);
  4415. primitive->material = material;
  4416. int mode = TINYGLTF_MODE_TRIANGLES;
  4417. ParseIntegerProperty(&mode, err, o, "mode", false);
  4418. primitive->mode = mode; // Why only triangles were supported ?
  4419. int indices = -1;
  4420. ParseIntegerProperty(&indices, err, o, "indices", false);
  4421. primitive->indices = indices;
  4422. if (!ParseStringIntegerProperty(&primitive->attributes, err, o, "attributes",
  4423. true, "Primitive")) {
  4424. return false;
  4425. }
  4426. // Look for morph targets
  4427. detail::json_const_iterator targetsObject;
  4428. if (detail::FindMember(o, "targets", targetsObject) &&
  4429. detail::IsArray(detail::GetValue(targetsObject))) {
  4430. auto targetsObjectEnd = detail::ArrayEnd(detail::GetValue(targetsObject));
  4431. for (detail::json_const_array_iterator i =
  4432. detail::ArrayBegin(detail::GetValue(targetsObject));
  4433. i != targetsObjectEnd; ++i) {
  4434. std::map<std::string, int> targetAttribues;
  4435. const detail::json &dict = *i;
  4436. if (detail::IsObject(dict)) {
  4437. detail::json_const_iterator dictIt(detail::ObjectBegin(dict));
  4438. detail::json_const_iterator dictItEnd(detail::ObjectEnd(dict));
  4439. for (; dictIt != dictItEnd; ++dictIt) {
  4440. int iVal;
  4441. if (detail::GetInt(detail::GetValue(dictIt), iVal))
  4442. targetAttribues[detail::GetKey(dictIt)] = iVal;
  4443. }
  4444. primitive->targets.emplace_back(std::move(targetAttribues));
  4445. }
  4446. }
  4447. }
  4448. ParseExtrasAndExtensions(primitive, err, o,
  4449. store_original_json_for_extras_and_extensions);
  4450. #ifdef TINYGLTF_ENABLE_DRACO
  4451. auto dracoExtension =
  4452. primitive->extensions.find("KHR_draco_mesh_compression");
  4453. if (dracoExtension != primitive->extensions.end()) {
  4454. ParseDracoExtension(primitive, model, err, warn, dracoExtension->second, strictness);
  4455. }
  4456. #else
  4457. (void)model;
  4458. (void)warn;
  4459. (void)strictness;
  4460. #endif
  4461. return true;
  4462. }
  4463. static bool ParseMesh(Mesh *mesh, Model *model,
  4464. std::string *err, std::string *warn,
  4465. const detail::json &o,
  4466. bool store_original_json_for_extras_and_extensions,
  4467. ParseStrictness strictness) {
  4468. ParseStringProperty(&mesh->name, err, o, "name", false);
  4469. mesh->primitives.clear();
  4470. detail::json_const_iterator primObject;
  4471. if (detail::FindMember(o, "primitives", primObject) &&
  4472. detail::IsArray(detail::GetValue(primObject))) {
  4473. detail::json_const_array_iterator primEnd =
  4474. detail::ArrayEnd(detail::GetValue(primObject));
  4475. for (detail::json_const_array_iterator i =
  4476. detail::ArrayBegin(detail::GetValue(primObject));
  4477. i != primEnd; ++i) {
  4478. Primitive primitive;
  4479. if (ParsePrimitive(&primitive, model, err, warn, *i,
  4480. store_original_json_for_extras_and_extensions,
  4481. strictness)) {
  4482. // Only add the primitive if the parsing succeeds.
  4483. mesh->primitives.emplace_back(std::move(primitive));
  4484. }
  4485. }
  4486. }
  4487. // Should probably check if has targets and if dimensions fit
  4488. ParseNumberArrayProperty(&mesh->weights, err, o, "weights", false);
  4489. ParseExtrasAndExtensions(mesh, err, o,
  4490. store_original_json_for_extras_and_extensions);
  4491. return true;
  4492. }
  4493. static bool ParseNode(Node *node, std::string *err, const detail::json &o,
  4494. bool store_original_json_for_extras_and_extensions) {
  4495. ParseStringProperty(&node->name, err, o, "name", false);
  4496. int skin = -1;
  4497. ParseIntegerProperty(&skin, err, o, "skin", false);
  4498. node->skin = skin;
  4499. // Matrix and T/R/S are exclusive
  4500. if (!ParseNumberArrayProperty(&node->matrix, err, o, "matrix", false)) {
  4501. ParseNumberArrayProperty(&node->rotation, err, o, "rotation", false);
  4502. ParseNumberArrayProperty(&node->scale, err, o, "scale", false);
  4503. ParseNumberArrayProperty(&node->translation, err, o, "translation", false);
  4504. }
  4505. int camera = -1;
  4506. ParseIntegerProperty(&camera, err, o, "camera", false);
  4507. node->camera = camera;
  4508. int mesh = -1;
  4509. ParseIntegerProperty(&mesh, err, o, "mesh", false);
  4510. node->mesh = mesh;
  4511. node->children.clear();
  4512. ParseIntegerArrayProperty(&node->children, err, o, "children", false);
  4513. ParseNumberArrayProperty(&node->weights, err, o, "weights", false);
  4514. ParseExtrasAndExtensions(node, err, o,
  4515. store_original_json_for_extras_and_extensions);
  4516. // KHR_lights_punctual: parse light source reference
  4517. int light = -1;
  4518. if (node->extensions.count("KHR_lights_punctual") != 0) {
  4519. auto const &light_ext = node->extensions["KHR_lights_punctual"];
  4520. if (light_ext.Has("light")) {
  4521. light = light_ext.Get("light").GetNumberAsInt();
  4522. } else {
  4523. if (err) {
  4524. *err +=
  4525. "Node has extension KHR_lights_punctual, but does not reference "
  4526. "a light source.\n";
  4527. }
  4528. return false;
  4529. }
  4530. }
  4531. node->light = light;
  4532. // KHR_audio: parse audio source reference
  4533. int emitter = -1;
  4534. if (node->extensions.count("KHR_audio") != 0) {
  4535. auto const &audio_ext = node->extensions["KHR_audio"];
  4536. if (audio_ext.Has("emitter")) {
  4537. emitter = audio_ext.Get("emitter").GetNumberAsInt();
  4538. } else {
  4539. if (err) {
  4540. *err +=
  4541. "Node has extension KHR_audio, but does not reference "
  4542. "a audio emitter.\n";
  4543. }
  4544. return false;
  4545. }
  4546. }
  4547. node->emitter = emitter;
  4548. node->lods.clear();
  4549. if (node->extensions.count("MSFT_lod") != 0) {
  4550. auto const &msft_lod_ext = node->extensions["MSFT_lod"];
  4551. if (msft_lod_ext.Has("ids")) {
  4552. auto idsArr = msft_lod_ext.Get("ids");
  4553. for (size_t i = 0; i < idsArr.ArrayLen(); ++i) {
  4554. node->lods.emplace_back(idsArr.Get(i).GetNumberAsInt());
  4555. }
  4556. } else {
  4557. if (err) {
  4558. *err +=
  4559. "Node has extension MSFT_lod, but does not reference "
  4560. "other nodes via their ids.\n";
  4561. }
  4562. return false;
  4563. }
  4564. }
  4565. return true;
  4566. }
  4567. static bool ParseScene(Scene *scene, std::string *err, const detail::json &o,
  4568. bool store_original_json_for_extras_and_extensions) {
  4569. ParseStringProperty(&scene->name, err, o, "name", false);
  4570. ParseIntegerArrayProperty(&scene->nodes, err, o, "nodes", false);
  4571. ParseExtrasAndExtensions(scene, err, o,
  4572. store_original_json_for_extras_and_extensions);
  4573. // Parse KHR_audio global emitters
  4574. if (scene->extensions.count("KHR_audio") != 0) {
  4575. auto const &audio_ext = scene->extensions["KHR_audio"];
  4576. if (audio_ext.Has("emitters")) {
  4577. auto emittersArr = audio_ext.Get("emitters");
  4578. for (size_t i = 0; i < emittersArr.ArrayLen(); ++i) {
  4579. scene->audioEmitters.emplace_back(emittersArr.Get(i).GetNumberAsInt());
  4580. }
  4581. } else {
  4582. if (err) {
  4583. *err +=
  4584. "Node has extension KHR_audio, but does not reference "
  4585. "a audio emitter.\n";
  4586. }
  4587. return false;
  4588. }
  4589. }
  4590. return true;
  4591. }
  4592. static bool ParsePbrMetallicRoughness(
  4593. PbrMetallicRoughness *pbr, std::string *err, const detail::json &o,
  4594. bool store_original_json_for_extras_and_extensions) {
  4595. if (pbr == nullptr) {
  4596. return false;
  4597. }
  4598. std::vector<double> baseColorFactor;
  4599. if (ParseNumberArrayProperty(&baseColorFactor, err, o, "baseColorFactor",
  4600. /* required */ false)) {
  4601. if (baseColorFactor.size() != 4) {
  4602. if (err) {
  4603. (*err) +=
  4604. "Array length of `baseColorFactor` parameter in "
  4605. "pbrMetallicRoughness must be 4, but got " +
  4606. std::to_string(baseColorFactor.size()) + "\n";
  4607. }
  4608. return false;
  4609. }
  4610. pbr->baseColorFactor = baseColorFactor;
  4611. }
  4612. {
  4613. detail::json_const_iterator it;
  4614. if (detail::FindMember(o, "baseColorTexture", it)) {
  4615. ParseTextureInfo(&pbr->baseColorTexture, err, detail::GetValue(it),
  4616. store_original_json_for_extras_and_extensions);
  4617. }
  4618. }
  4619. {
  4620. detail::json_const_iterator it;
  4621. if (detail::FindMember(o, "metallicRoughnessTexture", it)) {
  4622. ParseTextureInfo(&pbr->metallicRoughnessTexture, err,
  4623. detail::GetValue(it),
  4624. store_original_json_for_extras_and_extensions);
  4625. }
  4626. }
  4627. ParseNumberProperty(&pbr->metallicFactor, err, o, "metallicFactor", false);
  4628. ParseNumberProperty(&pbr->roughnessFactor, err, o, "roughnessFactor", false);
  4629. ParseExtrasAndExtensions(pbr, err, o,
  4630. store_original_json_for_extras_and_extensions);
  4631. return true;
  4632. }
  4633. static bool ParseMaterial(Material *material, std::string *err, std::string *warn,
  4634. const detail::json &o,
  4635. bool store_original_json_for_extras_and_extensions,
  4636. ParseStrictness strictness) {
  4637. ParseStringProperty(&material->name, err, o, "name", /* required */ false);
  4638. if (ParseNumberArrayProperty(&material->emissiveFactor, err, o,
  4639. "emissiveFactor",
  4640. /* required */ false)) {
  4641. if (strictness==ParseStrictness::Permissive && material->emissiveFactor.size() == 4) {
  4642. if (warn) {
  4643. (*warn) +=
  4644. "Array length of `emissiveFactor` parameter in "
  4645. "material must be 3, but got 4\n";
  4646. }
  4647. material->emissiveFactor.resize(3);
  4648. }
  4649. else if (material->emissiveFactor.size() != 3) {
  4650. if (err) {
  4651. (*err) +=
  4652. "Array length of `emissiveFactor` parameter in "
  4653. "material must be 3, but got " +
  4654. std::to_string(material->emissiveFactor.size()) + "\n";
  4655. }
  4656. return false;
  4657. }
  4658. } else {
  4659. // fill with default values
  4660. material->emissiveFactor = {0.0, 0.0, 0.0};
  4661. }
  4662. ParseStringProperty(&material->alphaMode, err, o, "alphaMode",
  4663. /* required */ false);
  4664. ParseNumberProperty(&material->alphaCutoff, err, o, "alphaCutoff",
  4665. /* required */ false);
  4666. ParseBooleanProperty(&material->doubleSided, err, o, "doubleSided",
  4667. /* required */ false);
  4668. {
  4669. detail::json_const_iterator it;
  4670. if (detail::FindMember(o, "pbrMetallicRoughness", it)) {
  4671. ParsePbrMetallicRoughness(&material->pbrMetallicRoughness, err,
  4672. detail::GetValue(it),
  4673. store_original_json_for_extras_and_extensions);
  4674. }
  4675. }
  4676. {
  4677. detail::json_const_iterator it;
  4678. if (detail::FindMember(o, "normalTexture", it)) {
  4679. ParseNormalTextureInfo(&material->normalTexture, err,
  4680. detail::GetValue(it),
  4681. store_original_json_for_extras_and_extensions);
  4682. }
  4683. }
  4684. {
  4685. detail::json_const_iterator it;
  4686. if (detail::FindMember(o, "occlusionTexture", it)) {
  4687. ParseOcclusionTextureInfo(&material->occlusionTexture, err,
  4688. detail::GetValue(it),
  4689. store_original_json_for_extras_and_extensions);
  4690. }
  4691. }
  4692. {
  4693. detail::json_const_iterator it;
  4694. if (detail::FindMember(o, "emissiveTexture", it)) {
  4695. ParseTextureInfo(&material->emissiveTexture, err, detail::GetValue(it),
  4696. store_original_json_for_extras_and_extensions);
  4697. }
  4698. }
  4699. // Old code path. For backward compatibility, we still store material values
  4700. // as Parameter. This will create duplicated information for
  4701. // example(pbrMetallicRoughness), but should be negligible in terms of memory
  4702. // consumption.
  4703. // TODO(syoyo): Remove in the next major release.
  4704. material->values.clear();
  4705. material->additionalValues.clear();
  4706. detail::json_const_iterator it(detail::ObjectBegin(o));
  4707. detail::json_const_iterator itEnd(detail::ObjectEnd(o));
  4708. for (; it != itEnd; ++it) {
  4709. std::string key(detail::GetKey(it));
  4710. if (key == "pbrMetallicRoughness") {
  4711. if (detail::IsObject(detail::GetValue(it))) {
  4712. const detail::json &values_object = detail::GetValue(it);
  4713. detail::json_const_iterator itVal(detail::ObjectBegin(values_object));
  4714. detail::json_const_iterator itValEnd(detail::ObjectEnd(values_object));
  4715. for (; itVal != itValEnd; ++itVal) {
  4716. Parameter param;
  4717. if (ParseParameterProperty(&param, err, values_object,
  4718. detail::GetKey(itVal), false)) {
  4719. material->values.emplace(detail::GetKey(itVal), std::move(param));
  4720. }
  4721. }
  4722. }
  4723. } else if (key == "extensions" || key == "extras") {
  4724. // done later, skip, otherwise poorly parsed contents will be saved in the
  4725. // parametermap and serialized again later
  4726. } else {
  4727. Parameter param;
  4728. if (ParseParameterProperty(&param, err, o, key, false)) {
  4729. // names of materials have already been parsed. Putting it in this map
  4730. // doesn't correctly reflect the glTF specification
  4731. if (key != "name")
  4732. material->additionalValues.emplace(std::move(key), std::move(param));
  4733. }
  4734. }
  4735. }
  4736. material->extensions.clear(); // Note(agnat): Why?
  4737. ParseExtrasAndExtensions(material, err, o,
  4738. store_original_json_for_extras_and_extensions);
  4739. material->lods.clear();
  4740. if (material->extensions.count("MSFT_lod") != 0) {
  4741. auto const &msft_lod_ext = material->extensions["MSFT_lod"];
  4742. if (msft_lod_ext.Has("ids")) {
  4743. auto idsArr = msft_lod_ext.Get("ids");
  4744. for (size_t i = 0; i < idsArr.ArrayLen(); ++i) {
  4745. material->lods.emplace_back(idsArr.Get(i).GetNumberAsInt());
  4746. }
  4747. } else {
  4748. if (err) {
  4749. *err +=
  4750. "Material has extension MSFT_lod, but does not reference "
  4751. "other materials via their ids.\n";
  4752. }
  4753. return false;
  4754. }
  4755. }
  4756. return true;
  4757. }
  4758. static bool ParseAnimationChannel(
  4759. AnimationChannel *channel, std::string *err, const detail::json &o,
  4760. bool store_original_json_for_extras_and_extensions) {
  4761. int samplerIndex = -1;
  4762. int targetIndex = -1;
  4763. if (!ParseIntegerProperty(&samplerIndex, err, o, "sampler", true,
  4764. "AnimationChannel")) {
  4765. if (err) {
  4766. (*err) += "`sampler` field is missing in animation channels\n";
  4767. }
  4768. return false;
  4769. }
  4770. detail::json_const_iterator targetIt;
  4771. if (detail::FindMember(o, "target", targetIt) &&
  4772. detail::IsObject(detail::GetValue(targetIt))) {
  4773. const detail::json &target_object = detail::GetValue(targetIt);
  4774. ParseIntegerProperty(&targetIndex, err, target_object, "node", false);
  4775. if (!ParseStringProperty(&channel->target_path, err, target_object, "path",
  4776. true)) {
  4777. if (err) {
  4778. (*err) += "`path` field is missing in animation.channels.target\n";
  4779. }
  4780. return false;
  4781. }
  4782. ParseExtensionsProperty(&channel->target_extensions, err, target_object);
  4783. ParseExtrasProperty(&channel->target_extras, target_object);
  4784. if (store_original_json_for_extras_and_extensions) {
  4785. {
  4786. detail::json_const_iterator it;
  4787. if (detail::FindMember(target_object, "extensions", it)) {
  4788. channel->target_extensions_json_string =
  4789. detail::JsonToString(detail::GetValue(it));
  4790. }
  4791. }
  4792. {
  4793. detail::json_const_iterator it;
  4794. if (detail::FindMember(target_object, "extras", it)) {
  4795. channel->target_extras_json_string =
  4796. detail::JsonToString(detail::GetValue(it));
  4797. }
  4798. }
  4799. }
  4800. }
  4801. channel->sampler = samplerIndex;
  4802. channel->target_node = targetIndex;
  4803. ParseExtrasAndExtensions(channel, err, o,
  4804. store_original_json_for_extras_and_extensions);
  4805. return true;
  4806. }
  4807. static bool ParseAnimation(Animation *animation, std::string *err,
  4808. const detail::json &o,
  4809. bool store_original_json_for_extras_and_extensions) {
  4810. {
  4811. detail::json_const_iterator channelsIt;
  4812. if (detail::FindMember(o, "channels", channelsIt) &&
  4813. detail::IsArray(detail::GetValue(channelsIt))) {
  4814. detail::json_const_array_iterator channelEnd =
  4815. detail::ArrayEnd(detail::GetValue(channelsIt));
  4816. for (detail::json_const_array_iterator i =
  4817. detail::ArrayBegin(detail::GetValue(channelsIt));
  4818. i != channelEnd; ++i) {
  4819. AnimationChannel channel;
  4820. if (ParseAnimationChannel(
  4821. &channel, err, *i,
  4822. store_original_json_for_extras_and_extensions)) {
  4823. // Only add the channel if the parsing succeeds.
  4824. animation->channels.emplace_back(std::move(channel));
  4825. }
  4826. }
  4827. }
  4828. }
  4829. {
  4830. detail::json_const_iterator samplerIt;
  4831. if (detail::FindMember(o, "samplers", samplerIt) &&
  4832. detail::IsArray(detail::GetValue(samplerIt))) {
  4833. const detail::json &sampler_array = detail::GetValue(samplerIt);
  4834. detail::json_const_array_iterator it = detail::ArrayBegin(sampler_array);
  4835. detail::json_const_array_iterator itEnd = detail::ArrayEnd(sampler_array);
  4836. for (; it != itEnd; ++it) {
  4837. const detail::json &s = *it;
  4838. AnimationSampler sampler;
  4839. int inputIndex = -1;
  4840. int outputIndex = -1;
  4841. if (!ParseIntegerProperty(&inputIndex, err, s, "input", true)) {
  4842. if (err) {
  4843. (*err) += "`input` field is missing in animation.sampler\n";
  4844. }
  4845. return false;
  4846. }
  4847. ParseStringProperty(&sampler.interpolation, err, s, "interpolation",
  4848. false);
  4849. if (!ParseIntegerProperty(&outputIndex, err, s, "output", true)) {
  4850. if (err) {
  4851. (*err) += "`output` field is missing in animation.sampler\n";
  4852. }
  4853. return false;
  4854. }
  4855. sampler.input = inputIndex;
  4856. sampler.output = outputIndex;
  4857. ParseExtrasAndExtensions(&sampler, err, o,
  4858. store_original_json_for_extras_and_extensions);
  4859. animation->samplers.emplace_back(std::move(sampler));
  4860. }
  4861. }
  4862. }
  4863. ParseStringProperty(&animation->name, err, o, "name", false);
  4864. ParseExtrasAndExtensions(animation, err, o,
  4865. store_original_json_for_extras_and_extensions);
  4866. return true;
  4867. }
  4868. static bool ParseSampler(Sampler *sampler, std::string *err,
  4869. const detail::json &o,
  4870. bool store_original_json_for_extras_and_extensions) {
  4871. ParseStringProperty(&sampler->name, err, o, "name", false);
  4872. int minFilter = -1;
  4873. int magFilter = -1;
  4874. int wrapS = TINYGLTF_TEXTURE_WRAP_REPEAT;
  4875. int wrapT = TINYGLTF_TEXTURE_WRAP_REPEAT;
  4876. // int wrapR = TINYGLTF_TEXTURE_WRAP_REPEAT;
  4877. ParseIntegerProperty(&minFilter, err, o, "minFilter", false);
  4878. ParseIntegerProperty(&magFilter, err, o, "magFilter", false);
  4879. ParseIntegerProperty(&wrapS, err, o, "wrapS", false);
  4880. ParseIntegerProperty(&wrapT, err, o, "wrapT", false);
  4881. // ParseIntegerProperty(&wrapR, err, o, "wrapR", false); // tinygltf
  4882. // extension
  4883. // TODO(syoyo): Check the value is allowed one.
  4884. // (e.g. we allow 9728(NEAREST), but don't allow 9727)
  4885. sampler->minFilter = minFilter;
  4886. sampler->magFilter = magFilter;
  4887. sampler->wrapS = wrapS;
  4888. sampler->wrapT = wrapT;
  4889. // sampler->wrapR = wrapR;
  4890. ParseExtrasAndExtensions(sampler, err, o,
  4891. store_original_json_for_extras_and_extensions);
  4892. return true;
  4893. }
  4894. static bool ParseSkin(Skin *skin, std::string *err, const detail::json &o,
  4895. bool store_original_json_for_extras_and_extensions) {
  4896. ParseStringProperty(&skin->name, err, o, "name", false, "Skin");
  4897. std::vector<int> joints;
  4898. if (!ParseIntegerArrayProperty(&joints, err, o, "joints", false, "Skin")) {
  4899. return false;
  4900. }
  4901. skin->joints = std::move(joints);
  4902. int skeleton = -1;
  4903. ParseIntegerProperty(&skeleton, err, o, "skeleton", false, "Skin");
  4904. skin->skeleton = skeleton;
  4905. int invBind = -1;
  4906. ParseIntegerProperty(&invBind, err, o, "inverseBindMatrices", false, "Skin");
  4907. skin->inverseBindMatrices = invBind;
  4908. ParseExtrasAndExtensions(skin, err, o,
  4909. store_original_json_for_extras_and_extensions);
  4910. return true;
  4911. }
  4912. static bool ParsePerspectiveCamera(
  4913. PerspectiveCamera *camera, std::string *err, const detail::json &o,
  4914. bool store_original_json_for_extras_and_extensions) {
  4915. double yfov = 0.0;
  4916. if (!ParseNumberProperty(&yfov, err, o, "yfov", true, "OrthographicCamera")) {
  4917. return false;
  4918. }
  4919. double znear = 0.0;
  4920. if (!ParseNumberProperty(&znear, err, o, "znear", true,
  4921. "PerspectiveCamera")) {
  4922. return false;
  4923. }
  4924. double aspectRatio = 0.0; // = invalid
  4925. ParseNumberProperty(&aspectRatio, err, o, "aspectRatio", false,
  4926. "PerspectiveCamera");
  4927. double zfar = 0.0; // = invalid
  4928. ParseNumberProperty(&zfar, err, o, "zfar", false, "PerspectiveCamera");
  4929. camera->aspectRatio = aspectRatio;
  4930. camera->zfar = zfar;
  4931. camera->yfov = yfov;
  4932. camera->znear = znear;
  4933. ParseExtrasAndExtensions(camera, err, o,
  4934. store_original_json_for_extras_and_extensions);
  4935. // TODO(syoyo): Validate parameter values.
  4936. return true;
  4937. }
  4938. static bool ParseSpotLight(SpotLight *light, std::string *err,
  4939. const detail::json &o,
  4940. bool store_original_json_for_extras_and_extensions) {
  4941. ParseNumberProperty(&light->innerConeAngle, err, o, "innerConeAngle", false);
  4942. ParseNumberProperty(&light->outerConeAngle, err, o, "outerConeAngle", false);
  4943. ParseExtrasAndExtensions(light, err, o,
  4944. store_original_json_for_extras_and_extensions);
  4945. // TODO(syoyo): Validate parameter values.
  4946. return true;
  4947. }
  4948. static bool ParseOrthographicCamera(
  4949. OrthographicCamera *camera, std::string *err, const detail::json &o,
  4950. bool store_original_json_for_extras_and_extensions) {
  4951. double xmag = 0.0;
  4952. if (!ParseNumberProperty(&xmag, err, o, "xmag", true, "OrthographicCamera")) {
  4953. return false;
  4954. }
  4955. double ymag = 0.0;
  4956. if (!ParseNumberProperty(&ymag, err, o, "ymag", true, "OrthographicCamera")) {
  4957. return false;
  4958. }
  4959. double zfar = 0.0;
  4960. if (!ParseNumberProperty(&zfar, err, o, "zfar", true, "OrthographicCamera")) {
  4961. return false;
  4962. }
  4963. double znear = 0.0;
  4964. if (!ParseNumberProperty(&znear, err, o, "znear", true,
  4965. "OrthographicCamera")) {
  4966. return false;
  4967. }
  4968. ParseExtrasAndExtensions(camera, err, o,
  4969. store_original_json_for_extras_and_extensions);
  4970. camera->xmag = xmag;
  4971. camera->ymag = ymag;
  4972. camera->zfar = zfar;
  4973. camera->znear = znear;
  4974. // TODO(syoyo): Validate parameter values.
  4975. return true;
  4976. }
  4977. static bool ParseCamera(Camera *camera, std::string *err, const detail::json &o,
  4978. bool store_original_json_for_extras_and_extensions) {
  4979. if (!ParseStringProperty(&camera->type, err, o, "type", true, "Camera")) {
  4980. return false;
  4981. }
  4982. if (camera->type.compare("orthographic") == 0) {
  4983. detail::json_const_iterator orthoIt;
  4984. if (!detail::FindMember(o, "orthographic", orthoIt)) {
  4985. if (err) {
  4986. std::stringstream ss;
  4987. ss << "Orthographic camera description not found." << std::endl;
  4988. (*err) += ss.str();
  4989. }
  4990. return false;
  4991. }
  4992. const detail::json &v = detail::GetValue(orthoIt);
  4993. if (!detail::IsObject(v)) {
  4994. if (err) {
  4995. std::stringstream ss;
  4996. ss << "\"orthographic\" is not a JSON object." << std::endl;
  4997. (*err) += ss.str();
  4998. }
  4999. return false;
  5000. }
  5001. if (!ParseOrthographicCamera(
  5002. &camera->orthographic, err, v,
  5003. store_original_json_for_extras_and_extensions)) {
  5004. return false;
  5005. }
  5006. } else if (camera->type.compare("perspective") == 0) {
  5007. detail::json_const_iterator perspIt;
  5008. if (!detail::FindMember(o, "perspective", perspIt)) {
  5009. if (err) {
  5010. std::stringstream ss;
  5011. ss << "Perspective camera description not found." << std::endl;
  5012. (*err) += ss.str();
  5013. }
  5014. return false;
  5015. }
  5016. const detail::json &v = detail::GetValue(perspIt);
  5017. if (!detail::IsObject(v)) {
  5018. if (err) {
  5019. std::stringstream ss;
  5020. ss << "\"perspective\" is not a JSON object." << std::endl;
  5021. (*err) += ss.str();
  5022. }
  5023. return false;
  5024. }
  5025. if (!ParsePerspectiveCamera(
  5026. &camera->perspective, err, v,
  5027. store_original_json_for_extras_and_extensions)) {
  5028. return false;
  5029. }
  5030. } else {
  5031. if (err) {
  5032. std::stringstream ss;
  5033. ss << "Invalid camera type: \"" << camera->type
  5034. << "\". Must be \"perspective\" or \"orthographic\"" << std::endl;
  5035. (*err) += ss.str();
  5036. }
  5037. return false;
  5038. }
  5039. ParseStringProperty(&camera->name, err, o, "name", false);
  5040. ParseExtrasAndExtensions(camera, err, o,
  5041. store_original_json_for_extras_and_extensions);
  5042. return true;
  5043. }
  5044. static bool ParseLight(Light *light, std::string *err, const detail::json &o,
  5045. bool store_original_json_for_extras_and_extensions) {
  5046. if (!ParseStringProperty(&light->type, err, o, "type", true)) {
  5047. return false;
  5048. }
  5049. if (light->type == "spot") {
  5050. detail::json_const_iterator spotIt;
  5051. if (!detail::FindMember(o, "spot", spotIt)) {
  5052. if (err) {
  5053. std::stringstream ss;
  5054. ss << "Spot light description not found." << std::endl;
  5055. (*err) += ss.str();
  5056. }
  5057. return false;
  5058. }
  5059. const detail::json &v = detail::GetValue(spotIt);
  5060. if (!detail::IsObject(v)) {
  5061. if (err) {
  5062. std::stringstream ss;
  5063. ss << "\"spot\" is not a JSON object." << std::endl;
  5064. (*err) += ss.str();
  5065. }
  5066. return false;
  5067. }
  5068. if (!ParseSpotLight(&light->spot, err, v,
  5069. store_original_json_for_extras_and_extensions)) {
  5070. return false;
  5071. }
  5072. }
  5073. ParseStringProperty(&light->name, err, o, "name", false);
  5074. ParseNumberArrayProperty(&light->color, err, o, "color", false);
  5075. ParseNumberProperty(&light->range, err, o, "range", false);
  5076. ParseNumberProperty(&light->intensity, err, o, "intensity", false);
  5077. ParseExtrasAndExtensions(light, err, o,
  5078. store_original_json_for_extras_and_extensions);
  5079. return true;
  5080. }
  5081. static bool ParsePositionalEmitter(
  5082. PositionalEmitter *positional, std::string *err, const detail::json &o,
  5083. bool store_original_json_for_extras_and_extensions) {
  5084. ParseNumberProperty(&positional->coneInnerAngle, err, o, "coneInnerAngle",
  5085. false);
  5086. ParseNumberProperty(&positional->coneOuterAngle, err, o, "coneOuterAngle",
  5087. false);
  5088. ParseNumberProperty(&positional->coneOuterGain, err, o, "coneOuterGain",
  5089. false);
  5090. ParseNumberProperty(&positional->maxDistance, err, o, "maxDistance", false);
  5091. ParseNumberProperty(&positional->refDistance, err, o, "refDistance", false);
  5092. ParseNumberProperty(&positional->rolloffFactor, err, o, "rolloffFactor",
  5093. false);
  5094. ParseExtrasAndExtensions(positional, err, o,
  5095. store_original_json_for_extras_and_extensions);
  5096. return true;
  5097. }
  5098. static bool ParseAudioEmitter(
  5099. AudioEmitter *emitter, std::string *err, const detail::json &o,
  5100. bool store_original_json_for_extras_and_extensions) {
  5101. if (!ParseStringProperty(&emitter->type, err, o, "type", true)) {
  5102. return false;
  5103. }
  5104. if (emitter->type == "positional") {
  5105. detail::json_const_iterator positionalIt;
  5106. if (!detail::FindMember(o, "positional", positionalIt)) {
  5107. if (err) {
  5108. std::stringstream ss;
  5109. ss << "Positional emitter description not found." << std::endl;
  5110. (*err) += ss.str();
  5111. }
  5112. return false;
  5113. }
  5114. const detail::json &v = detail::GetValue(positionalIt);
  5115. if (!detail::IsObject(v)) {
  5116. if (err) {
  5117. std::stringstream ss;
  5118. ss << "\"positional\" is not a JSON object." << std::endl;
  5119. (*err) += ss.str();
  5120. }
  5121. return false;
  5122. }
  5123. if (!ParsePositionalEmitter(
  5124. &emitter->positional, err, v,
  5125. store_original_json_for_extras_and_extensions)) {
  5126. return false;
  5127. }
  5128. }
  5129. ParseStringProperty(&emitter->name, err, o, "name", false);
  5130. ParseNumberProperty(&emitter->gain, err, o, "gain", false);
  5131. ParseBooleanProperty(&emitter->loop, err, o, "loop", false);
  5132. ParseBooleanProperty(&emitter->playing, err, o, "playing", false);
  5133. ParseStringProperty(&emitter->distanceModel, err, o, "distanceModel", false);
  5134. ParseIntegerProperty(&emitter->source, err, o, "source", true);
  5135. ParseExtrasAndExtensions(emitter, err, o,
  5136. store_original_json_for_extras_and_extensions);
  5137. return true;
  5138. }
  5139. static bool ParseAudioSource(
  5140. AudioSource *source, std::string *err, const detail::json &o,
  5141. bool store_original_json_for_extras_and_extensions) {
  5142. ParseStringProperty(&source->name, err, o, "name", false);
  5143. ParseStringProperty(&source->uri, err, o, "uri", false);
  5144. if (source->uri.empty()) {
  5145. ParseIntegerProperty(&source->bufferView, err, o, "bufferView", true);
  5146. ParseStringProperty(&source->mimeType, err, o, "mimeType", true);
  5147. }
  5148. ParseExtrasAndExtensions(source, err, o,
  5149. store_original_json_for_extras_and_extensions);
  5150. return true;
  5151. }
  5152. namespace detail {
  5153. template <typename Callback>
  5154. bool ForEachInArray(const detail::json &_v, const char *member, Callback &&cb) {
  5155. detail::json_const_iterator itm;
  5156. if (detail::FindMember(_v, member, itm) &&
  5157. detail::IsArray(detail::GetValue(itm))) {
  5158. const detail::json &root = detail::GetValue(itm);
  5159. auto it = detail::ArrayBegin(root);
  5160. auto end = detail::ArrayEnd(root);
  5161. for (; it != end; ++it) {
  5162. if (!cb(*it)) return false;
  5163. }
  5164. }
  5165. return true;
  5166. };
  5167. } // end of namespace detail
  5168. bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
  5169. const char *json_str,
  5170. unsigned int json_str_length,
  5171. const std::string &base_dir,
  5172. unsigned int check_sections) {
  5173. if (json_str_length < 4) {
  5174. if (err) {
  5175. (*err) = "JSON string too short.\n";
  5176. }
  5177. return false;
  5178. }
  5179. detail::JsonDocument v;
  5180. #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || \
  5181. defined(_CPPUNWIND)) && \
  5182. !defined(TINYGLTF_NOEXCEPTION)
  5183. try {
  5184. detail::JsonParse(v, json_str, json_str_length, true);
  5185. } catch (const std::exception &e) {
  5186. if (err) {
  5187. (*err) = e.what();
  5188. }
  5189. return false;
  5190. }
  5191. #else
  5192. {
  5193. detail::JsonParse(v, json_str, json_str_length);
  5194. if (!detail::IsObject(v)) {
  5195. // Assume parsing was failed.
  5196. if (err) {
  5197. (*err) = "Failed to parse JSON object\n";
  5198. }
  5199. return false;
  5200. }
  5201. }
  5202. #endif
  5203. if (!detail::IsObject(v)) {
  5204. // root is not an object.
  5205. if (err) {
  5206. (*err) = "Root element is not a JSON object\n";
  5207. }
  5208. return false;
  5209. }
  5210. {
  5211. bool version_found = false;
  5212. detail::json_const_iterator it;
  5213. if (detail::FindMember(v, "asset", it) &&
  5214. detail::IsObject(detail::GetValue(it))) {
  5215. auto &itObj = detail::GetValue(it);
  5216. detail::json_const_iterator version_it;
  5217. std::string versionStr;
  5218. if (detail::FindMember(itObj, "version", version_it) &&
  5219. detail::GetString(detail::GetValue(version_it), versionStr)) {
  5220. version_found = true;
  5221. }
  5222. }
  5223. if (version_found) {
  5224. // OK
  5225. } else if (check_sections & REQUIRE_VERSION) {
  5226. if (err) {
  5227. (*err) += "\"asset\" object not found in .gltf or not an object type\n";
  5228. }
  5229. return false;
  5230. }
  5231. }
  5232. // scene is not mandatory.
  5233. // FIXME Maybe a better way to handle it than removing the code
  5234. auto IsArrayMemberPresent = [](const detail::json &_v,
  5235. const char *name) -> bool {
  5236. detail::json_const_iterator it;
  5237. return detail::FindMember(_v, name, it) &&
  5238. detail::IsArray(detail::GetValue(it));
  5239. };
  5240. {
  5241. if ((check_sections & REQUIRE_SCENES) &&
  5242. !IsArrayMemberPresent(v, "scenes")) {
  5243. if (err) {
  5244. (*err) += "\"scenes\" object not found in .gltf or not an array type\n";
  5245. }
  5246. return false;
  5247. }
  5248. }
  5249. {
  5250. if ((check_sections & REQUIRE_NODES) && !IsArrayMemberPresent(v, "nodes")) {
  5251. if (err) {
  5252. (*err) += "\"nodes\" object not found in .gltf\n";
  5253. }
  5254. return false;
  5255. }
  5256. }
  5257. {
  5258. if ((check_sections & REQUIRE_ACCESSORS) &&
  5259. !IsArrayMemberPresent(v, "accessors")) {
  5260. if (err) {
  5261. (*err) += "\"accessors\" object not found in .gltf\n";
  5262. }
  5263. return false;
  5264. }
  5265. }
  5266. {
  5267. if ((check_sections & REQUIRE_BUFFERS) &&
  5268. !IsArrayMemberPresent(v, "buffers")) {
  5269. if (err) {
  5270. (*err) += "\"buffers\" object not found in .gltf\n";
  5271. }
  5272. return false;
  5273. }
  5274. }
  5275. {
  5276. if ((check_sections & REQUIRE_BUFFER_VIEWS) &&
  5277. !IsArrayMemberPresent(v, "bufferViews")) {
  5278. if (err) {
  5279. (*err) += "\"bufferViews\" object not found in .gltf\n";
  5280. }
  5281. return false;
  5282. }
  5283. }
  5284. // Reset the model
  5285. (*model) = Model();
  5286. // 1. Parse Asset
  5287. {
  5288. detail::json_const_iterator it;
  5289. if (detail::FindMember(v, "asset", it) &&
  5290. detail::IsObject(detail::GetValue(it))) {
  5291. const detail::json &root = detail::GetValue(it);
  5292. ParseAsset(&model->asset, err, root,
  5293. store_original_json_for_extras_and_extensions_);
  5294. }
  5295. }
  5296. using detail::ForEachInArray;
  5297. // 2. Parse extensionUsed
  5298. {
  5299. ForEachInArray(v, "extensionsUsed", [&](const detail::json &o) {
  5300. std::string str;
  5301. detail::GetString(o, str);
  5302. model->extensionsUsed.emplace_back(std::move(str));
  5303. return true;
  5304. });
  5305. }
  5306. {
  5307. ForEachInArray(v, "extensionsRequired", [&](const detail::json &o) {
  5308. std::string str;
  5309. detail::GetString(o, str);
  5310. model->extensionsRequired.emplace_back(std::move(str));
  5311. return true;
  5312. });
  5313. }
  5314. // 3. Parse Buffer
  5315. {
  5316. bool success = ForEachInArray(v, "buffers", [&](const detail::json &o) {
  5317. if (!detail::IsObject(o)) {
  5318. if (err) {
  5319. (*err) += "`buffers' does not contain an JSON object.";
  5320. }
  5321. return false;
  5322. }
  5323. Buffer buffer;
  5324. if (!ParseBuffer(&buffer, err, o,
  5325. store_original_json_for_extras_and_extensions_, &fs,
  5326. &uri_cb, base_dir, max_external_file_size_, is_binary_,
  5327. bin_data_, bin_size_)) {
  5328. return false;
  5329. }
  5330. model->buffers.emplace_back(std::move(buffer));
  5331. return true;
  5332. });
  5333. if (!success) {
  5334. return false;
  5335. }
  5336. }
  5337. // 4. Parse BufferView
  5338. {
  5339. bool success = ForEachInArray(v, "bufferViews", [&](const detail::json &o) {
  5340. if (!detail::IsObject(o)) {
  5341. if (err) {
  5342. (*err) += "`bufferViews' does not contain an JSON object.";
  5343. }
  5344. return false;
  5345. }
  5346. BufferView bufferView;
  5347. if (!ParseBufferView(&bufferView, err, o,
  5348. store_original_json_for_extras_and_extensions_)) {
  5349. return false;
  5350. }
  5351. model->bufferViews.emplace_back(std::move(bufferView));
  5352. return true;
  5353. });
  5354. if (!success) {
  5355. return false;
  5356. }
  5357. }
  5358. // 5. Parse Accessor
  5359. {
  5360. bool success = ForEachInArray(v, "accessors", [&](const detail::json &o) {
  5361. if (!detail::IsObject(o)) {
  5362. if (err) {
  5363. (*err) += "`accessors' does not contain an JSON object.";
  5364. }
  5365. return false;
  5366. }
  5367. Accessor accessor;
  5368. if (!ParseAccessor(&accessor, err, o,
  5369. store_original_json_for_extras_and_extensions_)) {
  5370. return false;
  5371. }
  5372. model->accessors.emplace_back(std::move(accessor));
  5373. return true;
  5374. });
  5375. if (!success) {
  5376. return false;
  5377. }
  5378. }
  5379. // 6. Parse Mesh
  5380. {
  5381. bool success = ForEachInArray(v, "meshes", [&](const detail::json &o) {
  5382. if (!detail::IsObject(o)) {
  5383. if (err) {
  5384. (*err) += "`meshes' does not contain an JSON object.";
  5385. }
  5386. return false;
  5387. }
  5388. Mesh mesh;
  5389. if (!ParseMesh(&mesh, model, err, warn, o,
  5390. store_original_json_for_extras_and_extensions_,
  5391. strictness_)) {
  5392. return false;
  5393. }
  5394. model->meshes.emplace_back(std::move(mesh));
  5395. return true;
  5396. });
  5397. if (!success) {
  5398. return false;
  5399. }
  5400. }
  5401. // Assign missing bufferView target types
  5402. // - Look for missing Mesh indices
  5403. // - Look for missing Mesh attributes
  5404. for (auto &mesh : model->meshes) {
  5405. for (auto &primitive : mesh.primitives) {
  5406. if (primitive.indices >
  5407. -1) // has indices from parsing step, must be Element Array Buffer
  5408. {
  5409. if (size_t(primitive.indices) >= model->accessors.size()) {
  5410. if (err) {
  5411. (*err) += "primitive indices accessor out of bounds";
  5412. }
  5413. return false;
  5414. }
  5415. const auto bufferView =
  5416. model->accessors[size_t(primitive.indices)].bufferView;
  5417. if (bufferView < 0) {
  5418. // skip, bufferView could be null(-1) for certain extensions
  5419. } else if (size_t(bufferView) >= model->bufferViews.size()) {
  5420. if (err) {
  5421. (*err) += "accessor[" + std::to_string(primitive.indices) +
  5422. "] invalid bufferView";
  5423. }
  5424. return false;
  5425. } else {
  5426. model->bufferViews[size_t(bufferView)].target =
  5427. TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
  5428. // we could optionally check if accessors' bufferView type is Scalar, as
  5429. // it should be
  5430. }
  5431. }
  5432. for (auto &attribute : primitive.attributes) {
  5433. const auto accessorsIndex = size_t(attribute.second);
  5434. if (accessorsIndex < model->accessors.size()) {
  5435. const auto bufferView = model->accessors[accessorsIndex].bufferView;
  5436. // bufferView could be null(-1) for sparse morph target
  5437. if (bufferView >= 0 && bufferView < (int)model->bufferViews.size()) {
  5438. model->bufferViews[size_t(bufferView)].target =
  5439. TINYGLTF_TARGET_ARRAY_BUFFER;
  5440. }
  5441. }
  5442. }
  5443. for (auto &target : primitive.targets) {
  5444. for (auto &attribute : target) {
  5445. const auto accessorsIndex = size_t(attribute.second);
  5446. if (accessorsIndex < model->accessors.size()) {
  5447. const auto bufferView = model->accessors[accessorsIndex].bufferView;
  5448. // bufferView could be null(-1) for sparse morph target
  5449. if (bufferView >= 0 &&
  5450. bufferView < (int)model->bufferViews.size()) {
  5451. model->bufferViews[size_t(bufferView)].target =
  5452. TINYGLTF_TARGET_ARRAY_BUFFER;
  5453. }
  5454. }
  5455. }
  5456. }
  5457. }
  5458. }
  5459. // 7. Parse Node
  5460. {
  5461. bool success = ForEachInArray(v, "nodes", [&](const detail::json &o) {
  5462. if (!detail::IsObject(o)) {
  5463. if (err) {
  5464. (*err) += "`nodes' does not contain an JSON object.";
  5465. }
  5466. return false;
  5467. }
  5468. Node node;
  5469. if (!ParseNode(&node, err, o,
  5470. store_original_json_for_extras_and_extensions_)) {
  5471. return false;
  5472. }
  5473. model->nodes.emplace_back(std::move(node));
  5474. return true;
  5475. });
  5476. if (!success) {
  5477. return false;
  5478. }
  5479. }
  5480. // 8. Parse scenes.
  5481. {
  5482. bool success = ForEachInArray(v, "scenes", [&](const detail::json &o) {
  5483. if (!detail::IsObject(o)) {
  5484. if (err) {
  5485. (*err) += "`scenes' does not contain an JSON object.";
  5486. }
  5487. return false;
  5488. }
  5489. Scene scene;
  5490. if (!ParseScene(&scene, err, o,
  5491. store_original_json_for_extras_and_extensions_)) {
  5492. return false;
  5493. }
  5494. model->scenes.emplace_back(std::move(scene));
  5495. return true;
  5496. });
  5497. if (!success) {
  5498. return false;
  5499. }
  5500. }
  5501. // 9. Parse default scenes.
  5502. {
  5503. detail::json_const_iterator rootIt;
  5504. int iVal;
  5505. if (detail::FindMember(v, "scene", rootIt) &&
  5506. detail::GetInt(detail::GetValue(rootIt), iVal)) {
  5507. model->defaultScene = iVal;
  5508. }
  5509. }
  5510. // 10. Parse Material
  5511. {
  5512. bool success = ForEachInArray(v, "materials", [&](const detail::json &o) {
  5513. if (!detail::IsObject(o)) {
  5514. if (err) {
  5515. (*err) += "`materials' does not contain an JSON object.";
  5516. }
  5517. return false;
  5518. }
  5519. Material material;
  5520. ParseStringProperty(&material.name, err, o, "name", false);
  5521. if (!ParseMaterial(&material, err, warn, o,
  5522. store_original_json_for_extras_and_extensions_,
  5523. strictness_)) {
  5524. return false;
  5525. }
  5526. model->materials.emplace_back(std::move(material));
  5527. return true;
  5528. });
  5529. if (!success) {
  5530. return false;
  5531. }
  5532. }
  5533. // 11. Parse Image
  5534. void *load_image_user_data{nullptr};
  5535. LoadImageDataOption load_image_option;
  5536. if (user_image_loader_) {
  5537. // Use user supplied pointer
  5538. load_image_user_data = load_image_user_data_;
  5539. } else {
  5540. load_image_option.preserve_channels = preserve_image_channels_;
  5541. load_image_option.as_is = images_as_is_;
  5542. load_image_user_data = reinterpret_cast<void *>(&load_image_option);
  5543. }
  5544. {
  5545. int idx = 0;
  5546. bool success = ForEachInArray(v, "images", [&](const detail::json &o) {
  5547. if (!detail::IsObject(o)) {
  5548. if (err) {
  5549. (*err) += "image[" + std::to_string(idx) + "] is not a JSON object.";
  5550. }
  5551. return false;
  5552. }
  5553. Image image;
  5554. if (!ParseImage(&image, idx, err, warn, o,
  5555. store_original_json_for_extras_and_extensions_, base_dir,
  5556. max_external_file_size_, &fs, &uri_cb,
  5557. this->LoadImageData, load_image_user_data)) {
  5558. return false;
  5559. }
  5560. if (image.bufferView != -1) {
  5561. // Load image from the buffer view.
  5562. if (size_t(image.bufferView) >= model->bufferViews.size()) {
  5563. if (err) {
  5564. std::stringstream ss;
  5565. ss << "image[" << idx << "] bufferView \"" << image.bufferView
  5566. << "\" not found in the scene." << std::endl;
  5567. (*err) += ss.str();
  5568. }
  5569. return false;
  5570. }
  5571. const BufferView &bufferView =
  5572. model->bufferViews[size_t(image.bufferView)];
  5573. if (size_t(bufferView.buffer) >= model->buffers.size()) {
  5574. if (err) {
  5575. std::stringstream ss;
  5576. ss << "image[" << idx << "] buffer \"" << bufferView.buffer
  5577. << "\" not found in the scene." << std::endl;
  5578. (*err) += ss.str();
  5579. }
  5580. return false;
  5581. }
  5582. const Buffer &buffer = model->buffers[size_t(bufferView.buffer)];
  5583. if (LoadImageData == nullptr) {
  5584. if (err) {
  5585. (*err) += "No LoadImageData callback specified.\n";
  5586. }
  5587. return false;
  5588. }
  5589. bool ret = LoadImageData(
  5590. &image, idx, err, warn, image.width, image.height,
  5591. &buffer.data[bufferView.byteOffset],
  5592. static_cast<int>(bufferView.byteLength), load_image_user_data);
  5593. if (!ret) {
  5594. return false;
  5595. }
  5596. }
  5597. model->images.emplace_back(std::move(image));
  5598. ++idx;
  5599. return true;
  5600. });
  5601. if (!success) {
  5602. return false;
  5603. }
  5604. }
  5605. // 12. Parse Texture
  5606. {
  5607. bool success = ForEachInArray(v, "textures", [&](const detail::json &o) {
  5608. if (!detail::IsObject(o)) {
  5609. if (err) {
  5610. (*err) += "`textures' does not contain an JSON object.";
  5611. }
  5612. return false;
  5613. }
  5614. Texture texture;
  5615. if (!ParseTexture(&texture, err, o,
  5616. store_original_json_for_extras_and_extensions_,
  5617. base_dir)) {
  5618. return false;
  5619. }
  5620. model->textures.emplace_back(std::move(texture));
  5621. return true;
  5622. });
  5623. if (!success) {
  5624. return false;
  5625. }
  5626. }
  5627. // 13. Parse Animation
  5628. {
  5629. bool success = ForEachInArray(v, "animations", [&](const detail::json &o) {
  5630. if (!detail::IsObject(o)) {
  5631. if (err) {
  5632. (*err) += "`animations' does not contain an JSON object.";
  5633. }
  5634. return false;
  5635. }
  5636. Animation animation;
  5637. if (!ParseAnimation(&animation, err, o,
  5638. store_original_json_for_extras_and_extensions_)) {
  5639. return false;
  5640. }
  5641. model->animations.emplace_back(std::move(animation));
  5642. return true;
  5643. });
  5644. if (!success) {
  5645. return false;
  5646. }
  5647. }
  5648. // 14. Parse Skin
  5649. {
  5650. bool success = ForEachInArray(v, "skins", [&](const detail::json &o) {
  5651. if (!detail::IsObject(o)) {
  5652. if (err) {
  5653. (*err) += "`skins' does not contain an JSON object.";
  5654. }
  5655. return false;
  5656. }
  5657. Skin skin;
  5658. if (!ParseSkin(&skin, err, o,
  5659. store_original_json_for_extras_and_extensions_)) {
  5660. return false;
  5661. }
  5662. model->skins.emplace_back(std::move(skin));
  5663. return true;
  5664. });
  5665. if (!success) {
  5666. return false;
  5667. }
  5668. }
  5669. // 15. Parse Sampler
  5670. {
  5671. bool success = ForEachInArray(v, "samplers", [&](const detail::json &o) {
  5672. if (!detail::IsObject(o)) {
  5673. if (err) {
  5674. (*err) += "`samplers' does not contain an JSON object.";
  5675. }
  5676. return false;
  5677. }
  5678. Sampler sampler;
  5679. if (!ParseSampler(&sampler, err, o,
  5680. store_original_json_for_extras_and_extensions_)) {
  5681. return false;
  5682. }
  5683. model->samplers.emplace_back(std::move(sampler));
  5684. return true;
  5685. });
  5686. if (!success) {
  5687. return false;
  5688. }
  5689. }
  5690. // 16. Parse Camera
  5691. {
  5692. bool success = ForEachInArray(v, "cameras", [&](const detail::json &o) {
  5693. if (!detail::IsObject(o)) {
  5694. if (err) {
  5695. (*err) += "`cameras' does not contain an JSON object.";
  5696. }
  5697. return false;
  5698. }
  5699. Camera camera;
  5700. if (!ParseCamera(&camera, err, o,
  5701. store_original_json_for_extras_and_extensions_)) {
  5702. return false;
  5703. }
  5704. model->cameras.emplace_back(std::move(camera));
  5705. return true;
  5706. });
  5707. if (!success) {
  5708. return false;
  5709. }
  5710. }
  5711. // 17. Parse Extras & Extensions
  5712. ParseExtrasAndExtensions(model, err, v,
  5713. store_original_json_for_extras_and_extensions_);
  5714. // 18. Specific extension implementations
  5715. {
  5716. detail::json_const_iterator rootIt;
  5717. if (detail::FindMember(v, "extensions", rootIt) &&
  5718. detail::IsObject(detail::GetValue(rootIt))) {
  5719. const detail::json &root = detail::GetValue(rootIt);
  5720. detail::json_const_iterator it(detail::ObjectBegin(root));
  5721. detail::json_const_iterator itEnd(detail::ObjectEnd(root));
  5722. for (; it != itEnd; ++it) {
  5723. // parse KHR_lights_punctual extension
  5724. std::string key(detail::GetKey(it));
  5725. if ((key == "KHR_lights_punctual") &&
  5726. detail::IsObject(detail::GetValue(it))) {
  5727. const detail::json &object = detail::GetValue(it);
  5728. detail::json_const_iterator itLight;
  5729. if (detail::FindMember(object, "lights", itLight)) {
  5730. const detail::json &lights = detail::GetValue(itLight);
  5731. if (!detail::IsArray(lights)) {
  5732. continue;
  5733. }
  5734. auto arrayIt(detail::ArrayBegin(lights));
  5735. auto arrayItEnd(detail::ArrayEnd(lights));
  5736. for (; arrayIt != arrayItEnd; ++arrayIt) {
  5737. Light light;
  5738. if (!ParseLight(&light, err, *arrayIt,
  5739. store_original_json_for_extras_and_extensions_)) {
  5740. return false;
  5741. }
  5742. model->lights.emplace_back(std::move(light));
  5743. }
  5744. }
  5745. }
  5746. // parse KHR_audio extension
  5747. if ((key == "KHR_audio") && detail::IsObject(detail::GetValue(it))) {
  5748. const detail::json &object = detail::GetValue(it);
  5749. detail::json_const_iterator itKhrAudio;
  5750. if (detail::FindMember(object, "emitters", itKhrAudio)) {
  5751. const detail::json &emitters = detail::GetValue(itKhrAudio);
  5752. if (!detail::IsArray(emitters)) {
  5753. continue;
  5754. }
  5755. auto arrayIt(detail::ArrayBegin(emitters));
  5756. auto arrayItEnd(detail::ArrayEnd(emitters));
  5757. for (; arrayIt != arrayItEnd; ++arrayIt) {
  5758. AudioEmitter emitter;
  5759. if (!ParseAudioEmitter(
  5760. &emitter, err, *arrayIt,
  5761. store_original_json_for_extras_and_extensions_)) {
  5762. return false;
  5763. }
  5764. model->audioEmitters.emplace_back(std::move(emitter));
  5765. }
  5766. }
  5767. if (detail::FindMember(object, "sources", itKhrAudio)) {
  5768. const detail::json &sources = detail::GetValue(itKhrAudio);
  5769. if (!detail::IsArray(sources)) {
  5770. continue;
  5771. }
  5772. auto arrayIt(detail::ArrayBegin(sources));
  5773. auto arrayItEnd(detail::ArrayEnd(sources));
  5774. for (; arrayIt != arrayItEnd; ++arrayIt) {
  5775. AudioSource source;
  5776. if (!ParseAudioSource(
  5777. &source, err, *arrayIt,
  5778. store_original_json_for_extras_and_extensions_)) {
  5779. return false;
  5780. }
  5781. model->audioSources.emplace_back(std::move(source));
  5782. }
  5783. }
  5784. }
  5785. }
  5786. }
  5787. }
  5788. return true;
  5789. }
  5790. bool TinyGLTF::LoadASCIIFromString(Model *model, std::string *err,
  5791. std::string *warn, const char *str,
  5792. unsigned int length,
  5793. const std::string &base_dir,
  5794. unsigned int check_sections) {
  5795. is_binary_ = false;
  5796. bin_data_ = nullptr;
  5797. bin_size_ = 0;
  5798. return LoadFromString(model, err, warn, str, length, base_dir,
  5799. check_sections);
  5800. }
  5801. bool TinyGLTF::LoadASCIIFromFile(Model *model, std::string *err,
  5802. std::string *warn, const std::string &filename,
  5803. unsigned int check_sections) {
  5804. std::stringstream ss;
  5805. if (fs.ReadWholeFile == nullptr) {
  5806. // Programmer error, assert() ?
  5807. ss << "Failed to read file: " << filename
  5808. << ": one or more FS callback not set" << std::endl;
  5809. if (err) {
  5810. (*err) = ss.str();
  5811. }
  5812. return false;
  5813. }
  5814. std::vector<unsigned char> data;
  5815. std::string fileerr;
  5816. bool fileread = fs.ReadWholeFile(&data, &fileerr, filename, fs.user_data);
  5817. if (!fileread) {
  5818. ss << "Failed to read file: " << filename << ": " << fileerr << std::endl;
  5819. if (err) {
  5820. (*err) = ss.str();
  5821. }
  5822. return false;
  5823. }
  5824. size_t sz = data.size();
  5825. if (sz == 0) {
  5826. if (err) {
  5827. (*err) = "Empty file.";
  5828. }
  5829. return false;
  5830. }
  5831. std::string basedir = GetBaseDir(filename);
  5832. bool ret = LoadASCIIFromString(
  5833. model, err, warn, reinterpret_cast<const char *>(&data.at(0)),
  5834. static_cast<unsigned int>(data.size()), basedir, check_sections);
  5835. return ret;
  5836. }
  5837. bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
  5838. std::string *warn,
  5839. const unsigned char *bytes,
  5840. unsigned int size,
  5841. const std::string &base_dir,
  5842. unsigned int check_sections) {
  5843. if (size < 20) {
  5844. if (err) {
  5845. (*err) = "Too short data size for glTF Binary.";
  5846. }
  5847. return false;
  5848. }
  5849. if (bytes[0] == 'g' && bytes[1] == 'l' && bytes[2] == 'T' &&
  5850. bytes[3] == 'F') {
  5851. // ok
  5852. } else {
  5853. if (err) {
  5854. (*err) = "Invalid magic.";
  5855. }
  5856. return false;
  5857. }
  5858. unsigned int version; // 4 bytes
  5859. unsigned int length; // 4 bytes
  5860. unsigned int chunk0_length; // 4 bytes
  5861. unsigned int chunk0_format; // 4 bytes;
  5862. memcpy(&version, bytes + 4, 4);
  5863. swap4(&version);
  5864. memcpy(&length, bytes + 8, 4); // Total glb size, including header and all chunks.
  5865. swap4(&length);
  5866. memcpy(&chunk0_length, bytes + 12, 4); // JSON data length
  5867. swap4(&chunk0_length);
  5868. memcpy(&chunk0_format, bytes + 16, 4);
  5869. swap4(&chunk0_format);
  5870. // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#binary-gltf-layout
  5871. //
  5872. // In case the Bin buffer is not present, the size is exactly 20 + size of
  5873. // JSON contents,
  5874. // so use "greater than" operator.
  5875. //
  5876. // https://github.com/syoyo/tinygltf/issues/372
  5877. // Use 64bit uint to avoid integer overflow.
  5878. uint64_t header_and_json_size = 20ull + uint64_t(chunk0_length);
  5879. if (header_and_json_size > (std::numeric_limits<uint32_t>::max)()) {
  5880. // Do not allow 4GB or more GLB data.
  5881. if (err) {
  5882. (*err) = "Invalid glTF binary. GLB data exceeds 4GB.";
  5883. }
  5884. return false;
  5885. }
  5886. if ((header_and_json_size > uint64_t(size)) || (chunk0_length < 1) ||
  5887. (length > size) || (header_and_json_size > uint64_t(length)) ||
  5888. (chunk0_format != 0x4E4F534A)) { // 0x4E4F534A = JSON format.
  5889. if (err) {
  5890. (*err) = "Invalid glTF binary.";
  5891. }
  5892. return false;
  5893. }
  5894. // Padding check
  5895. // The start and the end of each chunk must be aligned to a 4-byte boundary.
  5896. // No padding check for chunk0 start since its 4byte-boundary is ensured.
  5897. if ((header_and_json_size % 4) != 0) {
  5898. if (err) {
  5899. (*err) = "JSON Chunk end does not aligned to a 4-byte boundary.";
  5900. }
  5901. return false;
  5902. }
  5903. // std::cout << "header_and_json_size = " << header_and_json_size << "\n";
  5904. // std::cout << "length = " << length << "\n";
  5905. // Chunk1(BIN) data
  5906. // The spec says: When the binary buffer is empty or when it is stored by
  5907. // other means, this chunk SHOULD be omitted. So when header + JSON data ==
  5908. // binary size, Chunk1 is omitted.
  5909. if (header_and_json_size == uint64_t(length)) {
  5910. bin_data_ = nullptr;
  5911. bin_size_ = 0;
  5912. } else {
  5913. // Read Chunk1 info(BIN data)
  5914. //
  5915. // issue-440:
  5916. // 'SHOULD' in glTF spec means 'RECOMMENDED',
  5917. // So there is a situation that Chunk1(BIN) is composed of zero-sized BIN data
  5918. // (chunksize(0) + binformat(BIN) = 8bytes).
  5919. //
  5920. if ((header_and_json_size + 8ull) > uint64_t(length)) {
  5921. if (err) {
  5922. (*err) =
  5923. "Insufficient storage space for Chunk1(BIN data). At least Chunk1 "
  5924. "Must have 8 or more bytes, but got " +
  5925. std::to_string((header_and_json_size + 8ull) - uint64_t(length)) +
  5926. ".\n";
  5927. }
  5928. return false;
  5929. }
  5930. unsigned int chunk1_length{0}; // 4 bytes
  5931. unsigned int chunk1_format{0}; // 4 bytes;
  5932. memcpy(&chunk1_length, bytes + header_and_json_size,
  5933. 4); // Bin data length
  5934. swap4(&chunk1_length);
  5935. memcpy(&chunk1_format, bytes + header_and_json_size + 4, 4);
  5936. swap4(&chunk1_format);
  5937. if (chunk1_format != 0x004e4942) {
  5938. if (err) {
  5939. (*err) = "Invalid chunkType for Chunk1.";
  5940. }
  5941. return false;
  5942. }
  5943. if (chunk1_length == 0) {
  5944. if (header_and_json_size + 8 > uint64_t(length)) {
  5945. if (err) {
  5946. (*err) = "BIN Chunk header location exceeds the GLB size.";
  5947. }
  5948. return false;
  5949. }
  5950. bin_data_ = nullptr;
  5951. } else {
  5952. // When BIN chunk size is not zero, at least Chunk1 should have 12 bytes(8 bytes(header) + 4 bytes(bin
  5953. // payload could be 1~3 bytes, but need to be aligned to 4 bytes)
  5954. if (chunk1_length < 4) {
  5955. if (err) {
  5956. (*err) = "Insufficient Chunk1(BIN) data size.";
  5957. }
  5958. return false;
  5959. }
  5960. if ((chunk1_length % 4) != 0) {
  5961. if (strictness_==ParseStrictness::Permissive) {
  5962. if (warn) {
  5963. (*warn) += "BIN Chunk end is not aligned to a 4-byte boundary.\n";
  5964. }
  5965. }
  5966. else {
  5967. if (err) {
  5968. (*err) = "BIN Chunk end is not aligned to a 4-byte boundary.";
  5969. }
  5970. return false;
  5971. }
  5972. }
  5973. // +8 chunk1 header size.
  5974. if (uint64_t(chunk1_length) + header_and_json_size + 8 > uint64_t(length)) {
  5975. if (err) {
  5976. (*err) = "BIN Chunk data length exceeds the GLB size.";
  5977. }
  5978. return false;
  5979. }
  5980. bin_data_ = bytes + header_and_json_size +
  5981. 8; // 4 bytes (bin_buffer_length) + 4 bytes(bin_buffer_format)
  5982. }
  5983. bin_size_ = size_t(chunk1_length);
  5984. }
  5985. is_binary_ = true;
  5986. bool ret = LoadFromString(model, err, warn,
  5987. reinterpret_cast<const char *>(&bytes[20]),
  5988. chunk0_length, base_dir, check_sections);
  5989. if (!ret) {
  5990. return ret;
  5991. }
  5992. return true;
  5993. }
  5994. bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err,
  5995. std::string *warn,
  5996. const std::string &filename,
  5997. unsigned int check_sections) {
  5998. std::stringstream ss;
  5999. if (fs.ReadWholeFile == nullptr) {
  6000. // Programmer error, assert() ?
  6001. ss << "Failed to read file: " << filename
  6002. << ": one or more FS callback not set" << std::endl;
  6003. if (err) {
  6004. (*err) = ss.str();
  6005. }
  6006. return false;
  6007. }
  6008. std::vector<unsigned char> data;
  6009. std::string fileerr;
  6010. bool fileread = fs.ReadWholeFile(&data, &fileerr, filename, fs.user_data);
  6011. if (!fileread) {
  6012. ss << "Failed to read file: " << filename << ": " << fileerr << std::endl;
  6013. if (err) {
  6014. (*err) = ss.str();
  6015. }
  6016. return false;
  6017. }
  6018. std::string basedir = GetBaseDir(filename);
  6019. bool ret = LoadBinaryFromMemory(model, err, warn, &data.at(0),
  6020. static_cast<unsigned int>(data.size()),
  6021. basedir, check_sections);
  6022. return ret;
  6023. }
  6024. ///////////////////////
  6025. // GLTF Serialization
  6026. ///////////////////////
  6027. namespace detail {
  6028. detail::json JsonFromString(const char *s) {
  6029. #ifdef TINYGLTF_USE_RAPIDJSON
  6030. return detail::json(s, detail::GetAllocator());
  6031. #else
  6032. return detail::json(s);
  6033. #endif
  6034. }
  6035. void JsonAssign(detail::json &dest, const detail::json &src) {
  6036. #ifdef TINYGLTF_USE_RAPIDJSON
  6037. dest.CopyFrom(src, detail::GetAllocator());
  6038. #else
  6039. dest = src;
  6040. #endif
  6041. }
  6042. void JsonAddMember(detail::json &o, const char *key, detail::json &&value) {
  6043. #ifdef TINYGLTF_USE_RAPIDJSON
  6044. if (!o.IsObject()) {
  6045. o.SetObject();
  6046. }
  6047. // Issue 420.
  6048. // AddMember may create duplicated key, so use [] API when a key already
  6049. // exists.
  6050. // https://github.com/Tencent/rapidjson/issues/771#issuecomment-254386863
  6051. detail::json_const_iterator it;
  6052. if (detail::FindMember(o, key, it)) {
  6053. o[key] = std::move(value); // replace
  6054. } else {
  6055. o.AddMember(detail::json(key, detail::GetAllocator()), std::move(value),
  6056. detail::GetAllocator());
  6057. }
  6058. #else
  6059. o[key] = std::move(value);
  6060. #endif
  6061. }
  6062. void JsonPushBack(detail::json &o, detail::json &&value) {
  6063. #ifdef TINYGLTF_USE_RAPIDJSON
  6064. o.PushBack(std::move(value), detail::GetAllocator());
  6065. #else
  6066. o.push_back(std::move(value));
  6067. #endif
  6068. }
  6069. bool JsonIsNull(const detail::json &o) {
  6070. #ifdef TINYGLTF_USE_RAPIDJSON
  6071. return o.IsNull();
  6072. #else
  6073. return o.is_null();
  6074. #endif
  6075. }
  6076. void JsonSetObject(detail::json &o) {
  6077. #ifdef TINYGLTF_USE_RAPIDJSON
  6078. o.SetObject();
  6079. #else
  6080. o = o.object({});
  6081. #endif
  6082. }
  6083. void JsonReserveArray(detail::json &o, size_t s) {
  6084. #ifdef TINYGLTF_USE_RAPIDJSON
  6085. o.SetArray();
  6086. o.Reserve(static_cast<rapidjson::SizeType>(s), detail::GetAllocator());
  6087. #endif
  6088. (void)(o);
  6089. (void)(s);
  6090. }
  6091. } // namespace detail
  6092. // typedef std::pair<std::string, detail::json> json_object_pair;
  6093. template <typename T>
  6094. static void SerializeNumberProperty(const std::string &key, T number,
  6095. detail::json &obj) {
  6096. // obj.insert(
  6097. // json_object_pair(key, detail::json(static_cast<double>(number))));
  6098. // obj[key] = static_cast<double>(number);
  6099. detail::JsonAddMember(obj, key.c_str(), detail::json(number));
  6100. }
  6101. #ifdef TINYGLTF_USE_RAPIDJSON
  6102. template <>
  6103. void SerializeNumberProperty(const std::string &key, size_t number,
  6104. detail::json &obj) {
  6105. detail::JsonAddMember(obj, key.c_str(),
  6106. detail::json(static_cast<uint64_t>(number)));
  6107. }
  6108. #endif
  6109. template <typename T>
  6110. static void SerializeNumberArrayProperty(const std::string &key,
  6111. const std::vector<T> &value,
  6112. detail::json &obj) {
  6113. if (value.empty()) return;
  6114. detail::json ary;
  6115. detail::JsonReserveArray(ary, value.size());
  6116. for (const auto &s : value) {
  6117. detail::JsonPushBack(ary, detail::json(s));
  6118. }
  6119. detail::JsonAddMember(obj, key.c_str(), std::move(ary));
  6120. }
  6121. static void SerializeStringProperty(const std::string &key,
  6122. const std::string &value,
  6123. detail::json &obj) {
  6124. detail::JsonAddMember(obj, key.c_str(),
  6125. detail::JsonFromString(value.c_str()));
  6126. }
  6127. static void SerializeStringArrayProperty(const std::string &key,
  6128. const std::vector<std::string> &value,
  6129. detail::json &obj) {
  6130. detail::json ary;
  6131. detail::JsonReserveArray(ary, value.size());
  6132. for (auto &s : value) {
  6133. detail::JsonPushBack(ary, detail::JsonFromString(s.c_str()));
  6134. }
  6135. detail::JsonAddMember(obj, key.c_str(), std::move(ary));
  6136. }
  6137. static bool ValueToJson(const Value &value, detail::json *ret) {
  6138. detail::json obj;
  6139. #ifdef TINYGLTF_USE_RAPIDJSON
  6140. switch (value.Type()) {
  6141. case REAL_TYPE:
  6142. obj.SetDouble(value.Get<double>());
  6143. break;
  6144. case INT_TYPE:
  6145. obj.SetInt(value.Get<int>());
  6146. break;
  6147. case BOOL_TYPE:
  6148. obj.SetBool(value.Get<bool>());
  6149. break;
  6150. case STRING_TYPE:
  6151. obj.SetString(value.Get<std::string>().c_str(), detail::GetAllocator());
  6152. break;
  6153. case ARRAY_TYPE: {
  6154. obj.SetArray();
  6155. obj.Reserve(static_cast<rapidjson::SizeType>(value.ArrayLen()),
  6156. detail::GetAllocator());
  6157. for (unsigned int i = 0; i < value.ArrayLen(); ++i) {
  6158. Value elementValue = value.Get(int(i));
  6159. detail::json elementJson;
  6160. if (ValueToJson(value.Get(int(i)), &elementJson))
  6161. obj.PushBack(std::move(elementJson), detail::GetAllocator());
  6162. }
  6163. break;
  6164. }
  6165. case BINARY_TYPE:
  6166. // TODO
  6167. // obj = detail::json(value.Get<std::vector<unsigned char>>());
  6168. return false;
  6169. break;
  6170. case OBJECT_TYPE: {
  6171. obj.SetObject();
  6172. Value::Object objMap = value.Get<Value::Object>();
  6173. for (auto &it : objMap) {
  6174. detail::json elementJson;
  6175. if (ValueToJson(it.second, &elementJson)) {
  6176. obj.AddMember(detail::json(it.first.c_str(), detail::GetAllocator()),
  6177. std::move(elementJson), detail::GetAllocator());
  6178. }
  6179. }
  6180. break;
  6181. }
  6182. case NULL_TYPE:
  6183. default:
  6184. return false;
  6185. }
  6186. #else
  6187. switch (value.Type()) {
  6188. case REAL_TYPE:
  6189. obj = detail::json(value.Get<double>());
  6190. break;
  6191. case INT_TYPE:
  6192. obj = detail::json(value.Get<int>());
  6193. break;
  6194. case BOOL_TYPE:
  6195. obj = detail::json(value.Get<bool>());
  6196. break;
  6197. case STRING_TYPE:
  6198. obj = detail::json(value.Get<std::string>());
  6199. break;
  6200. case ARRAY_TYPE: {
  6201. for (size_t i = 0; i < value.ArrayLen(); ++i) {
  6202. Value elementValue = value.Get(i);
  6203. detail::json elementJson;
  6204. if (ValueToJson(value.Get(i), &elementJson))
  6205. obj.push_back(elementJson);
  6206. }
  6207. break;
  6208. }
  6209. case BINARY_TYPE:
  6210. // TODO
  6211. // obj = json(value.Get<std::vector<unsigned char>>());
  6212. return false;
  6213. break;
  6214. case OBJECT_TYPE: {
  6215. Value::Object objMap = value.Get<Value::Object>();
  6216. for (auto &it : objMap) {
  6217. detail::json elementJson;
  6218. if (ValueToJson(it.second, &elementJson)) obj[it.first] = elementJson;
  6219. }
  6220. break;
  6221. }
  6222. case NULL_TYPE:
  6223. default:
  6224. return false;
  6225. }
  6226. #endif
  6227. if (ret) *ret = std::move(obj);
  6228. return true;
  6229. }
  6230. static void SerializeValue(const std::string &key, const Value &value,
  6231. detail::json &obj) {
  6232. detail::json ret;
  6233. if (ValueToJson(value, &ret)) {
  6234. detail::JsonAddMember(obj, key.c_str(), std::move(ret));
  6235. }
  6236. }
  6237. static void SerializeGltfBufferData(const std::vector<unsigned char> &data,
  6238. detail::json &o) {
  6239. std::string header = "data:application/octet-stream;base64,";
  6240. if (data.size() > 0) {
  6241. std::string encodedData =
  6242. base64_encode(&data[0], static_cast<unsigned int>(data.size()));
  6243. SerializeStringProperty("uri", header + encodedData, o);
  6244. } else {
  6245. // Issue #229
  6246. // size 0 is allowed. Just emit mime header.
  6247. SerializeStringProperty("uri", header, o);
  6248. }
  6249. }
  6250. static bool SerializeGltfBufferData(const std::vector<unsigned char> &data,
  6251. const std::string &binFilename) {
  6252. #ifdef _WIN32
  6253. #if defined(__GLIBCXX__) // mingw
  6254. int file_descriptor = _wopen(UTF8ToWchar(binFilename).c_str(),
  6255. _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY, _S_IWRITE);
  6256. __gnu_cxx::stdio_filebuf<char> wfile_buf(
  6257. file_descriptor, std::ios_base::out | std::ios_base::binary);
  6258. std::ostream output(&wfile_buf);
  6259. if (!wfile_buf.is_open()) return false;
  6260. #elif defined(_MSC_VER)
  6261. std::ofstream output(UTF8ToWchar(binFilename).c_str(), std::ofstream::binary);
  6262. if (!output.is_open()) return false;
  6263. #else
  6264. std::ofstream output(binFilename.c_str(), std::ofstream::binary);
  6265. if (!output.is_open()) return false;
  6266. #endif
  6267. #else
  6268. std::ofstream output(binFilename.c_str(), std::ofstream::binary);
  6269. if (!output.is_open()) return false;
  6270. #endif
  6271. if (data.size() > 0) {
  6272. output.write(reinterpret_cast<const char *>(&data[0]),
  6273. std::streamsize(data.size()));
  6274. } else {
  6275. // Issue #229
  6276. // size 0 will be still valid buffer data.
  6277. // write empty file.
  6278. }
  6279. return true;
  6280. }
  6281. #if 0 // FIXME(syoyo): not used. will be removed in the future release.
  6282. static void SerializeParameterMap(ParameterMap &param, detail::json &o) {
  6283. for (ParameterMap::iterator paramIt = param.begin(); paramIt != param.end();
  6284. ++paramIt) {
  6285. if (paramIt->second.number_array.size()) {
  6286. SerializeNumberArrayProperty<double>(paramIt->first,
  6287. paramIt->second.number_array, o);
  6288. } else if (paramIt->second.json_double_value.size()) {
  6289. detail::json json_double_value;
  6290. for (std::map<std::string, double>::iterator it =
  6291. paramIt->second.json_double_value.begin();
  6292. it != paramIt->second.json_double_value.end(); ++it) {
  6293. if (it->first == "index") {
  6294. json_double_value[it->first] = paramIt->second.TextureIndex();
  6295. } else {
  6296. json_double_value[it->first] = it->second;
  6297. }
  6298. }
  6299. o[paramIt->first] = json_double_value;
  6300. } else if (!paramIt->second.string_value.empty()) {
  6301. SerializeStringProperty(paramIt->first, paramIt->second.string_value, o);
  6302. } else if (paramIt->second.has_number_value) {
  6303. o[paramIt->first] = paramIt->second.number_value;
  6304. } else {
  6305. o[paramIt->first] = paramIt->second.bool_value;
  6306. }
  6307. }
  6308. }
  6309. #endif
  6310. static void SerializeExtensionMap(const ExtensionMap &extensions,
  6311. detail::json &o) {
  6312. if (!extensions.size()) return;
  6313. detail::json extMap;
  6314. for (ExtensionMap::const_iterator extIt = extensions.begin();
  6315. extIt != extensions.end(); ++extIt) {
  6316. // Allow an empty object for extension(#97)
  6317. detail::json ret;
  6318. bool isNull = true;
  6319. if (ValueToJson(extIt->second, &ret)) {
  6320. isNull = detail::JsonIsNull(ret);
  6321. detail::JsonAddMember(extMap, extIt->first.c_str(), std::move(ret));
  6322. }
  6323. if (isNull) {
  6324. if (!(extIt->first.empty())) { // name should not be empty, but for sure
  6325. // create empty object so that an extension name is still included in
  6326. // json.
  6327. detail::json empty;
  6328. detail::JsonSetObject(empty);
  6329. detail::JsonAddMember(extMap, extIt->first.c_str(), std::move(empty));
  6330. }
  6331. }
  6332. }
  6333. detail::JsonAddMember(o, "extensions", std::move(extMap));
  6334. }
  6335. static void SerializeExtras(const Value &extras, detail::json &o) {
  6336. if (extras.Type() != NULL_TYPE) SerializeValue("extras", extras, o);
  6337. }
  6338. template <typename GltfType>
  6339. void SerializeExtrasAndExtensions(const GltfType &obj, detail::json &o) {
  6340. SerializeExtensionMap(obj.extensions, o);
  6341. SerializeExtras(obj.extras, o);
  6342. }
  6343. static void SerializeGltfAccessor(const Accessor &accessor, detail::json &o) {
  6344. if (accessor.bufferView >= 0)
  6345. SerializeNumberProperty<int>("bufferView", accessor.bufferView, o);
  6346. if (accessor.byteOffset != 0)
  6347. SerializeNumberProperty<size_t>("byteOffset", accessor.byteOffset, o);
  6348. SerializeNumberProperty<int>("componentType", accessor.componentType, o);
  6349. SerializeNumberProperty<size_t>("count", accessor.count, o);
  6350. if ((accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT) ||
  6351. (accessor.componentType == TINYGLTF_COMPONENT_TYPE_DOUBLE)) {
  6352. SerializeNumberArrayProperty<double>("min", accessor.minValues, o);
  6353. SerializeNumberArrayProperty<double>("max", accessor.maxValues, o);
  6354. } else {
  6355. // Issue #301. Serialize as integer.
  6356. // Assume int value is within [-2**31-1, 2**31-1]
  6357. {
  6358. std::vector<int> values;
  6359. std::transform(accessor.minValues.begin(), accessor.minValues.end(),
  6360. std::back_inserter(values),
  6361. [](double v) { return static_cast<int>(v); });
  6362. SerializeNumberArrayProperty<int>("min", values, o);
  6363. }
  6364. {
  6365. std::vector<int> values;
  6366. std::transform(accessor.maxValues.begin(), accessor.maxValues.end(),
  6367. std::back_inserter(values),
  6368. [](double v) { return static_cast<int>(v); });
  6369. SerializeNumberArrayProperty<int>("max", values, o);
  6370. }
  6371. }
  6372. if (accessor.normalized)
  6373. SerializeValue("normalized", Value(accessor.normalized), o);
  6374. std::string type;
  6375. switch (accessor.type) {
  6376. case TINYGLTF_TYPE_SCALAR:
  6377. type = "SCALAR";
  6378. break;
  6379. case TINYGLTF_TYPE_VEC2:
  6380. type = "VEC2";
  6381. break;
  6382. case TINYGLTF_TYPE_VEC3:
  6383. type = "VEC3";
  6384. break;
  6385. case TINYGLTF_TYPE_VEC4:
  6386. type = "VEC4";
  6387. break;
  6388. case TINYGLTF_TYPE_MAT2:
  6389. type = "MAT2";
  6390. break;
  6391. case TINYGLTF_TYPE_MAT3:
  6392. type = "MAT3";
  6393. break;
  6394. case TINYGLTF_TYPE_MAT4:
  6395. type = "MAT4";
  6396. break;
  6397. }
  6398. SerializeStringProperty("type", type, o);
  6399. if (!accessor.name.empty()) SerializeStringProperty("name", accessor.name, o);
  6400. SerializeExtrasAndExtensions(accessor, o);
  6401. // sparse
  6402. if (accessor.sparse.isSparse) {
  6403. detail::json sparse;
  6404. SerializeNumberProperty<int>("count", accessor.sparse.count, sparse);
  6405. {
  6406. detail::json indices;
  6407. SerializeNumberProperty<int>("bufferView",
  6408. accessor.sparse.indices.bufferView, indices);
  6409. SerializeNumberProperty<size_t>("byteOffset",
  6410. accessor.sparse.indices.byteOffset, indices);
  6411. SerializeNumberProperty<int>(
  6412. "componentType", accessor.sparse.indices.componentType, indices);
  6413. SerializeExtrasAndExtensions(accessor.sparse.indices, indices);
  6414. detail::JsonAddMember(sparse, "indices", std::move(indices));
  6415. }
  6416. {
  6417. detail::json values;
  6418. SerializeNumberProperty<int>("bufferView",
  6419. accessor.sparse.values.bufferView, values);
  6420. SerializeNumberProperty<size_t>("byteOffset",
  6421. accessor.sparse.values.byteOffset, values);
  6422. SerializeExtrasAndExtensions(accessor.sparse.values, values);
  6423. detail::JsonAddMember(sparse, "values", std::move(values));
  6424. }
  6425. SerializeExtrasAndExtensions(accessor.sparse, sparse);
  6426. detail::JsonAddMember(o, "sparse", std::move(sparse));
  6427. }
  6428. }
  6429. static void SerializeGltfAnimationChannel(const AnimationChannel &channel,
  6430. detail::json &o) {
  6431. SerializeNumberProperty("sampler", channel.sampler, o);
  6432. {
  6433. detail::json target;
  6434. if (channel.target_node >= 0) {
  6435. SerializeNumberProperty("node", channel.target_node, target);
  6436. }
  6437. SerializeStringProperty("path", channel.target_path, target);
  6438. SerializeExtensionMap(channel.target_extensions, target);
  6439. SerializeExtras(channel.target_extras, target);
  6440. detail::JsonAddMember(o, "target", std::move(target));
  6441. }
  6442. SerializeExtrasAndExtensions(channel, o);
  6443. }
  6444. static void SerializeGltfAnimationSampler(const AnimationSampler &sampler,
  6445. detail::json &o) {
  6446. SerializeNumberProperty("input", sampler.input, o);
  6447. SerializeNumberProperty("output", sampler.output, o);
  6448. SerializeStringProperty("interpolation", sampler.interpolation, o);
  6449. SerializeExtrasAndExtensions(sampler, o);
  6450. }
  6451. static void SerializeGltfAnimation(const Animation &animation,
  6452. detail::json &o) {
  6453. if (!animation.name.empty())
  6454. SerializeStringProperty("name", animation.name, o);
  6455. {
  6456. detail::json channels;
  6457. detail::JsonReserveArray(channels, animation.channels.size());
  6458. for (unsigned int i = 0; i < animation.channels.size(); ++i) {
  6459. detail::json channel;
  6460. AnimationChannel gltfChannel = animation.channels[i];
  6461. SerializeGltfAnimationChannel(gltfChannel, channel);
  6462. detail::JsonPushBack(channels, std::move(channel));
  6463. }
  6464. detail::JsonAddMember(o, "channels", std::move(channels));
  6465. }
  6466. {
  6467. detail::json samplers;
  6468. detail::JsonReserveArray(samplers, animation.samplers.size());
  6469. for (unsigned int i = 0; i < animation.samplers.size(); ++i) {
  6470. detail::json sampler;
  6471. AnimationSampler gltfSampler = animation.samplers[i];
  6472. SerializeGltfAnimationSampler(gltfSampler, sampler);
  6473. detail::JsonPushBack(samplers, std::move(sampler));
  6474. }
  6475. detail::JsonAddMember(o, "samplers", std::move(samplers));
  6476. }
  6477. SerializeExtrasAndExtensions(animation, o);
  6478. }
  6479. static void SerializeGltfAsset(const Asset &asset, detail::json &o) {
  6480. if (!asset.generator.empty()) {
  6481. SerializeStringProperty("generator", asset.generator, o);
  6482. }
  6483. if (!asset.copyright.empty()) {
  6484. SerializeStringProperty("copyright", asset.copyright, o);
  6485. }
  6486. auto version = asset.version;
  6487. if (version.empty()) {
  6488. // Just in case
  6489. // `version` must be defined
  6490. version = "2.0";
  6491. }
  6492. // TODO(syoyo): Do we need to check if `version` is greater or equal to 2.0?
  6493. SerializeStringProperty("version", version, o);
  6494. SerializeExtrasAndExtensions(asset, o);
  6495. }
  6496. static void SerializeGltfBufferBin(const Buffer &buffer, detail::json &o,
  6497. std::vector<unsigned char> &binBuffer) {
  6498. SerializeNumberProperty("byteLength", buffer.data.size(), o);
  6499. binBuffer = buffer.data;
  6500. if (buffer.name.size()) SerializeStringProperty("name", buffer.name, o);
  6501. SerializeExtrasAndExtensions(buffer, o);
  6502. }
  6503. static void SerializeGltfBuffer(const Buffer &buffer, detail::json &o) {
  6504. SerializeNumberProperty("byteLength", buffer.data.size(), o);
  6505. SerializeGltfBufferData(buffer.data, o);
  6506. if (buffer.name.size()) SerializeStringProperty("name", buffer.name, o);
  6507. SerializeExtrasAndExtensions(buffer, o);
  6508. }
  6509. static bool SerializeGltfBuffer(const Buffer &buffer, detail::json &o,
  6510. const std::string &binFilename,
  6511. const std::string &binUri) {
  6512. if (!SerializeGltfBufferData(buffer.data, binFilename)) return false;
  6513. SerializeNumberProperty("byteLength", buffer.data.size(), o);
  6514. SerializeStringProperty("uri", binUri, o);
  6515. if (buffer.name.size()) SerializeStringProperty("name", buffer.name, o);
  6516. SerializeExtrasAndExtensions(buffer, o);
  6517. return true;
  6518. }
  6519. static void SerializeGltfBufferView(const BufferView &bufferView,
  6520. detail::json &o) {
  6521. SerializeNumberProperty("buffer", bufferView.buffer, o);
  6522. SerializeNumberProperty<size_t>("byteLength", bufferView.byteLength, o);
  6523. // byteStride is optional, minimum allowed is 4
  6524. if (bufferView.byteStride >= 4) {
  6525. SerializeNumberProperty<size_t>("byteStride", bufferView.byteStride, o);
  6526. }
  6527. // byteOffset is optional, default is 0
  6528. if (bufferView.byteOffset > 0) {
  6529. SerializeNumberProperty<size_t>("byteOffset", bufferView.byteOffset, o);
  6530. }
  6531. // Target is optional, check if it contains a valid value
  6532. if (bufferView.target == TINYGLTF_TARGET_ARRAY_BUFFER ||
  6533. bufferView.target == TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER) {
  6534. SerializeNumberProperty("target", bufferView.target, o);
  6535. }
  6536. if (bufferView.name.size()) {
  6537. SerializeStringProperty("name", bufferView.name, o);
  6538. }
  6539. SerializeExtrasAndExtensions(bufferView, o);
  6540. }
  6541. static void SerializeGltfImage(const Image &image, const std::string &uri,
  6542. detail::json &o) {
  6543. // From 2.7.0, we look for `uri` parameter, not `Image.uri`
  6544. // if uri is empty, the mimeType and bufferview should be set
  6545. if (uri.empty()) {
  6546. SerializeStringProperty("mimeType", image.mimeType, o);
  6547. SerializeNumberProperty<int>("bufferView", image.bufferView, o);
  6548. } else {
  6549. SerializeStringProperty("uri", uri, o);
  6550. }
  6551. if (image.name.size()) {
  6552. SerializeStringProperty("name", image.name, o);
  6553. }
  6554. SerializeExtrasAndExtensions(image, o);
  6555. }
  6556. static void SerializeGltfTextureInfo(const TextureInfo &texinfo,
  6557. detail::json &o) {
  6558. SerializeNumberProperty("index", texinfo.index, o);
  6559. if (texinfo.texCoord != 0) {
  6560. SerializeNumberProperty("texCoord", texinfo.texCoord, o);
  6561. }
  6562. SerializeExtrasAndExtensions(texinfo, o);
  6563. }
  6564. static void SerializeGltfNormalTextureInfo(const NormalTextureInfo &texinfo,
  6565. detail::json &o) {
  6566. SerializeNumberProperty("index", texinfo.index, o);
  6567. if (texinfo.texCoord != 0) {
  6568. SerializeNumberProperty("texCoord", texinfo.texCoord, o);
  6569. }
  6570. if (!TINYGLTF_DOUBLE_EQUAL(texinfo.scale, 1.0)) {
  6571. SerializeNumberProperty("scale", texinfo.scale, o);
  6572. }
  6573. SerializeExtrasAndExtensions(texinfo, o);
  6574. }
  6575. static void SerializeGltfOcclusionTextureInfo(
  6576. const OcclusionTextureInfo &texinfo, detail::json &o) {
  6577. SerializeNumberProperty("index", texinfo.index, o);
  6578. if (texinfo.texCoord != 0) {
  6579. SerializeNumberProperty("texCoord", texinfo.texCoord, o);
  6580. }
  6581. if (!TINYGLTF_DOUBLE_EQUAL(texinfo.strength, 1.0)) {
  6582. SerializeNumberProperty("strength", texinfo.strength, o);
  6583. }
  6584. SerializeExtrasAndExtensions(texinfo, o);
  6585. }
  6586. static void SerializeGltfPbrMetallicRoughness(const PbrMetallicRoughness &pbr,
  6587. detail::json &o) {
  6588. std::vector<double> default_baseColorFactor = {1.0, 1.0, 1.0, 1.0};
  6589. if (!Equals(pbr.baseColorFactor, default_baseColorFactor)) {
  6590. SerializeNumberArrayProperty<double>("baseColorFactor", pbr.baseColorFactor,
  6591. o);
  6592. }
  6593. if (!TINYGLTF_DOUBLE_EQUAL(pbr.metallicFactor, 1.0)) {
  6594. SerializeNumberProperty("metallicFactor", pbr.metallicFactor, o);
  6595. }
  6596. if (!TINYGLTF_DOUBLE_EQUAL(pbr.roughnessFactor, 1.0)) {
  6597. SerializeNumberProperty("roughnessFactor", pbr.roughnessFactor, o);
  6598. }
  6599. if (pbr.baseColorTexture.index > -1) {
  6600. detail::json texinfo;
  6601. SerializeGltfTextureInfo(pbr.baseColorTexture, texinfo);
  6602. detail::JsonAddMember(o, "baseColorTexture", std::move(texinfo));
  6603. }
  6604. if (pbr.metallicRoughnessTexture.index > -1) {
  6605. detail::json texinfo;
  6606. SerializeGltfTextureInfo(pbr.metallicRoughnessTexture, texinfo);
  6607. detail::JsonAddMember(o, "metallicRoughnessTexture", std::move(texinfo));
  6608. }
  6609. SerializeExtrasAndExtensions(pbr, o);
  6610. }
  6611. static void SerializeGltfMaterial(const Material &material, detail::json &o) {
  6612. if (material.name.size()) {
  6613. SerializeStringProperty("name", material.name, o);
  6614. }
  6615. // QUESTION(syoyo): Write material parameters regardless of its default value?
  6616. if (!TINYGLTF_DOUBLE_EQUAL(material.alphaCutoff, 0.5)) {
  6617. SerializeNumberProperty("alphaCutoff", material.alphaCutoff, o);
  6618. }
  6619. if (material.alphaMode.compare("OPAQUE") != 0) {
  6620. SerializeStringProperty("alphaMode", material.alphaMode, o);
  6621. }
  6622. if (material.doubleSided != false)
  6623. detail::JsonAddMember(o, "doubleSided", detail::json(material.doubleSided));
  6624. if (material.normalTexture.index > -1) {
  6625. detail::json texinfo;
  6626. SerializeGltfNormalTextureInfo(material.normalTexture, texinfo);
  6627. detail::JsonAddMember(o, "normalTexture", std::move(texinfo));
  6628. }
  6629. if (material.occlusionTexture.index > -1) {
  6630. detail::json texinfo;
  6631. SerializeGltfOcclusionTextureInfo(material.occlusionTexture, texinfo);
  6632. detail::JsonAddMember(o, "occlusionTexture", std::move(texinfo));
  6633. }
  6634. if (material.emissiveTexture.index > -1) {
  6635. detail::json texinfo;
  6636. SerializeGltfTextureInfo(material.emissiveTexture, texinfo);
  6637. detail::JsonAddMember(o, "emissiveTexture", std::move(texinfo));
  6638. }
  6639. std::vector<double> default_emissiveFactor = {0.0, 0.0, 0.0};
  6640. if (!Equals(material.emissiveFactor, default_emissiveFactor)) {
  6641. SerializeNumberArrayProperty<double>("emissiveFactor",
  6642. material.emissiveFactor, o);
  6643. }
  6644. {
  6645. detail::json pbrMetallicRoughness;
  6646. SerializeGltfPbrMetallicRoughness(material.pbrMetallicRoughness,
  6647. pbrMetallicRoughness);
  6648. // Issue 204
  6649. // Do not serialize `pbrMetallicRoughness` if pbrMetallicRoughness has all
  6650. // default values(json is null). Otherwise it will serialize to
  6651. // `pbrMetallicRoughness : null`, which cannot be read by other glTF
  6652. // importers (and validators).
  6653. //
  6654. if (!detail::JsonIsNull(pbrMetallicRoughness)) {
  6655. detail::JsonAddMember(o, "pbrMetallicRoughness",
  6656. std::move(pbrMetallicRoughness));
  6657. }
  6658. }
  6659. #if 0 // legacy way. just for the record.
  6660. if (material.values.size()) {
  6661. detail::json pbrMetallicRoughness;
  6662. SerializeParameterMap(material.values, pbrMetallicRoughness);
  6663. detail::JsonAddMember(o, "pbrMetallicRoughness", std::move(pbrMetallicRoughness));
  6664. }
  6665. SerializeParameterMap(material.additionalValues, o);
  6666. #endif
  6667. SerializeExtrasAndExtensions(material, o);
  6668. // MSFT_lod
  6669. if (!material.lods.empty()) {
  6670. detail::json_iterator it;
  6671. if (!detail::FindMember(o, "extensions", it)) {
  6672. detail::json extensions;
  6673. detail::JsonSetObject(extensions);
  6674. detail::JsonAddMember(o, "extensions", std::move(extensions));
  6675. detail::FindMember(o, "extensions", it);
  6676. }
  6677. auto &extensions = detail::GetValue(it);
  6678. if (!detail::FindMember(extensions, "MSFT_lod", it)) {
  6679. detail::json lod;
  6680. detail::JsonSetObject(lod);
  6681. detail::JsonAddMember(extensions, "MSFT_lod", std::move(lod));
  6682. detail::FindMember(extensions, "MSFT_lod", it);
  6683. }
  6684. SerializeNumberArrayProperty<int>("ids", material.lods, detail::GetValue(it));
  6685. } else {
  6686. detail::json_iterator ext_it;
  6687. if (detail::FindMember(o, "extensions", ext_it)) {
  6688. auto &extensions = detail::GetValue(ext_it);
  6689. detail::json_iterator lp_it;
  6690. if (detail::FindMember(extensions, "MSFT_lod", lp_it)) {
  6691. detail::Erase(extensions, lp_it);
  6692. }
  6693. if (detail::IsEmpty(extensions)) {
  6694. detail::Erase(o, ext_it);
  6695. }
  6696. }
  6697. }
  6698. }
  6699. static void SerializeGltfMesh(const Mesh &mesh, detail::json &o) {
  6700. detail::json primitives;
  6701. detail::JsonReserveArray(primitives, mesh.primitives.size());
  6702. for (unsigned int i = 0; i < mesh.primitives.size(); ++i) {
  6703. detail::json primitive;
  6704. const Primitive &gltfPrimitive = mesh.primitives[i]; // don't make a copy
  6705. {
  6706. detail::json attributes;
  6707. for (auto attrIt = gltfPrimitive.attributes.begin();
  6708. attrIt != gltfPrimitive.attributes.end(); ++attrIt) {
  6709. SerializeNumberProperty<int>(attrIt->first, attrIt->second, attributes);
  6710. }
  6711. detail::JsonAddMember(primitive, "attributes", std::move(attributes));
  6712. }
  6713. // Indices is optional
  6714. if (gltfPrimitive.indices > -1) {
  6715. SerializeNumberProperty<int>("indices", gltfPrimitive.indices, primitive);
  6716. }
  6717. // Material is optional
  6718. if (gltfPrimitive.material > -1) {
  6719. SerializeNumberProperty<int>("material", gltfPrimitive.material,
  6720. primitive);
  6721. }
  6722. SerializeNumberProperty<int>("mode", gltfPrimitive.mode, primitive);
  6723. // Morph targets
  6724. if (gltfPrimitive.targets.size()) {
  6725. detail::json targets;
  6726. detail::JsonReserveArray(targets, gltfPrimitive.targets.size());
  6727. for (unsigned int k = 0; k < gltfPrimitive.targets.size(); ++k) {
  6728. detail::json targetAttributes;
  6729. std::map<std::string, int> targetData = gltfPrimitive.targets[k];
  6730. for (std::map<std::string, int>::iterator attrIt = targetData.begin();
  6731. attrIt != targetData.end(); ++attrIt) {
  6732. SerializeNumberProperty<int>(attrIt->first, attrIt->second,
  6733. targetAttributes);
  6734. }
  6735. detail::JsonPushBack(targets, std::move(targetAttributes));
  6736. }
  6737. detail::JsonAddMember(primitive, "targets", std::move(targets));
  6738. }
  6739. SerializeExtrasAndExtensions(gltfPrimitive, primitive);
  6740. detail::JsonPushBack(primitives, std::move(primitive));
  6741. }
  6742. detail::JsonAddMember(o, "primitives", std::move(primitives));
  6743. if (mesh.weights.size()) {
  6744. SerializeNumberArrayProperty<double>("weights", mesh.weights, o);
  6745. }
  6746. if (mesh.name.size()) {
  6747. SerializeStringProperty("name", mesh.name, o);
  6748. }
  6749. SerializeExtrasAndExtensions(mesh, o);
  6750. }
  6751. static void SerializeSpotLight(const SpotLight &spot, detail::json &o) {
  6752. SerializeNumberProperty("innerConeAngle", spot.innerConeAngle, o);
  6753. SerializeNumberProperty("outerConeAngle", spot.outerConeAngle, o);
  6754. SerializeExtrasAndExtensions(spot, o);
  6755. }
  6756. static void SerializeGltfLight(const Light &light, detail::json &o) {
  6757. if (!light.name.empty()) SerializeStringProperty("name", light.name, o);
  6758. SerializeNumberProperty("intensity", light.intensity, o);
  6759. if (light.range > 0.0) {
  6760. SerializeNumberProperty("range", light.range, o);
  6761. }
  6762. SerializeNumberArrayProperty("color", light.color, o);
  6763. SerializeStringProperty("type", light.type, o);
  6764. if (light.type == "spot") {
  6765. detail::json spot;
  6766. SerializeSpotLight(light.spot, spot);
  6767. detail::JsonAddMember(o, "spot", std::move(spot));
  6768. }
  6769. SerializeExtrasAndExtensions(light, o);
  6770. }
  6771. static void SerializeGltfPositionalEmitter(const PositionalEmitter &positional,
  6772. detail::json &o) {
  6773. if (!TINYGLTF_DOUBLE_EQUAL(positional.coneInnerAngle, 6.283185307179586))
  6774. SerializeNumberProperty("coneInnerAngle", positional.coneInnerAngle, o);
  6775. if (!TINYGLTF_DOUBLE_EQUAL(positional.coneOuterAngle, 6.283185307179586))
  6776. SerializeNumberProperty("coneOuterAngle", positional.coneOuterAngle, o);
  6777. if (positional.coneOuterGain > 0.0)
  6778. SerializeNumberProperty("coneOuterGain", positional.coneOuterGain, o);
  6779. if (!TINYGLTF_DOUBLE_EQUAL(positional.maxDistance, 100.0))
  6780. SerializeNumberProperty("maxDistance", positional.maxDistance, o);
  6781. if (!TINYGLTF_DOUBLE_EQUAL(positional.refDistance, 1.0))
  6782. SerializeNumberProperty("refDistance", positional.refDistance, o);
  6783. if (!TINYGLTF_DOUBLE_EQUAL(positional.rolloffFactor, 1.0))
  6784. SerializeNumberProperty("rolloffFactor", positional.rolloffFactor, o);
  6785. SerializeExtrasAndExtensions(positional, o);
  6786. }
  6787. static void SerializeGltfAudioEmitter(const AudioEmitter &emitter,
  6788. detail::json &o) {
  6789. if (!emitter.name.empty()) SerializeStringProperty("name", emitter.name, o);
  6790. if (!TINYGLTF_DOUBLE_EQUAL(emitter.gain, 1.0))
  6791. SerializeNumberProperty("gain", emitter.gain, o);
  6792. if (emitter.loop) SerializeNumberProperty("loop", emitter.loop, o);
  6793. if (emitter.playing) SerializeNumberProperty("playing", emitter.playing, o);
  6794. if (!emitter.type.empty()) SerializeStringProperty("type", emitter.type, o);
  6795. if (!emitter.distanceModel.empty())
  6796. SerializeStringProperty("distanceModel", emitter.distanceModel, o);
  6797. if (emitter.type == "positional") {
  6798. detail::json positional;
  6799. SerializeGltfPositionalEmitter(emitter.positional, positional);
  6800. detail::JsonAddMember(o, "positional", std::move(positional));
  6801. }
  6802. SerializeNumberProperty("source", emitter.source, o);
  6803. SerializeExtrasAndExtensions(emitter, o);
  6804. }
  6805. static void SerializeGltfAudioSource(const AudioSource &source,
  6806. detail::json &o) {
  6807. std::string name;
  6808. std::string uri;
  6809. std::string mimeType; // (required if no uri) ["audio/mp3", "audio/ogg",
  6810. // "audio/wav", "audio/m4a"]
  6811. if (!source.name.empty()) SerializeStringProperty("name", source.name, o);
  6812. if (source.uri.empty()) {
  6813. SerializeStringProperty("mimeType", source.mimeType, o);
  6814. SerializeNumberProperty<int>("bufferView", source.bufferView, o);
  6815. } else {
  6816. SerializeStringProperty("uri", source.uri, o);
  6817. }
  6818. SerializeExtrasAndExtensions(source, o);
  6819. }
  6820. static void SerializeGltfNode(const Node &node, detail::json &o) {
  6821. if (node.translation.size() > 0) {
  6822. SerializeNumberArrayProperty<double>("translation", node.translation, o);
  6823. }
  6824. if (node.rotation.size() > 0) {
  6825. SerializeNumberArrayProperty<double>("rotation", node.rotation, o);
  6826. }
  6827. if (node.scale.size() > 0) {
  6828. SerializeNumberArrayProperty<double>("scale", node.scale, o);
  6829. }
  6830. if (node.matrix.size() > 0) {
  6831. SerializeNumberArrayProperty<double>("matrix", node.matrix, o);
  6832. }
  6833. if (node.mesh != -1) {
  6834. SerializeNumberProperty<int>("mesh", node.mesh, o);
  6835. }
  6836. if (node.skin != -1) {
  6837. SerializeNumberProperty<int>("skin", node.skin, o);
  6838. }
  6839. if (node.camera != -1) {
  6840. SerializeNumberProperty<int>("camera", node.camera, o);
  6841. }
  6842. if (node.weights.size() > 0) {
  6843. SerializeNumberArrayProperty<double>("weights", node.weights, o);
  6844. }
  6845. SerializeExtrasAndExtensions(node, o);
  6846. // Note(agnat): If the asset was loaded from disk, the node may already
  6847. // contain the KHR_lights_punctual extension. If it was constructed in
  6848. // memory it does not. In any case we update the JSON property using
  6849. // the value from the struct. Last, if the node does not have a light
  6850. // reference but the extension is still present, we remove it.
  6851. if (node.light != -1) {
  6852. detail::json_iterator it;
  6853. if (!detail::FindMember(o, "extensions", it)) {
  6854. detail::json extensions;
  6855. detail::JsonSetObject(extensions);
  6856. detail::JsonAddMember(o, "extensions", std::move(extensions));
  6857. detail::FindMember(o, "extensions", it);
  6858. }
  6859. auto &extensions = detail::GetValue(it);
  6860. if (!detail::FindMember(extensions, "KHR_lights_punctual", it)) {
  6861. detail::json lights_punctual;
  6862. detail::JsonSetObject(lights_punctual);
  6863. detail::JsonAddMember(extensions, "KHR_lights_punctual",
  6864. std::move(lights_punctual));
  6865. detail::FindMember(extensions, "KHR_lights_punctual", it);
  6866. }
  6867. SerializeNumberProperty("light", node.light, detail::GetValue(it));
  6868. } else {
  6869. // node has no light ref (any longer)... so we clean up
  6870. detail::json_iterator ext_it;
  6871. if (detail::FindMember(o, "extensions", ext_it)) {
  6872. auto &extensions = detail::GetValue(ext_it);
  6873. detail::json_iterator lp_it;
  6874. if (detail::FindMember(extensions, "KHR_lights_punctual", lp_it)) {
  6875. detail::Erase(extensions, lp_it);
  6876. }
  6877. if (detail::IsEmpty(extensions)) {
  6878. detail::Erase(o, ext_it);
  6879. }
  6880. }
  6881. }
  6882. // KHR_audio
  6883. if (node.emitter != -1) {
  6884. detail::json_iterator it;
  6885. if (!detail::FindMember(o, "extensions", it)) {
  6886. detail::json extensions;
  6887. detail::JsonSetObject(extensions);
  6888. detail::JsonAddMember(o, "extensions", std::move(extensions));
  6889. detail::FindMember(o, "extensions", it);
  6890. }
  6891. auto &extensions = detail::GetValue(it);
  6892. if (!detail::FindMember(extensions, "KHR_audio", it)) {
  6893. detail::json audio;
  6894. detail::JsonSetObject(audio);
  6895. detail::JsonAddMember(extensions, "KHR_audio", std::move(audio));
  6896. detail::FindMember(extensions, "KHR_audio", it);
  6897. }
  6898. SerializeNumberProperty("emitter", node.emitter, detail::GetValue(it));
  6899. } else {
  6900. detail::json_iterator ext_it;
  6901. if (detail::FindMember(o, "extensions", ext_it)) {
  6902. auto &extensions = detail::GetValue(ext_it);
  6903. detail::json_iterator lp_it;
  6904. if (detail::FindMember(extensions, "KHR_audio", lp_it)) {
  6905. detail::Erase(extensions, lp_it);
  6906. }
  6907. if (detail::IsEmpty(extensions)) {
  6908. detail::Erase(o, ext_it);
  6909. }
  6910. }
  6911. }
  6912. // MSFT_lod
  6913. if (!node.lods.empty()) {
  6914. detail::json_iterator it;
  6915. if (!detail::FindMember(o, "extensions", it)) {
  6916. detail::json extensions;
  6917. detail::JsonSetObject(extensions);
  6918. detail::JsonAddMember(o, "extensions", std::move(extensions));
  6919. detail::FindMember(o, "extensions", it);
  6920. }
  6921. auto &extensions = detail::GetValue(it);
  6922. if (!detail::FindMember(extensions, "MSFT_lod", it)) {
  6923. detail::json lod;
  6924. detail::JsonSetObject(lod);
  6925. detail::JsonAddMember(extensions, "MSFT_lod", std::move(lod));
  6926. detail::FindMember(extensions, "MSFT_lod", it);
  6927. }
  6928. SerializeNumberArrayProperty<int>("ids", node.lods, detail::GetValue(it));
  6929. } else {
  6930. detail::json_iterator ext_it;
  6931. if (detail::FindMember(o, "extensions", ext_it)) {
  6932. auto &extensions = detail::GetValue(ext_it);
  6933. detail::json_iterator lp_it;
  6934. if (detail::FindMember(extensions, "MSFT_lod", lp_it)) {
  6935. detail::Erase(extensions, lp_it);
  6936. }
  6937. if (detail::IsEmpty(extensions)) {
  6938. detail::Erase(o, ext_it);
  6939. }
  6940. }
  6941. }
  6942. if (!node.name.empty()) SerializeStringProperty("name", node.name, o);
  6943. SerializeNumberArrayProperty<int>("children", node.children, o);
  6944. }
  6945. static void SerializeGltfSampler(const Sampler &sampler, detail::json &o) {
  6946. if (!sampler.name.empty()) {
  6947. SerializeStringProperty("name", sampler.name, o);
  6948. }
  6949. if (sampler.magFilter != -1) {
  6950. SerializeNumberProperty("magFilter", sampler.magFilter, o);
  6951. }
  6952. if (sampler.minFilter != -1) {
  6953. SerializeNumberProperty("minFilter", sampler.minFilter, o);
  6954. }
  6955. // SerializeNumberProperty("wrapR", sampler.wrapR, o);
  6956. SerializeNumberProperty("wrapS", sampler.wrapS, o);
  6957. SerializeNumberProperty("wrapT", sampler.wrapT, o);
  6958. SerializeExtrasAndExtensions(sampler, o);
  6959. }
  6960. static void SerializeGltfOrthographicCamera(const OrthographicCamera &camera,
  6961. detail::json &o) {
  6962. SerializeNumberProperty("zfar", camera.zfar, o);
  6963. SerializeNumberProperty("znear", camera.znear, o);
  6964. SerializeNumberProperty("xmag", camera.xmag, o);
  6965. SerializeNumberProperty("ymag", camera.ymag, o);
  6966. SerializeExtrasAndExtensions(camera, o);
  6967. }
  6968. static void SerializeGltfPerspectiveCamera(const PerspectiveCamera &camera,
  6969. detail::json &o) {
  6970. SerializeNumberProperty("zfar", camera.zfar, o);
  6971. SerializeNumberProperty("znear", camera.znear, o);
  6972. if (camera.aspectRatio > 0) {
  6973. SerializeNumberProperty("aspectRatio", camera.aspectRatio, o);
  6974. }
  6975. if (camera.yfov > 0) {
  6976. SerializeNumberProperty("yfov", camera.yfov, o);
  6977. }
  6978. SerializeExtrasAndExtensions(camera, o);
  6979. }
  6980. static void SerializeGltfCamera(const Camera &camera, detail::json &o) {
  6981. SerializeStringProperty("type", camera.type, o);
  6982. if (!camera.name.empty()) {
  6983. SerializeStringProperty("name", camera.name, o);
  6984. }
  6985. if (camera.type.compare("orthographic") == 0) {
  6986. detail::json orthographic;
  6987. SerializeGltfOrthographicCamera(camera.orthographic, orthographic);
  6988. detail::JsonAddMember(o, "orthographic", std::move(orthographic));
  6989. } else if (camera.type.compare("perspective") == 0) {
  6990. detail::json perspective;
  6991. SerializeGltfPerspectiveCamera(camera.perspective, perspective);
  6992. detail::JsonAddMember(o, "perspective", std::move(perspective));
  6993. } else {
  6994. // ???
  6995. }
  6996. SerializeExtrasAndExtensions(camera, o);
  6997. }
  6998. static void SerializeGltfScene(const Scene &scene, detail::json &o) {
  6999. SerializeNumberArrayProperty<int>("nodes", scene.nodes, o);
  7000. if (scene.name.size()) {
  7001. SerializeStringProperty("name", scene.name, o);
  7002. }
  7003. SerializeExtrasAndExtensions(scene, o);
  7004. // KHR_audio
  7005. if (!scene.audioEmitters.empty()) {
  7006. detail::json_iterator it;
  7007. if (!detail::FindMember(o, "extensions", it)) {
  7008. detail::json extensions;
  7009. detail::JsonSetObject(extensions);
  7010. detail::JsonAddMember(o, "extensions", std::move(extensions));
  7011. detail::FindMember(o, "extensions", it);
  7012. }
  7013. auto &extensions = detail::GetValue(it);
  7014. if (!detail::FindMember(extensions, "KHR_audio", it)) {
  7015. detail::json audio;
  7016. detail::JsonSetObject(audio);
  7017. detail::JsonAddMember(extensions, "KHR_audio", std::move(audio));
  7018. detail::FindMember(o, "KHR_audio", it);
  7019. }
  7020. SerializeNumberArrayProperty("emitters", scene.audioEmitters,
  7021. detail::GetValue(it));
  7022. } else {
  7023. detail::json_iterator ext_it;
  7024. if (detail::FindMember(o, "extensions", ext_it)) {
  7025. auto &extensions = detail::GetValue(ext_it);
  7026. detail::json_iterator lp_it;
  7027. if (detail::FindMember(extensions, "KHR_audio", lp_it)) {
  7028. detail::Erase(extensions, lp_it);
  7029. }
  7030. if (detail::IsEmpty(extensions)) {
  7031. detail::Erase(o, ext_it);
  7032. }
  7033. }
  7034. }
  7035. }
  7036. static void SerializeGltfSkin(const Skin &skin, detail::json &o) {
  7037. // required
  7038. SerializeNumberArrayProperty<int>("joints", skin.joints, o);
  7039. if (skin.inverseBindMatrices >= 0) {
  7040. SerializeNumberProperty("inverseBindMatrices", skin.inverseBindMatrices, o);
  7041. }
  7042. if (skin.skeleton >= 0) {
  7043. SerializeNumberProperty("skeleton", skin.skeleton, o);
  7044. }
  7045. if (skin.name.size()) {
  7046. SerializeStringProperty("name", skin.name, o);
  7047. }
  7048. SerializeExtrasAndExtensions(skin, o);
  7049. }
  7050. static void SerializeGltfTexture(const Texture &texture, detail::json &o) {
  7051. if (texture.sampler > -1) {
  7052. SerializeNumberProperty("sampler", texture.sampler, o);
  7053. }
  7054. if (texture.source > -1) {
  7055. SerializeNumberProperty("source", texture.source, o);
  7056. }
  7057. if (texture.name.size()) {
  7058. SerializeStringProperty("name", texture.name, o);
  7059. }
  7060. SerializeExtrasAndExtensions(texture, o);
  7061. }
  7062. ///
  7063. /// Serialize all properties except buffers and images.
  7064. ///
  7065. static void SerializeGltfModel(const Model *model, detail::json &o) {
  7066. // ACCESSORS
  7067. if (model->accessors.size()) {
  7068. detail::json accessors;
  7069. detail::JsonReserveArray(accessors, model->accessors.size());
  7070. for (unsigned int i = 0; i < model->accessors.size(); ++i) {
  7071. detail::json accessor;
  7072. SerializeGltfAccessor(model->accessors[i], accessor);
  7073. detail::JsonPushBack(accessors, std::move(accessor));
  7074. }
  7075. detail::JsonAddMember(o, "accessors", std::move(accessors));
  7076. }
  7077. // ANIMATIONS
  7078. if (model->animations.size()) {
  7079. detail::json animations;
  7080. detail::JsonReserveArray(animations, model->animations.size());
  7081. for (unsigned int i = 0; i < model->animations.size(); ++i) {
  7082. if (model->animations[i].channels.size()) {
  7083. detail::json animation;
  7084. SerializeGltfAnimation(model->animations[i], animation);
  7085. detail::JsonPushBack(animations, std::move(animation));
  7086. }
  7087. }
  7088. detail::JsonAddMember(o, "animations", std::move(animations));
  7089. }
  7090. // ASSET
  7091. detail::json asset;
  7092. SerializeGltfAsset(model->asset, asset);
  7093. detail::JsonAddMember(o, "asset", std::move(asset));
  7094. // BUFFERVIEWS
  7095. if (model->bufferViews.size()) {
  7096. detail::json bufferViews;
  7097. detail::JsonReserveArray(bufferViews, model->bufferViews.size());
  7098. for (unsigned int i = 0; i < model->bufferViews.size(); ++i) {
  7099. detail::json bufferView;
  7100. SerializeGltfBufferView(model->bufferViews[i], bufferView);
  7101. detail::JsonPushBack(bufferViews, std::move(bufferView));
  7102. }
  7103. detail::JsonAddMember(o, "bufferViews", std::move(bufferViews));
  7104. }
  7105. // Extensions required
  7106. if (model->extensionsRequired.size()) {
  7107. SerializeStringArrayProperty("extensionsRequired",
  7108. model->extensionsRequired, o);
  7109. }
  7110. // MATERIALS
  7111. if (model->materials.size()) {
  7112. detail::json materials;
  7113. detail::JsonReserveArray(materials, model->materials.size());
  7114. for (unsigned int i = 0; i < model->materials.size(); ++i) {
  7115. detail::json material;
  7116. SerializeGltfMaterial(model->materials[i], material);
  7117. if (detail::JsonIsNull(material)) {
  7118. // Issue 294.
  7119. // `material` does not have any required parameters
  7120. // so the result may be null(unmodified) when all material parameters
  7121. // have default value.
  7122. //
  7123. // null is not allowed thus we create an empty JSON object.
  7124. detail::JsonSetObject(material);
  7125. }
  7126. detail::JsonPushBack(materials, std::move(material));
  7127. }
  7128. detail::JsonAddMember(o, "materials", std::move(materials));
  7129. }
  7130. // MESHES
  7131. if (model->meshes.size()) {
  7132. detail::json meshes;
  7133. detail::JsonReserveArray(meshes, model->meshes.size());
  7134. for (unsigned int i = 0; i < model->meshes.size(); ++i) {
  7135. detail::json mesh;
  7136. SerializeGltfMesh(model->meshes[i], mesh);
  7137. detail::JsonPushBack(meshes, std::move(mesh));
  7138. }
  7139. detail::JsonAddMember(o, "meshes", std::move(meshes));
  7140. }
  7141. // NODES
  7142. if (model->nodes.size()) {
  7143. detail::json nodes;
  7144. detail::JsonReserveArray(nodes, model->nodes.size());
  7145. for (unsigned int i = 0; i < model->nodes.size(); ++i) {
  7146. detail::json node;
  7147. SerializeGltfNode(model->nodes[i], node);
  7148. if (detail::JsonIsNull(node)) {
  7149. // Issue 457.
  7150. // `node` does not have any required parameters,
  7151. // so the result may be null(unmodified) when all node parameters
  7152. // have default value.
  7153. //
  7154. // null is not allowed thus we create an empty JSON object.
  7155. detail::JsonSetObject(node);
  7156. }
  7157. detail::JsonPushBack(nodes, std::move(node));
  7158. }
  7159. detail::JsonAddMember(o, "nodes", std::move(nodes));
  7160. }
  7161. // SCENE
  7162. if (model->defaultScene > -1) {
  7163. SerializeNumberProperty<int>("scene", model->defaultScene, o);
  7164. }
  7165. // SCENES
  7166. if (model->scenes.size()) {
  7167. detail::json scenes;
  7168. detail::JsonReserveArray(scenes, model->scenes.size());
  7169. for (unsigned int i = 0; i < model->scenes.size(); ++i) {
  7170. detail::json currentScene;
  7171. SerializeGltfScene(model->scenes[i], currentScene);
  7172. if (detail::JsonIsNull(currentScene)) {
  7173. // Issue 464.
  7174. // `scene` does not have any required parameters,
  7175. // so the result may be null(unmodified) when all scene parameters
  7176. // have default value.
  7177. //
  7178. // null is not allowed thus we create an empty JSON object.
  7179. detail::JsonSetObject(currentScene);
  7180. }
  7181. detail::JsonPushBack(scenes, std::move(currentScene));
  7182. }
  7183. detail::JsonAddMember(o, "scenes", std::move(scenes));
  7184. }
  7185. // SKINS
  7186. if (model->skins.size()) {
  7187. detail::json skins;
  7188. detail::JsonReserveArray(skins, model->skins.size());
  7189. for (unsigned int i = 0; i < model->skins.size(); ++i) {
  7190. detail::json skin;
  7191. SerializeGltfSkin(model->skins[i], skin);
  7192. detail::JsonPushBack(skins, std::move(skin));
  7193. }
  7194. detail::JsonAddMember(o, "skins", std::move(skins));
  7195. }
  7196. // TEXTURES
  7197. if (model->textures.size()) {
  7198. detail::json textures;
  7199. detail::JsonReserveArray(textures, model->textures.size());
  7200. for (unsigned int i = 0; i < model->textures.size(); ++i) {
  7201. detail::json texture;
  7202. SerializeGltfTexture(model->textures[i], texture);
  7203. detail::JsonPushBack(textures, std::move(texture));
  7204. }
  7205. detail::JsonAddMember(o, "textures", std::move(textures));
  7206. }
  7207. // SAMPLERS
  7208. if (model->samplers.size()) {
  7209. detail::json samplers;
  7210. detail::JsonReserveArray(samplers, model->samplers.size());
  7211. for (unsigned int i = 0; i < model->samplers.size(); ++i) {
  7212. detail::json sampler;
  7213. SerializeGltfSampler(model->samplers[i], sampler);
  7214. detail::JsonPushBack(samplers, std::move(sampler));
  7215. }
  7216. detail::JsonAddMember(o, "samplers", std::move(samplers));
  7217. }
  7218. // CAMERAS
  7219. if (model->cameras.size()) {
  7220. detail::json cameras;
  7221. detail::JsonReserveArray(cameras, model->cameras.size());
  7222. for (unsigned int i = 0; i < model->cameras.size(); ++i) {
  7223. detail::json camera;
  7224. SerializeGltfCamera(model->cameras[i], camera);
  7225. detail::JsonPushBack(cameras, std::move(camera));
  7226. }
  7227. detail::JsonAddMember(o, "cameras", std::move(cameras));
  7228. }
  7229. // EXTRAS & EXTENSIONS
  7230. SerializeExtrasAndExtensions(*model, o);
  7231. auto extensionsUsed = model->extensionsUsed;
  7232. // LIGHTS as KHR_lights_punctual
  7233. if (model->lights.size()) {
  7234. detail::json lights;
  7235. detail::JsonReserveArray(lights, model->lights.size());
  7236. for (unsigned int i = 0; i < model->lights.size(); ++i) {
  7237. detail::json light;
  7238. SerializeGltfLight(model->lights[i], light);
  7239. detail::JsonPushBack(lights, std::move(light));
  7240. }
  7241. detail::json khr_lights_cmn;
  7242. detail::JsonAddMember(khr_lights_cmn, "lights", std::move(lights));
  7243. detail::json ext_j;
  7244. {
  7245. detail::json_const_iterator it;
  7246. if (detail::FindMember(o, "extensions", it)) {
  7247. detail::JsonAssign(ext_j, detail::GetValue(it));
  7248. }
  7249. }
  7250. detail::JsonAddMember(ext_j, "KHR_lights_punctual",
  7251. std::move(khr_lights_cmn));
  7252. detail::JsonAddMember(o, "extensions", std::move(ext_j));
  7253. // Also add "KHR_lights_punctual" to `extensionsUsed`
  7254. {
  7255. auto has_khr_lights_punctual =
  7256. std::find_if(extensionsUsed.begin(), extensionsUsed.end(),
  7257. [](const std::string &s) {
  7258. return (s.compare("KHR_lights_punctual") == 0);
  7259. });
  7260. if (has_khr_lights_punctual == extensionsUsed.end()) {
  7261. extensionsUsed.push_back("KHR_lights_punctual");
  7262. }
  7263. }
  7264. }
  7265. // KHR_audio
  7266. if (!model->audioEmitters.empty() || !model->audioSources.empty()) {
  7267. detail::json emitters;
  7268. detail::JsonReserveArray(emitters, model->audioEmitters.size());
  7269. for (unsigned int i = 0; i < model->audioEmitters.size(); ++i) {
  7270. detail::json emitter;
  7271. SerializeGltfAudioEmitter(model->audioEmitters[i], emitter);
  7272. detail::JsonPushBack(emitters, std::move(emitter));
  7273. }
  7274. detail::json khr_audio_cmn;
  7275. detail::JsonAddMember(khr_audio_cmn, "emitters", std::move(emitters));
  7276. detail::json sources;
  7277. detail::JsonReserveArray(sources, model->audioSources.size());
  7278. for (unsigned int i = 0; i < model->audioSources.size(); ++i) {
  7279. detail::json source;
  7280. SerializeGltfAudioSource(model->audioSources[i], source);
  7281. detail::JsonPushBack(sources, std::move(source));
  7282. }
  7283. detail::JsonAddMember(khr_audio_cmn, "sources", std::move(sources));
  7284. detail::json ext_j;
  7285. {
  7286. detail::json_const_iterator it;
  7287. if (detail::FindMember(o, "extensions", it)) {
  7288. detail::JsonAssign(ext_j, detail::GetValue(it));
  7289. }
  7290. }
  7291. detail::JsonAddMember(ext_j, "KHR_audio", std::move(khr_audio_cmn));
  7292. detail::JsonAddMember(o, "extensions", std::move(ext_j));
  7293. // Also add "KHR_audio" to `extensionsUsed`
  7294. {
  7295. auto has_khr_audio = std::find_if(
  7296. extensionsUsed.begin(), extensionsUsed.end(),
  7297. [](const std::string &s) { return (s.compare("KHR_audio") == 0); });
  7298. if (has_khr_audio == extensionsUsed.end()) {
  7299. extensionsUsed.push_back("KHR_audio");
  7300. }
  7301. }
  7302. }
  7303. // MSFT_lod
  7304. // Look if there is a node that employs MSFT_lod
  7305. auto msft_lod_nodes_it = std::find_if(
  7306. model->nodes.begin(), model->nodes.end(),
  7307. [](const Node& node) { return !node.lods.empty(); });
  7308. // Look if there is a material that employs MSFT_lod
  7309. auto msft_lod_materials_it = std::find_if(
  7310. model->materials.begin(), model->materials.end(),
  7311. [](const Material& material) {return !material.lods.empty(); });
  7312. // If either a node or a material employ MSFT_lod, then we need
  7313. // to add MSFT_lod to the list of used extensions.
  7314. if (msft_lod_nodes_it != model->nodes.end() || msft_lod_materials_it != model->materials.end()) {
  7315. // First check if MSFT_lod is already registered as used extension
  7316. auto has_msft_lod = std::find_if(
  7317. extensionsUsed.begin(), extensionsUsed.end(),
  7318. [](const std::string &s) { return (s.compare("MSFT_lod") == 0); });
  7319. // If MSFT_lod is not registered yet, add it
  7320. if (has_msft_lod == extensionsUsed.end()) {
  7321. extensionsUsed.push_back("MSFT_lod");
  7322. }
  7323. }
  7324. // Extensions used
  7325. if (extensionsUsed.size()) {
  7326. SerializeStringArrayProperty("extensionsUsed", extensionsUsed, o);
  7327. }
  7328. }
  7329. static bool WriteGltfStream(std::ostream &stream, const std::string &content) {
  7330. stream << content << std::endl;
  7331. return stream.good();
  7332. }
  7333. static bool WriteGltfFile(const std::string &output,
  7334. const std::string &content) {
  7335. #ifdef _WIN32
  7336. #if defined(_MSC_VER)
  7337. std::ofstream gltfFile(UTF8ToWchar(output).c_str());
  7338. #elif defined(__GLIBCXX__)
  7339. int file_descriptor = _wopen(UTF8ToWchar(output).c_str(),
  7340. _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY, _S_IWRITE);
  7341. __gnu_cxx::stdio_filebuf<char> wfile_buf(
  7342. file_descriptor, std::ios_base::out | std::ios_base::binary);
  7343. std::ostream gltfFile(&wfile_buf);
  7344. if (!wfile_buf.is_open()) return false;
  7345. #else
  7346. std::ofstream gltfFile(output.c_str());
  7347. if (!gltfFile.is_open()) return false;
  7348. #endif
  7349. #else
  7350. std::ofstream gltfFile(output.c_str());
  7351. if (!gltfFile.is_open()) return false;
  7352. #endif
  7353. return WriteGltfStream(gltfFile, content);
  7354. }
  7355. static bool WriteBinaryGltfStream(std::ostream &stream,
  7356. const std::string &content,
  7357. const std::vector<unsigned char> &binBuffer) {
  7358. const std::string header = "glTF";
  7359. const int version = 2;
  7360. const uint32_t content_size = uint32_t(content.size());
  7361. const uint32_t binBuffer_size = uint32_t(binBuffer.size());
  7362. // determine number of padding bytes required to ensure 4 byte alignment
  7363. const uint32_t content_padding_size =
  7364. content_size % 4 == 0 ? 0 : 4 - content_size % 4;
  7365. const uint32_t bin_padding_size =
  7366. binBuffer_size % 4 == 0 ? 0 : 4 - binBuffer_size % 4;
  7367. // 12 bytes for header, JSON content length, 8 bytes for JSON chunk info.
  7368. // Chunk data must be located at 4-byte boundary, which may require padding
  7369. const uint32_t length =
  7370. 12 + 8 + content_size + content_padding_size +
  7371. (binBuffer_size ? (8 + binBuffer_size + bin_padding_size) : 0);
  7372. stream.write(header.c_str(), std::streamsize(header.size()));
  7373. stream.write(reinterpret_cast<const char *>(&version), sizeof(version));
  7374. stream.write(reinterpret_cast<const char *>(&length), sizeof(length));
  7375. // JSON chunk info, then JSON data
  7376. const uint32_t model_length = uint32_t(content.size()) + content_padding_size;
  7377. const uint32_t model_format = 0x4E4F534A;
  7378. stream.write(reinterpret_cast<const char *>(&model_length),
  7379. sizeof(model_length));
  7380. stream.write(reinterpret_cast<const char *>(&model_format),
  7381. sizeof(model_format));
  7382. stream.write(content.c_str(), std::streamsize(content.size()));
  7383. // Chunk must be multiplies of 4, so pad with spaces
  7384. if (content_padding_size > 0) {
  7385. const std::string padding = std::string(size_t(content_padding_size), ' ');
  7386. stream.write(padding.c_str(), std::streamsize(padding.size()));
  7387. }
  7388. if (binBuffer.size() > 0) {
  7389. // BIN chunk info, then BIN data
  7390. const uint32_t bin_length = uint32_t(binBuffer.size()) + bin_padding_size;
  7391. const uint32_t bin_format = 0x004e4942;
  7392. stream.write(reinterpret_cast<const char *>(&bin_length),
  7393. sizeof(bin_length));
  7394. stream.write(reinterpret_cast<const char *>(&bin_format),
  7395. sizeof(bin_format));
  7396. stream.write(reinterpret_cast<const char *>(binBuffer.data()),
  7397. std::streamsize(binBuffer.size()));
  7398. // Chunksize must be multiplies of 4, so pad with zeroes
  7399. if (bin_padding_size > 0) {
  7400. const std::vector<unsigned char> padding =
  7401. std::vector<unsigned char>(size_t(bin_padding_size), 0);
  7402. stream.write(reinterpret_cast<const char *>(padding.data()),
  7403. std::streamsize(padding.size()));
  7404. }
  7405. }
  7406. stream.flush();
  7407. return stream.good();
  7408. }
  7409. static bool WriteBinaryGltfFile(const std::string &output,
  7410. const std::string &content,
  7411. const std::vector<unsigned char> &binBuffer) {
  7412. #ifdef _WIN32
  7413. #if defined(_MSC_VER)
  7414. std::ofstream gltfFile(UTF8ToWchar(output).c_str(), std::ios::binary);
  7415. #elif defined(__GLIBCXX__)
  7416. int file_descriptor = _wopen(UTF8ToWchar(output).c_str(),
  7417. _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY, _S_IWRITE);
  7418. __gnu_cxx::stdio_filebuf<char> wfile_buf(
  7419. file_descriptor, std::ios_base::out | std::ios_base::binary);
  7420. std::ostream gltfFile(&wfile_buf);
  7421. #else
  7422. std::ofstream gltfFile(output.c_str(), std::ios::binary);
  7423. #endif
  7424. #else
  7425. std::ofstream gltfFile(output.c_str(), std::ios::binary);
  7426. #endif
  7427. return WriteBinaryGltfStream(gltfFile, content, binBuffer);
  7428. }
  7429. bool TinyGLTF::WriteGltfSceneToStream(const Model *model, std::ostream &stream,
  7430. bool prettyPrint = true,
  7431. bool writeBinary = false) {
  7432. detail::JsonDocument output;
  7433. /// Serialize all properties except buffers and images.
  7434. SerializeGltfModel(model, output);
  7435. // BUFFERS
  7436. std::vector<unsigned char> binBuffer;
  7437. if (model->buffers.size()) {
  7438. detail::json buffers;
  7439. detail::JsonReserveArray(buffers, model->buffers.size());
  7440. for (unsigned int i = 0; i < model->buffers.size(); ++i) {
  7441. detail::json buffer;
  7442. if (writeBinary && i == 0 && model->buffers[i].uri.empty()) {
  7443. SerializeGltfBufferBin(model->buffers[i], buffer, binBuffer);
  7444. } else {
  7445. SerializeGltfBuffer(model->buffers[i], buffer);
  7446. }
  7447. detail::JsonPushBack(buffers, std::move(buffer));
  7448. }
  7449. detail::JsonAddMember(output, "buffers", std::move(buffers));
  7450. }
  7451. // IMAGES
  7452. if (model->images.size()) {
  7453. detail::json images;
  7454. detail::JsonReserveArray(images, model->images.size());
  7455. for (unsigned int i = 0; i < model->images.size(); ++i) {
  7456. detail::json image;
  7457. std::string dummystring;
  7458. // UpdateImageObject need baseDir but only uses it if embeddedImages is
  7459. // enabled, since we won't write separate images when writing to a stream
  7460. // we
  7461. std::string uri;
  7462. if (!UpdateImageObject(model->images[i], dummystring, int(i), true,
  7463. &fs, &uri_cb, this->WriteImageData,
  7464. this->write_image_user_data_, &uri)) {
  7465. return false;
  7466. }
  7467. SerializeGltfImage(model->images[i], uri, image);
  7468. detail::JsonPushBack(images, std::move(image));
  7469. }
  7470. detail::JsonAddMember(output, "images", std::move(images));
  7471. }
  7472. if (writeBinary) {
  7473. return WriteBinaryGltfStream(stream, detail::JsonToString(output),
  7474. binBuffer);
  7475. } else {
  7476. return WriteGltfStream(stream,
  7477. detail::JsonToString(output, prettyPrint ? 2 : -1));
  7478. }
  7479. }
  7480. bool TinyGLTF::WriteGltfSceneToFile(const Model *model,
  7481. const std::string &filename,
  7482. bool embedImages = false,
  7483. bool embedBuffers = false,
  7484. bool prettyPrint = true,
  7485. bool writeBinary = false) {
  7486. detail::JsonDocument output;
  7487. std::string defaultBinFilename = GetBaseFilename(filename);
  7488. std::string defaultBinFileExt = ".bin";
  7489. std::string::size_type pos =
  7490. defaultBinFilename.rfind('.', defaultBinFilename.length());
  7491. if (pos != std::string::npos) {
  7492. defaultBinFilename = defaultBinFilename.substr(0, pos);
  7493. }
  7494. std::string baseDir = GetBaseDir(filename);
  7495. if (baseDir.empty()) {
  7496. baseDir = "./";
  7497. }
  7498. /// Serialize all properties except buffers and images.
  7499. SerializeGltfModel(model, output);
  7500. // BUFFERS
  7501. std::vector<std::string> usedFilenames;
  7502. std::vector<unsigned char> binBuffer;
  7503. if (model->buffers.size()) {
  7504. detail::json buffers;
  7505. detail::JsonReserveArray(buffers, model->buffers.size());
  7506. for (unsigned int i = 0; i < model->buffers.size(); ++i) {
  7507. detail::json buffer;
  7508. if (writeBinary && i == 0 && model->buffers[i].uri.empty()) {
  7509. SerializeGltfBufferBin(model->buffers[i], buffer, binBuffer);
  7510. } else if (embedBuffers) {
  7511. SerializeGltfBuffer(model->buffers[i], buffer);
  7512. } else {
  7513. std::string binSavePath;
  7514. std::string binFilename;
  7515. std::string binUri;
  7516. if (!model->buffers[i].uri.empty() &&
  7517. !IsDataURI(model->buffers[i].uri)) {
  7518. binUri = model->buffers[i].uri;
  7519. if (!uri_cb.decode(binUri, &binFilename, uri_cb.user_data)) {
  7520. return false;
  7521. }
  7522. } else {
  7523. binFilename = defaultBinFilename + defaultBinFileExt;
  7524. bool inUse = true;
  7525. int numUsed = 0;
  7526. while (inUse) {
  7527. inUse = false;
  7528. for (const std::string &usedName : usedFilenames) {
  7529. if (binFilename.compare(usedName) != 0) continue;
  7530. inUse = true;
  7531. binFilename = defaultBinFilename + std::to_string(numUsed++) +
  7532. defaultBinFileExt;
  7533. break;
  7534. }
  7535. }
  7536. if (uri_cb.encode) {
  7537. if (!uri_cb.encode(binFilename, "buffer", &binUri,
  7538. uri_cb.user_data)) {
  7539. return false;
  7540. }
  7541. } else {
  7542. binUri = binFilename;
  7543. }
  7544. }
  7545. usedFilenames.push_back(binFilename);
  7546. binSavePath = JoinPath(baseDir, binFilename);
  7547. if (!SerializeGltfBuffer(model->buffers[i], buffer, binSavePath,
  7548. binUri)) {
  7549. return false;
  7550. }
  7551. }
  7552. detail::JsonPushBack(buffers, std::move(buffer));
  7553. }
  7554. detail::JsonAddMember(output, "buffers", std::move(buffers));
  7555. }
  7556. // IMAGES
  7557. if (model->images.size()) {
  7558. detail::json images;
  7559. detail::JsonReserveArray(images, model->images.size());
  7560. for (unsigned int i = 0; i < model->images.size(); ++i) {
  7561. detail::json image;
  7562. std::string uri;
  7563. if (!UpdateImageObject(model->images[i], baseDir, int(i), embedImages,
  7564. &fs, &uri_cb, this->WriteImageData,
  7565. this->write_image_user_data_, &uri)) {
  7566. return false;
  7567. }
  7568. SerializeGltfImage(model->images[i], uri, image);
  7569. detail::JsonPushBack(images, std::move(image));
  7570. }
  7571. detail::JsonAddMember(output, "images", std::move(images));
  7572. }
  7573. if (writeBinary) {
  7574. return WriteBinaryGltfFile(filename, detail::JsonToString(output),
  7575. binBuffer);
  7576. } else {
  7577. return WriteGltfFile(filename,
  7578. detail::JsonToString(output, (prettyPrint ? 2 : -1)));
  7579. }
  7580. }
  7581. } // namespace tinygltf
  7582. #ifdef __clang__
  7583. #pragma clang diagnostic pop
  7584. #endif
  7585. #endif // TINYGLTF_IMPLEMENTATION