ufbx.c 805 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343
  1. /*
  2. I added this license block, otherwise verbatim.
  3. https://github.com/bqqbarbhg/ufbx
  4. ALTERNATIVE A - MIT License
  5. Copyright (c) 2020 Samuli Raivio
  6. Permission is hereby granted, free of charge, to any person obtaining a copy of
  7. this software and associated documentation files (the "Software"), to deal in
  8. the Software without restriction, including without limitation the rights to
  9. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  10. of the Software, and to permit persons to whom the Software is furnished to do
  11. so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in all
  13. copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. SOFTWARE.
  21. */
  22. #include "ufbx.h"
  23. #ifndef UFBX_UFBX_C_INLCUDE
  24. #define UFBX_UFBX_C_INLCUDED
  25. // -- User configuration
  26. #if defined(UFBX_CONFIG_SOURCE)
  27. #include UFBX_CONFIG_SOURCE
  28. #endif
  29. // -- Configuration
  30. #define UFBXI_MAX_NON_ARRAY_VALUES 8
  31. #define UFBXI_MAX_NODE_DEPTH 64
  32. #define UFBXI_MAX_SKIP_SIZE 0x40000000
  33. #define UFBXI_MAP_MAX_SCAN 32
  34. #define UFBXI_KD_FAST_DEPTH 6
  35. #define UFBXI_HUGE_MAX_SCAN 16
  36. #ifndef UFBXI_MAX_NURBS_ORDER
  37. #define UFBXI_MAX_NURBS_ORDER 128
  38. #endif
  39. // -- Feature exclusion
  40. #if !defined(UFBX_ONLY_LOADING)
  41. #if !defined(UFBX_NO_SUBDIVISION)
  42. #define UFBXI_FEATURE_SUBDIVISION 1
  43. #endif
  44. #if !defined(UFBX_NO_TESSELLATION)
  45. #define UFBXI_FEATURE_TESSELLATION 1
  46. #endif
  47. #if !defined(UFBX_NO_GEOMETRY_CACHE)
  48. #define UFBXI_FEATURE_GEOMETRY_CACHE 1
  49. #endif
  50. #if !defined(UFBX_NO_SCENE_EVALUATION)
  51. #define UFBXI_FEATURE_SCENE_EVALUATION 1
  52. #endif
  53. #if !defined(UFBX_NO_TRIANGULATION)
  54. #define UFBXI_FEATURE_TRIANGULATION 1
  55. #endif
  56. #endif
  57. #if defined(UFBX_DEV)
  58. #if !defined(UFBX_NO_ERROR_STACK)
  59. #define UFBXI_FEATURE_ERROR_STACK 1
  60. #endif
  61. #endif
  62. #if !defined(UFBXI_FEATURE_SUBDIVISION) && defined(UFBX_ENABLE_SUBDIVISION)
  63. #define UFBXI_FEATURE_SUBDIVISION 1
  64. #endif
  65. #if !defined(UFBXI_FEATURE_TESSELLATION) && defined(UFBX_ENABLE_TESSELLATION)
  66. #define UFBXI_FEATURE_TESSELLATION 1
  67. #endif
  68. #if !defined(UFBXI_FEATURE_GEOMETRY_CACHE) && defined(UFBX_ENABLE_GEOMETRY_CACHE)
  69. #define UFBXI_FEATURE_GEOMETRY_CACHE 1
  70. #endif
  71. #if !defined(UFBXI_FEATURE_SCENE_EVALUATION) && defined(UFBX_ENABLE_SCENE_EVALUATION)
  72. #define UFBXI_FEATURE_SCENE_EVALUATION 1
  73. #endif
  74. #if !defined(UFBXI_FEATURE_TRIANGULATION) && defined(UFBX_ENABLE_TRIANGULATION)
  75. #define UFBXI_FEATURE_TRIANGULATION 1
  76. #endif
  77. #if !defined(UFBXI_FEATURE_ERROR_STACK) && defined(UFBX_ENABLE_ERROR_STACK)
  78. #define UFBXI_FEATURE_ERROR_STACK 1
  79. #endif
  80. #if !defined(UFBXI_FEATURE_SUBDIVISION)
  81. #define UFBXI_FEATURE_SUBDIVISION 0
  82. #endif
  83. #if !defined(UFBXI_FEATURE_TESSELLATION)
  84. #define UFBXI_FEATURE_TESSELLATION 0
  85. #endif
  86. #if !defined(UFBXI_FEATURE_GEOMETRY_CACHE)
  87. #define UFBXI_FEATURE_GEOMETRY_CACHE 0
  88. #endif
  89. #if !defined(UFBXI_FEATURE_SCENE_EVALUATION)
  90. #define UFBXI_FEATURE_SCENE_EVALUATION 0
  91. #endif
  92. #if !defined(UFBXI_FEATURE_TRIANGULATION)
  93. #define UFBXI_FEATURE_TRIANGULATION 0
  94. #endif
  95. #if !defined(UFBXI_FEATURE_ERROR_STACK)
  96. #define UFBXI_FEATURE_ERROR_STACK 0
  97. #endif
  98. // Derived features
  99. #if UFBXI_FEATURE_GEOMETRY_CACHE
  100. #define UFBXI_FEATURE_XML 1
  101. #else
  102. #define UFBXI_FEATURE_XML 0
  103. #endif
  104. #if UFBXI_FEATURE_TESSELLATION
  105. #define UFBXI_FEATURE_SPATIAL 1
  106. #else
  107. #define UFBXI_FEATURE_SPATIAL 0
  108. #endif
  109. #if UFBXI_FEATURE_TRIANGULATION
  110. #define UFBXI_FEATURE_KD 1
  111. #else
  112. #define UFBXI_FEATURE_KD 0
  113. #endif
  114. #if !UFBXI_FEATURE_SUBDIVISION || !UFBXI_FEATURE_TESSELLATION || !UFBXI_FEATURE_GEOMETRY_CACHE || !UFBXI_FEATURE_SCENE_EVALUATION || !UFBXI_FEATURE_TRIANGULATION || !UFBXI_FEATURE_XML || !UFBXI_FEATURE_SPATIAL || !UFBXI_FEATURE_KD
  115. #define UFBXI_PARTIAL_FEATURES 1
  116. #endif
  117. // -- Headers
  118. #include <string.h>
  119. #include <stdlib.h>
  120. #include <stdio.h>
  121. #include <stdarg.h>
  122. #include <locale.h>
  123. #if !defined(UFBX_NO_MATH_H)
  124. #include <math.h>
  125. #define UFBX_INFINITY INFINITY
  126. #define UFBX_NAN NAN
  127. #endif
  128. #if !defined(UFBX_MATH_PREFIX)
  129. #define UFBX_MATH_PREFIX
  130. #endif
  131. #define ufbxi_math_cat2(a, b) a##b
  132. #define ufbxi_math_cat(a, b) ufbxi_math_cat2(a, b)
  133. #define ufbxi_math_fn(name) ufbxi_math_cat(UFBX_MATH_PREFIX, name)
  134. #if !defined(UFBX_NO_MATH_DEFINES)
  135. #define ufbx_sqrt ufbxi_math_fn(sqrt)
  136. #define ufbx_fabs ufbxi_math_fn(fabs)
  137. #define ufbx_pow ufbxi_math_fn(pow)
  138. #define ufbx_sin ufbxi_math_fn(sin)
  139. #define ufbx_cos ufbxi_math_fn(cos)
  140. #define ufbx_tan ufbxi_math_fn(tan)
  141. #define ufbx_asin ufbxi_math_fn(asin)
  142. #define ufbx_acos ufbxi_math_fn(acos)
  143. #define ufbx_atan ufbxi_math_fn(atan)
  144. #define ufbx_atan2 ufbxi_math_fn(atan2)
  145. #define ufbx_copysign ufbxi_math_fn(copysign)
  146. #define ufbx_fmin ufbxi_math_fn(fmin)
  147. #define ufbx_fmax ufbxi_math_fn(fmax)
  148. #define ufbx_frexp ufbxi_math_fn(frexp)
  149. #endif
  150. #if defined(UFBX_NO_MATH_H) && !defined(UFBX_NO_MATH_DECLARATIONS)
  151. double ufbx_sqrt(double x);
  152. double ufbx_sin(double x);
  153. double ufbx_cos(double x);
  154. double ufbx_tan(double x);
  155. double ufbx_asin(double x);
  156. double ufbx_acos(double x);
  157. double ufbx_atan(double x);
  158. double ufbx_atan2(double y, double x);
  159. double ufbx_pow(double x, double y);
  160. double ufbx_fmin(double a, double b);
  161. double ufbx_fmax(double a, double b);
  162. double ufbx_fabs(double x);
  163. double ufbx_frexp(double x, int *eptr);
  164. double ufbx_copysign(double x, double y);
  165. #endif
  166. #if !defined(UFBX_INFINITY)
  167. #define UFBX_INFINITY (1e+300 * 1e+300)
  168. #endif
  169. #if !defined(UFBX_NAN)
  170. #define UFBX_NAN (UFBX_INFINITY * 0.0f)
  171. #endif
  172. // -- Platform
  173. #if !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
  174. #define ufbxi_noinline __declspec(noinline)
  175. #define ufbxi_forceinline __forceinline
  176. #define ufbxi_restrict __restrict
  177. #if defined(__cplusplus) && _MSC_VER >= 1900
  178. #define ufbxi_nodiscard [[nodiscard]]
  179. #elif defined(_Check_return_)
  180. #define ufbxi_nodiscard _Check_return_
  181. #else
  182. #define ufbxi_nodiscard
  183. #endif
  184. #define ufbxi_unused
  185. #define ufbxi_unlikely(cond) (cond)
  186. #elif !defined(UFBX_STANDARD_C) && (defined(__GNUC__) || defined(__clang__))
  187. #define ufbxi_noinline __attribute__((noinline))
  188. #define ufbxi_forceinline inline __attribute__((always_inline))
  189. #define ufbxi_restrict __restrict
  190. #define ufbxi_nodiscard __attribute__((warn_unused_result))
  191. #define ufbxi_unused __attribute__((unused))
  192. #define ufbxi_unlikely(cond) __builtin_expect((cond), 0)
  193. #else
  194. #define ufbxi_noinline
  195. #define ufbxi_forceinline
  196. #define ufbxi_nodiscard
  197. #define ufbxi_restrict
  198. #define ufbxi_unused
  199. #define ufbxi_unlikely(cond) (cond)
  200. #endif
  201. #if !defined(UFBX_STANDARD_C) && defined(__clang__)
  202. #define ufbxi_nounroll _Pragma("clang loop unroll(disable)") _Pragma("clang loop vectorize(disable)")
  203. #elif !defined(UFBX_STANDARD_C) && defined(__GNUC__)
  204. #define ufbxi_nounroll _Pragma("GCC unroll 0")
  205. #elif !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
  206. #define ufbxi_nounroll __pragma(loop(no_vector))
  207. #else
  208. #define ufbxi_nounroll
  209. #endif
  210. #if defined(__GNUC__) && !defined(__clang__)
  211. #define ufbxi_ignore(cond) (void)!(cond)
  212. #else
  213. #define ufbxi_ignore(cond) (void)(cond)
  214. #endif
  215. #if defined(_MSC_VER)
  216. #pragma warning(push)
  217. #pragma warning(disable: 4200) // nonstandard extension used: zero-sized array in struct/union
  218. #pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union
  219. #pragma warning(disable: 4127) // conditional expression is constant
  220. #pragma warning(disable: 4706) // assignment within conditional expression
  221. #pragma warning(disable: 4789) // buffer 'type_and_name' of size 8 bytes will be overrun; 16 bytes will be written starting at offset 0
  222. #if defined(UFBX_STANDARD_C)
  223. #pragma warning(disable: 4996) // 'fopen': This function or variable may be unsafe. Consider using fopen_s instead.
  224. #endif
  225. #endif
  226. #if defined(__clang__)
  227. #pragma clang diagnostic push
  228. #pragma clang diagnostic ignored "-Wmissing-field-initializers"
  229. #pragma clang diagnostic ignored "-Wmissing-braces"
  230. #if defined(UFBX_STANDARD_C)
  231. #pragma clang diagnostic ignored "-Wunused-function"
  232. #endif
  233. #if defined(UFBXI_PARTIAL_FEATURES)
  234. #pragma clang diagnostic ignored "-Wunused-function"
  235. #pragma clang diagnostic ignored "-Wunused-parameter"
  236. #endif
  237. #endif
  238. #if defined(__GNUC__)
  239. #pragma GCC diagnostic push
  240. #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
  241. #pragma GCC diagnostic ignored "-Wmissing-braces"
  242. #if defined(UFBX_STANDARD_C)
  243. #pragma GCC diagnostic ignored "-Wunused-function"
  244. #endif
  245. #if defined(UFBXI_PARTIAL_FEATURES)
  246. #pragma GCC diagnostic ignored "-Wunused-function"
  247. #pragma GCC diagnostic ignored "-Wunused-parameter"
  248. #endif
  249. #endif
  250. #if !defined(ufbx_static_assert)
  251. #if defined(__cplusplus) && __cplusplus >= 201103
  252. #define ufbx_static_assert(desc, cond) static_assert(cond, #desc ": " #cond)
  253. #else
  254. #define ufbx_static_assert(desc, cond) typedef char ufbxi_static_assert_##desc[(cond)?1:-1]
  255. #endif
  256. #endif
  257. #if defined(__has_feature)
  258. #if __has_feature(undefined_behavior_sanitizer) && !defined(UFBX_UBSAN)
  259. #define UFBX_UBSAN 1
  260. #endif
  261. #endif
  262. #if defined(__SANITIZE_UNDEFINED__) && !defined(UFBX_UBSAN)
  263. #define UFBX_UBSAN 1
  264. #endif
  265. // Don't use unaligned loads with UB-sanitizer
  266. #if defined(UFBX_UBSAN) && !defined(UFBX_NO_UNALIGNED_LOADS)
  267. #define UFBX_NO_UNALIGNED_LOADS
  268. #endif
  269. #if defined(__clang_analyzer__) && !defined(UFBX_STATIC_ANALYSIS)
  270. #define UFBX_STATIC_ANALYSIS 1
  271. #endif
  272. #if defined(UFBX_STATIC_ANALYSIS)
  273. bool g_analysis_opaque;
  274. #define ufbxi_maybe_null(ptr) (g_analysis_opaque ? (ptr) : NULL)
  275. #else
  276. #define ufbxi_maybe_null(ptr) (ptr)
  277. #endif
  278. #if !defined(ufbxi_trace)
  279. #if defined(UFBX_TRACE)
  280. #define ufbxi_trace(desc) (fprintf(stderr, "ufbx trace: %s:%d: %s\n", __FILE__, __LINE__, #desc), fflush(stderr), desc)
  281. #else
  282. #define ufbxi_trace(desc) (desc)
  283. #endif
  284. #endif
  285. #ifndef UFBX_PATH_SEPARATOR
  286. #if defined(_WIN32)
  287. #define UFBX_PATH_SEPARATOR '\\'
  288. #else
  289. #define UFBX_PATH_SEPARATOR '/'
  290. #endif
  291. #endif
  292. #if !defined(UFBX_STANDARD_C) && defined(_POSIX_C_SOURCE)
  293. #if _POSIX_C_SOURCE >= 200112l
  294. #ifndef UFBX_HAS_FTELLO
  295. #define UFBX_HAS_FTELLO
  296. #endif
  297. #endif
  298. #endif
  299. // Unaligned little-endian load functions
  300. // On platforms that support unaligned access natively (x86, x64, ARM64) just use normal loads,
  301. // with unaligned attributes, otherwise do manual byte-wise load.
  302. #define ufbxi_read_u8(ptr) (*(const uint8_t*)(ptr))
  303. // Detect support for `__attribute__((aligned(1)))`
  304. #if !defined(UFBX_STANDARD_C) && (defined(__clang__) && defined(__APPLE__))
  305. // Apple overrides Clang versioning, 5.0 here maps to 3.3
  306. #if __clang_major__ >= 5
  307. #define UFBXI_HAS_ATTRIBUTE_ALIGNED 1
  308. #endif
  309. #elif !defined(UFBX_STANDARD_C) && defined(__clang__)
  310. #if (__clang_major__ >= 4) || (__clang_major__ == 3 && __clang_minor__ >= 3)
  311. #define UFBXI_HAS_ATTRIBUTE_ALIGNED 1
  312. #endif
  313. #elif !defined(UFBX_STANDARD_C) && defined(__GNUC__)
  314. #if __GNUC__ >= 5
  315. #define UFBXI_HAS_ATTRIBUTE_ALIGNED 1
  316. #endif
  317. #endif
  318. #if defined(UFBXI_HAS_ATTRIBUTE_ALIGNED)
  319. #define UFBXI_HAS_UNALIGNED 1
  320. #define ufbxi_unaligned
  321. typedef uint16_t __attribute__((aligned(1))) ufbxi_unaligned_u16;
  322. typedef uint32_t __attribute__((aligned(1))) ufbxi_unaligned_u32;
  323. typedef uint64_t __attribute__((aligned(1))) ufbxi_unaligned_u64;
  324. typedef float __attribute__((aligned(1))) ufbxi_unaligned_f32;
  325. typedef double __attribute__((aligned(1))) ufbxi_unaligned_f64;
  326. #elif !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
  327. #define UFBXI_HAS_UNALIGNED 1
  328. #if defined(_M_IX86)
  329. // MSVC seems to assume all pointers are unaligned for x86
  330. #define ufbxi_unaligned
  331. #else
  332. #define ufbxi_unaligned __unaligned
  333. #endif
  334. typedef uint16_t ufbxi_unaligned_u16;
  335. typedef uint32_t ufbxi_unaligned_u32;
  336. typedef uint64_t ufbxi_unaligned_u64;
  337. typedef float ufbxi_unaligned_f32;
  338. typedef double ufbxi_unaligned_f64;
  339. #endif
  340. #if defined(UFBXI_HAS_UNALIGNED) && ((defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) || defined(__wasm__) || defined(__EMSCRIPTEN__)) && !defined(UFBX_NO_UNALIGNED_LOADS) || defined(UFBX_USE_UNALIGNED_LOADS))
  341. #define ufbxi_read_u16(ptr) (*(const ufbxi_unaligned ufbxi_unaligned_u16*)(ptr))
  342. #define ufbxi_read_u32(ptr) (*(const ufbxi_unaligned ufbxi_unaligned_u32*)(ptr))
  343. #define ufbxi_read_u64(ptr) (*(const ufbxi_unaligned ufbxi_unaligned_u64*)(ptr))
  344. #define ufbxi_read_f32(ptr) (*(const ufbxi_unaligned ufbxi_unaligned_f32*)(ptr))
  345. #define ufbxi_read_f64(ptr) (*(const ufbxi_unaligned ufbxi_unaligned_f64*)(ptr))
  346. #else
  347. static ufbxi_forceinline uint16_t ufbxi_read_u16(const void *ptr) {
  348. const char *p = (const char*)ptr;
  349. return (uint16_t)(
  350. (unsigned)(uint8_t)p[0] << 0u |
  351. (unsigned)(uint8_t)p[1] << 8u );
  352. }
  353. static ufbxi_forceinline uint32_t ufbxi_read_u32(const void *ptr) {
  354. const char *p = (const char*)ptr;
  355. return (uint32_t)(
  356. (unsigned)(uint8_t)p[0] << 0u |
  357. (unsigned)(uint8_t)p[1] << 8u |
  358. (unsigned)(uint8_t)p[2] << 16u |
  359. (unsigned)(uint8_t)p[3] << 24u );
  360. }
  361. static ufbxi_forceinline uint64_t ufbxi_read_u64(const void *ptr) {
  362. const char *p = (const char*)ptr;
  363. return (uint64_t)(
  364. (uint64_t)(uint8_t)p[0] << 0u |
  365. (uint64_t)(uint8_t)p[1] << 8u |
  366. (uint64_t)(uint8_t)p[2] << 16u |
  367. (uint64_t)(uint8_t)p[3] << 24u |
  368. (uint64_t)(uint8_t)p[4] << 32u |
  369. (uint64_t)(uint8_t)p[5] << 40u |
  370. (uint64_t)(uint8_t)p[6] << 48u |
  371. (uint64_t)(uint8_t)p[7] << 56u );
  372. }
  373. static ufbxi_forceinline float ufbxi_read_f32(const void *ptr) {
  374. uint32_t u = ufbxi_read_u32(ptr);
  375. float f;
  376. memcpy(&f, &u, 4);
  377. return f;
  378. }
  379. static ufbxi_forceinline double ufbxi_read_f64(const void *ptr) {
  380. uint64_t u = ufbxi_read_u64(ptr);
  381. double f;
  382. memcpy(&f, &u, 8);
  383. return f;
  384. }
  385. #endif
  386. #define ufbxi_read_i8(ptr) (int8_t)(ufbxi_read_u8(ptr))
  387. #define ufbxi_read_i16(ptr) (int16_t)(ufbxi_read_u16(ptr))
  388. #define ufbxi_read_i32(ptr) (int32_t)(ufbxi_read_u32(ptr))
  389. #define ufbxi_read_i64(ptr) (int64_t)(ufbxi_read_u64(ptr))
  390. ufbx_static_assert(sizeof_bool, sizeof(bool) == 1);
  391. ufbx_static_assert(sizeof_char, sizeof(char) == 1);
  392. ufbx_static_assert(sizeof_i8, sizeof(int8_t) == 1);
  393. ufbx_static_assert(sizeof_i16, sizeof(int16_t) == 2);
  394. ufbx_static_assert(sizeof_i32, sizeof(int32_t) == 4);
  395. ufbx_static_assert(sizeof_i64, sizeof(int64_t) == 8);
  396. ufbx_static_assert(sizeof_u8, sizeof(uint8_t) == 1);
  397. ufbx_static_assert(sizeof_u16, sizeof(uint16_t) == 2);
  398. ufbx_static_assert(sizeof_u32, sizeof(uint32_t) == 4);
  399. ufbx_static_assert(sizeof_u64, sizeof(uint64_t) == 8);
  400. ufbx_static_assert(sizeof_f32, sizeof(float) == 4);
  401. ufbx_static_assert(sizeof_f64, sizeof(double) == 8);
  402. // -- Atomic counter
  403. #define UFBXI_THREAD_SAFE 1
  404. #if !defined(UFBX_STANDARD_C) && (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER))
  405. typedef size_t ufbxi_atomic_counter;
  406. #define ufbxi_atomic_counter_init(ptr) (*(ptr) = 0)
  407. #define ufbxi_atomic_counter_free(ptr) (*(ptr) = 0)
  408. #define ufbxi_atomic_counter_inc(ptr) __sync_fetch_and_add((ptr), 1)
  409. #define ufbxi_atomic_counter_dec(ptr) __sync_fetch_and_sub((ptr), 1)
  410. #elif !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
  411. #if defined(_M_X64) || defined(_M_ARM64)
  412. #if defined(__cplusplus)
  413. extern "C" __int64 _InterlockedIncrement64(__int64 volatile * lpAddend);
  414. extern "C" __int64 _InterlockedDecrement64(__int64 volatile * lpAddend);
  415. #else
  416. __int64 _InterlockedIncrement64(__int64 volatile * lpAddend);
  417. __int64 _InterlockedDecrement64(__int64 volatile * lpAddend);
  418. #endif
  419. typedef volatile __int64 ufbxi_atomic_counter;
  420. #define ufbxi_atomic_counter_init(ptr) (*(ptr) = 0)
  421. #define ufbxi_atomic_counter_free(ptr) (*(ptr) = 0)
  422. #define ufbxi_atomic_counter_inc(ptr) ((size_t)_InterlockedIncrement64(ptr) - 1)
  423. #define ufbxi_atomic_counter_dec(ptr) ((size_t)_InterlockedDecrement64(ptr) + 1)
  424. #else
  425. #if defined(__cplusplus)
  426. extern "C" long _InterlockedIncrement(long volatile * lpAddend);
  427. extern "C" long _InterlockedDecrement(long volatile * lpAddend);
  428. #else
  429. long _InterlockedIncrement(long volatile * lpAddend);
  430. long _InterlockedDecrement(long volatile * lpAddend);
  431. #endif
  432. typedef volatile long ufbxi_atomic_counter;
  433. #define ufbxi_atomic_counter_init(ptr) (*(ptr) = 0)
  434. #define ufbxi_atomic_counter_free(ptr) (*(ptr) = 0)
  435. #define ufbxi_atomic_counter_inc(ptr) ((size_t)_InterlockedIncrement(ptr) - 1)
  436. #define ufbxi_atomic_counter_dec(ptr) ((size_t)_InterlockedDecrement(ptr) + 1)
  437. #endif
  438. #elif !defined(UFBX_STANDARD_C) && defined(__TINYC__)
  439. #if defined(__x86_64__) || defined(_AMD64_)
  440. static size_t ufbxi_tcc_atomic_add(volatile size_t *dst, size_t value) {
  441. __asm__ __volatile__("lock; xaddq %0, %1;" : "+r" (value), "=m" (*dst) : "m" (dst));
  442. return value;
  443. }
  444. #elif defined(__i386__) || defined(_X86_)
  445. static size_t ufbxi_tcc_atomic_add(volatile size_t *dst, size_t value) {
  446. __asm__ __volatile__("lock; xaddl %0, %1;" : "+r" (value), "=m" (*dst) : "m" (dst));
  447. return value;
  448. }
  449. #else
  450. #error Unexpected TCC architecture
  451. #endif
  452. typedef volatile size_t ufbxi_atomic_counter;
  453. #define ufbxi_atomic_counter_init(ptr) (*(ptr) = 0)
  454. #define ufbxi_atomic_counter_free(ptr) (*(ptr) = 0)
  455. #define ufbxi_atomic_counter_inc(ptr) ufbxi_tcc_atomic_add((ptr), 1)
  456. #define ufbxi_atomic_counter_dec(ptr) ufbxi_tcc_atomic_add((ptr), SIZE_MAX)
  457. #elif defined(__cplusplus) && (__cplusplus >= 201103L)
  458. #include <new>
  459. #include <atomic>
  460. typedef struct { alignas(std::atomic_size_t) char data[sizeof(std::atomic_size_t)]; } ufbxi_atomic_counter;
  461. #define ufbxi_atomic_counter_init(ptr) (new (&(ptr)->data) std::atomic_size_t(0))
  462. #define ufbxi_atomic_counter_free(ptr) (((std::atomic_size_t*)(ptr)->data)->~atomic_size_t())
  463. #define ufbxi_atomic_counter_inc(ptr) ((std::atomic_size_t*)(ptr)->data)->fetch_add(1)
  464. #define ufbxi_atomic_counter_dec(ptr) ((std::atomic_size_t*)(ptr)->data)->fetch_sub(1)
  465. #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__)
  466. #include <stdatomic.h>
  467. typedef volatile atomic_size_t ufbxi_atomic_counter;
  468. #define ufbxi_atomic_counter_init(ptr) atomic_init(ptr, 0)
  469. #define ufbxi_atomic_counter_free(ptr) (void)0
  470. #define ufbxi_atomic_counter_inc(ptr) atomic_fetch_add((ptr), 1)
  471. #define ufbxi_atomic_counter_dec(ptr) atomic_fetch_sub((ptr), 1)
  472. #else
  473. typedef volatile size_t ufbxi_atomic_counter;
  474. #define ufbxi_atomic_counter_init(ptr) (*(ptr) = 0)
  475. #define ufbxi_atomic_counter_free(ptr) (*(ptr) = 0)
  476. #define ufbxi_atomic_counter_inc(ptr) ((*(ptr))++)
  477. #define ufbxi_atomic_counter_dec(ptr) ((*(ptr))--)
  478. #undef UFBXI_THREAD_SAFE
  479. #define UFBXI_THREAD_SAFE 0
  480. #endif
  481. // -- Version
  482. #define UFBX_SOURCE_VERSION ufbx_pack_version(0, 1, 1)
  483. const uint32_t ufbx_source_version = UFBX_SOURCE_VERSION;
  484. ufbx_static_assert(source_header_version, UFBX_SOURCE_VERSION/1000u == UFBX_HEADER_VERSION/1000u);
  485. // -- Debug
  486. #if defined(UFBX_DEBUG_BINARY_SEARCH) || defined(UFBX_REGRESSION)
  487. #define ufbxi_clamp_linear_threshold(v) (2)
  488. #else
  489. #define ufbxi_clamp_linear_threshold(v) (v)
  490. #endif
  491. #if defined(UFBX_REGRESSION)
  492. #undef UFBXI_MAX_SKIP_SIZE
  493. #define UFBXI_MAX_SKIP_SIZE 128
  494. #undef UFBXI_MAP_MAX_SCAN
  495. #define UFBXI_MAP_MAX_SCAN 2
  496. #undef UFBXI_KD_FAST_DEPTH
  497. #define UFBXI_KD_FAST_DEPTH 2
  498. #endif
  499. #if defined(UFBX_REGRESSION)
  500. #define ufbxi_regression_assert(cond) ufbx_assert(cond)
  501. #else
  502. #define ufbxi_regression_assert(cond) (void)0
  503. #endif
  504. #if defined(UFBX_REGRESSION) || defined(UFBX_DEV)
  505. #define ufbxi_dev_assert(cond) ufbx_assert(cond)
  506. #else
  507. #define ufbxi_dev_assert(cond) (void)0
  508. #endif
  509. // -- Utility
  510. #if defined(UFBX_UBSAN)
  511. static void ufbxi_assert_zero(size_t offset) { ufbx_assert(offset == 0); }
  512. #define ufbxi_add_ptr(ptr, offset) ((ptr) ? (ptr) + (offset) : (ufbxi_assert_zero((size_t)(offset)), (ptr)))
  513. #else
  514. #define ufbxi_add_ptr(ptr, offset) ((ptr) + (offset))
  515. #endif
  516. #define ufbxi_arraycount(arr) (sizeof(arr) / sizeof(*(arr)))
  517. #define ufbxi_for(m_type, m_name, m_begin, m_num) for (m_type *m_name = m_begin, *m_name##_end = ufbxi_add_ptr(m_name, m_num); m_name != m_name##_end; m_name++)
  518. #define ufbxi_for_ptr(m_type, m_name, m_begin, m_num) for (m_type **m_name = m_begin, **m_name##_end = ufbxi_add_ptr(m_name, m_num); m_name != m_name##_end; m_name++)
  519. // WARNING: Evaluates `m_list` twice!
  520. #define ufbxi_for_list(m_type, m_name, m_list) for (m_type *m_name = (m_list).data, *m_name##_end = ufbxi_add_ptr(m_name, (m_list).count); m_name != m_name##_end; m_name++)
  521. #define ufbxi_for_ptr_list(m_type, m_name, m_list) for (m_type **m_name = (m_list).data, **m_name##_end = ufbxi_add_ptr(m_name, (m_list).count); m_name != m_name##_end; m_name++)
  522. #define ufbxi_string_literal(str) { str, sizeof(str) - 1 }
  523. static ufbxi_forceinline uint32_t ufbxi_min32(uint32_t a, uint32_t b) { return a < b ? a : b; }
  524. static ufbxi_forceinline uint32_t ufbxi_max32(uint32_t a, uint32_t b) { return a < b ? b : a; }
  525. static ufbxi_forceinline uint64_t ufbxi_min64(uint64_t a, uint64_t b) { return a < b ? a : b; }
  526. static ufbxi_forceinline uint64_t ufbxi_max64(uint64_t a, uint64_t b) { return a < b ? b : a; }
  527. static ufbxi_forceinline size_t ufbxi_min_sz(size_t a, size_t b) { return a < b ? a : b; }
  528. static ufbxi_forceinline size_t ufbxi_max_sz(size_t a, size_t b) { return a < b ? b : a; }
  529. static ufbxi_forceinline ufbx_real ufbxi_min_real(ufbx_real a, ufbx_real b) { return a < b ? a : b; }
  530. static ufbxi_forceinline ufbx_real ufbxi_max_real(ufbx_real a, ufbx_real b) { return a < b ? b : a; }
  531. static ufbxi_forceinline int32_t ufbxi_f64_to_i32(double value)
  532. {
  533. if (ufbx_fabs(value) <= (double)INT32_MAX) {
  534. return (int32_t)value;
  535. } else {
  536. return value >= 0.0 ? INT32_MAX : INT32_MIN;
  537. }
  538. }
  539. static ufbxi_forceinline int64_t ufbxi_f64_to_i64(double value)
  540. {
  541. if (ufbx_fabs(value) <= (double)INT64_MAX) {
  542. return (int64_t)value;
  543. } else {
  544. return value >= 0.0 ? INT64_MAX : INT64_MIN;
  545. }
  546. }
  547. #if defined(UFBX_REGRESSION)
  548. static size_t ufbxi_to_size(ptrdiff_t delta) {
  549. ufbx_assert(delta >= 0);
  550. return (size_t)delta;
  551. }
  552. #else
  553. #define ufbxi_to_size(delta) ((size_t)(delta))
  554. #endif
  555. // Stable sort array `m_type m_data[m_size]` using the predicate `m_cmp_lambda(a, b)`
  556. // `m_linear_size` is a hint for how large blocks handle initially do with insertion sort
  557. // `m_tmp` must be a memory buffer with at least the same size and alignment as `m_data`
  558. #define ufbxi_macro_stable_sort(m_type, m_linear_size, m_data, m_tmp, m_size, m_cmp_lambda) do { \
  559. typedef m_type mi_type; \
  560. mi_type *mi_src = (mi_type*)(m_tmp); \
  561. mi_type *mi_data = m_data, *mi_dst = mi_data; \
  562. size_t mi_block_size = ufbxi_clamp_linear_threshold(m_linear_size), mi_size = m_size; \
  563. /* Insertion sort in `m_linear_size` blocks */ \
  564. for (size_t mi_base = 0; mi_base < mi_size; mi_base += mi_block_size) { \
  565. size_t mi_i_end = mi_base + mi_block_size; \
  566. if (mi_i_end > mi_size) mi_i_end = mi_size; \
  567. for (size_t mi_i = mi_base + 1; mi_i < mi_i_end; mi_i++) { \
  568. size_t mi_j = mi_i; \
  569. mi_src[0] = mi_dst[mi_i]; \
  570. for (; mi_j != mi_base; --mi_j) { \
  571. mi_type *a = &mi_src[0], *b = &mi_dst[mi_j - 1]; \
  572. if (!( m_cmp_lambda )) break; \
  573. mi_dst[mi_j] = mi_dst[mi_j - 1]; \
  574. } \
  575. mi_dst[mi_j] = mi_src[0]; \
  576. } \
  577. } \
  578. /* Merge sort ping-ponging between `m_data` and `m_tmp` */ \
  579. for (; mi_block_size < mi_size; mi_block_size *= 2) { \
  580. mi_type *mi_swap = mi_dst; mi_dst = mi_src; mi_src = mi_swap; \
  581. for (size_t mi_base = 0; mi_base < mi_size; mi_base += mi_block_size * 2) { \
  582. size_t mi_i = mi_base, mi_i_end = mi_base + mi_block_size; \
  583. size_t mi_j = mi_i_end, mi_j_end = mi_j + mi_block_size; \
  584. size_t mi_k = mi_base; \
  585. if (mi_i_end > mi_size) mi_i_end = mi_size; \
  586. if (mi_j_end > mi_size) mi_j_end = mi_size; \
  587. while ((mi_i < mi_i_end) & (mi_j < mi_j_end)) { \
  588. mi_type *a = &mi_src[mi_j], *b = &mi_src[mi_i]; \
  589. if ( m_cmp_lambda ) { \
  590. mi_dst[mi_k] = *a; mi_j++; \
  591. } else { \
  592. mi_dst[mi_k] = *b; mi_i++; \
  593. } \
  594. mi_k++; \
  595. } \
  596. while (mi_i < mi_i_end) mi_dst[mi_k++] = mi_src[mi_i++]; \
  597. while (mi_j < mi_j_end) mi_dst[mi_k++] = mi_src[mi_j++]; \
  598. } \
  599. } \
  600. /* Copy the result to `m_data` if we ended up in `m_tmp` */ \
  601. if (mi_dst != mi_data) memcpy((void*)mi_data, mi_dst, sizeof(mi_type) * mi_size); \
  602. } while (0)
  603. #define ufbxi_macro_lower_bound_eq(m_type, m_linear_size, m_result_ptr, m_data, m_begin, m_size, m_cmp_lambda, m_eq_lambda) do { \
  604. typedef m_type mi_type; \
  605. const mi_type *mi_data = (m_data); \
  606. size_t mi_lo = m_begin, mi_hi = m_size, mi_linear_size = ufbxi_clamp_linear_threshold(m_linear_size); \
  607. ufbx_assert(mi_linear_size > 1); \
  608. /* Binary search until we get down to `m_linear_size` elements */ \
  609. while (mi_hi - mi_lo > mi_linear_size) { \
  610. size_t mi_mid = mi_lo + (mi_hi - mi_lo) / 2; \
  611. const mi_type *a = &mi_data[mi_mid]; \
  612. if ( m_cmp_lambda ) { mi_lo = mi_mid + 1; } else { mi_hi = mi_mid + 1; } \
  613. } \
  614. /* Linearly scan until we find the edge */ \
  615. for (; mi_lo < mi_hi; mi_lo++) { \
  616. const mi_type *a = &mi_data[mi_lo]; \
  617. if ( m_eq_lambda ) { *(m_result_ptr) = mi_lo; break; } \
  618. } \
  619. } while (0)
  620. #define ufbxi_macro_upper_bound_eq(m_type, m_linear_size, m_result_ptr, m_data, m_begin, m_size, m_eq_lambda) do { \
  621. typedef m_type mi_type; \
  622. const mi_type *mi_data = (m_data); \
  623. size_t mi_lo = m_begin, mi_hi = m_size, mi_linear_size = ufbxi_clamp_linear_threshold(m_linear_size); \
  624. ufbx_assert(mi_linear_size > 1); \
  625. /* Linearly scan with galloping */ \
  626. for (size_t mi_step = 1; mi_step < 100 && mi_hi - mi_lo > mi_step; mi_step *= 2) { \
  627. const mi_type *a = &mi_data[mi_lo + mi_step]; \
  628. if (!( m_eq_lambda )) { mi_hi = mi_lo + mi_step; break; } \
  629. mi_lo += mi_step; \
  630. } \
  631. /* Binary search until we get down to `m_linear_size` elements */ \
  632. while (mi_hi - mi_lo > mi_linear_size) { \
  633. size_t mi_mid = mi_lo + (mi_hi - mi_lo) / 2; \
  634. const mi_type *a = &mi_data[mi_mid]; \
  635. if ( m_eq_lambda ) { mi_lo = mi_mid + 1; } else { mi_hi = mi_mid + 1; } \
  636. } \
  637. /* Linearly scan until we find the edge */ \
  638. for (; mi_lo < mi_hi; mi_lo++) { \
  639. const mi_type *a = &mi_data[mi_lo]; \
  640. if (!( m_eq_lambda )) break; \
  641. } \
  642. *(m_result_ptr) = mi_lo; \
  643. } while (0)
  644. typedef bool ufbxi_less_fn(void *user, const void *a, const void *b);
  645. static ufbxi_noinline void ufbxi_stable_sort(size_t stride, size_t linear_size, void *in_data, void *in_tmp, size_t size, ufbxi_less_fn *less_fn, void *less_user)
  646. {
  647. (void)linear_size;
  648. char *src = (char*)in_tmp;
  649. char *data = (char*)in_data, *dst = (char*)data;
  650. size_t block_size = ufbxi_clamp_linear_threshold(linear_size);
  651. /* Insertion sort in `linear_size` blocks */
  652. for (size_t base = 0; base < size; base += block_size) {
  653. size_t i_end = base + block_size;
  654. if (i_end > size) i_end = size;
  655. for (size_t i = base + 1; i < i_end; i++) {
  656. {
  657. char *a = dst + i * stride, *b = dst + (i - 1) * stride;
  658. if (!less_fn(less_user, a, b)) continue;
  659. }
  660. size_t j = i - 1;
  661. memcpy(src, dst + i * stride, stride);
  662. memcpy(dst + i * stride, dst + j * stride, stride);
  663. for (; j != base; --j) {
  664. char *a = src, *b = dst + (j - 1) * stride;
  665. if (!less_fn(less_user, a, b)) break;
  666. memcpy(dst + j * stride, dst + (j - 1) * stride, stride);
  667. }
  668. memcpy(dst + j * stride, src, stride);
  669. }
  670. }
  671. /* Merge sort ping-ponging between `data` and `tmp` */
  672. for (; block_size < size; block_size *= 2) {
  673. char *swap = dst; dst = src; src = swap;
  674. for (size_t base = 0; base < size; base += block_size * 2) {
  675. size_t i = base, i_end = base + block_size;
  676. size_t j = i_end, j_end = j + block_size;
  677. size_t k = base;
  678. if (i_end > size) i_end = size;
  679. if (j_end > size) j_end = size;
  680. while ((i < i_end) & (j < j_end)) {
  681. char *a = src + j * stride, *b = src + i * stride;
  682. if (less_fn(less_user, a, b)) {
  683. memcpy(dst + k * stride, a, stride);
  684. j++;
  685. } else {
  686. memcpy(dst + k * stride, b, stride);
  687. i++;
  688. }
  689. k++;
  690. }
  691. memcpy(dst + k * stride, src + i * stride, (i_end - i) * stride);
  692. if (j < j_end) {
  693. memcpy(dst + (k + (i_end - i)) * stride, src + j * stride, (j_end - j) * stride);
  694. }
  695. }
  696. }
  697. /* Copy the result to `data` if we ended up in `tmp` */
  698. if (dst != data) memcpy((void*)data, dst, size * stride);
  699. }
  700. // -- DEFLATE implementation
  701. // Pretty much based on Sean Barrett's `stb_image` deflate
  702. #if !defined(ufbx_inflate)
  703. // Lookup data: [0:13] extra mask [13:17] extra bits [17:32] base value
  704. // Generated by `misc/deflate_lut.py`
  705. static const uint32_t ufbxi_deflate_length_lut[] = {
  706. 0x00060000, 0x00080000, 0x000a0000, 0x000c0000, 0x000e0000, 0x00100000, 0x00120000, 0x00140000,
  707. 0x00162001, 0x001a2001, 0x001e2001, 0x00222001, 0x00264003, 0x002e4003, 0x00364003, 0x003e4003,
  708. 0x00466007, 0x00566007, 0x00666007, 0x00766007, 0x0086800f, 0x00a6800f, 0x00c6800f, 0x00e6800f,
  709. 0x0106a01f, 0x0146a01f, 0x0186a01f, 0x01c6a01f, 0x02040000, 0x00000000, 0x00000000,
  710. };
  711. static const uint32_t ufbxi_deflate_dist_lut[] = {
  712. 0x00020000, 0x00040000, 0x00060000, 0x00080000, 0x000a2001, 0x000e2001, 0x00124003, 0x001a4003,
  713. 0x00226007, 0x00326007, 0x0042800f, 0x0062800f, 0x0082a01f, 0x00c2a01f, 0x0102c03f, 0x0182c03f,
  714. 0x0202e07f, 0x0302e07f, 0x040300ff, 0x060300ff, 0x080321ff, 0x0c0321ff, 0x100343ff, 0x180343ff,
  715. 0x200367ff, 0x300367ff, 0x40038fff, 0x60038fff, 0x8003bfff, 0xc003bfff,
  716. };
  717. static const uint8_t ufbxi_deflate_code_length_permutation[] = {
  718. 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,
  719. };
  720. #define UFBXI_HUFF_MAX_BITS 16
  721. #define UFBXI_HUFF_MAX_VALUE 288
  722. #define UFBXI_HUFF_FAST_BITS 9
  723. #define UFBXI_HUFF_FAST_SIZE (1 << UFBXI_HUFF_FAST_BITS)
  724. #define UFBXI_HUFF_FAST_MASK (UFBXI_HUFF_FAST_SIZE - 1)
  725. typedef struct {
  726. // Number of bytes left to read from `read_fn()`
  727. size_t input_left;
  728. // User-supplied read callback
  729. ufbx_read_fn *read_fn;
  730. void *read_user;
  731. // Buffer to read to from `read_fn()`, may point to `local_buffer` if user
  732. // didn't supply a suitable buffer.
  733. char *buffer;
  734. size_t buffer_size;
  735. // Current chunk of data to process, either the initial buffer of input
  736. // or part of `buffer`.
  737. const char *chunk_begin; // < Begin of the buffer
  738. const char *chunk_ptr; // < Next bytes to read to `bits`
  739. const char *chunk_yield; // < End of data before needing to call `ufbxi_bit_yield()`
  740. const char *chunk_end; // < End of data before needing to call `ufbxi_bit_refill()`
  741. const char *chunk_real_end; // < Actual end of the data buffer
  742. // Amount of bytes read before the current chunk
  743. size_t num_read_before_chunk;
  744. uint64_t progress_bias;
  745. uint64_t progress_total;
  746. size_t progress_interval;
  747. uint64_t bits; // < Buffered bits
  748. size_t left; // < Number of valid low bits in `bits`
  749. // Progress tracking, maybe `NULL` it not requested
  750. ufbx_progress_cb progress_cb;
  751. // When `progress_cb.fn()` returns `false` set the `cancelled` flag and
  752. // set the buffered bits to `cancel_bits`.
  753. uint64_t cancel_bits;
  754. bool cancelled;
  755. char local_buffer[256];
  756. } ufbxi_bit_stream;
  757. typedef struct {
  758. uint32_t num_symbols;
  759. uint16_t sorted_to_sym[UFBXI_HUFF_MAX_VALUE]; // < Sorted symbol index to symbol
  760. uint16_t past_max_code[UFBXI_HUFF_MAX_BITS]; // < One past maximum code value per bit length
  761. int16_t code_to_sorted[UFBXI_HUFF_MAX_BITS]; // < Code to sorted symbol index per bit length
  762. uint16_t fast_sym[UFBXI_HUFF_FAST_SIZE]; // < Fast symbol lookup [0:12] symbol [12:16] bits
  763. uint32_t end_of_block_bits;
  764. } ufbxi_huff_tree;
  765. typedef struct {
  766. ufbxi_huff_tree lit_length;
  767. ufbxi_huff_tree dist;
  768. } ufbxi_trees;
  769. typedef struct {
  770. bool initialized;
  771. ufbxi_trees static_trees;
  772. } ufbxi_inflate_retain_imp;
  773. ufbx_static_assert(inflate_retain_size, sizeof(ufbxi_inflate_retain_imp) <= sizeof(ufbx_inflate_retain));
  774. typedef struct {
  775. ufbxi_bit_stream stream;
  776. char *out_begin;
  777. char *out_ptr;
  778. char *out_end;
  779. } ufbxi_deflate_context;
  780. static ufbxi_forceinline uint32_t
  781. ufbxi_bit_reverse(uint32_t mask, uint32_t num_bits)
  782. {
  783. ufbxi_dev_assert(num_bits <= 16);
  784. uint32_t x = mask;
  785. x = (((x & 0xaaaa) >> 1) | ((x & 0x5555) << 1));
  786. x = (((x & 0xcccc) >> 2) | ((x & 0x3333) << 2));
  787. x = (((x & 0xf0f0) >> 4) | ((x & 0x0f0f) << 4));
  788. x = (((x & 0xff00) >> 8) | ((x & 0x00ff) << 8));
  789. return x >> (16 - num_bits);
  790. }
  791. static ufbxi_noinline const char *
  792. ufbxi_bit_chunk_refill(ufbxi_bit_stream *s, const char *ptr)
  793. {
  794. // Copy any left-over data to the beginning of `buffer`
  795. size_t left = ufbxi_to_size(s->chunk_real_end - ptr);
  796. ufbxi_dev_assert(left < 64);
  797. memmove(s->buffer, ptr, left);
  798. s->num_read_before_chunk += ufbxi_to_size(ptr - s->chunk_begin);
  799. // Read more user data if the user supplied a `read_fn()`, otherwise
  800. // we assume the initial data chunk is the whole input buffer.
  801. if (s->read_fn) {
  802. size_t to_read = ufbxi_min_sz(s->input_left, s->buffer_size - left);
  803. if (to_read > 0) {
  804. size_t num_read = s->read_fn(s->read_user, s->buffer + left, to_read);
  805. // TOOD: IO error, should unify with (currently broken) cancel logic
  806. if (num_read > to_read) num_read = 0;
  807. ufbxi_dev_assert(s->input_left >= num_read);
  808. s->input_left -= num_read;
  809. left += num_read;
  810. }
  811. }
  812. // Pad the rest with zeros
  813. if (left < 64) {
  814. memset(s->buffer + left, 0, 64 - left);
  815. left = 64;
  816. }
  817. s->chunk_begin = s->buffer;
  818. s->chunk_ptr = s->buffer;
  819. s->chunk_end = s->buffer + left - 8;
  820. s->chunk_real_end = s->buffer + left;
  821. return s->buffer;
  822. }
  823. static ufbxi_noinline void ufbxi_bit_stream_init(ufbxi_bit_stream *s, const ufbx_inflate_input *input)
  824. {
  825. size_t data_size = input->data_size;
  826. if (data_size > input->total_size) {
  827. data_size = input->total_size;
  828. }
  829. s->read_fn = input->read_fn;
  830. s->read_user = input->read_user;
  831. s->progress_cb = input->progress_cb;
  832. s->chunk_begin = (const char*)input->data;
  833. s->chunk_ptr = (const char*)input->data;
  834. s->chunk_end = (const char*)input->data + data_size - 8;
  835. s->chunk_real_end = (const char*)input->data + data_size;
  836. s->input_left = input->total_size - data_size;
  837. // Use the user buffer if it's large enough, otherwise `local_buffer`
  838. if (input->buffer_size > sizeof(s->local_buffer)) {
  839. s->buffer = (char*)input->buffer;
  840. s->buffer_size = input->buffer_size;
  841. } else {
  842. s->buffer = s->local_buffer;
  843. s->buffer_size = sizeof(s->local_buffer);
  844. }
  845. s->num_read_before_chunk = 0;
  846. s->progress_bias = input->progress_size_before;
  847. s->progress_total = input->total_size + input->progress_size_before + input->progress_size_after;
  848. if (!s->progress_cb.fn || input->progress_interval_hint >= SIZE_MAX) {
  849. s->progress_interval = SIZE_MAX;
  850. } else if (input->progress_interval_hint > 0) {
  851. s->progress_interval = (size_t)input->progress_interval_hint;
  852. } else {
  853. s->progress_interval = 0x4000;
  854. }
  855. s->cancelled = false;
  856. // Clear the initial bit buffer
  857. s->bits = 0;
  858. s->left = 0;
  859. // If the initial data buffer is not large enough to be read directly
  860. // from refill the chunk once.
  861. if (data_size < 64) {
  862. ufbxi_bit_chunk_refill(s, s->chunk_begin);
  863. }
  864. if (s->progress_cb.fn && ufbxi_to_size(s->chunk_end - s->chunk_ptr) > s->progress_interval + 8) {
  865. s->chunk_yield = s->chunk_ptr + s->progress_interval;
  866. } else {
  867. s->chunk_yield = s->chunk_end;
  868. }
  869. }
  870. static ufbxi_noinline const char *
  871. ufbxi_bit_yield(ufbxi_bit_stream *s, const char *ptr)
  872. {
  873. if (ptr > s->chunk_end) {
  874. ptr = ufbxi_bit_chunk_refill(s, ptr);
  875. }
  876. if (s->progress_cb.fn && ufbxi_to_size(s->chunk_end - ptr) > s->progress_interval + 8) {
  877. s->chunk_yield = ptr + s->progress_interval;
  878. } else {
  879. s->chunk_yield = s->chunk_end;
  880. }
  881. if (s->progress_cb.fn) {
  882. size_t num_read = s->num_read_before_chunk + ufbxi_to_size(ptr - s->chunk_begin);
  883. ufbx_progress progress = { s->progress_bias + num_read, s->progress_total };
  884. uint32_t result = (uint32_t)s->progress_cb.fn(s->progress_cb.user, &progress);
  885. ufbx_assert(result == UFBX_PROGRESS_CONTINUE || result == UFBX_PROGRESS_CANCEL);
  886. if (result == UFBX_PROGRESS_CANCEL) {
  887. s->cancelled = true;
  888. ptr = s->local_buffer;
  889. memset(s->local_buffer, 0, sizeof(s->local_buffer));
  890. }
  891. }
  892. return ptr;
  893. }
  894. static ufbxi_forceinline void
  895. ufbxi_bit_refill(uint64_t *p_bits, size_t *p_left, const char **p_data, ufbxi_bit_stream *s)
  896. {
  897. if (*p_data > s->chunk_yield) {
  898. *p_data = ufbxi_bit_yield(s, *p_data);
  899. if (s->cancelled) {
  900. // Force an end-of-block symbol when cancelled so we don't need an
  901. // extra branch in the chunk decoding loop.
  902. *p_bits = s->cancel_bits;
  903. }
  904. }
  905. // See https://fgiesen.wordpress.com/2018/02/20/reading-bits-in-far-too-many-ways-part-2/
  906. // variant 4. This branchless refill guarantees [56,63] bits to be valid in `*p_bits`.
  907. *p_bits |= ufbxi_read_u64(*p_data) << *p_left;
  908. *p_data += (63 - *p_left) >> 3;
  909. *p_left |= 56;
  910. }
  911. static ufbxi_noinline int
  912. ufbxi_bit_copy_bytes(void *dst, ufbxi_bit_stream *s, size_t len)
  913. {
  914. ufbx_assert(s->left % 8 == 0);
  915. char *ptr = (char*)dst;
  916. // Copy the buffered bits first
  917. while (len > 0 && s->left > 0) {
  918. *ptr++ = (char)(uint8_t)s->bits;
  919. len -= 1;
  920. s->bits >>= 8;
  921. s->left -= 8;
  922. }
  923. // We need to clear the top bits as there may be data
  924. // read ahead past `s->left` in some cases
  925. s->bits = 0;
  926. // Copy the current chunk
  927. size_t chunk_left = ufbxi_to_size(s->chunk_real_end - s->chunk_ptr);
  928. if (chunk_left >= len) {
  929. memcpy(ptr, s->chunk_ptr, len);
  930. s->chunk_ptr += len;
  931. return 1;
  932. } else {
  933. memcpy(ptr, s->chunk_ptr, chunk_left);
  934. s->chunk_ptr += chunk_left;
  935. ptr += chunk_left;
  936. len -= chunk_left;
  937. }
  938. // Read extra bytes from user
  939. if (len > s->input_left) return 0;
  940. size_t num_read = 0;
  941. if (s->read_fn) {
  942. num_read = s->read_fn(s->read_user, ptr, len);
  943. s->input_left -= num_read;
  944. }
  945. return num_read == len;
  946. }
  947. // 0: Success
  948. // -1: Overfull
  949. // -2: Underfull
  950. static ufbxi_noinline ptrdiff_t
  951. ufbxi_huff_build(ufbxi_huff_tree *tree, uint8_t *sym_bits, uint32_t sym_count)
  952. {
  953. ufbx_assert(sym_count <= UFBXI_HUFF_MAX_VALUE);
  954. tree->num_symbols = sym_count;
  955. // Count the number of codes per bit length
  956. // `bit_counts[0]` contains the number of non-used symbols
  957. uint32_t bits_counts[UFBXI_HUFF_MAX_BITS];
  958. memset(bits_counts, 0, sizeof(bits_counts));
  959. for (uint32_t i = 0; i < sym_count; i++) {
  960. uint32_t bits = sym_bits[i];
  961. ufbx_assert(bits < UFBXI_HUFF_MAX_BITS);
  962. bits_counts[bits]++;
  963. }
  964. uint32_t nonzero_sym_count = sym_count - bits_counts[0];
  965. uint32_t total_syms[UFBXI_HUFF_MAX_BITS];
  966. uint32_t first_code[UFBXI_HUFF_MAX_BITS];
  967. tree->code_to_sorted[0] = INT16_MAX;
  968. tree->past_max_code[0] = 0;
  969. total_syms[0] = 0;
  970. // Resolve the maximum code per bit length and ensure that the tree is not
  971. // overfull or underfull.
  972. {
  973. int num_codes_left = 1;
  974. uint32_t code = 0;
  975. uint32_t prev_count = 0;
  976. for (uint32_t bits = 1; bits < UFBXI_HUFF_MAX_BITS; bits++) {
  977. uint32_t count = bits_counts[bits];
  978. code = (code + prev_count) << 1;
  979. first_code[bits] = code;
  980. tree->past_max_code[bits] = (uint16_t)(code + count);
  981. uint32_t prev_syms = total_syms[bits - 1];
  982. total_syms[bits] = prev_syms + count;
  983. // Each bit level doubles the amount of codes and potentially removes some
  984. num_codes_left = (num_codes_left << 1) - (int32_t)count;
  985. if (num_codes_left < 0) {
  986. return -1;
  987. }
  988. if (count > 0) {
  989. tree->code_to_sorted[bits] = (int16_t)((int)prev_syms - (int)code);
  990. } else {
  991. tree->code_to_sorted[bits] = INT16_MAX;
  992. }
  993. prev_count = count;
  994. }
  995. // All codes should be used if there's more than one symbol
  996. if (nonzero_sym_count > 1 && num_codes_left != 0) {
  997. return -2;
  998. }
  999. }
  1000. tree->end_of_block_bits = 0;
  1001. // Generate per-length sorted-to-symbol and fast lookup tables
  1002. uint32_t bits_index[UFBXI_HUFF_MAX_BITS] = { 0 };
  1003. memset(tree->sorted_to_sym, 0xff, sizeof(tree->sorted_to_sym));
  1004. memset(tree->fast_sym, 0, sizeof(tree->fast_sym));
  1005. for (uint32_t i = 0; i < sym_count; i++) {
  1006. uint32_t bits = sym_bits[i];
  1007. if (bits == 0) continue;
  1008. uint32_t index = bits_index[bits]++;
  1009. uint32_t sorted = total_syms[bits - 1] + index;
  1010. tree->sorted_to_sym[sorted] = (uint16_t)i;
  1011. // Reverse the code and fill all fast lookups with the reversed prefix
  1012. uint32_t code = first_code[bits] + index;
  1013. uint32_t rev_code = ufbxi_bit_reverse(code, bits);
  1014. if (bits <= UFBXI_HUFF_FAST_BITS) {
  1015. uint16_t fast_sym = (uint16_t)(i | bits << 12);
  1016. uint32_t hi_max = 1u << (UFBXI_HUFF_FAST_BITS - bits);
  1017. for (uint32_t hi = 0; hi < hi_max; hi++) {
  1018. ufbxi_dev_assert(tree->fast_sym[rev_code | hi << bits] == 0);
  1019. tree->fast_sym[rev_code | hi << bits] = fast_sym;
  1020. }
  1021. }
  1022. // Store the end-of-block code so we can interrupt decoding
  1023. if (i == 256) {
  1024. tree->end_of_block_bits = rev_code;
  1025. }
  1026. }
  1027. return 0;
  1028. }
  1029. static ufbxi_forceinline uint32_t
  1030. ufbxi_huff_decode_bits(const ufbxi_huff_tree *tree, uint64_t *p_bits, size_t *p_left)
  1031. {
  1032. // If the code length is less than or equal UFBXI_HUFF_FAST_BITS we can
  1033. // resolve the symbol and bit length directly from a lookup table.
  1034. uint32_t fast_sym_bits = tree->fast_sym[*p_bits & UFBXI_HUFF_FAST_MASK];
  1035. if (fast_sym_bits != 0) {
  1036. uint32_t bits = fast_sym_bits >> 12;
  1037. *p_bits >>= bits;
  1038. *p_left -= bits;
  1039. return fast_sym_bits & 0x3ff;
  1040. }
  1041. // The code length must be longer than UFBXI_HUFF_FAST_BITS, reverse the prefix
  1042. // and build the code one bit at a time until we are in range for the bit length.
  1043. uint32_t code = ufbxi_bit_reverse((uint32_t)*p_bits, UFBXI_HUFF_FAST_BITS + 1);
  1044. *p_bits >>= UFBXI_HUFF_FAST_BITS + 1;
  1045. *p_left -= UFBXI_HUFF_FAST_BITS + 1;
  1046. for (uint32_t bits = UFBXI_HUFF_FAST_BITS + 1; bits < UFBXI_HUFF_MAX_BITS; bits++) {
  1047. if (code < tree->past_max_code[bits]) {
  1048. uint32_t sorted = (uint32_t)((int32_t)code + (int32_t)tree->code_to_sorted[bits]);
  1049. if (sorted >= tree->num_symbols) return ~0u;
  1050. return tree->sorted_to_sym[sorted];
  1051. }
  1052. code = code << 1 | (uint32_t)(*p_bits & 1);
  1053. *p_bits >>= 1;
  1054. *p_left -= 1;
  1055. }
  1056. // We shouldn't get here unless the tree is underfull _or_ has only
  1057. // one symbol where the code `1` is invalid.
  1058. return ~0u;
  1059. }
  1060. static ufbxi_noinline void ufbxi_init_static_huff(ufbxi_trees *trees)
  1061. {
  1062. ptrdiff_t err = 0;
  1063. // 0-143: 8 bits, 144-255: 9 bits, 256-279: 7 bits, 280-287: 8 bits
  1064. uint8_t lit_length_bits[288];
  1065. memset(lit_length_bits + 0, 8, 144 - 0);
  1066. memset(lit_length_bits + 144, 9, 256 - 144);
  1067. memset(lit_length_bits + 256, 7, 280 - 256);
  1068. memset(lit_length_bits + 280, 8, 288 - 280);
  1069. err |= ufbxi_huff_build(&trees->lit_length, lit_length_bits, sizeof(lit_length_bits));
  1070. // "Distance codes 0-31 are represented by (fixed-length) 5-bit codes"
  1071. uint8_t dist_bits[32];
  1072. memset(dist_bits + 0, 5, 32 - 0);
  1073. err |= ufbxi_huff_build(&trees->dist, dist_bits, sizeof(dist_bits));
  1074. // Building the static trees cannot fail as we use pre-defined code lengths.
  1075. ufbxi_ignore(err);
  1076. ufbx_assert(err == 0);
  1077. }
  1078. // 0: Success
  1079. // -1: Huffman Overfull
  1080. // -2: Huffman Underfull
  1081. // -3: Code 16 repeat overflow
  1082. // -4: Code 17 repeat overflow
  1083. // -5: Code 18 repeat overflow
  1084. // -6: Bad length code
  1085. // -7: Cancelled
  1086. static ufbxi_noinline ptrdiff_t
  1087. ufbxi_init_dynamic_huff_tree(ufbxi_deflate_context *dc, const ufbxi_huff_tree *huff_code_length,
  1088. ufbxi_huff_tree *tree, uint32_t num_symbols)
  1089. {
  1090. uint8_t code_lengths[UFBXI_HUFF_MAX_VALUE];
  1091. ufbx_assert(num_symbols <= UFBXI_HUFF_MAX_VALUE);
  1092. uint64_t bits = dc->stream.bits;
  1093. size_t left = dc->stream.left;
  1094. const char *data = dc->stream.chunk_ptr;
  1095. uint32_t symbol_index = 0;
  1096. uint8_t prev = 0;
  1097. while (symbol_index < num_symbols) {
  1098. ufbxi_bit_refill(&bits, &left, &data, &dc->stream);
  1099. if (dc->stream.cancelled) return -7;
  1100. uint32_t inst = ufbxi_huff_decode_bits(huff_code_length, &bits, &left);
  1101. if (inst <= 15) {
  1102. // "0 - 15: Represent code lengths of 0 - 15"
  1103. prev = (uint8_t)inst;
  1104. code_lengths[symbol_index++] = (uint8_t)inst;
  1105. } else if (inst == 16) {
  1106. // "16: Copy the previous code length 3 - 6 times. The next 2 bits indicate repeat length."
  1107. uint32_t num = 3 + ((uint32_t)bits & 0x3);
  1108. bits >>= 2;
  1109. left -= 2;
  1110. if (symbol_index + num > num_symbols) return -3;
  1111. memset(code_lengths + symbol_index, prev, num);
  1112. symbol_index += num;
  1113. } else if (inst == 17) {
  1114. // "17: Repeat a code length of 0 for 3 - 10 times. (3 bits of length)"
  1115. uint32_t num = 3 + ((uint32_t)bits & 0x7);
  1116. bits >>= 3;
  1117. left -= 3;
  1118. if (symbol_index + num > num_symbols) return -4;
  1119. memset(code_lengths + symbol_index, 0, num);
  1120. symbol_index += num;
  1121. prev = 0;
  1122. } else if (inst == 18) {
  1123. // "18: Repeat a code length of 0 for 11 - 138 times (7 bits of length)"
  1124. uint32_t num = 11 + ((uint32_t)bits & 0x7f);
  1125. bits >>= 7;
  1126. left -= 7;
  1127. if (symbol_index + num > num_symbols) return -5;
  1128. memset(code_lengths + symbol_index, 0, num);
  1129. symbol_index += num;
  1130. prev = 0;
  1131. } else {
  1132. return -6;
  1133. }
  1134. }
  1135. ptrdiff_t err = ufbxi_huff_build(tree, code_lengths, num_symbols);
  1136. if (err != 0) return err;
  1137. dc->stream.bits = bits;
  1138. dc->stream.left = left;
  1139. dc->stream.chunk_ptr = data;
  1140. return 0;
  1141. }
  1142. static ufbxi_noinline ptrdiff_t
  1143. ufbxi_init_dynamic_huff(ufbxi_deflate_context *dc, ufbxi_trees *trees)
  1144. {
  1145. uint64_t bits = dc->stream.bits;
  1146. size_t left = dc->stream.left;
  1147. const char *data = dc->stream.chunk_ptr;
  1148. ufbxi_bit_refill(&bits, &left, &data, &dc->stream);
  1149. if (dc->stream.cancelled) return -28;
  1150. // The header contains the number of Huffman codes in each of the three trees.
  1151. uint32_t num_lit_lengths = 257 + (bits & 0x1f);
  1152. uint32_t num_dists = 1 + (bits >> 5 & 0x1f);
  1153. uint32_t num_code_lengths = 4 + (bits >> 10 & 0xf);
  1154. bits >>= 14;
  1155. left -= 14;
  1156. // Code lengths for the "code length" Huffman tree are represented literally
  1157. // 3 bits in order of: 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 up to
  1158. // `num_code_lengths`, rest of the code lengths are 0 (unused)
  1159. uint8_t code_lengths[19];
  1160. memset(code_lengths, 0, sizeof(code_lengths));
  1161. for (size_t len_i = 0; len_i < num_code_lengths; len_i++) {
  1162. if (len_i == 14) {
  1163. ufbxi_bit_refill(&bits, &left, &data, &dc->stream);
  1164. if (dc->stream.cancelled) return -28;
  1165. }
  1166. code_lengths[ufbxi_deflate_code_length_permutation[len_i]] = (uint32_t)bits & 0x7;
  1167. bits >>= 3;
  1168. left -= 3;
  1169. }
  1170. dc->stream.bits = bits;
  1171. dc->stream.left = left;
  1172. dc->stream.chunk_ptr = data;
  1173. ufbxi_huff_tree huff_code_length;
  1174. ptrdiff_t err;
  1175. // Build the temporary "code length" Huffman tree used to encode the actual
  1176. // trees used to compress the data. Use that to build the literal/length and
  1177. // distance trees.
  1178. err = ufbxi_huff_build(&huff_code_length, code_lengths, ufbxi_arraycount(code_lengths));
  1179. if (err) return -14 + 1 + err;
  1180. err = ufbxi_init_dynamic_huff_tree(dc, &huff_code_length, &trees->lit_length, num_lit_lengths);
  1181. if (err) return err == -7 ? -28 : -16 + 1 + err;
  1182. err = ufbxi_init_dynamic_huff_tree(dc, &huff_code_length, &trees->dist, num_dists);
  1183. if (err) return err == -7 ? -28 : -22 + 1 + err;
  1184. return 0;
  1185. }
  1186. static ufbxi_noinline uint32_t ufbxi_adler32(const void *data, size_t size)
  1187. {
  1188. size_t a = 1, b = 0;
  1189. const char *p = (const char*)data;
  1190. // Adler-32 consists of two running sums modulo 65521. As an optimization
  1191. // we can accumulate N sums before applying the modulo, where N depends on
  1192. // the size of the type holding the sum.
  1193. const size_t num_before_wrap = sizeof(size_t) == 8 ? 380368439u : 5552u;
  1194. size_t size_left = size;
  1195. while (size_left > 0) {
  1196. size_t num = size_left <= num_before_wrap ? size_left : num_before_wrap;
  1197. size_left -= num;
  1198. const char *end = p + num;
  1199. while (end - p >= 8) {
  1200. a += (size_t)(uint8_t)p[0]; b += a;
  1201. a += (size_t)(uint8_t)p[1]; b += a;
  1202. a += (size_t)(uint8_t)p[2]; b += a;
  1203. a += (size_t)(uint8_t)p[3]; b += a;
  1204. a += (size_t)(uint8_t)p[4]; b += a;
  1205. a += (size_t)(uint8_t)p[5]; b += a;
  1206. a += (size_t)(uint8_t)p[6]; b += a;
  1207. a += (size_t)(uint8_t)p[7]; b += a;
  1208. p += 8;
  1209. }
  1210. while (p != end) {
  1211. a += (size_t)(uint8_t)p[0]; b += a;
  1212. p++;
  1213. }
  1214. a %= 65521u;
  1215. b %= 65521u;
  1216. }
  1217. return (uint32_t)((b << 16) | (a & 0xffff));
  1218. }
  1219. static ufbxi_noinline int
  1220. ufbxi_inflate_block(ufbxi_deflate_context *dc, ufbxi_trees *trees)
  1221. {
  1222. char *out_ptr = dc->out_ptr;
  1223. char *const out_begin = dc->out_begin;
  1224. char *const out_end = dc->out_end;
  1225. uint64_t bits = dc->stream.bits;
  1226. size_t left = dc->stream.left;
  1227. const char *data = dc->stream.chunk_ptr;
  1228. // Make the stream return the lit/len end of block Huffman code on cancellation
  1229. dc->stream.cancel_bits = trees->lit_length.end_of_block_bits;
  1230. for (;;) {
  1231. // NOTE: Cancellation handled implicitly by forcing an end-of-chunk symbol
  1232. ufbxi_bit_refill(&bits, &left, &data, &dc->stream);
  1233. // Decode literal/length value from input stream
  1234. uint32_t lit_length = ufbxi_huff_decode_bits(&trees->lit_length, &bits, &left);
  1235. // If value < 256: copy value (literal byte) to output stream
  1236. if (lit_length < 256) {
  1237. if (out_ptr == out_end) {
  1238. return -10;
  1239. }
  1240. *out_ptr++ = (char)lit_length;
  1241. } else if (lit_length - 257 <= 285 - 257) {
  1242. // If value = 257..285: Decode extra length and distance and copy `length` bytes
  1243. // from `distance` bytes before in the buffer.
  1244. uint32_t length, distance;
  1245. // Length: Look up base length and add optional additional bits
  1246. {
  1247. uint32_t lut = ufbxi_deflate_length_lut[lit_length - 257];
  1248. uint32_t base = lut >> 17;
  1249. uint32_t offset = ((uint32_t)bits & lut & 0x1fff);
  1250. uint32_t offset_bits = (lut >> 13) & 0xf;
  1251. bits >>= offset_bits;
  1252. left -= offset_bits;
  1253. length = base + offset;
  1254. }
  1255. // Distance: Decode as a Huffman code and add optional additional bits
  1256. {
  1257. uint32_t dist = ufbxi_huff_decode_bits(&trees->dist, &bits, &left);
  1258. if (dist >= 30) {
  1259. return -11;
  1260. }
  1261. uint32_t lut = ufbxi_deflate_dist_lut[dist];
  1262. uint32_t base = lut >> 17;
  1263. uint32_t offset = ((uint32_t)bits & lut & 0x1fff);
  1264. uint32_t offset_bits = (lut >> 13) & 0xf;
  1265. bits >>= offset_bits;
  1266. left -= offset_bits;
  1267. distance = base + offset;
  1268. }
  1269. if ((ptrdiff_t)distance > out_ptr - out_begin || (ptrdiff_t)length > out_end - out_ptr) {
  1270. return -12;
  1271. }
  1272. ufbx_assert(length > 0);
  1273. const char *src = out_ptr - distance;
  1274. char *dst = out_ptr;
  1275. out_ptr += length;
  1276. {
  1277. // TODO: Do something better than per-byte copy
  1278. char *end = dst + length;
  1279. while (end - dst >= 4) {
  1280. dst[0] = src[0];
  1281. dst[1] = src[1];
  1282. dst[2] = src[2];
  1283. dst[3] = src[3];
  1284. dst += 4;
  1285. src += 4;
  1286. }
  1287. while (dst != end) {
  1288. *dst++ = *src++;
  1289. }
  1290. }
  1291. } else if (lit_length == 256) {
  1292. break;
  1293. } else {
  1294. return -13;
  1295. }
  1296. }
  1297. dc->out_ptr = out_ptr;
  1298. dc->stream.bits = bits;
  1299. dc->stream.left = left;
  1300. dc->stream.chunk_ptr = data;
  1301. return 0;
  1302. }
  1303. // TODO: Error codes should have a quick test if the destination buffer overflowed
  1304. // Returns actual number of decompressed bytes or negative error:
  1305. // -1: Bad compression method (ZLIB header)
  1306. // -2: Requires dictionary (ZLIB header)
  1307. // -3: Bad FCHECK (ZLIB header)
  1308. // -4: Bad NLEN (Uncompressed LEN != ~NLEN)
  1309. // -5: Uncompressed source overflow
  1310. // -6: Uncompressed destination overflow
  1311. // -7: Bad block type
  1312. // -8: Truncated checksum (deprecated, reported as -9)
  1313. // -9: Checksum mismatch
  1314. // -10: Literal destination overflow
  1315. // -11: Bad distance code or distance of (30..31)
  1316. // -12: Match out of bounds
  1317. // -13: Bad lit/length code
  1318. // -14: Codelen Huffman Overfull
  1319. // -15: Codelen Huffman Underfull
  1320. // -16 - -21: Litlen Huffman: Overfull / Underfull / Repeat 16/17/18 overflow / Bad length code
  1321. // -22 - -27: Distance Huffman: Overfull / Underfull / Repeat 16/17/18 overflow / Bad length code
  1322. // -28: Cancelled
  1323. ptrdiff_t ufbx_inflate(void *dst, size_t dst_size, const ufbx_inflate_input *input, ufbx_inflate_retain *retain)
  1324. {
  1325. ufbxi_inflate_retain_imp *ret_imp = (ufbxi_inflate_retain_imp*)retain;
  1326. ptrdiff_t err;
  1327. ufbxi_deflate_context dc;
  1328. ufbxi_bit_stream_init(&dc.stream, input);
  1329. dc.out_begin = (char*)dst;
  1330. dc.out_ptr = (char*)dst;
  1331. dc.out_end = (char*)dst + dst_size;
  1332. uint64_t bits = dc.stream.bits;
  1333. size_t left = dc.stream.left;
  1334. const char *data = dc.stream.chunk_ptr;
  1335. ufbxi_bit_refill(&bits, &left, &data, &dc.stream);
  1336. if (dc.stream.cancelled) return -28;
  1337. // Zlib header
  1338. if (!input->no_header) {
  1339. size_t cmf = (size_t)(bits & 0xff);
  1340. size_t flg = (size_t)(bits >> 8) & 0xff;
  1341. bits >>= 16;
  1342. left -= 16;
  1343. if ((cmf & 0xf) != 0x8) return -1;
  1344. if ((flg & 0x20) != 0) return -2;
  1345. if ((cmf << 8 | flg) % 31u != 0) return -3;
  1346. }
  1347. for (;;) {
  1348. ufbxi_bit_refill(&bits, &left, &data, &dc.stream);
  1349. if (dc.stream.cancelled) return -28;
  1350. // Block header: [0:1] BFINAL [1:3] BTYPE
  1351. size_t header = (size_t)bits & 0x7;
  1352. bits >>= 3;
  1353. left -= 3;
  1354. size_t type = header >> 1;
  1355. if (type == 0) {
  1356. // Round up to the next byte
  1357. size_t align_bits = left & 0x7;
  1358. bits >>= align_bits;
  1359. left -= align_bits;
  1360. size_t len = (size_t)(bits & 0xffff);
  1361. size_t nlen = (size_t)((bits >> 16) & 0xffff);
  1362. if ((len ^ nlen) != 0xffff) return -4;
  1363. if (dc.out_end - dc.out_ptr < (ptrdiff_t)len) return -6;
  1364. bits >>= 32;
  1365. left -= 32;
  1366. dc.stream.bits = bits;
  1367. dc.stream.left = left;
  1368. dc.stream.chunk_ptr = data;
  1369. // Copy `len` bytes of literal data
  1370. if (!ufbxi_bit_copy_bytes(dc.out_ptr, &dc.stream, len)) return -5;
  1371. dc.out_ptr += len;
  1372. } else if (type <= 2) {
  1373. dc.stream.bits = bits;
  1374. dc.stream.left = left;
  1375. dc.stream.chunk_ptr = data;
  1376. ufbxi_trees tree_data;
  1377. ufbxi_trees *trees;
  1378. if (type == 1) {
  1379. // Static Huffman: Initialize the trees once and cache them in `retain`.
  1380. if (!ret_imp->initialized) {
  1381. ufbxi_init_static_huff(&ret_imp->static_trees);
  1382. ret_imp->initialized = true;
  1383. }
  1384. trees = &ret_imp->static_trees;
  1385. } else {
  1386. // Dynamic Huffman
  1387. err = ufbxi_init_dynamic_huff(&dc, &tree_data);
  1388. if (err) return err;
  1389. trees = &tree_data;
  1390. }
  1391. err = ufbxi_inflate_block(&dc, trees);
  1392. if (err) return err;
  1393. // `ufbxi_inflate_block()` returns normally on cancel so check it here
  1394. if (dc.stream.cancelled) return -28;
  1395. } else {
  1396. // 0b11 - reserved (error)
  1397. return -7;
  1398. }
  1399. bits = dc.stream.bits;
  1400. left = dc.stream.left;
  1401. data = dc.stream.chunk_ptr;
  1402. // BFINAL: End of stream
  1403. if (header & 1) break;
  1404. }
  1405. // Check Adler-32
  1406. {
  1407. // Round up to the next byte
  1408. size_t align_bits = left & 0x7;
  1409. bits >>= align_bits;
  1410. left -= align_bits;
  1411. ufbxi_bit_refill(&bits, &left, &data, &dc.stream);
  1412. if (dc.stream.cancelled) return -28;
  1413. if (!input->no_checksum) {
  1414. uint32_t ref = (uint32_t)bits;
  1415. ref = (ref>>24) | ((ref>>8)&0xff00) | ((ref<<8)&0xff0000) | (ref<<24);
  1416. uint32_t checksum = ufbxi_adler32(dc.out_begin, ufbxi_to_size(dc.out_ptr - dc.out_begin));
  1417. if (ref != checksum) {
  1418. return -9;
  1419. }
  1420. }
  1421. }
  1422. return dc.out_ptr - dc.out_begin;
  1423. }
  1424. #endif // !defined(ufbx_inflate)
  1425. // -- Errors
  1426. static ufbxi_noinline void ufbxi_panicf_imp(ufbx_panic *panic, const char *fmt, ...)
  1427. {
  1428. if (panic && panic->did_panic) return;
  1429. va_list args;
  1430. va_start(args, fmt);
  1431. if (panic) {
  1432. panic->did_panic = true;
  1433. int result = vsnprintf(panic->message, sizeof(panic->message), fmt, args);
  1434. if (result < 0) result = 0;
  1435. size_t length = ufbxi_min_sz((size_t)result, sizeof(panic->message) - 1);
  1436. // HACK: On some MSYS/MinGW implementations `snprintf` is broken and does
  1437. // not write the null terminator on trunctation, it's always safe to do so
  1438. // let's just do it unconditionally here...
  1439. panic->message[length] = '\0';
  1440. panic->message_length = length;
  1441. } else {
  1442. fprintf(stderr, "ufbx panic: ");
  1443. vfprintf(stderr, fmt, args);
  1444. fprintf(stderr, "\n");
  1445. }
  1446. va_end(args);
  1447. if (!panic) {
  1448. ufbx_assert(false && "ufbx panic: See stderr for more information");
  1449. }
  1450. }
  1451. #define ufbxi_panicf(panic, cond, ...) \
  1452. ((cond) ? false : (ufbxi_panicf_imp((panic), __VA_ARGS__), true))
  1453. // Prefix the error condition with $Description\0 for a human readable description
  1454. #define ufbxi_error_msg(cond, msg) "$" msg "\0" cond
  1455. static ufbxi_noinline int ufbxi_fail_imp_err(ufbx_error *err, const char *cond, const char *func, uint32_t line)
  1456. {
  1457. if (cond[0] == '$') {
  1458. if (!err->description.data) {
  1459. err->description.data = cond + 1;
  1460. err->description.length = strlen(err->description.data);
  1461. }
  1462. cond = cond + strlen(cond) + 1;
  1463. }
  1464. // NOTE: This is the base function all fails boil down to, place a breakpoint here to
  1465. // break at the first error
  1466. if (err->stack_size < UFBX_ERROR_STACK_MAX_DEPTH) {
  1467. ufbx_error_frame *frame = &err->stack[err->stack_size++];
  1468. frame->description.data = cond;
  1469. frame->description.length = strlen(cond);
  1470. frame->function.data = func;
  1471. frame->function.length = strlen(func);
  1472. frame->source_line = line;
  1473. }
  1474. return 0;
  1475. }
  1476. #if UFBXI_FEATURE_ERROR_STACK
  1477. #define ufbxi_function __FUNCTION__
  1478. #define ufbxi_line __LINE__
  1479. #define ufbxi_cond_str(cond) #cond
  1480. #else
  1481. #define ufbxi_function ""
  1482. #define ufbxi_line 0
  1483. #define ufbxi_cond_str(cond) ""
  1484. #endif
  1485. #define ufbxi_check_err(err, cond) do { if (ufbxi_unlikely(!ufbxi_trace(cond))) { ufbxi_fail_imp_err((err), ufbxi_cond_str(cond), ufbxi_function, ufbxi_line); return 0; } } while (0)
  1486. #define ufbxi_check_return_err(err, cond, ret) do { if (ufbxi_unlikely(!ufbxi_trace(cond))) { ufbxi_fail_imp_err((err), ufbxi_cond_str(cond), ufbxi_function, ufbxi_line); return ret; } } while (0)
  1487. #define ufbxi_fail_err(err, desc) return ufbxi_fail_imp_err(err, desc, ufbxi_function, ufbxi_line)
  1488. #define ufbxi_check_err_msg(err, cond, msg) do { if (ufbxi_unlikely(!ufbxi_trace(cond))) { ufbxi_fail_imp_err((err), ufbxi_error_msg(ufbxi_cond_str(cond), msg), ufbxi_function, ufbxi_line); return 0; } } while (0)
  1489. #define ufbxi_check_return_err_msg(err, cond, ret, msg) do { if (ufbxi_unlikely(!ufbxi_trace(cond))) { ufbxi_fail_imp_err((err), ufbxi_error_msg(ufbxi_cond_str(cond), msg), ufbxi_function, ufbxi_line); return ret; } } while (0)
  1490. #define ufbxi_fail_err_msg(err, desc, msg) return ufbxi_fail_imp_err(err, ufbxi_error_msg(desc, msg), ufbxi_function, ufbxi_line)
  1491. #define ufbxi_report_err_msg(err, desc, msg) (void)ufbxi_fail_imp_err(err, ufbxi_error_msg(desc, msg), ufbxi_function, ufbxi_line)
  1492. static ufbxi_noinline void ufbxi_fix_error_type(ufbx_error *error, const char *default_desc)
  1493. {
  1494. const char *desc = error->description.data;
  1495. if (!desc) desc = default_desc;
  1496. error->type = UFBX_ERROR_UNKNOWN;
  1497. if (!strcmp(desc, "Out of memory")) {
  1498. error->type = UFBX_ERROR_OUT_OF_MEMORY;
  1499. } else if (!strcmp(desc, "Memory limit exceeded")) {
  1500. error->type = UFBX_ERROR_MEMORY_LIMIT;
  1501. } else if (!strcmp(desc, "Allocation limit exceeded")) {
  1502. error->type = UFBX_ERROR_ALLOCATION_LIMIT;
  1503. } else if (!strcmp(desc, "Truncated file")) {
  1504. error->type = UFBX_ERROR_TRUNCATED_FILE;
  1505. } else if (!strcmp(desc, "IO error")) {
  1506. error->type = UFBX_ERROR_IO;
  1507. } else if (!strcmp(desc, "Cancelled")) {
  1508. error->type = UFBX_ERROR_CANCELLED;
  1509. } else if (!strcmp(desc, "Not an FBX file")) {
  1510. error->type = UFBX_ERROR_NOT_FBX;
  1511. } else if (!strcmp(desc, "File not found")) {
  1512. error->type = UFBX_ERROR_FILE_NOT_FOUND;
  1513. } else if (!strcmp(desc, "Uninitialized options")) {
  1514. error->type = UFBX_ERROR_UNINITIALIZED_OPTIONS;
  1515. } else if (!strcmp(desc, "Zero vertex size")) {
  1516. error->type = UFBX_ERROR_ZERO_VERTEX_SIZE;
  1517. } else if (!strcmp(desc, "Invalid UTF-8")) {
  1518. error->type = UFBX_ERROR_INVALID_UTF8;
  1519. } else if (!strcmp(desc, "Feature disabled")) {
  1520. error->type = UFBX_ERROR_FEATURE_DISABLED;
  1521. } else if (!strcmp(desc, "Bad NURBS geometry")) {
  1522. error->type = UFBX_ERROR_BAD_NURBS;
  1523. } else if (!strcmp(desc, "Bad index")) {
  1524. error->type = UFBX_ERROR_BAD_INDEX;
  1525. } else if (!strcmp(desc, "Unsafe options")) {
  1526. error->type = UFBX_ERROR_UNSAFE_OPTIONS;
  1527. }
  1528. error->description.data = desc;
  1529. error->description.length = strlen(desc);
  1530. }
  1531. // -- Allocator
  1532. // Returned for zero size allocations, place in the constant data
  1533. // to catch writes to bad allocations.
  1534. #if defined(UFBX_REGRESSION)
  1535. static const char ufbxi_zero_size_buffer[4096] = { 0 };
  1536. #else
  1537. static const char ufbxi_zero_size_buffer[64] = { 0 };
  1538. #endif
  1539. static ufbxi_forceinline size_t ufbxi_align_to_mask(size_t value, size_t align_mask)
  1540. {
  1541. return value + (((size_t)0 - value) & align_mask);
  1542. }
  1543. static ufbxi_forceinline size_t ufbxi_size_align_mask(size_t size)
  1544. {
  1545. // Align to the all bits below the lowest set one in `size`
  1546. // up to a maximum of 0x7 (align to 8 bytes).
  1547. return ((size ^ (size - 1)) >> 1) & 0x7;
  1548. }
  1549. typedef struct {
  1550. ufbx_error *error;
  1551. size_t current_size;
  1552. size_t max_size;
  1553. size_t num_allocs;
  1554. size_t max_allocs;
  1555. size_t huge_size;
  1556. size_t chunk_max;
  1557. ufbx_allocator_opts ator;
  1558. } ufbxi_allocator;
  1559. static ufbxi_forceinline bool ufbxi_does_overflow(size_t total, size_t a, size_t b)
  1560. {
  1561. // If `a` and `b` have at most 4 bits per `size_t` byte, the product can't overflow.
  1562. if (((a | b) >> sizeof(size_t)*4) != 0) {
  1563. if (a != 0 && total / a != b) return true;
  1564. }
  1565. return false;
  1566. }
  1567. static ufbxi_noinline void *ufbxi_alloc_size(ufbxi_allocator *ator, size_t size, size_t n)
  1568. {
  1569. // Always succeed with an emtpy non-NULL buffer for empty allocations
  1570. ufbx_assert(size > 0);
  1571. if (n == 0) return (void*)ufbxi_zero_size_buffer;
  1572. size_t total = size * n;
  1573. ufbxi_check_return_err(ator->error, !ufbxi_does_overflow(total, size, n), NULL);
  1574. ufbxi_check_return_err(ator->error, total <= SIZE_MAX / 2, NULL); // Make sure it's always safe to double allocations
  1575. ufbxi_check_return_err_msg(ator->error, total <= ator->max_size - ator->current_size, NULL, "Memory limit exceeded");
  1576. ufbxi_check_return_err_msg(ator->error, ator->num_allocs < ator->max_allocs, NULL, "Allocation limit exceeded");
  1577. ator->num_allocs++;
  1578. ator->current_size += total;
  1579. void *ptr;
  1580. if (ator->ator.allocator.alloc_fn) {
  1581. ptr = ator->ator.allocator.alloc_fn(ator->ator.allocator.user, total);
  1582. } else if (ator->ator.allocator.realloc_fn) {
  1583. ptr = ator->ator.allocator.realloc_fn(ator->ator.allocator.user, NULL, 0, total);
  1584. } else {
  1585. ptr = malloc(total);
  1586. }
  1587. ufbxi_check_return_err_msg(ator->error, ptr, NULL, "Out of memory");
  1588. ufbx_assert(((uintptr_t)ptr & ufbxi_size_align_mask(total)) == 0);
  1589. return ptr;
  1590. }
  1591. static void ufbxi_free_size(ufbxi_allocator *ator, size_t size, void *ptr, size_t n);
  1592. static ufbxi_noinline void *ufbxi_realloc_size(ufbxi_allocator *ator, size_t size, void *old_ptr, size_t old_n, size_t n)
  1593. {
  1594. ufbx_assert(size > 0);
  1595. // realloc() with zero old/new size is equivalent to alloc()/free()
  1596. if (old_n == 0) return ufbxi_alloc_size(ator, size, n);
  1597. if (n == 0) { ufbxi_free_size(ator, size, old_ptr, old_n); return NULL; }
  1598. size_t old_total = size * old_n;
  1599. size_t total = size * n;
  1600. // The old values have been checked by a previous allocate call
  1601. ufbx_assert(!ufbxi_does_overflow(old_total, size, old_n));
  1602. ufbx_assert(old_total <= ator->current_size);
  1603. ufbxi_check_return_err(ator->error, !ufbxi_does_overflow(total, size, n), NULL);
  1604. ufbxi_check_return_err(ator->error, total <= SIZE_MAX / 2, NULL); // Make sure it's always safe to double allocations
  1605. ufbxi_check_return_err_msg(ator->error, total <= ator->max_size - ator->current_size, NULL, "Memory limit exceeded");
  1606. ufbxi_check_return_err_msg(ator->error, ator->num_allocs < ator->max_allocs, NULL, "Allocation limit exceeded");
  1607. ator->num_allocs++;
  1608. ator->current_size += total;
  1609. ator->current_size -= old_total;
  1610. void *ptr;
  1611. if (ator->ator.allocator.realloc_fn) {
  1612. ptr = ator->ator.allocator.realloc_fn(ator->ator.allocator.user, old_ptr, old_total, total);
  1613. } else if (ator->ator.allocator.alloc_fn) {
  1614. // Use user-provided alloc_fn() and free_fn()
  1615. ptr = ator->ator.allocator.alloc_fn(ator->ator.allocator.user, total);
  1616. if (ptr) memcpy(ptr, old_ptr, old_total);
  1617. if (ator->ator.allocator.free_fn) {
  1618. ator->ator.allocator.free_fn(ator->ator.allocator.user, old_ptr, old_total);
  1619. }
  1620. } else {
  1621. ptr = realloc(old_ptr, total);
  1622. }
  1623. ufbxi_check_return_err_msg(ator->error, ptr, NULL, "Out of memory");
  1624. ufbx_assert(((uintptr_t)ptr & ufbxi_size_align_mask(total)) == 0);
  1625. return ptr;
  1626. }
  1627. static ufbxi_noinline void ufbxi_free_size(ufbxi_allocator *ator, size_t size, void *ptr, size_t n)
  1628. {
  1629. ufbx_assert(size > 0);
  1630. if (n == 0) return;
  1631. ufbx_assert(ptr);
  1632. size_t total = size * n;
  1633. // The old values have been checked by a previous allocate call
  1634. ufbx_assert(!ufbxi_does_overflow(total, size, n));
  1635. ufbx_assert(total <= ator->current_size);
  1636. ator->current_size -= total;
  1637. if (ator->ator.allocator.alloc_fn || ator->ator.allocator.realloc_fn) {
  1638. // Don't call default free() if there is an user-provided `alloc_fn()`
  1639. if (ator->ator.allocator.free_fn) {
  1640. ator->ator.allocator.free_fn(ator->ator.allocator.user, ptr, total);
  1641. } else if (ator->ator.allocator.realloc_fn) {
  1642. ator->ator.allocator.realloc_fn(ator->ator.allocator.user, ptr, total, 0);
  1643. }
  1644. } else {
  1645. free(ptr);
  1646. }
  1647. }
  1648. ufbxi_nodiscard static bool ufbxi_grow_array_size(ufbxi_allocator *ator, size_t size, void *p_ptr, size_t *p_cap, size_t n)
  1649. {
  1650. if (n <= *p_cap) return true;
  1651. void *ptr = *(void**)p_ptr;
  1652. size_t old_n = *p_cap;
  1653. if (old_n >= n) return true;
  1654. size_t new_n = ufbxi_max_sz(old_n * 2, n);
  1655. void *new_ptr = ufbxi_realloc_size(ator, size, ptr, old_n, new_n);
  1656. if (!new_ptr) return false;
  1657. *(void**)p_ptr = new_ptr;
  1658. *p_cap = new_n;
  1659. return true;
  1660. }
  1661. static ufbxi_noinline void ufbxi_free_ator(ufbxi_allocator *ator)
  1662. {
  1663. ufbx_assert(ator->current_size == 0);
  1664. ufbx_free_allocator_fn *free_fn = ator->ator.allocator.free_allocator_fn;
  1665. if (free_fn) {
  1666. void *user = ator->ator.allocator.user;
  1667. free_fn(user);
  1668. }
  1669. }
  1670. #define ufbxi_alloc(ator, type, n) ufbxi_maybe_null((type*)ufbxi_alloc_size((ator), sizeof(type), (n)))
  1671. #define ufbxi_alloc_zero(ator, type, n) ufbxi_maybe_null((type*)ufbxi_alloc_zero_size((ator), sizeof(type), (n)))
  1672. #define ufbxi_realloc(ator, type, old_ptr, old_n, n) ufbxi_maybe_null((type*)ufbxi_realloc_size((ator), sizeof(type), (old_ptr), (old_n), (n)))
  1673. #define ufbxi_realloc_zero(ator, type, old_ptr, old_n, n) ufbxi_maybe_null((type*)ufbxi_realloc_zero_size((ator), sizeof(type), (old_ptr), (old_n), (n)))
  1674. #define ufbxi_free(ator, type, ptr, n) ufbxi_free_size((ator), sizeof(type), (ptr), (n))
  1675. #define ufbxi_grow_array(ator, p_ptr, p_cap, n) ufbxi_grow_array_size((ator), sizeof(**(p_ptr)), (p_ptr), (p_cap), (n))
  1676. // -- Memory buffer
  1677. //
  1678. // General purpose memory buffer that can be used either as a chunked linear memory
  1679. // allocator or a non-contiguous stack. You can convert the contents of `ufbxi_buf`
  1680. // to a contiguous range of memory by calling `ufbxi_make_array[_all]()`
  1681. typedef struct ufbxi_buf_padding ufbxi_buf_padding;
  1682. typedef struct ufbxi_buf_chunk ufbxi_buf_chunk;
  1683. struct ufbxi_buf_padding {
  1684. size_t original_pos; // < Original position before aligning
  1685. size_t prev_padding; // < Starting offset of the previous `ufbxi_buf_padding`
  1686. };
  1687. struct ufbxi_buf_chunk {
  1688. // Linked list of nodes
  1689. ufbxi_buf_chunk *root;
  1690. ufbxi_buf_chunk *prev;
  1691. ufbxi_buf_chunk *next;
  1692. void *align_0; // < Align to 4x pointer size (16/32 bytes)
  1693. size_t size; // < Size of the chunk `data`, excluding this header
  1694. size_t pushed_pos; // < Size of valid data when pushed to the list
  1695. size_t next_size; // < Next geometrically growing chunk size to allocate
  1696. size_t padding_pos; // < One past the offset of the most recent `ufbxi_buf_padding`
  1697. char data[]; // < Must be aligned to 8 bytes
  1698. };
  1699. ufbx_static_assert(buf_chunk_align, offsetof(ufbxi_buf_chunk, data) % 8 == 0);
  1700. typedef struct {
  1701. ufbxi_allocator *ator;
  1702. // Current chunks for normal and huge allocations.
  1703. // Ordered buffers (`!ufbx_buf.unordered`) never use `chunks[1]`
  1704. ufbxi_buf_chunk *chunks[2];
  1705. // Inline state for non-huge chunks
  1706. size_t pos; // < Next offset to allocate from
  1707. size_t size; // < Size of the current chunk ie. `chunks[0]->size` (or 0 if `chunks[0] == NULL`)
  1708. size_t num_items; // < Number of individual items pushed to the buffer
  1709. bool unordered; // < Does not support popping from the buffer
  1710. bool clearable; // < Supports clearing the whole buffer even if `unordered`
  1711. } ufbxi_buf;
  1712. typedef struct {
  1713. ufbxi_buf_chunk *chunk;
  1714. size_t pos;
  1715. size_t num_items;
  1716. } ufbxi_buf_state;
  1717. static ufbxi_noinline void *ufbxi_push_size_new_block(ufbxi_buf *b, size_t size)
  1718. {
  1719. bool huge = size >= b->ator->huge_size;
  1720. // Use the second chunk "list" for huge unordered chunks.
  1721. // The state of these chunks is not tracked by `ufbxi_buf.pos/size`.
  1722. uint32_t list_ix = ((uint32_t)b->unordered & (uint32_t)huge);
  1723. ufbxi_buf_chunk *chunk = b->chunks[list_ix];
  1724. if (chunk) {
  1725. if (list_ix == 0) {
  1726. // Store the final position for the retired chunk and scan free
  1727. // chunks in case we find one the allocation fits in.
  1728. chunk->pushed_pos = b->pos;
  1729. ufbxi_buf_chunk *next = chunk->next;
  1730. while (next != NULL) {
  1731. chunk = next;
  1732. ufbx_assert(b->unordered || chunk->pushed_pos == 0);
  1733. chunk->pushed_pos = 0;
  1734. if (size <= chunk->size) {
  1735. b->chunks[0] = chunk;
  1736. b->pos = (uint32_t)size;
  1737. b->size = chunk->size;
  1738. return chunk->data;
  1739. }
  1740. next = chunk->next;
  1741. }
  1742. } else if (b->clearable) {
  1743. // Keep track of the `UFBXI_HUGE_MAX_SCAN` largest chunks and
  1744. // retain them. Overflowing chunks are freed in `ufbxi_buf_clear()`
  1745. size_t align_mask = ufbxi_size_align_mask(size);
  1746. ufbxi_buf_chunk *next = chunk;
  1747. ufbxi_buf_chunk *best_chunk = NULL;
  1748. size_t best_space = SIZE_MAX;
  1749. // Clearable huge chunks are sorted by descending size. Check the first N
  1750. // chunks for reuse and find the place a new block should be inserted if
  1751. // no suitable space is found. Chunk ordering in the tail doesn't matter
  1752. // as those chunks are never reused.
  1753. // Unreachable chunks in the tail are freed in `ufbxi_buf_clear()`.
  1754. for (size_t i = 0; next && i < UFBXI_HUGE_MAX_SCAN; i++) {
  1755. if (next->size < size) break;
  1756. chunk = next;
  1757. // Try to reuse chunks using a best-fit strategy.
  1758. size_t pos = ufbxi_align_to_mask(chunk->pushed_pos, align_mask);
  1759. size_t space = chunk->size - pos;
  1760. if (size <= space) {
  1761. if (space < best_space) {
  1762. best_chunk = chunk;
  1763. best_space = space;
  1764. }
  1765. }
  1766. next = chunk->next;
  1767. }
  1768. // Early return if we found a slot.
  1769. if (best_chunk) {
  1770. size_t pos = ufbxi_align_to_mask(best_chunk->pushed_pos, align_mask);
  1771. best_chunk->pushed_pos = pos + size;
  1772. return best_chunk->data + pos;
  1773. }
  1774. }
  1775. }
  1776. // Allocate a new chunk, grow `next_size` geometrically but don't double
  1777. // the current or previous user sizes if they are larger.
  1778. size_t chunk_size, next_size;
  1779. // If `size` is larger than `huge_size` don't grow `next_size` geometrically,
  1780. // but use a dedicated allocation.
  1781. if (huge) {
  1782. next_size = chunk ? chunk->next_size : 4096;
  1783. if (next_size > b->ator->chunk_max) next_size = b->ator->chunk_max;
  1784. chunk_size = size;
  1785. } else {
  1786. next_size = chunk ? chunk->next_size * 2 : 4096;
  1787. if (next_size > b->ator->chunk_max) next_size = b->ator->chunk_max;
  1788. chunk_size = next_size - sizeof(ufbxi_buf_chunk);
  1789. if (chunk_size < size) chunk_size = size;
  1790. }
  1791. // Align chunk sizes to 16 bytes
  1792. chunk_size = ufbxi_align_to_mask(chunk_size, 0xf);
  1793. ufbxi_buf_chunk *new_chunk = (ufbxi_buf_chunk*)ufbxi_alloc_size(b->ator, 1, sizeof(ufbxi_buf_chunk) + chunk_size);
  1794. if (!new_chunk) return NULL;
  1795. new_chunk->prev = chunk;
  1796. new_chunk->size = chunk_size;
  1797. new_chunk->next_size = next_size;
  1798. new_chunk->align_0 = NULL;
  1799. new_chunk->padding_pos = 0;
  1800. new_chunk->pushed_pos = 0;
  1801. // Link the chunk to the list and set it as the active one
  1802. if (chunk) {
  1803. ufbxi_buf_chunk *next = chunk->next;
  1804. if (next) next->prev = new_chunk;
  1805. new_chunk->next = next;
  1806. chunk->next = new_chunk;
  1807. new_chunk->root = chunk->root;
  1808. } else {
  1809. new_chunk->next = NULL;
  1810. new_chunk->root = new_chunk;
  1811. }
  1812. if (list_ix == 0) {
  1813. b->chunks[0] = new_chunk;
  1814. b->pos = size;
  1815. b->size = chunk_size;
  1816. } else {
  1817. ufbxi_buf_chunk *root = b->chunks[1];
  1818. if (!root) {
  1819. b->chunks[1] = new_chunk;
  1820. } else if (root->size < chunk_size) {
  1821. // Swap root and self if necessary, we should have bailed out
  1822. // in the search loop in the first iteration so `new_chunk` should
  1823. // directly follow `root`.
  1824. // HACK: This ends up with `chunks[1]` entries having inconsistent
  1825. // `ufbxi_buf_chunk.root` pointers but other code only reads `chunks[1].root`
  1826. // TODO: Move roots out of the chunks?
  1827. ufbx_assert(root->next == new_chunk);
  1828. ufbx_assert(new_chunk->prev == root);
  1829. if (new_chunk->next) new_chunk->next->prev = root;
  1830. root->next = new_chunk->next;
  1831. new_chunk->next = root;
  1832. new_chunk->prev = NULL;
  1833. new_chunk->root = new_chunk;
  1834. b->chunks[1] = new_chunk;
  1835. }
  1836. new_chunk->pushed_pos = size;
  1837. }
  1838. return new_chunk->data;
  1839. }
  1840. static ufbxi_noinline void *ufbxi_push_size(ufbxi_buf *b, size_t size, size_t n)
  1841. {
  1842. // Always succeed with an emtpy non-NULL buffer for empty allocations
  1843. ufbx_assert(size > 0);
  1844. if (n == 0) return (void*)ufbxi_zero_size_buffer;
  1845. b->num_items += n;
  1846. size_t total = size * n;
  1847. if (ufbxi_does_overflow(total, size, n)) return NULL;
  1848. // Align to the natural alignment based on the size
  1849. size_t align_mask = ufbxi_size_align_mask(size);
  1850. size_t pos = ufbxi_align_to_mask(b->pos, align_mask);
  1851. if (!b->unordered && pos != b->pos) {
  1852. // Alignment mismatch in an unordered block. Align to 16 bytes to guarantee
  1853. // sufficient alignment for anything afterwards and mark the padding.
  1854. // If we overflow the current block we don't need to care as the block
  1855. // boundaries are not contiguous.
  1856. pos = ufbxi_align_to_mask(b->pos, 0xf);
  1857. if (total < SIZE_MAX - 16 && total + 16 <= b->size - pos) {
  1858. ufbxi_buf_chunk *chunk = b->chunks[0];
  1859. ufbxi_buf_padding *padding = (ufbxi_buf_padding*)(chunk->data + pos);
  1860. padding->original_pos = b->pos;
  1861. padding->prev_padding = chunk->padding_pos;
  1862. chunk->padding_pos = pos + 16 + 1;
  1863. b->pos = pos + 16 + total;
  1864. return (char*)padding + 16;
  1865. } else {
  1866. return ufbxi_push_size_new_block(b, total);
  1867. }
  1868. } else {
  1869. // Try to push to the current block. Allocate a new block
  1870. // if the aligned size doesn't fit.
  1871. if (total <= b->size - pos) {
  1872. b->pos = pos + total;
  1873. return b->chunks[0]->data + pos;
  1874. } else {
  1875. return ufbxi_push_size_new_block(b, total);
  1876. }
  1877. }
  1878. }
  1879. static ufbxi_forceinline void *ufbxi_push_size_zero(ufbxi_buf *b, size_t size, size_t n)
  1880. {
  1881. void *ptr = ufbxi_push_size(b, size, n);
  1882. if (ptr) memset(ptr, 0, size * n);
  1883. return ptr;
  1884. }
  1885. ufbxi_nodiscard static ufbxi_forceinline void *ufbxi_push_size_copy(ufbxi_buf *b, size_t size, size_t n, const void *data)
  1886. {
  1887. // Always succeed with an emtpy non-NULL buffer for empty allocations, even if `data == NULL`
  1888. ufbx_assert(size > 0);
  1889. if (n == 0) return (void*)ufbxi_zero_size_buffer;
  1890. ufbx_assert(data);
  1891. void *ptr = ufbxi_push_size(b, size, n);
  1892. if (ptr) memcpy(ptr, data, size * n);
  1893. return ptr;
  1894. }
  1895. static ufbxi_noinline void ufbxi_buf_free_unused(ufbxi_buf *b)
  1896. {
  1897. ufbx_assert(!b->unordered);
  1898. ufbxi_buf_chunk *chunk = b->chunks[0];
  1899. if (!chunk) return;
  1900. ufbxi_buf_chunk *next = chunk->next;
  1901. while (next) {
  1902. ufbxi_buf_chunk *to_free = next;
  1903. next = next->next;
  1904. ufbxi_free_size(b->ator, 1, to_free, sizeof(ufbxi_buf_chunk) + to_free->size);
  1905. }
  1906. chunk->next = NULL;
  1907. while (b->pos == 0 && chunk) {
  1908. ufbxi_buf_chunk *prev = chunk->prev;
  1909. ufbxi_free_size(b->ator, 1, chunk, sizeof(ufbxi_buf_chunk) + chunk->size);
  1910. chunk = prev;
  1911. b->chunks[0] = prev;
  1912. if (prev) {
  1913. prev->next = NULL;
  1914. b->pos = prev->pushed_pos;
  1915. b->size = prev->size;
  1916. } else {
  1917. b->pos = 0;
  1918. b->size = 0;
  1919. }
  1920. }
  1921. }
  1922. static ufbxi_noinline void ufbxi_pop_size(ufbxi_buf *b, size_t size, size_t n, void *dst)
  1923. {
  1924. ufbx_assert(!b->unordered);
  1925. ufbx_assert(size > 0);
  1926. ufbx_assert(b->num_items >= n);
  1927. b->num_items -= n;
  1928. char *ptr = (char*)dst;
  1929. size_t bytes_left = size * n;
  1930. // We've already pushed this, it better not overflow
  1931. ufbx_assert(!ufbxi_does_overflow(bytes_left, size, n));
  1932. if (ptr) {
  1933. ptr += bytes_left;
  1934. size_t pos = b->pos;
  1935. for (;;) {
  1936. ufbxi_buf_chunk *chunk = b->chunks[0];
  1937. if (bytes_left <= pos) {
  1938. // Rest of the data is in this single chunk
  1939. pos -= bytes_left;
  1940. b->pos = pos;
  1941. ptr -= bytes_left;
  1942. if (bytes_left > 0) {
  1943. memcpy(ptr, chunk->data + pos, bytes_left);
  1944. }
  1945. break;
  1946. } else {
  1947. // Pop the whole chunk
  1948. ptr -= pos;
  1949. bytes_left -= pos;
  1950. memcpy(ptr, chunk->data, pos);
  1951. chunk->pushed_pos = 0;
  1952. chunk = chunk->prev;
  1953. b->chunks[0] = chunk;
  1954. b->size = chunk->size;
  1955. pos = chunk->pushed_pos;
  1956. }
  1957. }
  1958. } else {
  1959. size_t pos = b->pos;
  1960. for (;;) {
  1961. ufbxi_buf_chunk *chunk = b->chunks[0];
  1962. if (bytes_left <= pos) {
  1963. // Rest of the data is in this single chunk
  1964. pos -= bytes_left;
  1965. b->pos = pos;
  1966. break;
  1967. } else {
  1968. // Pop the whole chunk
  1969. bytes_left -= pos;
  1970. chunk->pushed_pos = 0;
  1971. chunk = chunk->prev;
  1972. b->chunks[0] = chunk;
  1973. b->size = chunk->size;
  1974. pos = chunk->pushed_pos;
  1975. }
  1976. }
  1977. }
  1978. // Check if we need to rewind past some alignment padding
  1979. ufbxi_buf_chunk *chunk = b->chunks[0];
  1980. if (chunk) {
  1981. size_t pos = b->pos, padding_pos = chunk->padding_pos;
  1982. if (pos < padding_pos) {
  1983. ufbx_assert(pos + 1 == padding_pos);
  1984. ufbxi_buf_padding *padding = (ufbxi_buf_padding*)(chunk->data + padding_pos - 1 - 16);
  1985. b->pos = padding->original_pos;
  1986. chunk->padding_pos = padding->prev_padding;
  1987. }
  1988. }
  1989. // Immediately free popped items if all the allocations are huge
  1990. // as it means we want to have dedicated allocations for each push.
  1991. if (b->ator->huge_size <= 1) {
  1992. ufbxi_buf_free_unused(b);
  1993. }
  1994. }
  1995. static ufbxi_noinline void *ufbxi_push_pop_size(ufbxi_buf *dst, ufbxi_buf *src, size_t size, size_t n)
  1996. {
  1997. void *data = ufbxi_push_size(dst, size, n);
  1998. if (!data) return NULL;
  1999. ufbxi_pop_size(src, size, n, data);
  2000. return data;
  2001. }
  2002. static ufbxi_noinline void ufbxi_buf_free(ufbxi_buf *buf)
  2003. {
  2004. ufbxi_nounroll for (size_t i = 0; i < 2; i++) {
  2005. ufbxi_buf_chunk *chunk = buf->chunks[i];
  2006. if (chunk) {
  2007. chunk = chunk->root;
  2008. while (chunk) {
  2009. ufbxi_buf_chunk *next = chunk->next;
  2010. ufbxi_free_size(buf->ator, 1, chunk, sizeof(ufbxi_buf_chunk) + chunk->size);
  2011. chunk = next;
  2012. }
  2013. }
  2014. buf->chunks[i] = NULL;
  2015. }
  2016. buf->pos = 0;
  2017. buf->size = 0;
  2018. buf->num_items = 0;
  2019. }
  2020. static ufbxi_noinline void ufbxi_buf_clear(ufbxi_buf *buf)
  2021. {
  2022. // Only unordered or clearable buffers can be cleared
  2023. ufbx_assert(!buf->unordered || buf->clearable);
  2024. // Free the memory if using ASAN
  2025. if (buf->ator->huge_size <= 1) {
  2026. ufbxi_buf_free(buf);
  2027. return;
  2028. }
  2029. // Reset the non-huge chunks as `chunk->next` is always free.
  2030. ufbxi_buf_chunk *chunk = buf->chunks[0];
  2031. if (chunk) {
  2032. ufbxi_buf_chunk *root = chunk->root;
  2033. buf->chunks[0] = root;
  2034. buf->pos = 0;
  2035. buf->size = root->size;
  2036. }
  2037. buf->num_items = 0;
  2038. // Huge chunks are always sorted by descending size and
  2039. // `chunks[1]` points to the largest one.
  2040. ufbxi_buf_chunk *huge = buf->chunks[1];
  2041. if (huge) {
  2042. // Reset the first N ones that are tracked.
  2043. for (size_t i = 0; huge && i < UFBXI_HUGE_MAX_SCAN; i++) {
  2044. huge->pushed_pos = 0;
  2045. huge = huge->next;
  2046. }
  2047. // Got unreachable tail that should be freed: Unlink from the last
  2048. // tracked chunk and free the rest.
  2049. if (huge) {
  2050. huge->prev->next = NULL;
  2051. while (huge) {
  2052. ufbxi_buf_chunk *next = huge->next;
  2053. ufbxi_free_size(buf->ator, 1, huge, sizeof(ufbxi_buf_chunk) + huge->size);
  2054. huge = next;
  2055. }
  2056. }
  2057. }
  2058. }
  2059. #define ufbxi_push(b, type, n) ufbxi_maybe_null((type*)ufbxi_push_size((b), sizeof(type), (n)))
  2060. #define ufbxi_push_zero(b, type, n) ufbxi_maybe_null((type*)ufbxi_push_size_zero((b), sizeof(type), (n)))
  2061. #define ufbxi_push_copy(b, type, n, data) ufbxi_maybe_null((type*)ufbxi_push_size_copy((b), sizeof(type), (n), (data)))
  2062. #define ufbxi_pop(b, type, n, dst) ufbxi_pop_size((b), sizeof(type), (n), (dst))
  2063. #define ufbxi_push_pop(dst, src, type, n) ufbxi_maybe_null((type*)ufbxi_push_pop_size((dst), (src), sizeof(type), (n)))
  2064. // -- Hash map
  2065. //
  2066. // The actual element comparison is left to the user of `ufbxi_map`, see usage below.
  2067. //
  2068. // NOTES:
  2069. // ufbxi_map_insert() does not support duplicate values, use find first if duplicates are possible!
  2070. // Inserting duplicate elements fails with an assertion if `UFBX_REGRESSION` is enabled.
  2071. typedef struct ufbxi_aa_node ufbxi_aa_node;
  2072. typedef int ufbxi_cmp_fn(void *user, const void *a, const void *b);
  2073. struct ufbxi_aa_node {
  2074. ufbxi_aa_node *left, *right;
  2075. uint32_t level;
  2076. uint32_t index;
  2077. };
  2078. typedef struct {
  2079. ufbxi_allocator *ator;
  2080. size_t data_size;
  2081. void *items;
  2082. uint64_t *entries;
  2083. uint32_t mask;
  2084. uint32_t capacity;
  2085. uint32_t size;
  2086. ufbxi_cmp_fn *cmp_fn;
  2087. void *cmp_user;
  2088. ufbxi_buf aa_buf;
  2089. ufbxi_aa_node *aa_root;
  2090. } ufbxi_map;
  2091. static ufbxi_noinline void ufbxi_map_init(ufbxi_map *map, ufbxi_allocator *ator, ufbxi_cmp_fn *cmp_fn, void *cmp_user)
  2092. {
  2093. map->ator = ator;
  2094. map->aa_buf.ator = ator;
  2095. map->cmp_fn = cmp_fn;
  2096. map->cmp_user = cmp_user;
  2097. }
  2098. static ufbxi_noinline void ufbxi_map_free(ufbxi_map *map)
  2099. {
  2100. ufbxi_buf_free(&map->aa_buf);
  2101. ufbxi_free(map->ator, char, map->entries, map->data_size);
  2102. map->entries = NULL;
  2103. map->items = NULL;
  2104. map->aa_root = NULL;
  2105. map->mask = map->capacity = map->size = 0;
  2106. }
  2107. static ufbxi_noinline ufbxi_aa_node *ufbxi_aa_tree_insert(ufbxi_map *map, ufbxi_aa_node *node, const void *value, uint32_t index, size_t item_size)
  2108. {
  2109. if (!node) {
  2110. ufbxi_aa_node *new_node = ufbxi_push(&map->aa_buf, ufbxi_aa_node, 1);
  2111. if (!new_node) return NULL;
  2112. new_node->left = NULL;
  2113. new_node->right = NULL;
  2114. new_node->level = 1;
  2115. new_node->index = index;
  2116. return new_node;
  2117. }
  2118. void *entry = (char*)map->items + node->index * item_size;
  2119. int cmp = map->cmp_fn(map->cmp_user, value, entry);
  2120. if (cmp < 0) {
  2121. node->left = ufbxi_aa_tree_insert(map, node->left, value, index, item_size);
  2122. } else if (cmp >= 0) {
  2123. node->right = ufbxi_aa_tree_insert(map, node->right, value, index, item_size);
  2124. }
  2125. if (node->left && node->left->level == node->level) {
  2126. ufbxi_aa_node *left = node->left;
  2127. node->left = left->right;
  2128. left->right = node;
  2129. node = left;
  2130. }
  2131. if (node->right && node->right->right && node->right->right->level == node->level) {
  2132. ufbxi_aa_node *right = node->right;
  2133. node->right = right->left;
  2134. right->left = node;
  2135. right->level += 1;
  2136. node = right;
  2137. }
  2138. return node;
  2139. }
  2140. static ufbxi_noinline void *ufbxi_aa_tree_find(ufbxi_map *map, const void *value, size_t item_size)
  2141. {
  2142. ufbxi_aa_node *node = map->aa_root;
  2143. while (node) {
  2144. void *entry = (char*)map->items + node->index * item_size;
  2145. int cmp = map->cmp_fn(map->cmp_user, value, entry);
  2146. if (cmp < 0) {
  2147. node = node->left;
  2148. } else if (cmp > 0) {
  2149. node = node->right;
  2150. } else {
  2151. return entry;
  2152. }
  2153. }
  2154. return NULL;
  2155. }
  2156. static ufbxi_noinline bool ufbxi_map_grow_size_imp(ufbxi_map *map, size_t item_size, size_t min_size)
  2157. {
  2158. ufbx_assert(min_size > 0);
  2159. const double load_factor = 0.7;
  2160. // Find the lowest power of two size that fits `min_size` within `load_factor`
  2161. size_t num_entries = map->mask + 1;
  2162. size_t new_size = (size_t)((double)num_entries * load_factor);
  2163. if (min_size < map->capacity + 1) min_size = map->capacity + 1;
  2164. while (new_size < min_size) {
  2165. num_entries *= 2;
  2166. new_size = (size_t)((double)num_entries * load_factor);
  2167. }
  2168. // Check for overflow
  2169. ufbxi_check_return_err(map->ator->error, SIZE_MAX / num_entries > sizeof(uint64_t), false);
  2170. size_t alloc_size = num_entries * sizeof(uint64_t);
  2171. // Allocate a combined entry/item memory block
  2172. ufbxi_check_return_err(map->ator->error, (SIZE_MAX - alloc_size) / new_size > item_size, false);
  2173. size_t data_size = alloc_size + new_size * item_size;
  2174. char *data = ufbxi_alloc(map->ator, char, data_size);
  2175. ufbxi_check_return_err(map->ator->error, data, false);
  2176. // Copy the previous user items over
  2177. uint64_t *old_entries = map->entries;
  2178. uint64_t *new_entries = (uint64_t*)data;
  2179. void *new_items = data + alloc_size;
  2180. if (map->size > 0) {
  2181. memcpy(new_items, map->items, item_size * map->size);
  2182. }
  2183. // Re-hash the entries
  2184. uint32_t old_mask = map->mask;
  2185. uint32_t new_mask = (uint32_t)(num_entries) - 1;
  2186. memset(new_entries, 0, sizeof(uint64_t) * num_entries);
  2187. if (old_mask) {
  2188. for (uint32_t i = 0; i <= old_mask; i++) {
  2189. uint64_t entry, new_entry = old_entries[i];
  2190. if (!new_entry) continue;
  2191. // Reconstruct the hash of the old entry at `i`
  2192. uint32_t old_scan = (uint32_t)(new_entry & old_mask) - 1;
  2193. uint32_t hash = ((uint32_t)new_entry & ~old_mask) | ((i - old_scan) & old_mask);
  2194. uint32_t slot = hash & new_mask;
  2195. new_entry &= ~(uint64_t)new_mask;
  2196. // Scan forward until we find an empty slot, potentially swapping
  2197. // `new_element` if it has a shorter scan distance (Robin Hood).
  2198. uint32_t scan = 1;
  2199. while ((entry = new_entries[slot]) != 0) {
  2200. uint32_t entry_scan = (entry & new_mask);
  2201. if (entry_scan < scan) {
  2202. new_entries[slot] = new_entry + scan;
  2203. new_entry = (entry & ~(uint64_t)new_mask);
  2204. scan = entry_scan;
  2205. }
  2206. scan += 1;
  2207. slot = (slot + 1) & new_mask;
  2208. }
  2209. new_entries[slot] = new_entry + scan;
  2210. }
  2211. }
  2212. // And finally free the previous allocation
  2213. ufbxi_free(map->ator, char, (char*)old_entries, map->data_size);
  2214. map->items = new_items;
  2215. map->data_size = data_size;
  2216. map->entries = new_entries;
  2217. map->mask = new_mask;
  2218. map->capacity = (uint32_t)new_size;
  2219. return true;
  2220. }
  2221. static ufbxi_forceinline bool ufbxi_map_grow_size(ufbxi_map *map, size_t size, size_t min_size)
  2222. {
  2223. if (map->size < map->capacity && map->capacity >= min_size) return true;
  2224. return ufbxi_map_grow_size_imp(map, size, min_size);
  2225. }
  2226. static ufbxi_noinline void *ufbxi_map_find_size(ufbxi_map *map, size_t size, uint32_t hash, const void *value)
  2227. {
  2228. uint64_t *entries = map->entries;
  2229. uint32_t mask = map->mask, scan = 0;
  2230. uint32_t ref = hash & ~mask;
  2231. if (!mask || scan == UINT32_MAX) return 0;
  2232. // Scan entries until we find an exact match of the hash or until we hit
  2233. // an element that has lower scan distance than our search (Robin Hood).
  2234. // The encoding guarantees that zero slots also terminate with the same test.
  2235. for (;;) {
  2236. uint64_t entry = entries[(hash + scan) & mask];
  2237. scan += 1;
  2238. if ((uint32_t)entry == ref + scan) {
  2239. uint32_t index = (uint32_t)(entry >> 32u);
  2240. void *data = (char*)map->items + size * index;
  2241. int cmp = map->cmp_fn(map->cmp_user, value, data);
  2242. if (cmp == 0) return data;
  2243. } else if ((entry & mask) < scan) {
  2244. if (map->aa_root) {
  2245. return ufbxi_aa_tree_find(map, value, size);
  2246. } else {
  2247. return NULL;
  2248. }
  2249. }
  2250. }
  2251. }
  2252. static ufbxi_noinline void *ufbxi_map_insert_size(ufbxi_map *map, size_t size, uint32_t hash, const void *value)
  2253. {
  2254. if (!ufbxi_map_grow_size(map, size, 64)) return NULL;
  2255. ufbxi_regression_assert(ufbxi_map_find_size(map, size, hash, value) == NULL);
  2256. uint32_t index = map->size++;
  2257. uint64_t *entries = map->entries;
  2258. uint32_t mask = map->mask;
  2259. // Scan forward until we find an empty slot, potentially swapping
  2260. // `new_element` if it has a shorter scan distance (Robin Hood).
  2261. uint32_t slot = hash & mask;
  2262. uint64_t entry, new_entry = (uint64_t)index << 32u | (hash & ~mask);
  2263. uint32_t scan = 1;
  2264. while ((entry = entries[slot]) != 0) {
  2265. uint32_t entry_scan = (entry & mask);
  2266. if (entry_scan < scan) {
  2267. entries[slot] = new_entry + scan;
  2268. new_entry = (entry & ~(uint64_t)mask);
  2269. scan = entry_scan;
  2270. }
  2271. scan += 1;
  2272. slot = (slot + 1) & mask;
  2273. if (scan > UFBXI_MAP_MAX_SCAN) {
  2274. uint32_t new_index = (uint32_t)(new_entry >> 32u);
  2275. const void *new_value = new_index == index ? value : (const void*)((char*)map->items + size * new_index);
  2276. map->aa_root = ufbxi_aa_tree_insert(map, map->aa_root, new_value, new_index, size);
  2277. return (char*)map->items + size * index;
  2278. }
  2279. }
  2280. entries[slot] = new_entry + scan;
  2281. return (char*)map->items + size * index;
  2282. }
  2283. #define ufbxi_map_grow(map, type, min_size) ufbxi_map_grow_size((map), sizeof(type), (min_size))
  2284. #define ufbxi_map_find(map, type, hash, value) (type*)ufbxi_map_find_size((map), sizeof(type), (hash), (value))
  2285. #define ufbxi_map_insert(map, type, hash, value) (type*)ufbxi_map_insert_size((map), sizeof(type), (hash), (value))
  2286. static int ufbxi_map_cmp_uint64(void *user, const void *va, const void *vb)
  2287. {
  2288. (void)user;
  2289. uint64_t a = *(const uint64_t*)va, b = *(const uint64_t*)vb;
  2290. if (a < b) return -1;
  2291. if (a > b) return +1;
  2292. return 0;
  2293. }
  2294. static int ufbxi_map_cmp_const_char_ptr(void *user, const void *va, const void *vb)
  2295. {
  2296. (void)user;
  2297. const char *a = *(const char **)va, *b = *(const char **)vb;
  2298. if (a < b) return -1;
  2299. if (a > b) return +1;
  2300. return 0;
  2301. }
  2302. static int ufbxi_map_cmp_uintptr(void *user, const void *va, const void *vb)
  2303. {
  2304. (void)user;
  2305. uintptr_t a = *(const uintptr_t*)va, b = *(const uintptr_t*)vb;
  2306. if (a < b) return -1;
  2307. if (a > b) return +1;
  2308. return 0;
  2309. }
  2310. // -- Hash functions
  2311. static ufbxi_noinline uint32_t ufbxi_hash_string(const char *str, size_t length)
  2312. {
  2313. uint32_t hash = (uint32_t)length;
  2314. uint32_t seed = UINT32_C(0x9e3779b9);
  2315. if (length >= 4) {
  2316. do {
  2317. uint32_t word = ufbxi_read_u32(str);
  2318. hash = ((hash << 5u | hash >> 27u) ^ word) * seed;
  2319. str += 4;
  2320. length -= 4;
  2321. } while (length >= 4);
  2322. uint32_t word = ufbxi_read_u32(str + length - 4);
  2323. hash = ((hash << 5u | hash >> 27u) ^ word) * seed;
  2324. } else {
  2325. uint32_t word = 0;
  2326. if (length >= 1) word |= (uint32_t)(uint8_t)str[0] << 0;
  2327. if (length >= 2) word |= (uint32_t)(uint8_t)str[1] << 8;
  2328. if (length >= 3) word |= (uint32_t)(uint8_t)str[2] << 16;
  2329. hash = ((hash << 5u | hash >> 27u) ^ word) * seed;
  2330. }
  2331. hash ^= hash >> 16;
  2332. hash *= UINT32_C(0x7feb352d);
  2333. hash ^= hash >> 15;
  2334. return hash;
  2335. }
  2336. // NOTE: _Must_ match `ufbxi_hash_string()`
  2337. static ufbxi_noinline uint32_t ufbxi_hash_string_check_ascii(const char *str, size_t length, bool *p_non_ascii)
  2338. {
  2339. uint32_t ascii_mask = 0;
  2340. uint32_t zero_mask = 0;
  2341. ufbx_assert(length > 0);
  2342. uint32_t hash = (uint32_t)length;
  2343. uint32_t seed = UINT32_C(0x9e3779b9);
  2344. if (length >= 4) {
  2345. do {
  2346. uint32_t word = ufbxi_read_u32(str);
  2347. ascii_mask |= word;
  2348. zero_mask |= UINT32_C(0x80808080) - word;
  2349. hash = ((hash << 5u | hash >> 27u) ^ word) * seed;
  2350. str += 4;
  2351. length -= 4;
  2352. } while (length >= 4);
  2353. uint32_t word = ufbxi_read_u32(str + length - 4);
  2354. ascii_mask |= word;
  2355. zero_mask |= UINT32_C(0x80808080) - word;
  2356. hash = ((hash << 5u | hash >> 27u) ^ word) * seed;
  2357. } else {
  2358. uint32_t word = 0;
  2359. if (length >= 1) word |= (uint32_t)(uint8_t)str[0] << 0;
  2360. if (length >= 2) word |= (uint32_t)(uint8_t)str[1] << 8;
  2361. if (length >= 3) word |= (uint32_t)(uint8_t)str[2] << 16;
  2362. ascii_mask |= word;
  2363. zero_mask |= (UINT32_C(0x80808080) >> ((4u - length) * 8u)) - word;
  2364. hash = ((hash << 5u | hash >> 27u) ^ word) * seed;
  2365. }
  2366. // If any character has high bit set or is zero we're not ASCII
  2367. if (((ascii_mask | zero_mask) & 0x80808080u) != 0) {
  2368. *p_non_ascii = true;
  2369. }
  2370. hash ^= hash >> 16;
  2371. hash *= UINT32_C(0x7feb352d);
  2372. hash ^= hash >> 15;
  2373. return hash;
  2374. }
  2375. static ufbxi_forceinline uint32_t ufbxi_hash32(uint32_t x)
  2376. {
  2377. x ^= x >> 16;
  2378. x *= UINT32_C(0x7feb352d);
  2379. x ^= x >> 15;
  2380. x *= UINT32_C(0x846ca68b);
  2381. x ^= x >> 16;
  2382. return x;
  2383. }
  2384. static ufbxi_forceinline uint32_t ufbxi_hash64(uint64_t x)
  2385. {
  2386. x ^= x >> 32;
  2387. x *= UINT64_C(0xd6e8feb86659fd93);
  2388. x ^= x >> 32;
  2389. x *= UINT64_C(0xd6e8feb86659fd93);
  2390. x ^= x >> 32;
  2391. return (uint32_t)x;
  2392. }
  2393. static ufbxi_forceinline uint32_t ufbxi_hash_uptr(uintptr_t ptr)
  2394. {
  2395. return sizeof(ptr) == 8 ? ufbxi_hash64((uint64_t)ptr) : ufbxi_hash32((uint32_t)ptr);
  2396. }
  2397. #define ufbxi_hash_ptr(ptr) ufbxi_hash_uptr((uintptr_t)(ptr))
  2398. // -- String pool
  2399. // All strings found in FBX files are interned for deduplication and fast
  2400. // comparison. Our fixed internal strings (`ufbxi_String`) are considered the
  2401. // canonical pointers for said strings so we can compare them by address.
  2402. typedef struct {
  2403. ufbx_error *error;
  2404. ufbxi_buf buf; // < Buffer for the actual string data
  2405. ufbxi_map map; // < Map of `ufbxi_string`
  2406. size_t initial_size; // < Number of initial entries
  2407. char *temp_str; // < Temporary string buffer of `temp_cap`
  2408. size_t temp_cap; // < Capacity of the temporary buffer
  2409. ufbx_unicode_error_handling error_handling;
  2410. } ufbxi_string_pool;
  2411. typedef struct {
  2412. const char *raw_data; // < UTF-8 data follows at `raw_length+1` if `utf8_length > 0`
  2413. uint32_t raw_length; // < Length of the non-sanitized original string
  2414. uint32_t utf8_length; // < Length of sanitized UTF-8 string (or zero)
  2415. } ufbxi_sanitized_string;
  2416. static ufbxi_forceinline bool ufbxi_str_equal(ufbx_string a, ufbx_string b)
  2417. {
  2418. return a.length == b.length && !memcmp(a.data, b.data, a.length);
  2419. }
  2420. static ufbxi_forceinline bool ufbxi_str_less(ufbx_string a, ufbx_string b)
  2421. {
  2422. size_t len = ufbxi_min_sz(a.length, b.length);
  2423. int cmp = memcmp(a.data, b.data, len);
  2424. if (cmp != 0) return cmp < 0;
  2425. return a.length < b.length;
  2426. }
  2427. static ufbxi_forceinline int ufbxi_str_cmp(ufbx_string a, ufbx_string b)
  2428. {
  2429. size_t len = ufbxi_min_sz(a.length, b.length);
  2430. int cmp = memcmp(a.data, b.data, len);
  2431. if (cmp != 0) return cmp;
  2432. if (a.length != b.length) return a.length < b.length ? -1 : 1;
  2433. return 0;
  2434. }
  2435. static ufbxi_forceinline ufbx_string ufbxi_str_c(const char *str)
  2436. {
  2437. ufbx_string s = { str, strlen(str) };
  2438. return s;
  2439. }
  2440. static ufbxi_forceinline bool ufbxi_starts_with(ufbx_string str, ufbx_string prefix)
  2441. {
  2442. return str.length >= prefix.length && !memcmp(str.data, prefix.data, prefix.length);
  2443. }
  2444. static ufbxi_forceinline bool ufbxi_ends_with(ufbx_string str, ufbx_string suffix)
  2445. {
  2446. return str.length >= suffix.length && !memcmp(str.data + str.length - suffix.length, suffix.data, suffix.length);
  2447. }
  2448. static ufbxi_noinline bool ufbxi_remove_prefix_len(ufbx_string *str, const char *prefix, size_t prefix_len)
  2449. {
  2450. ufbx_string prefix_str = { prefix, prefix_len };
  2451. if (ufbxi_starts_with(*str, prefix_str)) {
  2452. str->data += prefix_len;
  2453. str->length -= prefix_len;
  2454. return true;
  2455. }
  2456. return false;
  2457. }
  2458. static ufbxi_noinline bool ufbxi_remove_suffix_len(ufbx_string *str, const char *suffix, size_t suffix_len)
  2459. {
  2460. ufbx_string suffix_str = { suffix, suffix_len };
  2461. if (ufbxi_ends_with(*str, suffix_str)) {
  2462. str->length -= suffix_len;
  2463. return true;
  2464. }
  2465. return false;
  2466. }
  2467. static ufbxi_forceinline bool ufbxi_remove_prefix_str(ufbx_string *str, ufbx_string prefix)
  2468. {
  2469. return ufbxi_remove_prefix_len(str, prefix.data, prefix.length);
  2470. }
  2471. static ufbxi_forceinline bool ufbxi_remove_suffix_c(ufbx_string *str, const char *suffix)
  2472. {
  2473. return ufbxi_remove_suffix_len(str, suffix, strlen(suffix));
  2474. }
  2475. static int ufbxi_map_cmp_string(void *user, const void *va, const void *vb)
  2476. {
  2477. (void)user;
  2478. const ufbx_string *a = (const ufbx_string*)va, *b = (const ufbx_string*)vb;
  2479. return ufbxi_str_cmp(*a, *b);
  2480. }
  2481. static const char ufbxi_empty_char[1] = { '\0' };
  2482. static void ufbxi_string_pool_temp_free(ufbxi_string_pool *pool)
  2483. {
  2484. ufbxi_free(pool->map.ator, char, pool->temp_str, pool->temp_cap);
  2485. ufbxi_map_free(&pool->map);
  2486. }
  2487. ufbxi_nodiscard static size_t ufbxi_add_replacement_char(ufbxi_string_pool *pool, char *dst, char c)
  2488. {
  2489. switch (pool->error_handling) {
  2490. case UFBX_UNICODE_ERROR_HANDLING_REPLACEMENT_CHARACTER:
  2491. dst[0] = (char)(uint8_t)0xefu;
  2492. dst[1] = (char)(uint8_t)0xbfu;
  2493. dst[2] = (char)(uint8_t)0xbdu;
  2494. return 3;
  2495. case UFBX_UNICODE_ERROR_HANDLING_UNDERSCORE:
  2496. dst[0] = '_';
  2497. return 1;
  2498. case UFBX_UNICODE_ERROR_HANDLING_QUESTION_MARK:
  2499. dst[0] = '?';
  2500. return 1;
  2501. case UFBX_UNICODE_ERROR_HANDLING_REMOVE:
  2502. return 0;
  2503. case UFBX_UNICODE_ERROR_HANDLING_UNSAFE_IGNORE:
  2504. dst[0] = c;
  2505. return 1;
  2506. default:
  2507. return 0;
  2508. }
  2509. }
  2510. ufbxi_nodiscard static ufbxi_noinline size_t ufbxi_utf8_valid_length(const char *str, size_t length)
  2511. {
  2512. size_t index = 0;
  2513. while (index < length) {
  2514. uint8_t c = (uint8_t)str[index];
  2515. size_t left = length - index;
  2516. if ((c & 0x80) == 0) {
  2517. if (c != 0) {
  2518. index += 1;
  2519. continue;
  2520. }
  2521. } else if ((c & 0xe0) == 0xc0 && left >= 2) {
  2522. uint8_t t0 = (uint8_t)str[index + 1];
  2523. uint32_t code = (uint32_t)c << 8 | (uint32_t)t0;
  2524. if ((code & 0xc0) == 0x80 && code >= 0xc280) {
  2525. index += 2;
  2526. continue;
  2527. }
  2528. } else if ((c & 0xf0) == 0xe0 && left >= 3) {
  2529. uint8_t t0 = (uint8_t)str[index + 1], t1 = (uint8_t)str[index + 2];
  2530. uint32_t code = (uint32_t)c << 16 | (uint32_t)t0 << 8 | (uint32_t)t1;
  2531. if ((code & 0xc0c0) == 0x8080 && code >= 0xe0a080 && (code < 0xeda080 || code >= 0xee8080)) {
  2532. index += 3;
  2533. continue;
  2534. }
  2535. } else if ((c & 0xf8) == 0xf0 && left >= 4) {
  2536. uint8_t t0 = (uint8_t)str[index + 1], t1 = (uint8_t)str[index + 2], t2 = (uint8_t)str[index + 3];
  2537. uint32_t code = (uint32_t)c << 24 | (uint32_t)t0 << 16 | (uint32_t)t1 << 8 | (uint32_t)t2;
  2538. if ((code & 0xc0c0c0) == 0x808080 && code >= 0xf0908080 && code >= 0x400) {
  2539. index += 4;
  2540. continue;
  2541. }
  2542. }
  2543. break;
  2544. }
  2545. ufbx_assert(index <= length);
  2546. return index;
  2547. }
  2548. ufbxi_nodiscard static ufbxi_noinline int ufbxi_sanitize_string(ufbxi_string_pool *pool, ufbxi_sanitized_string *sanitized, const char *str, size_t length, size_t valid_length, bool push_both)
  2549. {
  2550. // Handle only invalid cases here
  2551. ufbx_assert(valid_length < length);
  2552. ufbxi_check_err_msg(pool->error, pool->error_handling != UFBX_UNICODE_ERROR_HANDLING_ABORT_LOADING, "Invalid UTF-8");
  2553. size_t index = valid_length;
  2554. size_t dst_len = index;
  2555. if (push_both) {
  2556. // Copy both the full raw string and the initial valid part
  2557. ufbxi_check_err(pool->error, length <= SIZE_MAX / 2 - 64);
  2558. ufbxi_check_err(pool->error, ufbxi_grow_array(pool->map.ator, &pool->temp_str, &pool->temp_cap, length * 2 + 64));
  2559. memcpy(pool->temp_str, str, length);
  2560. pool->temp_str[length] = '\0';
  2561. memcpy(pool->temp_str + length + 1, str, index);
  2562. dst_len += length + 1;
  2563. } else {
  2564. // Copy the initial valid part
  2565. ufbxi_check_err(pool->error, length <= SIZE_MAX - 64);
  2566. ufbxi_check_err(pool->error, ufbxi_grow_array(pool->map.ator, &pool->temp_str, &pool->temp_cap, length + 64));
  2567. memcpy(pool->temp_str, str, index);
  2568. }
  2569. char *dst = pool->temp_str;
  2570. while (index < length) {
  2571. uint8_t c = (uint8_t)str[index];
  2572. size_t left = length - index;
  2573. // Not optimal but not the worst thing ever
  2574. if (pool->temp_cap - dst_len < 16) {
  2575. ufbxi_check_err(pool->error, ufbxi_grow_array(pool->map.ator, &pool->temp_str, &pool->temp_cap, dst_len + 16));
  2576. dst = pool->temp_str;
  2577. }
  2578. if ((c & 0x80) == 0) {
  2579. if (c != 0) {
  2580. dst[dst_len] = (char)c;
  2581. dst_len += 1;
  2582. index += 1;
  2583. continue;
  2584. }
  2585. } else if ((c & 0xe0) == 0xc0 && left >= 2) {
  2586. uint8_t t0 = (uint8_t)str[index + 1];
  2587. uint32_t code = (uint32_t)c << 8 | (uint32_t)t0 << 0;
  2588. if ((code & 0xc0) == 0x80 && code >= 0xc280) {
  2589. dst[dst_len + 0] = (char)c;
  2590. dst[dst_len + 1] = (char)t0;
  2591. dst_len += 2;
  2592. index += 2;
  2593. continue;
  2594. }
  2595. } else if ((c & 0xf0) == 0xe0 && left >= 3) {
  2596. uint8_t t0 = (uint8_t)str[index + 1], t1 = (uint8_t)str[index + 2];
  2597. uint32_t code = (uint32_t)c << 16 | (uint32_t)t0 << 8 | (uint32_t)t1;
  2598. if ((code & 0xc0c0) == 0x8080 && code >= 0xe0a080 && (code < 0xeda080 || code >= 0xee8080)) {
  2599. dst[dst_len + 0] = (char)c;
  2600. dst[dst_len + 1] = (char)t0;
  2601. dst[dst_len + 2] = (char)t1;
  2602. dst_len += 3;
  2603. index += 3;
  2604. continue;
  2605. }
  2606. } else if ((c & 0xf8) == 0xf0 && left >= 4) {
  2607. uint8_t t0 = (uint8_t)str[index + 1], t1 = (uint8_t)str[index + 2], t2 = (uint8_t)str[index + 3];
  2608. uint32_t code = (uint32_t)c << 24 | (uint32_t)t0 << 16 | (uint32_t)t1 << 8 | (uint32_t)t2;
  2609. if ((code & 0xc0c0c0) == 0x808080 && code >= 0xf0908080 && code >= 0x400) {
  2610. dst[dst_len + 0] = (char)c;
  2611. dst[dst_len + 1] = (char)t0;
  2612. dst[dst_len + 2] = (char)t1;
  2613. dst[dst_len + 3] = (char)t2;
  2614. dst_len += 4;
  2615. index += 4;
  2616. continue;
  2617. }
  2618. }
  2619. dst_len += ufbxi_add_replacement_char(pool, dst + dst_len, (char)c);
  2620. index++;
  2621. }
  2622. // Sanitized strings are packed to 32-bit integers, in practice this should be fine
  2623. // as strings are limited to 32-bit length in FBX itself.
  2624. // The only problem case is a massive string that is full of unicode errors, ie.
  2625. // >1GB binary blob, but these should never be sanitized.
  2626. ufbxi_check_err(pool->error, length <= UINT32_MAX);
  2627. sanitized->raw_data = pool->temp_str;
  2628. if (push_both) {
  2629. // Reserve `UINT32_MAX` for invalid UTF-8 without sanitization
  2630. size_t utf8_length = dst_len - (length + 1);
  2631. ufbxi_check_err(pool->error, utf8_length < UINT32_MAX);
  2632. sanitized->raw_length = (uint32_t)length;
  2633. sanitized->utf8_length = (uint32_t)utf8_length;
  2634. } else {
  2635. ufbxi_check_err(pool->error, dst_len <= UINT32_MAX);
  2636. sanitized->raw_length = (uint32_t)dst_len;
  2637. sanitized->utf8_length = 0;
  2638. }
  2639. return 1;
  2640. }
  2641. ufbxi_nodiscard static ufbxi_noinline int ufbxi_push_sanitized_string(ufbxi_string_pool *pool, ufbxi_sanitized_string *sanitized, const char *str, size_t length, uint32_t hash, bool raw)
  2642. {
  2643. ufbxi_regression_assert(hash == ufbxi_hash_string(str, length));
  2644. ufbxi_check_err(pool->error, length <= UINT32_MAX);
  2645. ufbxi_check_err(pool->error, ufbxi_map_grow(&pool->map, ufbx_string, pool->initial_size));
  2646. const char *total_data = str;
  2647. size_t total_length = length;
  2648. sanitized->raw_length = (uint32_t)length;
  2649. sanitized->utf8_length = 0;
  2650. if (!raw) {
  2651. size_t valid_length = ufbxi_utf8_valid_length(str, length);
  2652. if (valid_length != length) {
  2653. ufbxi_check_err(pool->error, ufbxi_sanitize_string(pool, sanitized, str, length, valid_length, true));
  2654. total_data = sanitized->raw_data;
  2655. total_length = sanitized->raw_length + sanitized->utf8_length + 1;
  2656. hash = ufbxi_hash_string(str, length);
  2657. }
  2658. }
  2659. ufbx_string ref = { total_data, total_length };
  2660. ufbx_string *entry = ufbxi_map_find(&pool->map, ufbx_string, hash, &ref);
  2661. if (entry) {
  2662. sanitized->raw_data = entry->data;
  2663. } else {
  2664. entry = ufbxi_map_insert(&pool->map, ufbx_string, hash, &ref);
  2665. ufbxi_check_err(pool->error, entry);
  2666. entry->length = total_length;
  2667. char *dst = ufbxi_push(&pool->buf, char, total_length + 1);
  2668. ufbxi_check_err(pool->error, dst);
  2669. memcpy(dst, total_data, total_length);
  2670. dst[total_length] = '\0';
  2671. entry->data = dst;
  2672. sanitized->raw_data = dst;
  2673. }
  2674. return 1;
  2675. }
  2676. ufbxi_nodiscard static ufbxi_noinline const char *ufbxi_push_string_imp(ufbxi_string_pool *pool, const char *str, size_t length, size_t *p_out_length, bool copy, bool raw)
  2677. {
  2678. if (length == 0) return ufbxi_empty_char;
  2679. ufbxi_check_return_err(pool->error, ufbxi_map_grow(&pool->map, ufbx_string, pool->initial_size), NULL);
  2680. uint32_t hash;
  2681. if (raw) {
  2682. hash = ufbxi_hash_string(str, length);
  2683. } else {
  2684. bool non_ascii = false;
  2685. hash = ufbxi_hash_string_check_ascii(str, length, &non_ascii);
  2686. if (non_ascii) {
  2687. size_t valid_length = ufbxi_utf8_valid_length(str, length);
  2688. if (valid_length < length) {
  2689. ufbxi_sanitized_string sanitized;
  2690. ufbxi_check_return_err(pool->error, ufbxi_sanitize_string(pool, &sanitized, str, length, valid_length, false), NULL);
  2691. str = sanitized.raw_data;
  2692. length = sanitized.raw_length;
  2693. hash = ufbxi_hash_string(str, length);
  2694. *p_out_length = length;
  2695. }
  2696. }
  2697. }
  2698. ufbx_string ref = { str, length };
  2699. ufbx_string *entry = ufbxi_map_find(&pool->map, ufbx_string, hash, &ref);
  2700. if (entry) return entry->data;
  2701. entry = ufbxi_map_insert(&pool->map, ufbx_string, hash, &ref);
  2702. ufbxi_check_return_err(pool->error, entry, NULL);
  2703. entry->length = length;
  2704. if (copy) {
  2705. char *dst = ufbxi_push(&pool->buf, char, length + 1);
  2706. ufbxi_check_return_err(pool->error, dst, NULL);
  2707. memcpy(dst, str, length);
  2708. dst[length] = '\0';
  2709. entry->data = dst;
  2710. } else {
  2711. entry->data = str;
  2712. }
  2713. return entry->data;
  2714. }
  2715. ufbxi_nodiscard static ufbxi_forceinline const char *ufbxi_push_string(ufbxi_string_pool *pool, const char *str, size_t length, size_t *p_out_length, bool raw)
  2716. {
  2717. return ufbxi_push_string_imp(pool, str, length, p_out_length, true, raw);
  2718. }
  2719. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_push_string_place(ufbxi_string_pool *pool, const char **p_str, size_t *p_length, bool raw)
  2720. {
  2721. const char *str = *p_str;
  2722. size_t length = *p_length;
  2723. ufbxi_check_err(pool->error, str || length == 0);
  2724. str = ufbxi_push_string(pool, str, length, p_length, raw);
  2725. ufbxi_check_err(pool->error, str);
  2726. *p_str = str;
  2727. return 1;
  2728. }
  2729. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_push_string_place_str(ufbxi_string_pool *pool, ufbx_string *p_str, bool raw)
  2730. {
  2731. ufbxi_check_err(pool->error, p_str);
  2732. return ufbxi_push_string_place(pool, &p_str->data, &p_str->length, raw);
  2733. }
  2734. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_push_string_place_blob(ufbxi_string_pool *pool, ufbx_blob *p_blob, bool raw)
  2735. {
  2736. if (p_blob->size == 0) {
  2737. p_blob->data = NULL;
  2738. return 1;
  2739. }
  2740. p_blob->data = ufbxi_push_string(pool, (const char*)p_blob->data, p_blob->size, &p_blob->size, raw);
  2741. ufbxi_check_err(pool->error, p_blob->data);
  2742. return 1;
  2743. }
  2744. // -- String constants
  2745. //
  2746. // All strings in FBX files are pooled so by having canonical string constant
  2747. // addresses we can compare strings to these constants by comparing pointers.
  2748. // Keep the list alphabetically sorted!
  2749. static const char ufbxi_AllSame[] = "AllSame";
  2750. static const char ufbxi_Alphas[] = "Alphas";
  2751. static const char ufbxi_AmbientColor[] = "AmbientColor";
  2752. static const char ufbxi_AnimationCurveNode[] = "AnimationCurveNode";
  2753. static const char ufbxi_AnimationCurve[] = "AnimationCurve";
  2754. static const char ufbxi_AnimationLayer[] = "AnimationLayer";
  2755. static const char ufbxi_AnimationStack[] = "AnimationStack";
  2756. static const char ufbxi_ApertureFormat[] = "ApertureFormat";
  2757. static const char ufbxi_ApertureMode[] = "ApertureMode";
  2758. static const char ufbxi_AreaLightShape[] = "AreaLightShape";
  2759. static const char ufbxi_AspectH[] = "AspectH";
  2760. static const char ufbxi_AspectHeight[] = "AspectHeight";
  2761. static const char ufbxi_AspectRatioMode[] = "AspectRatioMode";
  2762. static const char ufbxi_AspectW[] = "AspectW";
  2763. static const char ufbxi_AspectWidth[] = "AspectWidth";
  2764. static const char ufbxi_BaseLayer[] = "BaseLayer";
  2765. static const char ufbxi_BinaryData[] = "BinaryData";
  2766. static const char ufbxi_BindPose[] = "BindPose";
  2767. static const char ufbxi_BindingTable[] = "BindingTable";
  2768. static const char ufbxi_Binormals[] = "Binormals";
  2769. static const char ufbxi_BinormalsIndex[] = "BinormalsIndex";
  2770. static const char ufbxi_BinormalsW[] = "BinormalsW";
  2771. static const char ufbxi_BlendMode[] = "BlendMode";
  2772. static const char ufbxi_BlendModes[] = "BlendModes";
  2773. static const char ufbxi_BlendShapeChannel[] = "BlendShapeChannel";
  2774. static const char ufbxi_BlendShape[] = "BlendShape";
  2775. static const char ufbxi_BlendWeights[] = "BlendWeights";
  2776. static const char ufbxi_BoundaryRule[] = "BoundaryRule";
  2777. static const char ufbxi_Boundary[] = "Boundary";
  2778. static const char ufbxi_ByEdge[] = "ByEdge";
  2779. static const char ufbxi_ByPolygonVertex[] = "ByPolygonVertex";
  2780. static const char ufbxi_ByPolygon[] = "ByPolygon";
  2781. static const char ufbxi_ByVertex[] = "ByVertex";
  2782. static const char ufbxi_ByVertice[] = "ByVertice";
  2783. static const char ufbxi_Cache[] = "Cache";
  2784. static const char ufbxi_CameraStereo[] = "CameraStereo";
  2785. static const char ufbxi_CameraSwitcher[] = "CameraSwitcher";
  2786. static const char ufbxi_Camera[] = "Camera";
  2787. static const char ufbxi_CastLight[] = "CastLight";
  2788. static const char ufbxi_CastShadows[] = "CastShadows";
  2789. static const char ufbxi_Channel[] = "Channel";
  2790. static const char ufbxi_Character[] = "Character";
  2791. static const char ufbxi_Children[] = "Children";
  2792. static const char ufbxi_Cluster[] = "Cluster";
  2793. static const char ufbxi_CollectionExclusive[] = "CollectionExclusive";
  2794. static const char ufbxi_Collection[] = "Collection";
  2795. static const char ufbxi_ColorIndex[] = "ColorIndex";
  2796. static const char ufbxi_Color[] = "Color";
  2797. static const char ufbxi_Colors[] = "Colors";
  2798. static const char ufbxi_Cone_angle[] = "Cone angle";
  2799. static const char ufbxi_ConeAngle[] = "ConeAngle";
  2800. static const char ufbxi_Connections[] = "Connections";
  2801. static const char ufbxi_Constraint[] = "Constraint";
  2802. static const char ufbxi_Content[] = "Content";
  2803. static const char ufbxi_CoordAxisSign[] = "CoordAxisSign";
  2804. static const char ufbxi_CoordAxis[] = "CoordAxis";
  2805. static const char ufbxi_Count[] = "Count";
  2806. static const char ufbxi_Creator[] = "Creator";
  2807. static const char ufbxi_CurrentTextureBlendMode[] = "CurrentTextureBlendMode";
  2808. static const char ufbxi_CurrentTimeMarker[] = "CurrentTimeMarker";
  2809. static const char ufbxi_CustomFrameRate[] = "CustomFrameRate";
  2810. static const char ufbxi_DecayType[] = "DecayType";
  2811. static const char ufbxi_DefaultCamera[] = "DefaultCamera";
  2812. static const char ufbxi_Default[] = "Default";
  2813. static const char ufbxi_Definitions[] = "Definitions";
  2814. static const char ufbxi_DeformPercent[] = "DeformPercent";
  2815. static const char ufbxi_Deformer[] = "Deformer";
  2816. static const char ufbxi_DiffuseColor[] = "DiffuseColor";
  2817. static const char ufbxi_Dimension[] = "Dimension";
  2818. static const char ufbxi_Dimensions[] = "Dimensions";
  2819. static const char ufbxi_DisplayLayer[] = "DisplayLayer";
  2820. static const char ufbxi_Document[] = "Document";
  2821. static const char ufbxi_Documents[] = "Documents";
  2822. static const char ufbxi_EdgeCrease[] = "EdgeCrease";
  2823. static const char ufbxi_EdgeIndexArray[] = "EdgeIndexArray";
  2824. static const char ufbxi_Edges[] = "Edges";
  2825. static const char ufbxi_EmissiveColor[] = "EmissiveColor";
  2826. static const char ufbxi_Entry[] = "Entry";
  2827. static const char ufbxi_FBXHeaderExtension[] = "FBXHeaderExtension";
  2828. static const char ufbxi_FBXVersion[] = "FBXVersion";
  2829. static const char ufbxi_FKEffector[] = "FKEffector";
  2830. static const char ufbxi_FbxPropertyEntry[] = "FbxPropertyEntry";
  2831. static const char ufbxi_FbxSemanticEntry[] = "FbxSemanticEntry";
  2832. static const char ufbxi_FieldOfViewX[] = "FieldOfViewX";
  2833. static const char ufbxi_FieldOfViewY[] = "FieldOfViewY";
  2834. static const char ufbxi_FieldOfView[] = "FieldOfView";
  2835. static const char ufbxi_FileName[] = "FileName";
  2836. static const char ufbxi_Filename[] = "Filename";
  2837. static const char ufbxi_FilmHeight[] = "FilmHeight";
  2838. static const char ufbxi_FilmSqueezeRatio[] = "FilmSqueezeRatio";
  2839. static const char ufbxi_FilmWidth[] = "FilmWidth";
  2840. static const char ufbxi_FlipNormals[] = "FlipNormals";
  2841. static const char ufbxi_FocalLength[] = "FocalLength";
  2842. static const char ufbxi_Form[] = "Form";
  2843. static const char ufbxi_Freeze[] = "Freeze";
  2844. static const char ufbxi_FrontAxisSign[] = "FrontAxisSign";
  2845. static const char ufbxi_FrontAxis[] = "FrontAxis";
  2846. static const char ufbxi_FullWeights[] = "FullWeights";
  2847. static const char ufbxi_GateFit[] = "GateFit";
  2848. static const char ufbxi_GeometricRotation[] = "GeometricRotation";
  2849. static const char ufbxi_GeometricScaling[] = "GeometricScaling";
  2850. static const char ufbxi_GeometricTranslation[] = "GeometricTranslation";
  2851. static const char ufbxi_GeometryUVInfo[] = "GeometryUVInfo";
  2852. static const char ufbxi_Geometry[] = "Geometry";
  2853. static const char ufbxi_GlobalSettings[] = "GlobalSettings";
  2854. static const char ufbxi_Hole[] = "Hole";
  2855. static const char ufbxi_HotSpot[] = "HotSpot";
  2856. static const char ufbxi_IKEffector[] = "IKEffector";
  2857. static const char ufbxi_Implementation[] = "Implementation";
  2858. static const char ufbxi_Indexes[] = "Indexes";
  2859. static const char ufbxi_InheritType[] = "InheritType";
  2860. static const char ufbxi_InnerAngle[] = "InnerAngle";
  2861. static const char ufbxi_Intensity[] = "Intensity";
  2862. static const char ufbxi_IsTheNodeInSet[] = "IsTheNodeInSet";
  2863. static const char ufbxi_KeyAttrDataFloat[] = "KeyAttrDataFloat";
  2864. static const char ufbxi_KeyAttrFlags[] = "KeyAttrFlags";
  2865. static const char ufbxi_KeyAttrRefCount[] = "KeyAttrRefCount";
  2866. static const char ufbxi_KeyCount[] = "KeyCount";
  2867. static const char ufbxi_KeyTime[] = "KeyTime";
  2868. static const char ufbxi_KeyValueFloat[] = "KeyValueFloat";
  2869. static const char ufbxi_Key[] = "Key";
  2870. static const char ufbxi_KnotVectorU[] = "KnotVectorU";
  2871. static const char ufbxi_KnotVectorV[] = "KnotVectorV";
  2872. static const char ufbxi_KnotVector[] = "KnotVector";
  2873. static const char ufbxi_LayerElementBinormal[] = "LayerElementBinormal";
  2874. static const char ufbxi_LayerElementColor[] = "LayerElementColor";
  2875. static const char ufbxi_LayerElementEdgeCrease[] = "LayerElementEdgeCrease";
  2876. static const char ufbxi_LayerElementHole[] = "LayerElementHole";
  2877. static const char ufbxi_LayerElementMaterial[] = "LayerElementMaterial";
  2878. static const char ufbxi_LayerElementNormal[] = "LayerElementNormal";
  2879. static const char ufbxi_LayerElementPolygonGroup[] = "LayerElementPolygonGroup";
  2880. static const char ufbxi_LayerElementSmoothing[] = "LayerElementSmoothing";
  2881. static const char ufbxi_LayerElementTangent[] = "LayerElementTangent";
  2882. static const char ufbxi_LayerElementUV[] = "LayerElementUV";
  2883. static const char ufbxi_LayerElementVertexCrease[] = "LayerElementVertexCrease";
  2884. static const char ufbxi_LayerElementVisibility[] = "LayerElementVisibility";
  2885. static const char ufbxi_LayerElement[] = "LayerElement";
  2886. static const char ufbxi_Layer[] = "Layer";
  2887. static const char ufbxi_LayeredTexture[] = "LayeredTexture";
  2888. static const char ufbxi_Lcl_Rotation[] = "Lcl Rotation";
  2889. static const char ufbxi_Lcl_Scaling[] = "Lcl Scaling";
  2890. static const char ufbxi_Lcl_Translation[] = "Lcl Translation";
  2891. static const char ufbxi_LeftCamera[] = "LeftCamera";
  2892. static const char ufbxi_LightType[] = "LightType";
  2893. static const char ufbxi_Light[] = "Light";
  2894. static const char ufbxi_LimbLength[] = "LimbLength";
  2895. static const char ufbxi_LimbNode[] = "LimbNode";
  2896. static const char ufbxi_Limb[] = "Limb";
  2897. static const char ufbxi_Line[] = "Line";
  2898. static const char ufbxi_Link[] = "Link";
  2899. static const char ufbxi_LocalStart[] = "LocalStart";
  2900. static const char ufbxi_LocalStop[] = "LocalStop";
  2901. static const char ufbxi_LocalTime[] = "LocalTime";
  2902. static const char ufbxi_LodGroup[] = "LodGroup";
  2903. static const char ufbxi_MappingInformationType[] = "MappingInformationType";
  2904. static const char ufbxi_Marker[] = "Marker";
  2905. static const char ufbxi_MaterialAssignation[] = "MaterialAssignation";
  2906. static const char ufbxi_Material[] = "Material";
  2907. static const char ufbxi_Materials[] = "Materials";
  2908. static const char ufbxi_Matrix[] = "Matrix";
  2909. static const char ufbxi_Mesh[] = "Mesh";
  2910. static const char ufbxi_Model[] = "Model";
  2911. static const char ufbxi_Name[] = "Name";
  2912. static const char ufbxi_NodeAttributeName[] = "NodeAttributeName";
  2913. static const char ufbxi_NodeAttribute[] = "NodeAttribute";
  2914. static const char ufbxi_Node[] = "Node";
  2915. static const char ufbxi_Normals[] = "Normals";
  2916. static const char ufbxi_NormalsIndex[] = "NormalsIndex";
  2917. static const char ufbxi_NormalsW[] = "NormalsW";
  2918. static const char ufbxi_Null[] = "Null";
  2919. static const char ufbxi_NurbsCurve[] = "NurbsCurve";
  2920. static const char ufbxi_NurbsSurfaceOrder[] = "NurbsSurfaceOrder";
  2921. static const char ufbxi_NurbsSurface[] = "NurbsSurface";
  2922. static const char ufbxi_Nurbs[] = "Nurbs";
  2923. static const char ufbxi_OO[] = "OO\0";
  2924. static const char ufbxi_OP[] = "OP\0";
  2925. static const char ufbxi_ObjectMetaData[] = "ObjectMetaData";
  2926. static const char ufbxi_ObjectType[] = "ObjectType";
  2927. static const char ufbxi_Objects[] = "Objects";
  2928. static const char ufbxi_Order[] = "Order";
  2929. static const char ufbxi_OriginalUnitScaleFactor[] = "OriginalUnitScaleFactor";
  2930. static const char ufbxi_OriginalUpAxisSign[] = "OriginalUpAxisSign";
  2931. static const char ufbxi_OriginalUpAxis[] = "OriginalUpAxis";
  2932. static const char ufbxi_OuterAngle[] = "OuterAngle";
  2933. static const char ufbxi_PO[] = "PO\0";
  2934. static const char ufbxi_PP[] = "PP\0";
  2935. static const char ufbxi_PointsIndex[] = "PointsIndex";
  2936. static const char ufbxi_Points[] = "Points";
  2937. static const char ufbxi_PolygonGroup[] = "PolygonGroup";
  2938. static const char ufbxi_PolygonIndexArray[] = "PolygonIndexArray";
  2939. static const char ufbxi_PolygonVertexIndex[] = "PolygonVertexIndex";
  2940. static const char ufbxi_PoseNode[] = "PoseNode";
  2941. static const char ufbxi_Pose[] = "Pose";
  2942. static const char ufbxi_PostRotation[] = "PostRotation";
  2943. static const char ufbxi_PreRotation[] = "PreRotation";
  2944. static const char ufbxi_PreviewDivisionLevels[] = "PreviewDivisionLevels";
  2945. static const char ufbxi_Properties60[] = "Properties60";
  2946. static const char ufbxi_Properties70[] = "Properties70";
  2947. static const char ufbxi_PropertyTemplate[] = "PropertyTemplate";
  2948. static const char ufbxi_R[] = "R\0\0";
  2949. static const char ufbxi_ReferenceStart[] = "ReferenceStart";
  2950. static const char ufbxi_ReferenceStop[] = "ReferenceStop";
  2951. static const char ufbxi_ReferenceTime[] = "ReferenceTime";
  2952. static const char ufbxi_RelativeFileName[] = "RelativeFileName";
  2953. static const char ufbxi_RelativeFilename[] = "RelativeFilename";
  2954. static const char ufbxi_RenderDivisionLevels[] = "RenderDivisionLevels";
  2955. static const char ufbxi_RightCamera[] = "RightCamera";
  2956. static const char ufbxi_RootNode[] = "RootNode";
  2957. static const char ufbxi_Root[] = "Root";
  2958. static const char ufbxi_RotationAccumulationMode[] = "RotationAccumulationMode";
  2959. static const char ufbxi_RotationOffset[] = "RotationOffset";
  2960. static const char ufbxi_RotationOrder[] = "RotationOrder";
  2961. static const char ufbxi_RotationPivot[] = "RotationPivot";
  2962. static const char ufbxi_Rotation[] = "Rotation";
  2963. static const char ufbxi_S[] = "S\0\0";
  2964. static const char ufbxi_ScaleAccumulationMode[] = "ScaleAccumulationMode";
  2965. static const char ufbxi_ScalingOffset[] = "ScalingOffset";
  2966. static const char ufbxi_ScalingPivot[] = "ScalingPivot";
  2967. static const char ufbxi_Scaling[] = "Scaling";
  2968. static const char ufbxi_SceneInfo[] = "SceneInfo";
  2969. static const char ufbxi_SelectionNode[] = "SelectionNode";
  2970. static const char ufbxi_SelectionSet[] = "SelectionSet";
  2971. static const char ufbxi_ShadingModel[] = "ShadingModel";
  2972. static const char ufbxi_Shape[] = "Shape";
  2973. static const char ufbxi_Shininess[] = "Shininess";
  2974. static const char ufbxi_Show[] = "Show";
  2975. static const char ufbxi_Size[] = "Size";
  2976. static const char ufbxi_Skin[] = "Skin";
  2977. static const char ufbxi_SkinningType[] = "SkinningType";
  2978. static const char ufbxi_Smoothing[] = "Smoothing";
  2979. static const char ufbxi_Smoothness[] = "Smoothness";
  2980. static const char ufbxi_SnapOnFrameMode[] = "SnapOnFrameMode";
  2981. static const char ufbxi_SpecularColor[] = "SpecularColor";
  2982. static const char ufbxi_Step[] = "Step";
  2983. static const char ufbxi_SubDeformer[] = "SubDeformer";
  2984. static const char ufbxi_T[] = "T\0\0";
  2985. static const char ufbxi_Take[] = "Take";
  2986. static const char ufbxi_Takes[] = "Takes";
  2987. static const char ufbxi_Tangents[] = "Tangents";
  2988. static const char ufbxi_TangentsIndex[] = "TangentsIndex";
  2989. static const char ufbxi_TangentsW[] = "TangentsW";
  2990. static const char ufbxi_Texture[] = "Texture";
  2991. static const char ufbxi_Texture_alpha[] = "Texture alpha";
  2992. static const char ufbxi_TextureId[] = "TextureId";
  2993. static const char ufbxi_TextureRotationPivot[] = "TextureRotationPivot";
  2994. static const char ufbxi_TextureScalingPivot[] = "TextureScalingPivot";
  2995. static const char ufbxi_TextureUV[] = "TextureUV";
  2996. static const char ufbxi_TextureUVVerticeIndex[] = "TextureUVVerticeIndex";
  2997. static const char ufbxi_TimeMarker[] = "TimeMarker";
  2998. static const char ufbxi_TimeMode[] = "TimeMode";
  2999. static const char ufbxi_TimeProtocol[] = "TimeProtocol";
  3000. static const char ufbxi_TimeSpanStart[] = "TimeSpanStart";
  3001. static const char ufbxi_TimeSpanStop[] = "TimeSpanStop";
  3002. static const char ufbxi_TransformLink[] = "TransformLink";
  3003. static const char ufbxi_Transform[] = "Transform";
  3004. static const char ufbxi_Translation[] = "Translation";
  3005. static const char ufbxi_TrimNurbsSurface[] = "TrimNurbsSurface";
  3006. static const char ufbxi_Type[] = "Type";
  3007. static const char ufbxi_TypedIndex[] = "TypedIndex";
  3008. static const char ufbxi_UVIndex[] = "UVIndex";
  3009. static const char ufbxi_UVSet[] = "UVSet";
  3010. static const char ufbxi_UVSwap[] = "UVSwap";
  3011. static const char ufbxi_UV[] = "UV\0";
  3012. static const char ufbxi_UnitScaleFactor[] = "UnitScaleFactor";
  3013. static const char ufbxi_UpAxisSign[] = "UpAxisSign";
  3014. static const char ufbxi_UpAxis[] = "UpAxis";
  3015. static const char ufbxi_VertexCacheDeformer[] = "VertexCacheDeformer";
  3016. static const char ufbxi_VertexCrease[] = "VertexCrease";
  3017. static const char ufbxi_VertexCreaseIndex[] = "VertexCreaseIndex";
  3018. static const char ufbxi_VertexIndexArray[] = "VertexIndexArray";
  3019. static const char ufbxi_Vertices[] = "Vertices";
  3020. static const char ufbxi_Video[] = "Video";
  3021. static const char ufbxi_Visibility[] = "Visibility";
  3022. static const char ufbxi_Weight[] = "Weight";
  3023. static const char ufbxi_Weights[] = "Weights";
  3024. static const char ufbxi_WrapModeU[] = "WrapModeU";
  3025. static const char ufbxi_WrapModeV[] = "WrapModeV";
  3026. static const char ufbxi_X[] = "X\0\0";
  3027. static const char ufbxi_Y[] = "Y\0\0";
  3028. static const char ufbxi_Z[] = "Z\0\0";
  3029. static const char ufbxi_d_X[] = "d|X";
  3030. static const char ufbxi_d_Y[] = "d|Y";
  3031. static const char ufbxi_d_Z[] = "d|Z";
  3032. static ufbx_string ufbxi_strings[] = {
  3033. { ufbxi_AllSame, 7 },
  3034. { ufbxi_Alphas, 6 },
  3035. { ufbxi_AmbientColor, 12 },
  3036. { ufbxi_AnimationCurve, 14 },
  3037. { ufbxi_AnimationCurveNode, 18 },
  3038. { ufbxi_AnimationLayer, 14 },
  3039. { ufbxi_AnimationStack, 14 },
  3040. { ufbxi_ApertureFormat, 14 },
  3041. { ufbxi_ApertureMode, 12 },
  3042. { ufbxi_AreaLightShape, 14 },
  3043. { ufbxi_AspectH, 7 },
  3044. { ufbxi_AspectHeight, 12 },
  3045. { ufbxi_AspectRatioMode, 15 },
  3046. { ufbxi_AspectW, 7 },
  3047. { ufbxi_AspectWidth, 11 },
  3048. { ufbxi_BaseLayer, 9 },
  3049. { ufbxi_BinaryData, 10 },
  3050. { ufbxi_BindPose, 8 },
  3051. { ufbxi_BindingTable, 12 },
  3052. { ufbxi_Binormals, 9 },
  3053. { ufbxi_BinormalsIndex, 14 },
  3054. { ufbxi_BinormalsW, 10 },
  3055. { ufbxi_BlendMode, 9 },
  3056. { ufbxi_BlendModes, 10 },
  3057. { ufbxi_BlendShape, 10 },
  3058. { ufbxi_BlendShapeChannel, 17 },
  3059. { ufbxi_BlendWeights, 12 },
  3060. { ufbxi_Boundary, 8 },
  3061. { ufbxi_BoundaryRule, 12 },
  3062. { ufbxi_ByEdge, 6 },
  3063. { ufbxi_ByPolygon, 9 },
  3064. { ufbxi_ByPolygonVertex, 15 },
  3065. { ufbxi_ByVertex, 8 },
  3066. { ufbxi_ByVertice, 9 },
  3067. { ufbxi_Cache, 5 },
  3068. { ufbxi_Camera, 6 },
  3069. { ufbxi_CameraStereo, 12 },
  3070. { ufbxi_CameraSwitcher, 14 },
  3071. { ufbxi_CastLight, 9 },
  3072. { ufbxi_CastShadows, 11 },
  3073. { ufbxi_Channel, 7 },
  3074. { ufbxi_Character, sizeof(ufbxi_Character) - 1 },
  3075. { ufbxi_Children, 8 },
  3076. { ufbxi_Cluster, 7 },
  3077. { ufbxi_Collection, 10 },
  3078. { ufbxi_CollectionExclusive, 19 },
  3079. { ufbxi_Color, 5 },
  3080. { ufbxi_ColorIndex, 10 },
  3081. { ufbxi_Colors, 6 },
  3082. { ufbxi_Cone_angle, 10 },
  3083. { ufbxi_ConeAngle, 9 },
  3084. { ufbxi_Connections, 11 },
  3085. { ufbxi_Constraint, sizeof(ufbxi_Constraint) - 1 },
  3086. { ufbxi_Content, 7 },
  3087. { ufbxi_CoordAxis, 9 },
  3088. { ufbxi_CoordAxisSign, 13 },
  3089. { ufbxi_Count, 5 },
  3090. { ufbxi_Creator, 7 },
  3091. { ufbxi_CurrentTextureBlendMode, 23 },
  3092. { ufbxi_CurrentTimeMarker, 17 },
  3093. { ufbxi_CustomFrameRate, 15 },
  3094. { ufbxi_DecayType, 9 },
  3095. { ufbxi_Default, 7 },
  3096. { ufbxi_DefaultCamera, 13 },
  3097. { ufbxi_Definitions, 11 },
  3098. { ufbxi_DeformPercent, 13 },
  3099. { ufbxi_Deformer, 8 },
  3100. { ufbxi_DiffuseColor, 12 },
  3101. { ufbxi_Dimension, 9 },
  3102. { ufbxi_Dimensions, 10 },
  3103. { ufbxi_DisplayLayer, 12 },
  3104. { ufbxi_Document, 8 },
  3105. { ufbxi_Documents, 9 },
  3106. { ufbxi_EdgeCrease, 10 },
  3107. { ufbxi_EdgeIndexArray, 14 },
  3108. { ufbxi_Edges, 5 },
  3109. { ufbxi_EmissiveColor, 13 },
  3110. { ufbxi_Entry, 5 },
  3111. { ufbxi_FBXHeaderExtension, 18 },
  3112. { ufbxi_FBXVersion, 10 },
  3113. { ufbxi_FKEffector, 10 },
  3114. { ufbxi_FbxPropertyEntry, 16 },
  3115. { ufbxi_FbxSemanticEntry, 16 },
  3116. { ufbxi_FieldOfView, 11 },
  3117. { ufbxi_FieldOfViewX, 12 },
  3118. { ufbxi_FieldOfViewY, 12 },
  3119. { ufbxi_FileName, 8 },
  3120. { ufbxi_Filename, 8 },
  3121. { ufbxi_FilmHeight, 10 },
  3122. { ufbxi_FilmSqueezeRatio, 16 },
  3123. { ufbxi_FilmWidth, 9 },
  3124. { ufbxi_FlipNormals, 11 },
  3125. { ufbxi_FocalLength, 11 },
  3126. { ufbxi_Form, 4 },
  3127. { ufbxi_Freeze, 6 },
  3128. { ufbxi_FrontAxis, 9 },
  3129. { ufbxi_FrontAxisSign, 13 },
  3130. { ufbxi_FullWeights, 11 },
  3131. { ufbxi_GateFit, 7 },
  3132. { ufbxi_GeometricRotation, 17 },
  3133. { ufbxi_GeometricScaling, 16 },
  3134. { ufbxi_GeometricTranslation, 20 },
  3135. { ufbxi_Geometry, 8 },
  3136. { ufbxi_GeometryUVInfo, 14 },
  3137. { ufbxi_GlobalSettings, 14 },
  3138. { ufbxi_Hole, 4 },
  3139. { ufbxi_HotSpot, 7 },
  3140. { ufbxi_IKEffector, 10 },
  3141. { ufbxi_Implementation, 14 },
  3142. { ufbxi_Indexes, 7 },
  3143. { ufbxi_InheritType, 11 },
  3144. { ufbxi_InnerAngle, 10 },
  3145. { ufbxi_Intensity, 9 },
  3146. { ufbxi_IsTheNodeInSet, 14 },
  3147. { ufbxi_Key, 3 },
  3148. { ufbxi_KeyAttrDataFloat, 16 },
  3149. { ufbxi_KeyAttrFlags, 12 },
  3150. { ufbxi_KeyAttrRefCount, 15 },
  3151. { ufbxi_KeyCount, 8 },
  3152. { ufbxi_KeyTime, 7 },
  3153. { ufbxi_KeyValueFloat, 13 },
  3154. { ufbxi_KnotVector, 10 },
  3155. { ufbxi_KnotVectorU, 11 },
  3156. { ufbxi_KnotVectorV, 11 },
  3157. { ufbxi_Layer, 5 },
  3158. { ufbxi_LayerElement, 12 },
  3159. { ufbxi_LayerElementBinormal, 20 },
  3160. { ufbxi_LayerElementColor, 17 },
  3161. { ufbxi_LayerElementEdgeCrease, 22 },
  3162. { ufbxi_LayerElementHole, 16 },
  3163. { ufbxi_LayerElementMaterial, 20 },
  3164. { ufbxi_LayerElementNormal, 18 },
  3165. { ufbxi_LayerElementPolygonGroup, 24 },
  3166. { ufbxi_LayerElementSmoothing, 21 },
  3167. { ufbxi_LayerElementTangent, 19 },
  3168. { ufbxi_LayerElementUV, 14 },
  3169. { ufbxi_LayerElementVertexCrease, 24 },
  3170. { ufbxi_LayerElementVisibility, 22 },
  3171. { ufbxi_LayeredTexture, 14 },
  3172. { ufbxi_Lcl_Rotation, 12 },
  3173. { ufbxi_Lcl_Scaling, 11 },
  3174. { ufbxi_Lcl_Translation, 15 },
  3175. { ufbxi_LeftCamera, 10 },
  3176. { ufbxi_Light, 5 },
  3177. { ufbxi_LightType, 9 },
  3178. { ufbxi_Limb, 4 },
  3179. { ufbxi_LimbLength, 10 },
  3180. { ufbxi_LimbNode, 8 },
  3181. { ufbxi_Line, 4 },
  3182. { ufbxi_Link, 4 },
  3183. { ufbxi_LocalStart, 10 },
  3184. { ufbxi_LocalStop, 9 },
  3185. { ufbxi_LocalTime, 9 },
  3186. { ufbxi_LodGroup, 8 },
  3187. { ufbxi_MappingInformationType, 22 },
  3188. { ufbxi_Marker, 6 },
  3189. { ufbxi_Material, 8 },
  3190. { ufbxi_MaterialAssignation, 19 },
  3191. { ufbxi_Materials, 9 },
  3192. { ufbxi_Matrix, 6 },
  3193. { ufbxi_Mesh, 4 },
  3194. { ufbxi_Model, 5 },
  3195. { ufbxi_Name, 4 },
  3196. { ufbxi_Node, 4 },
  3197. { ufbxi_NodeAttribute, 13 },
  3198. { ufbxi_NodeAttributeName, 17 },
  3199. { ufbxi_Normals, 7 },
  3200. { ufbxi_NormalsIndex, 12 },
  3201. { ufbxi_NormalsW, 8 },
  3202. { ufbxi_Null, 4 },
  3203. { ufbxi_Nurbs, 5 },
  3204. { ufbxi_NurbsCurve, 10 },
  3205. { ufbxi_NurbsSurface, 12 },
  3206. { ufbxi_NurbsSurfaceOrder, 17 },
  3207. { ufbxi_OO, 2 },
  3208. { ufbxi_OP, 2 },
  3209. { ufbxi_ObjectMetaData, 14 },
  3210. { ufbxi_ObjectType, 10 },
  3211. { ufbxi_Objects, 7 },
  3212. { ufbxi_Order, 5 },
  3213. { ufbxi_OriginalUnitScaleFactor, 23 },
  3214. { ufbxi_OriginalUpAxis, 14 },
  3215. { ufbxi_OriginalUpAxisSign, 18 },
  3216. { ufbxi_OuterAngle, 10 },
  3217. { ufbxi_PO, 2 },
  3218. { ufbxi_PP, 2 },
  3219. { ufbxi_Points, 6 },
  3220. { ufbxi_PointsIndex, 11 },
  3221. { ufbxi_PolygonGroup, 12 },
  3222. { ufbxi_PolygonIndexArray, 17 },
  3223. { ufbxi_PolygonVertexIndex, 18 },
  3224. { ufbxi_Pose, 4 },
  3225. { ufbxi_PoseNode, 8 },
  3226. { ufbxi_PostRotation, 12 },
  3227. { ufbxi_PreRotation, 11 },
  3228. { ufbxi_PreviewDivisionLevels, 21 },
  3229. { ufbxi_Properties60, 12 },
  3230. { ufbxi_Properties70, 12 },
  3231. { ufbxi_PropertyTemplate, 16 },
  3232. { ufbxi_R, 1 },
  3233. { ufbxi_ReferenceStart, 14 },
  3234. { ufbxi_ReferenceStop, 13 },
  3235. { ufbxi_ReferenceTime, 13 },
  3236. { ufbxi_RelativeFileName, 16 },
  3237. { ufbxi_RelativeFilename, 16 },
  3238. { ufbxi_RenderDivisionLevels, 20 },
  3239. { ufbxi_RightCamera, 11 },
  3240. { ufbxi_Root, 4 },
  3241. { ufbxi_RootNode, 8 },
  3242. { ufbxi_Rotation, 8 },
  3243. { ufbxi_RotationAccumulationMode, 24 },
  3244. { ufbxi_RotationOffset, 14 },
  3245. { ufbxi_RotationOrder, 13 },
  3246. { ufbxi_RotationPivot, 13 },
  3247. { ufbxi_S, 1 },
  3248. { ufbxi_ScaleAccumulationMode, 21 },
  3249. { ufbxi_Scaling, 7 },
  3250. { ufbxi_ScalingOffset, 13 },
  3251. { ufbxi_ScalingPivot, 12 },
  3252. { ufbxi_SceneInfo, 9 },
  3253. { ufbxi_SelectionNode, 13 },
  3254. { ufbxi_SelectionSet, 12 },
  3255. { ufbxi_ShadingModel, 12 },
  3256. { ufbxi_Shape, 5 },
  3257. { ufbxi_Shininess, 9 },
  3258. { ufbxi_Show, 4 },
  3259. { ufbxi_Size, 4 },
  3260. { ufbxi_Skin, 4 },
  3261. { ufbxi_SkinningType, 12 },
  3262. { ufbxi_Smoothing, 9 },
  3263. { ufbxi_Smoothness, 10 },
  3264. { ufbxi_SnapOnFrameMode, 15 },
  3265. { ufbxi_SpecularColor, 13 },
  3266. { ufbxi_Step, 4 },
  3267. { ufbxi_SubDeformer, 11 },
  3268. { ufbxi_T, 1 },
  3269. { ufbxi_Take, 4 },
  3270. { ufbxi_Takes, 5 },
  3271. { ufbxi_Tangents, 8 },
  3272. { ufbxi_TangentsIndex, 13 },
  3273. { ufbxi_TangentsW, 9 },
  3274. { ufbxi_Texture, 7 },
  3275. { ufbxi_Texture_alpha, 13 },
  3276. { ufbxi_TextureId, 9 },
  3277. { ufbxi_TextureRotationPivot, 20 },
  3278. { ufbxi_TextureScalingPivot, 19 },
  3279. { ufbxi_TextureUV, 9 },
  3280. { ufbxi_TextureUVVerticeIndex, 21 },
  3281. { ufbxi_TimeMarker, 10 },
  3282. { ufbxi_TimeMode, 8 },
  3283. { ufbxi_TimeProtocol, 12 },
  3284. { ufbxi_TimeSpanStart, 13 },
  3285. { ufbxi_TimeSpanStop, 12 },
  3286. { ufbxi_Transform, 9 },
  3287. { ufbxi_TransformLink, 13 },
  3288. { ufbxi_Translation, 11 },
  3289. { ufbxi_TrimNurbsSurface, 16 },
  3290. { ufbxi_Type, 4 },
  3291. { ufbxi_TypedIndex, 10 },
  3292. { ufbxi_UV, 2 },
  3293. { ufbxi_UVIndex, 7 },
  3294. { ufbxi_UVSet, 5 },
  3295. { ufbxi_UVSwap, 6 },
  3296. { ufbxi_UnitScaleFactor, 15 },
  3297. { ufbxi_UpAxis, 6 },
  3298. { ufbxi_UpAxisSign, 10 },
  3299. { ufbxi_VertexCacheDeformer, 19 },
  3300. { ufbxi_VertexCrease, 12 },
  3301. { ufbxi_VertexCreaseIndex, 17 },
  3302. { ufbxi_VertexIndexArray, 16 },
  3303. { ufbxi_Vertices, 8 },
  3304. { ufbxi_Video, 5 },
  3305. { ufbxi_Visibility, 10 },
  3306. { ufbxi_Weight, 6 },
  3307. { ufbxi_Weights, 7 },
  3308. { ufbxi_WrapModeU, 9 },
  3309. { ufbxi_WrapModeV, 9 },
  3310. { ufbxi_X, 1 },
  3311. { ufbxi_Y, 1 },
  3312. { ufbxi_Z, 1 },
  3313. { ufbxi_d_X, 3 },
  3314. { ufbxi_d_Y, 3 },
  3315. { ufbxi_d_Z, 3 },
  3316. };
  3317. static ufbxi_noinline const char *ufbxi_find_canonical_string(const char *data, size_t length)
  3318. {
  3319. ufbx_string str = { data, length };
  3320. size_t ix = SIZE_MAX;
  3321. ufbxi_macro_lower_bound_eq(ufbx_string, 8, &ix, ufbxi_strings, 0, ufbxi_arraycount(ufbxi_strings),
  3322. ( ufbxi_str_less(*a, str) ), ( ufbxi_str_equal(*a, str) ));
  3323. if (ix < SIZE_MAX) {
  3324. return ufbxi_strings[ix].data;
  3325. } else {
  3326. return data;
  3327. }
  3328. }
  3329. // -- Type definitions
  3330. typedef struct ufbxi_node ufbxi_node;
  3331. typedef enum {
  3332. UFBXI_VALUE_NONE,
  3333. UFBXI_VALUE_NUMBER,
  3334. UFBXI_VALUE_STRING,
  3335. UFBXI_VALUE_ARRAY,
  3336. } ufbxi_value_type;
  3337. typedef union {
  3338. struct { double f; int64_t i; }; // < if `UFBXI_PROP_NUMBER`
  3339. ufbxi_sanitized_string s; // < if `UFBXI_PROP_STRING`
  3340. } ufbxi_value;
  3341. typedef struct {
  3342. void *data; // < Pointer to `size` bool/int32_t/int64_t/float/double elements
  3343. size_t size; // < Number of elements
  3344. char type; // < FBX type code: b/i/l/f/d
  3345. } ufbxi_value_array;
  3346. struct ufbxi_node {
  3347. const char *name; // < Name of the node (pooled, comapre with == to ufbxi_* strings)
  3348. uint32_t num_children; // < Number of child nodes
  3349. uint8_t name_len; // < Length of `name` in bytes
  3350. // If `value_type_mask == UFBXI_PROP_ARRAY` then the node is an array
  3351. // (`array` field is valid) otherwise the node has N values in `vals`
  3352. // where the type of each value is stored in 2 bits per value from LSB.
  3353. // ie. `vals[ix]` type is `(value_type_mask >> (ix*2)) & 0x3`
  3354. uint16_t value_type_mask;
  3355. ufbxi_node *children;
  3356. union {
  3357. ufbxi_value_array *array; // if `prop_type_mask == UFBXI_PROP_ARRAY`
  3358. ufbxi_value *vals; // otherwise
  3359. };
  3360. };
  3361. #define UFBXI_SCENE_IMP_MAGIC 0x58424655
  3362. #define UFBXI_MESH_IMP_MAGIC 0x48534d55
  3363. #define UFBXI_LINE_CURVE_IMP_MAGIC 0x55434c55
  3364. #define UFBXI_CACHE_IMP_MAGIC 0x48434355
  3365. #define UFBXI_REFCOUNT_IMP_MAGIC 0x46455255
  3366. typedef struct ufbxi_refcount ufbxi_refcount;
  3367. struct ufbxi_refcount {
  3368. ufbxi_refcount *parent;
  3369. void *align_0;
  3370. uint32_t self_magic;
  3371. uint32_t type_magic;
  3372. uint64_t zero_pad_pre[8];
  3373. ufbxi_atomic_counter refcount;
  3374. uint64_t zero_pad_post[8];
  3375. };
  3376. static ufbxi_noinline void ufbxi_init_ref(ufbxi_refcount *refcount, uint32_t magic, ufbxi_refcount *parent);
  3377. static ufbxi_noinline void ufbxi_retain_ref(ufbxi_refcount *refcount);
  3378. #define ufbxi_get_imp(type, ptr) ((type*)((char*)ptr - sizeof(ufbxi_refcount)))
  3379. typedef struct {
  3380. ufbxi_refcount refcount;
  3381. ufbx_scene scene;
  3382. uint32_t magic;
  3383. ufbxi_allocator ator;
  3384. ufbxi_buf result_buf;
  3385. ufbxi_buf string_buf;
  3386. } ufbxi_scene_imp;
  3387. ufbx_static_assert(scene_imp_offset, offsetof(ufbxi_scene_imp, scene) == sizeof(ufbxi_refcount));
  3388. typedef struct {
  3389. ufbxi_refcount refcount;
  3390. ufbx_mesh mesh;
  3391. uint32_t magic;
  3392. ufbxi_allocator ator;
  3393. ufbxi_buf result_buf;
  3394. } ufbxi_mesh_imp;
  3395. ufbx_static_assert(mesh_imp_offset, offsetof(ufbxi_mesh_imp, mesh) == sizeof(ufbxi_refcount));
  3396. typedef struct {
  3397. // Semantic string data and length eg. for a string token
  3398. // this string doesn't include the quotes.
  3399. char *str_data;
  3400. size_t str_len;
  3401. size_t str_cap;
  3402. // Type of the token, either single character such as '{' or ':'
  3403. // or one of UFBXI_ASCII_* defines.
  3404. char type;
  3405. // Parsed semantic value
  3406. union {
  3407. double f64;
  3408. int64_t i64;
  3409. size_t name_len;
  3410. } value;
  3411. } ufbxi_ascii_token;
  3412. typedef struct {
  3413. size_t max_token_length;
  3414. const char *src;
  3415. const char *src_yield;
  3416. const char *src_end;
  3417. bool read_first_comment;
  3418. bool found_version;
  3419. bool parse_as_f32;
  3420. ufbxi_ascii_token prev_token;
  3421. ufbxi_ascii_token token;
  3422. } ufbxi_ascii;
  3423. typedef struct {
  3424. const char *type;
  3425. ufbx_string sub_type;
  3426. ufbx_props props;
  3427. } ufbxi_template;
  3428. typedef struct {
  3429. uint64_t fbx_id;
  3430. uint32_t element_id;
  3431. } ufbxi_fbx_id_entry;
  3432. typedef struct {
  3433. uint64_t node_fbx_id;
  3434. uint64_t attr_fbx_id;
  3435. } ufbxi_fbx_attr_entry;
  3436. // Temporary connection before we resolve the element pointers
  3437. typedef struct {
  3438. uint64_t src, dst;
  3439. ufbx_string src_prop;
  3440. ufbx_string dst_prop;
  3441. } ufbxi_tmp_connection;
  3442. typedef struct {
  3443. uint64_t fbx_id;
  3444. ufbx_string name;
  3445. ufbx_props props;
  3446. ufbx_dom_node *dom_node;
  3447. } ufbxi_element_info;
  3448. typedef struct {
  3449. uint64_t bone_fbx_id;
  3450. ufbx_matrix bone_to_world;
  3451. } ufbxi_tmp_bone_pose;
  3452. typedef struct {
  3453. ufbx_string prop_name;
  3454. uint32_t *face_texture;
  3455. size_t num_faces;
  3456. bool all_same;
  3457. } ufbxi_tmp_mesh_texture;
  3458. typedef struct {
  3459. ufbxi_tmp_mesh_texture *texture_arr;
  3460. size_t texture_count;
  3461. } ufbxi_mesh_extra;
  3462. typedef struct {
  3463. int32_t material_id;
  3464. int32_t texture_id;
  3465. ufbx_string prop_name;
  3466. } ufbxi_tmp_material_texture;
  3467. typedef struct {
  3468. int32_t *blend_modes;
  3469. size_t num_blend_modes;
  3470. ufbx_real *alphas;
  3471. size_t num_alphas;
  3472. } ufbxi_texture_extra;
  3473. typedef struct {
  3474. ufbx_error error;
  3475. uint32_t version;
  3476. ufbx_exporter exporter;
  3477. uint32_t exporter_version;
  3478. bool from_ascii;
  3479. bool local_big_endian;
  3480. bool file_big_endian;
  3481. bool sure_fbx;
  3482. ufbx_load_opts opts;
  3483. // IO
  3484. uint64_t data_offset;
  3485. ufbx_read_fn *read_fn;
  3486. ufbx_skip_fn *skip_fn;
  3487. ufbx_close_fn *close_fn;
  3488. void *read_user;
  3489. char *read_buffer;
  3490. size_t read_buffer_size;
  3491. const char *data_begin;
  3492. const char *data;
  3493. size_t yield_size;
  3494. size_t data_size;
  3495. // Allocators
  3496. ufbxi_allocator ator_result;
  3497. ufbxi_allocator ator_tmp;
  3498. // Temporary maps
  3499. ufbxi_map prop_type_map; // < `ufbxi_prop_type_name` Property type to enum
  3500. ufbxi_map fbx_id_map; // < `ufbxi_fbx_id_entry` FBX ID to local ID
  3501. // 6x00 specific maps
  3502. ufbxi_map fbx_attr_map; // < `ufbxi_fbx_attr_entry` Node ID to attrib ID
  3503. ufbxi_map node_prop_set; // < `const char*` Node property names
  3504. // DOM nodes
  3505. ufbxi_map dom_node_map; // < `const char*` Node property names
  3506. // Temporary array
  3507. char *tmp_arr;
  3508. size_t tmp_arr_size;
  3509. char *swap_arr;
  3510. size_t swap_arr_size;
  3511. // Generated index buffers
  3512. size_t max_zero_indices;
  3513. size_t max_consecutive_indices;
  3514. // Temporary buffers
  3515. ufbxi_buf tmp;
  3516. ufbxi_buf tmp_parse;
  3517. ufbxi_buf tmp_stack;
  3518. ufbxi_buf tmp_connections;
  3519. ufbxi_buf tmp_node_ids;
  3520. ufbxi_buf tmp_elements;
  3521. ufbxi_buf tmp_element_offsets;
  3522. ufbxi_buf tmp_typed_element_offsets[UFBX_ELEMENT_TYPE_COUNT];
  3523. ufbxi_buf tmp_mesh_textures;
  3524. ufbxi_buf tmp_full_weights;
  3525. ufbxi_buf tmp_dom_nodes;
  3526. size_t tmp_element_byte_offset;
  3527. ufbxi_template *templates;
  3528. size_t num_templates;
  3529. ufbx_dom_node *dom_parse_toplevel;
  3530. size_t dom_parse_num_children;
  3531. // String pool
  3532. ufbxi_string_pool string_pool;
  3533. // Result buffers, these are retained in `ufbx_scene` returned to user.
  3534. ufbxi_buf result;
  3535. // Top-level state
  3536. ufbxi_node *top_nodes;
  3537. size_t top_nodes_len, top_nodes_cap;
  3538. bool parsed_to_end;
  3539. // "Focused" top-level node and child index, if `top_child_index == SIZE_MAX`
  3540. // the children are parsed on demand.
  3541. ufbxi_node *top_node;
  3542. size_t top_child_index;
  3543. ufbxi_node top_child;
  3544. bool has_next_child;
  3545. // Shared consecutive and all-zero index buffers
  3546. uint32_t *zero_indices;
  3547. uint32_t *consecutive_indices;
  3548. // Call progress function periodically
  3549. ptrdiff_t progress_timer;
  3550. uint64_t progress_bytes_total;
  3551. size_t progress_interval;
  3552. // Extra data on the side of elements
  3553. void **element_extra_arr;
  3554. size_t element_extra_cap;
  3555. ufbxi_ascii ascii;
  3556. ufbxi_node root;
  3557. ufbx_scene scene;
  3558. ufbxi_scene_imp *scene_imp;
  3559. ufbx_inflate_retain *inflate_retain;
  3560. uint64_t root_id;
  3561. uint32_t num_elements;
  3562. ufbxi_node legacy_node;
  3563. uint64_t legacy_implicit_anim_layer_id;
  3564. double ktime_to_sec;
  3565. } ufbxi_context;
  3566. static ufbxi_noinline int ufbxi_fail_imp(ufbxi_context *uc, const char *cond, const char *func, uint32_t line)
  3567. {
  3568. return ufbxi_fail_imp_err(&uc->error, cond, func, line);
  3569. }
  3570. #define ufbxi_check(cond) if (ufbxi_unlikely(!ufbxi_trace(cond))) return ufbxi_fail_imp(uc, ufbxi_cond_str(cond), ufbxi_function, ufbxi_line)
  3571. #define ufbxi_check_return(cond, ret) do { if (ufbxi_unlikely(!ufbxi_trace(cond))) { ufbxi_fail_imp(uc, ufbxi_cond_str(cond), ufbxi_function, ufbxi_line); return ret; } } while (0)
  3572. #define ufbxi_fail(desc) return ufbxi_fail_imp(uc, desc, ufbxi_function, ufbxi_line)
  3573. #define ufbxi_fail_return(desc, ret) do { ufbxi_fail_imp(uc, desc, ufbxi_function, ufbxi_line); return ret; } while (0)
  3574. #define ufbxi_check_msg(cond, msg) if (ufbxi_unlikely(!ufbxi_trace(cond))) return ufbxi_fail_imp(uc, ufbxi_error_msg(ufbxi_cond_str(cond), msg), ufbxi_function, ufbxi_line)
  3575. #define ufbxi_check_return_msg(cond, ret, msg) do { if (ufbxi_unlikely(!ufbxi_trace(cond))) { ufbxi_fail_imp(uc, ufbxi_error_msg(ufbxi_cond_str(cond), msg), ufbxi_function, ufbxi_line); return ret; } } while (0)
  3576. #define ufbxi_fail_msg(desc, msg) return ufbxi_fail_imp(uc, ufbxi_error_msg(desc, msg), ufbxi_function, ufbxi_line)
  3577. // -- Progress
  3578. static ufbxi_forceinline uint64_t ufbxi_get_read_offset(ufbxi_context *uc)
  3579. {
  3580. return uc->data_offset + ufbxi_to_size(uc->data - uc->data_begin);
  3581. }
  3582. ufbxi_nodiscard static ufbxi_noinline int ufbxi_report_progress(ufbxi_context *uc)
  3583. {
  3584. if (!uc->opts.progress_cb.fn) return 1;
  3585. ufbx_progress progress;
  3586. progress.bytes_read = ufbxi_get_read_offset(uc);
  3587. progress.bytes_total = uc->progress_bytes_total;
  3588. uc->progress_timer = 1024;
  3589. uint32_t result = (uint32_t)uc->opts.progress_cb.fn(uc->opts.progress_cb.user, &progress);
  3590. ufbx_assert(result == UFBX_PROGRESS_CONTINUE || result == UFBX_PROGRESS_CANCEL);
  3591. ufbxi_check_msg(result != UFBX_PROGRESS_CANCEL, "Cancelled");
  3592. return 1;
  3593. }
  3594. // TODO: Remove `ufbxi_unused` when it's not needed anymore
  3595. ufbxi_unused ufbxi_nodiscard static ufbxi_forceinline int ufbxi_progress(ufbxi_context *uc, size_t work_units)
  3596. {
  3597. if (!uc->opts.progress_cb.fn) return 1;
  3598. ptrdiff_t left = uc->progress_timer - (ptrdiff_t)work_units;
  3599. uc->progress_timer = left;
  3600. if (left > 0) return 1;
  3601. return ufbxi_report_progress(uc);
  3602. }
  3603. // -- IO
  3604. static ufbxi_noinline const char *ufbxi_refill(ufbxi_context *uc, size_t size)
  3605. {
  3606. ufbx_assert(uc->data_size < size);
  3607. ufbxi_check_return_msg(uc->read_fn, NULL, "Truncated file");
  3608. void *data_to_free = NULL;
  3609. size_t size_to_free = 0;
  3610. // Grow the read buffer if necessary, data is copied over below with the
  3611. // usual path so the free is deferred (`size_to_free`, `data_to_free`)
  3612. if (size > uc->read_buffer_size) {
  3613. size_t new_size = ufbxi_max_sz(size, uc->opts.read_buffer_size);
  3614. new_size = ufbxi_max_sz(new_size, uc->read_buffer_size * 2);
  3615. size_to_free = uc->read_buffer_size;
  3616. data_to_free = uc->read_buffer;
  3617. char *new_buffer = ufbxi_alloc(&uc->ator_tmp, char, new_size);
  3618. ufbxi_check_return(new_buffer, NULL);
  3619. uc->read_buffer = new_buffer;
  3620. uc->read_buffer_size = new_size;
  3621. }
  3622. // Copy the remains of the previous buffer to the beginning of the new one
  3623. size_t num_read = uc->data_size;
  3624. if (num_read > 0) {
  3625. memmove(uc->read_buffer, uc->data, num_read);
  3626. }
  3627. if (size_to_free) {
  3628. ufbxi_free(&uc->ator_tmp, char, data_to_free, size_to_free);
  3629. }
  3630. // Fill the rest of the buffer with user data
  3631. size_t to_read = uc->read_buffer_size - num_read;
  3632. size_t read_result = uc->read_fn(uc->read_user, uc->read_buffer + num_read, to_read);
  3633. ufbxi_check_return_msg(read_result != SIZE_MAX, NULL, "IO error");
  3634. ufbxi_check_return(read_result <= to_read, NULL);
  3635. num_read += read_result;
  3636. ufbxi_check_return_msg(num_read >= size, NULL, "Truncated file");
  3637. uc->data_offset += ufbxi_to_size(uc->data - uc->data_begin);
  3638. uc->data_begin = uc->data = uc->read_buffer;
  3639. uc->data_size = num_read;
  3640. return uc->read_buffer;
  3641. }
  3642. static ufbxi_noinline const char *ufbxi_yield(ufbxi_context *uc, size_t size)
  3643. {
  3644. const char *ret;
  3645. uc->data_size += uc->yield_size;
  3646. if (uc->data_size >= size) {
  3647. ret = uc->data;
  3648. } else {
  3649. ret = ufbxi_refill(uc, size);
  3650. }
  3651. uc->yield_size = ufbxi_min_sz(uc->data_size, ufbxi_max_sz(size, uc->progress_interval));
  3652. uc->data_size -= uc->yield_size;
  3653. ufbxi_check_return(ufbxi_report_progress(uc), NULL);
  3654. return ret;
  3655. }
  3656. static ufbxi_forceinline const char *ufbxi_peek_bytes(ufbxi_context *uc, size_t size)
  3657. {
  3658. if (uc->yield_size >= size) {
  3659. return uc->data;
  3660. } else {
  3661. return ufbxi_yield(uc, size);
  3662. }
  3663. }
  3664. static ufbxi_forceinline const char *ufbxi_read_bytes(ufbxi_context *uc, size_t size)
  3665. {
  3666. // Refill the current buffer if necessary
  3667. const char *ret;
  3668. if (uc->yield_size >= size) {
  3669. ret = uc->data;
  3670. } else {
  3671. ret = ufbxi_yield(uc, size);
  3672. if (!ret) return NULL;
  3673. }
  3674. // Advance the read position inside the current buffer
  3675. uc->yield_size -= size;
  3676. uc->data = ret + size;
  3677. return ret;
  3678. }
  3679. static ufbxi_forceinline void ufbxi_consume_bytes(ufbxi_context *uc, size_t size)
  3680. {
  3681. // Bytes must have been checked first with `ufbxi_peek_bytes()`
  3682. ufbx_assert(size <= uc->yield_size);
  3683. uc->yield_size -= size;
  3684. uc->data += size;
  3685. }
  3686. ufbxi_nodiscard static ufbxi_noinline int ufbxi_skip_bytes(ufbxi_context *uc, uint64_t size)
  3687. {
  3688. if (uc->skip_fn) {
  3689. uc->data_size += uc->yield_size;
  3690. uc->yield_size = 0;
  3691. if (size > uc->data_size) {
  3692. size -= uc->data_size;
  3693. uc->data += uc->data_size;
  3694. uc->data_size = 0;
  3695. uc->data_offset += size;
  3696. while (size >= UFBXI_MAX_SKIP_SIZE) {
  3697. size -= UFBXI_MAX_SKIP_SIZE;
  3698. ufbxi_check_msg(uc->skip_fn(uc->read_user, UFBXI_MAX_SKIP_SIZE - 1), "Truncated file");
  3699. // Check that we can read at least one byte in case the file is broken
  3700. // and causes us to seek indefinitely forwards as `fseek()` does not
  3701. // report if we hit EOF...
  3702. char single_byte[1];
  3703. size_t num_read = uc->read_fn(uc->read_user, single_byte, 1);
  3704. ufbxi_check_msg(num_read <= 1, "IO error");
  3705. ufbxi_check_msg(num_read == 1, "Truncated file");
  3706. }
  3707. if (size > 0) {
  3708. ufbxi_check_msg(uc->skip_fn(uc->read_user, (size_t)size), "Truncated file");
  3709. }
  3710. } else {
  3711. uc->data += (size_t)size;
  3712. uc->data_size -= (size_t)size;
  3713. }
  3714. uc->yield_size = ufbxi_min_sz(uc->data_size, uc->progress_interval);
  3715. uc->data_size -= uc->yield_size;
  3716. } else {
  3717. // Read and discard bytes in reasonable chunks
  3718. uint64_t skip_size = ufbxi_max64(uc->read_buffer_size, uc->opts.read_buffer_size);
  3719. while (size > 0) {
  3720. uint64_t to_skip = ufbxi_min64(size, skip_size);
  3721. ufbxi_check(ufbxi_read_bytes(uc, (size_t)to_skip));
  3722. size -= to_skip;
  3723. }
  3724. }
  3725. return 1;
  3726. }
  3727. ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_to(ufbxi_context *uc, void *dst, size_t size)
  3728. {
  3729. char *ptr = (char*)dst;
  3730. uc->data_size += uc->yield_size;
  3731. uc->yield_size = 0;
  3732. // Copy data from the current buffer first
  3733. size_t len = ufbxi_min_sz(uc->data_size, size);
  3734. memcpy(ptr, uc->data, len);
  3735. uc->data += len;
  3736. uc->data_size -= len;
  3737. ptr += len;
  3738. size -= len;
  3739. // If there's data left to copy try to read from user IO
  3740. // TODO: Progress reporting here...
  3741. if (size > 0) {
  3742. uc->data_offset += ufbxi_to_size(uc->data - uc->data_begin);
  3743. uc->data_begin = uc->data = NULL;
  3744. uc->data_size = 0;
  3745. ufbxi_check(uc->read_fn);
  3746. len = uc->read_fn(uc->read_user, ptr, size);
  3747. ufbxi_check_msg(len != SIZE_MAX, "IO error");
  3748. ufbxi_check(len == size);
  3749. uc->data_offset += size;
  3750. }
  3751. uc->yield_size = ufbxi_min_sz(uc->data_size, uc->progress_interval);
  3752. uc->data_size -= uc->yield_size;
  3753. return 1;
  3754. }
  3755. // -- File IO
  3756. static ufbxi_noinline void ufbxi_init_ator(ufbx_error *error, ufbxi_allocator *ator, const ufbx_allocator_opts *opts)
  3757. {
  3758. ufbx_allocator_opts zero_opts;
  3759. if (!opts) {
  3760. memset(&zero_opts, 0, sizeof(zero_opts));
  3761. opts = &zero_opts;
  3762. }
  3763. ator->error = error;
  3764. ator->ator = *opts;
  3765. ator->max_size = opts->memory_limit ? opts->memory_limit : SIZE_MAX;
  3766. ator->max_allocs = opts->allocation_limit ? opts->allocation_limit : SIZE_MAX;
  3767. ator->huge_size = opts->huge_threshold ? opts->huge_threshold : 0x100000;
  3768. ator->chunk_max = opts->max_chunk_size ? opts->max_chunk_size : 0x1000000;
  3769. }
  3770. static ufbxi_noinline FILE *ufbxi_fopen(const char *path, size_t path_len, ufbxi_allocator *tmp_ator)
  3771. {
  3772. #if !defined(UFBX_STANDARD_C) && defined(_WIN32)
  3773. wchar_t wpath_buf[256];
  3774. wchar_t *wpath = NULL;
  3775. if (path_len == SIZE_MAX) {
  3776. path_len = strlen(path);
  3777. }
  3778. if (path_len < ufbxi_arraycount(wpath_buf) - 1) {
  3779. wpath = wpath_buf;
  3780. } else {
  3781. wpath = ufbxi_alloc(tmp_ator, wchar_t, path_len + 1);
  3782. if (!wpath) return NULL;
  3783. }
  3784. // Convert UTF-8 to UTF-16 but allow stray surrogate pairs as the Windows
  3785. // file system encoding allows them as well..
  3786. size_t wlen = 0;
  3787. for (size_t i = 0; i < path_len; ) {
  3788. uint32_t code = UINT32_MAX;
  3789. char c = path[i++];
  3790. if ((c & 0x80) == 0) {
  3791. code = (uint32_t)c;
  3792. } else if ((c & 0xe0) == 0xc0) {
  3793. code = (uint32_t)(c & 0x1f);
  3794. if (i < path_len) code = code << 6 | (uint32_t)(path[i++] & 0x3f);
  3795. } else if ((c & 0xf0) == 0xe0) {
  3796. code = (uint32_t)(c & 0x0f);
  3797. if (i < path_len) code = code << 6 | (uint32_t)(path[i++] & 0x3f);
  3798. if (i < path_len) code = code << 6 | (uint32_t)(path[i++] & 0x3f);
  3799. } else if ((c & 0xf8) == 0xf0) {
  3800. code = (uint32_t)(c & 0x07);
  3801. if (i < path_len) code = code << 6 | (uint32_t)(path[i++] & 0x3f);
  3802. if (i < path_len) code = code << 6 | (uint32_t)(path[i++] & 0x3f);
  3803. if (i < path_len) code = code << 6 | (uint32_t)(path[i++] & 0x3f);
  3804. }
  3805. if (code < 0x10000) {
  3806. wpath[wlen++] = (wchar_t)code;
  3807. } else {
  3808. code -= 0x10000;
  3809. wpath[wlen++] = (wchar_t)(0xd800 + (code >> 10));
  3810. wpath[wlen++] = (wchar_t)(0xdc00 + (code & 0x3ff));
  3811. }
  3812. }
  3813. wpath[wlen] = 0;
  3814. FILE *file = NULL;
  3815. #if defined(_MSC_VER) && _MSC_VER >= 1400
  3816. if (_wfopen_s(&file, wpath, L"rb") != 0) {
  3817. file = NULL;
  3818. }
  3819. #else
  3820. file = _wfopen(wpath, L"rb");
  3821. #endif
  3822. if (wpath != wpath_buf) {
  3823. ufbxi_free(tmp_ator, wchar_t, wpath, path_len + 1);
  3824. }
  3825. return file;
  3826. #else
  3827. if (path_len == SIZE_MAX) {
  3828. return fopen(path, "rb");
  3829. }
  3830. char copy_buf[256];
  3831. char *copy = NULL;
  3832. if (path_len < ufbxi_arraycount(copy_buf) - 1) {
  3833. copy = copy_buf;
  3834. } else {
  3835. copy = ufbxi_alloc(tmp_ator, char, path_len + 1);
  3836. if (!copy) return NULL;
  3837. }
  3838. memcpy(copy, path, path_len);
  3839. copy[path_len] = '\0';
  3840. FILE *file = fopen(copy, "rb");
  3841. if (copy != copy_buf) {
  3842. ufbxi_free(tmp_ator, char, copy, path_len + 1);
  3843. }
  3844. return file;
  3845. #endif
  3846. }
  3847. static uint64_t ufbxi_ftell(FILE *file)
  3848. {
  3849. #if !defined(UFBX_STANDARD_C) && defined(UFBX_HAS_FTELLO)
  3850. off_t result = ftello(file);
  3851. if (result >= 0) return (uint64_t)result;
  3852. #elif !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
  3853. int64_t result = _ftelli64(file);
  3854. if (result >= 0) return (uint64_t)result;
  3855. #else
  3856. long result = ftell(file);
  3857. if (result >= 0) return (uint64_t)result;
  3858. #endif
  3859. return UINT64_MAX;
  3860. }
  3861. static size_t ufbxi_file_read(void *user, void *data, size_t max_size)
  3862. {
  3863. FILE *file = (FILE*)user;
  3864. if (ferror(file)) return SIZE_MAX;
  3865. return fread(data, 1, max_size, file);
  3866. }
  3867. static bool ufbxi_file_skip(void *user, size_t size)
  3868. {
  3869. FILE *file = (FILE*)user;
  3870. ufbx_assert(size <= UFBXI_MAX_SKIP_SIZE);
  3871. if (fseek(file, (long)size, SEEK_CUR) != 0) return false;
  3872. if (ferror(file)) return false;
  3873. return true;
  3874. }
  3875. static void ufbxi_file_close(void *user)
  3876. {
  3877. FILE *file = (FILE*)user;
  3878. fclose(file);
  3879. }
  3880. // -- XML
  3881. #if UFBXI_FEATURE_XML
  3882. typedef struct ufbxi_xml_tag ufbxi_xml_tag;
  3883. typedef struct ufbxi_xml_attrib ufbxi_xml_attrib;
  3884. typedef struct ufbxi_xml_document ufbxi_xml_document;
  3885. struct ufbxi_xml_attrib {
  3886. ufbx_string name;
  3887. ufbx_string value;
  3888. };
  3889. struct ufbxi_xml_tag {
  3890. ufbx_string name;
  3891. ufbx_string text;
  3892. ufbxi_xml_attrib *attribs;
  3893. size_t num_attribs;
  3894. ufbxi_xml_tag *children;
  3895. size_t num_children;
  3896. };
  3897. struct ufbxi_xml_document {
  3898. ufbxi_xml_tag *root;
  3899. ufbxi_buf buf;
  3900. };
  3901. typedef struct {
  3902. ufbx_error error;
  3903. ufbxi_allocator *ator;
  3904. ufbxi_buf tmp_stack;
  3905. ufbxi_buf result;
  3906. ufbxi_xml_document *doc;
  3907. ufbx_read_fn *read_fn;
  3908. void *read_user;
  3909. char *tok;
  3910. size_t tok_cap;
  3911. size_t tok_len;
  3912. const char *pos, *pos_end;
  3913. char data[4096];
  3914. bool io_error;
  3915. size_t depth;
  3916. } ufbxi_xml_context;
  3917. enum {
  3918. UFBXI_XML_CTYPE_WHITESPACE = 0x1,
  3919. UFBXI_XML_CTYPE_SINGLE_QUOTE = 0x2,
  3920. UFBXI_XML_CTYPE_DOUBLE_QUOTE = 0x4,
  3921. UFBXI_XML_CTYPE_NAME_END = 0x8,
  3922. UFBXI_XML_CTYPE_TAG_START = 0x10,
  3923. UFBXI_XML_CTYPE_END_OF_FILE = 0x20,
  3924. };
  3925. // Generated by `misc/gen_xml_ctype.py`
  3926. static const uint8_t ufbxi_xml_ctype[256] = {
  3927. 32,0,0,0,0,0,0,0,0,9,9,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  3928. 9,0,12,0,0,0,0,10,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,16,8,8,8,
  3929. };
  3930. static ufbxi_noinline void ufbxi_xml_refill(ufbxi_xml_context *xc)
  3931. {
  3932. size_t num = xc->read_fn(xc->read_user, xc->data, sizeof(xc->data));
  3933. if (num == SIZE_MAX || num < sizeof(xc->data)) xc->io_error = true;
  3934. if (num < sizeof(xc->data)) {
  3935. xc->data[num++] = '\0';
  3936. }
  3937. xc->pos = xc->data;
  3938. xc->pos_end = xc->data + num;
  3939. }
  3940. static ufbxi_forceinline void ufbxi_xml_advance(ufbxi_xml_context *xc)
  3941. {
  3942. if (++xc->pos == xc->pos_end) ufbxi_xml_refill(xc);
  3943. }
  3944. ufbxi_nodiscard static ufbxi_noinline int ufbxi_xml_push_token_char(ufbxi_xml_context *xc, char c)
  3945. {
  3946. if (xc->tok_len == xc->tok_cap) {
  3947. ufbxi_check_err(&xc->error, ufbxi_grow_array(xc->ator, &xc->tok, &xc->tok_cap, xc->tok_len + 1));
  3948. }
  3949. xc->tok[xc->tok_len++] = c;
  3950. return 1;
  3951. }
  3952. static ufbxi_noinline int ufbxi_xml_accept(ufbxi_xml_context *xc, char ch)
  3953. {
  3954. if (*xc->pos == ch) {
  3955. ufbxi_xml_advance(xc);
  3956. return 1;
  3957. } else {
  3958. return 0;
  3959. }
  3960. }
  3961. static ufbxi_noinline void ufbxi_xml_skip_while(ufbxi_xml_context *xc, uint32_t ctypes)
  3962. {
  3963. while (ufbxi_xml_ctype[(uint8_t)*xc->pos] & ctypes) {
  3964. ufbxi_xml_advance(xc);
  3965. }
  3966. }
  3967. ufbxi_nodiscard static ufbxi_noinline int ufbxi_xml_skip_until_string(ufbxi_xml_context *xc, ufbx_string *dst, const char *suffix)
  3968. {
  3969. xc->tok_len = 0;
  3970. size_t match_len = 0, ix = 0, suffix_len = strlen(suffix);
  3971. char buf[16] = { 0 };
  3972. size_t wrap_mask = sizeof(buf) - 1;
  3973. ufbx_assert(suffix_len < sizeof(buf));
  3974. for (;;) {
  3975. char c = *xc->pos;
  3976. ufbxi_check_err_msg(&xc->error, c != 0, "Truncated file");
  3977. ufbxi_xml_advance(xc);
  3978. if (ix >= suffix_len) {
  3979. ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, buf[(ix - suffix_len) & wrap_mask]));
  3980. }
  3981. buf[ix++ & wrap_mask] = c;
  3982. for (match_len = 0; match_len < suffix_len; match_len++) {
  3983. if (buf[(ix - suffix_len + match_len) & wrap_mask] != suffix[match_len]) {
  3984. break;
  3985. }
  3986. }
  3987. if (match_len == suffix_len) break;
  3988. }
  3989. ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, '\0'));
  3990. if (dst) {
  3991. dst->length = xc->tok_len - 1;
  3992. dst->data = ufbxi_push_copy(&xc->result, char, xc->tok_len, xc->tok);
  3993. ufbxi_check_err(&xc->error, dst->data);
  3994. }
  3995. return 1;
  3996. }
  3997. static ufbxi_noinline int ufbxi_xml_read_until(ufbxi_xml_context *xc, ufbx_string *dst, uint32_t ctypes)
  3998. {
  3999. xc->tok_len = 0;
  4000. for (;;) {
  4001. char c = *xc->pos;
  4002. if (c == '&') {
  4003. size_t entity_begin = xc->tok_len;
  4004. for (;;) {
  4005. ufbxi_xml_advance(xc);
  4006. c = *xc->pos;
  4007. ufbxi_check_err(&xc->error, c != '\0');
  4008. if (c == ';') break;
  4009. ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, c));
  4010. }
  4011. ufbxi_xml_advance(xc);
  4012. ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, '\0'));
  4013. char *entity = xc->tok + entity_begin;
  4014. xc->tok_len = entity_begin;
  4015. if (entity[0] == '#') {
  4016. unsigned long code = 0;
  4017. if (entity[1] == 'x') {
  4018. code = strtoul(entity + 2, NULL, 16);
  4019. } else {
  4020. code = strtoul(entity + 1, NULL, 10);
  4021. }
  4022. char bytes[5] = { 0 };
  4023. if (code < 0x80) {
  4024. bytes[0] = (char)code;
  4025. } else if (code < 0x800) {
  4026. bytes[0] = (char)(0xc0 | (code>>6));
  4027. bytes[1] = (char)(0x80 | (code & 0x3f));
  4028. } else if (code < 0x10000) {
  4029. bytes[0] = (char)(0xe0 | (code>>12));
  4030. bytes[1] = (char)(0x80 | ((code>>6) & 0x3f));
  4031. bytes[2] = (char)(0x80 | (code & 0x3f));
  4032. } else {
  4033. bytes[0] = (char)(0xf0 | (code>>18));
  4034. bytes[1] = (char)(0x80 | ((code>>12) & 0x3f));
  4035. bytes[2] = (char)(0x80 | ((code>>6) & 0x3f));
  4036. bytes[3] = (char)(0x80 | (code & 0x3f));
  4037. }
  4038. for (char *b = bytes; *b; b++) {
  4039. ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, *b));
  4040. }
  4041. } else {
  4042. char ch = '\0';
  4043. if (!strcmp(entity, "lt")) ch = '<';
  4044. else if (!strcmp(entity, "quot")) ch = '"';
  4045. else if (!strcmp(entity, "amp")) ch = '&';
  4046. else if (!strcmp(entity, "apos")) ch = '\'';
  4047. else if (!strcmp(entity, "gt")) ch = '>';
  4048. if (ch) {
  4049. ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, ch));
  4050. }
  4051. }
  4052. } else {
  4053. if ((ufbxi_xml_ctype[(uint8_t)c] & ctypes) != 0) break;
  4054. ufbxi_check_err_msg(&xc->error, c != 0, "Truncated file");
  4055. ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, c));
  4056. ufbxi_xml_advance(xc);
  4057. }
  4058. }
  4059. ufbxi_check_err(&xc->error, ufbxi_xml_push_token_char(xc, '\0'));
  4060. if (dst) {
  4061. dst->length = xc->tok_len - 1;
  4062. dst->data = ufbxi_push_copy(&xc->result, char, xc->tok_len, xc->tok);
  4063. ufbxi_check_err(&xc->error, dst->data);
  4064. }
  4065. return 1;
  4066. }
  4067. static ufbxi_noinline int ufbxi_xml_parse_tag(ufbxi_xml_context *xc, bool *p_closing, const char *opening)
  4068. {
  4069. if (!ufbxi_xml_accept(xc, '<')) {
  4070. if (*xc->pos == '\0') {
  4071. *p_closing = true;
  4072. } else {
  4073. ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, NULL, UFBXI_XML_CTYPE_TAG_START | UFBXI_XML_CTYPE_END_OF_FILE));
  4074. bool has_text = false;
  4075. for (size_t i = 0; i < xc->tok_len; i++) {
  4076. if ((ufbxi_xml_ctype[(uint8_t)xc->tok[i]] & UFBXI_XML_CTYPE_WHITESPACE) == 0) {
  4077. has_text = true;
  4078. break;
  4079. }
  4080. }
  4081. if (has_text) {
  4082. ufbxi_xml_tag *tag = ufbxi_push_zero(&xc->tmp_stack, ufbxi_xml_tag, 1);
  4083. ufbxi_check_err(&xc->error, tag);
  4084. tag->name.data = ufbxi_empty_char;
  4085. tag->text.length = xc->tok_len - 1;
  4086. tag->text.data = ufbxi_push_copy(&xc->result, char, xc->tok_len, xc->tok);
  4087. ufbxi_check_err(&xc->error, tag->text.data);
  4088. }
  4089. }
  4090. return 1;
  4091. }
  4092. if (ufbxi_xml_accept(xc, '/')) {
  4093. ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, NULL, UFBXI_XML_CTYPE_NAME_END));
  4094. ufbxi_check_err(&xc->error, opening && !strcmp(xc->tok, opening));
  4095. ufbxi_xml_skip_while(xc, UFBXI_XML_CTYPE_WHITESPACE);
  4096. if (!ufbxi_xml_accept(xc, '>')) return 0;
  4097. *p_closing = true;
  4098. return 1;
  4099. } else if (ufbxi_xml_accept(xc, '!')) {
  4100. if (ufbxi_xml_accept(xc, '[')) {
  4101. for (const char *ch = "CDATA["; *ch; ch++) {
  4102. if (!ufbxi_xml_accept(xc, *ch)) return 0;
  4103. }
  4104. ufbxi_xml_tag *tag = ufbxi_push_zero(&xc->tmp_stack, ufbxi_xml_tag, 1);
  4105. ufbxi_check_err(&xc->error, tag);
  4106. ufbxi_check_err(&xc->error, ufbxi_xml_skip_until_string(xc, &tag->text, "]]>"));
  4107. tag->name.data = ufbxi_empty_char;
  4108. } else if (ufbxi_xml_accept(xc, '-')) {
  4109. if (!ufbxi_xml_accept(xc, '-')) return 0;
  4110. ufbxi_check_err(&xc->error, ufbxi_xml_skip_until_string(xc, NULL, "-->"));
  4111. } else {
  4112. // TODO: !DOCTYPE
  4113. ufbxi_check_err(&xc->error, ufbxi_xml_skip_until_string(xc, NULL, ">"));
  4114. }
  4115. return 1;
  4116. } else if (ufbxi_xml_accept(xc, '?')) {
  4117. ufbxi_check_err(&xc->error, ufbxi_xml_skip_until_string(xc, NULL, "?>"));
  4118. return 1;
  4119. }
  4120. ufbxi_xml_tag *tag = ufbxi_push_zero(&xc->tmp_stack, ufbxi_xml_tag, 1);
  4121. ufbxi_check_err(&xc->error, tag);
  4122. ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, &tag->name, UFBXI_XML_CTYPE_NAME_END));
  4123. tag->text.data = ufbxi_empty_char;
  4124. bool has_children = false;
  4125. size_t num_attribs = 0;
  4126. for (;;) {
  4127. ufbxi_xml_skip_while(xc, UFBXI_XML_CTYPE_WHITESPACE);
  4128. if (ufbxi_xml_accept(xc, '/')) {
  4129. if (!ufbxi_xml_accept(xc, '>')) return 0;
  4130. break;
  4131. } else if (ufbxi_xml_accept(xc, '>')) {
  4132. has_children = true;
  4133. break;
  4134. } else {
  4135. ufbxi_xml_attrib *attrib = ufbxi_push_zero(&xc->tmp_stack, ufbxi_xml_attrib, 1);
  4136. ufbxi_check_err(&xc->error, attrib);
  4137. ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, &attrib->name, UFBXI_XML_CTYPE_NAME_END));
  4138. ufbxi_xml_skip_while(xc, UFBXI_XML_CTYPE_WHITESPACE);
  4139. if (!ufbxi_xml_accept(xc, '=')) return 0;
  4140. ufbxi_xml_skip_while(xc, UFBXI_XML_CTYPE_WHITESPACE);
  4141. uint32_t quote_ctype = 0;
  4142. if (ufbxi_xml_accept(xc, '"')) {
  4143. quote_ctype = UFBXI_XML_CTYPE_DOUBLE_QUOTE;
  4144. } else if (ufbxi_xml_accept(xc, '\'')) {
  4145. quote_ctype = UFBXI_XML_CTYPE_SINGLE_QUOTE;
  4146. } else {
  4147. ufbxi_fail_err(&xc->error, "Bad attrib value");
  4148. }
  4149. ufbxi_check_err(&xc->error, ufbxi_xml_read_until(xc, &attrib->value, quote_ctype));
  4150. ufbxi_xml_advance(xc);
  4151. num_attribs++;
  4152. }
  4153. }
  4154. tag->num_attribs = num_attribs;
  4155. tag->attribs = ufbxi_push_pop(&xc->result, &xc->tmp_stack, ufbxi_xml_attrib, num_attribs);
  4156. ufbxi_check_err(&xc->error, tag->attribs);
  4157. if (has_children) {
  4158. size_t children_begin = xc->tmp_stack.num_items;
  4159. for (;;) {
  4160. bool closing = false;
  4161. ufbxi_check_err(&xc->error, ufbxi_xml_parse_tag(xc, &closing, tag->name.data));
  4162. if (closing) break;
  4163. }
  4164. tag->num_children = xc->tmp_stack.num_items - children_begin;
  4165. tag->children = ufbxi_push_pop(&xc->result, &xc->tmp_stack, ufbxi_xml_tag, tag->num_children);
  4166. ufbxi_check_err(&xc->error, tag->children);
  4167. }
  4168. return 1;
  4169. }
  4170. static ufbxi_noinline int ufbxi_xml_parse_root(ufbxi_xml_context *xc)
  4171. {
  4172. ufbxi_xml_tag *tag = ufbxi_push_zero(&xc->result, ufbxi_xml_tag, 1);
  4173. ufbxi_check_err(&xc->error, tag);
  4174. tag->name.data = ufbxi_empty_char;
  4175. tag->text.data = ufbxi_empty_char;
  4176. for (;;) {
  4177. bool closing = false;
  4178. ufbxi_check_err(&xc->error, ufbxi_xml_parse_tag(xc, &closing, NULL));
  4179. if (closing) break;
  4180. }
  4181. tag->num_children = xc->tmp_stack.num_items;
  4182. tag->children = ufbxi_push_pop(&xc->result, &xc->tmp_stack, ufbxi_xml_tag, tag->num_children);
  4183. ufbxi_check_err(&xc->error, tag->children);
  4184. xc->doc = ufbxi_push(&xc->result, ufbxi_xml_document, 1);
  4185. ufbxi_check_err(&xc->error, xc->doc);
  4186. xc->doc->root = tag;
  4187. xc->doc->buf = xc->result;
  4188. return 1;
  4189. }
  4190. typedef struct {
  4191. ufbxi_allocator *ator;
  4192. ufbx_read_fn *read_fn;
  4193. void *read_user;
  4194. const char *prefix;
  4195. size_t prefix_length;
  4196. } ufbxi_xml_load_opts;
  4197. static ufbxi_noinline ufbxi_xml_document *ufbxi_load_xml(ufbxi_xml_load_opts *opts, ufbx_error *error)
  4198. {
  4199. ufbxi_xml_context xc = { UFBX_ERROR_NONE };
  4200. xc.ator = opts->ator;
  4201. xc.read_fn = opts->read_fn;
  4202. xc.read_user = opts->read_user;
  4203. xc.tmp_stack.ator = xc.ator;
  4204. xc.result.ator = xc.ator;
  4205. xc.result.unordered = true;
  4206. if (opts->prefix_length > 0) {
  4207. xc.pos = opts->prefix;
  4208. xc.pos_end = opts->prefix + opts->prefix_length;
  4209. } else {
  4210. ufbxi_xml_refill(&xc);
  4211. }
  4212. int ok = ufbxi_xml_parse_root(&xc);
  4213. ufbxi_buf_free(&xc.tmp_stack);
  4214. ufbxi_free(xc.ator, char, xc.tok, xc.tok_cap);
  4215. if (ok) {
  4216. return xc.doc;
  4217. } else {
  4218. ufbxi_buf_free(&xc.result);
  4219. if (error) {
  4220. *error = xc.error;
  4221. }
  4222. return NULL;
  4223. }
  4224. }
  4225. static ufbxi_noinline void ufbxi_free_xml(ufbxi_xml_document *doc)
  4226. {
  4227. ufbxi_buf buf = doc->buf;
  4228. ufbxi_buf_free(&buf);
  4229. }
  4230. static ufbxi_noinline ufbxi_xml_tag *ufbxi_xml_find_child(ufbxi_xml_tag *tag, const char *name)
  4231. {
  4232. ufbxi_for(ufbxi_xml_tag, child, tag->children, tag->num_children) {
  4233. if (!strcmp(child->name.data, name)) {
  4234. return child;
  4235. }
  4236. }
  4237. return NULL;
  4238. }
  4239. static ufbxi_noinline ufbxi_xml_attrib *ufbxi_xml_find_attrib(ufbxi_xml_tag *tag, const char *name)
  4240. {
  4241. ufbxi_for(ufbxi_xml_attrib, attrib, tag->attribs, tag->num_attribs) {
  4242. if (!strcmp(attrib->name.data, name)) {
  4243. return attrib;
  4244. }
  4245. }
  4246. return NULL;
  4247. }
  4248. #endif
  4249. // -- FBX value type information
  4250. static char ufbxi_normalize_array_type(char type) {
  4251. switch (type) {
  4252. case 'r': return sizeof(ufbx_real) == sizeof(float) ? 'f' : 'd';
  4253. case 'b': return 'c';
  4254. default: return type;
  4255. }
  4256. }
  4257. static ufbxi_noinline size_t ufbxi_array_type_size(char type)
  4258. {
  4259. switch (type) {
  4260. case 'r': return sizeof(ufbx_real);
  4261. case 'b': return sizeof(bool);
  4262. case 'c': return sizeof(uint8_t);
  4263. case 'i': return sizeof(int32_t);
  4264. case 'l': return sizeof(int64_t);
  4265. case 'f': return sizeof(float);
  4266. case 'd': return sizeof(double);
  4267. case 's': return sizeof(ufbx_string);
  4268. case 'S': return sizeof(ufbx_string);
  4269. case 'C': return sizeof(ufbx_string);
  4270. default: return 1;
  4271. }
  4272. }
  4273. // -- Node operations
  4274. static ufbxi_noinline ufbxi_node *ufbxi_find_child(ufbxi_node *node, const char *name)
  4275. {
  4276. ufbxi_for(ufbxi_node, c, node->children, node->num_children) {
  4277. if (c->name == name) return c;
  4278. }
  4279. return NULL;
  4280. }
  4281. // Retrieve values from nodes with type codes:
  4282. // Any: '_' (ignore)
  4283. // NUMBER: 'I' int32_t 'L' int64_t 'F' float 'D' double 'R' ufbxi_real 'B' bool 'Z' size_t
  4284. // STRING: 'S' ufbx_string 'C' const char* (checked) 's' ufbx_string 'c' const char * (unchecked) 'b' ufbx_blob
  4285. ufbxi_nodiscard ufbxi_forceinline static int ufbxi_get_val_at(ufbxi_node *node, size_t ix, char fmt, void *v)
  4286. {
  4287. ufbxi_dev_assert(ix < UFBXI_MAX_NON_ARRAY_VALUES);
  4288. ufbxi_value_type type = (ufbxi_value_type)((node->value_type_mask >> (ix*2)) & 0x3);
  4289. switch (fmt) {
  4290. case '_': return 1;
  4291. case 'I': if (type == UFBXI_VALUE_NUMBER) { *(int32_t*)v = (int32_t)node->vals[ix].i; return 1; } else return 0;
  4292. case 'L': if (type == UFBXI_VALUE_NUMBER) { *(int64_t*)v = (int64_t)node->vals[ix].i; return 1; } else return 0;
  4293. case 'F': if (type == UFBXI_VALUE_NUMBER) { *(float*)v = (float)node->vals[ix].f; return 1; } else return 0;
  4294. case 'D': if (type == UFBXI_VALUE_NUMBER) { *(double*)v = (double)node->vals[ix].f; return 1; } else return 0;
  4295. case 'R': if (type == UFBXI_VALUE_NUMBER) { *(ufbx_real*)v = (ufbx_real)node->vals[ix].f; return 1; } else return 0;
  4296. case 'B': if (type == UFBXI_VALUE_NUMBER) { *(bool*)v = node->vals[ix].i != 0; return 1; } else return 0;
  4297. case 'Z': if (type == UFBXI_VALUE_NUMBER) { if (node->vals[ix].i < 0) return 0; *(size_t*)v = (size_t)node->vals[ix].i; return 1; } else return 0;
  4298. case 'S': if (type == UFBXI_VALUE_STRING) {
  4299. ufbxi_sanitized_string src = node->vals[ix].s;
  4300. ufbx_string *dst = (ufbx_string*)v;
  4301. if (src.utf8_length > 0) {
  4302. if (src.utf8_length == UINT32_MAX) return 0;
  4303. dst->data = src.raw_data + src.raw_length + 1;
  4304. dst->length = src.utf8_length;
  4305. } else {
  4306. dst->data = src.raw_data;
  4307. dst->length = src.raw_length;
  4308. }
  4309. return 1;
  4310. } else return 0;
  4311. case 's': if (type == UFBXI_VALUE_STRING) {
  4312. ufbxi_sanitized_string src = node->vals[ix].s;
  4313. ufbx_string *dst = (ufbx_string*)v;
  4314. dst->data = src.raw_data;
  4315. dst->length = src.raw_length;
  4316. return 1;
  4317. } else return 0;
  4318. case 'C': if (type == UFBXI_VALUE_STRING) {
  4319. ufbxi_sanitized_string src = node->vals[ix].s;
  4320. const char **dst = (const char **)v;
  4321. if (src.utf8_length > 0) {
  4322. if (src.utf8_length == UINT32_MAX) return 0;
  4323. *dst = src.raw_data + src.raw_length + 1;
  4324. } else {
  4325. *dst = src.raw_data;
  4326. }
  4327. return 1;
  4328. } else return 0;
  4329. case 'c': if (type == UFBXI_VALUE_STRING) {
  4330. ufbxi_sanitized_string src = node->vals[ix].s;
  4331. const char **dst = (const char **)v;
  4332. *dst = src.raw_data;
  4333. return 1;
  4334. } else return 0;
  4335. case 'b': if (type == UFBXI_VALUE_STRING) {
  4336. ufbxi_sanitized_string src = node->vals[ix].s;
  4337. ufbx_blob *dst = (ufbx_blob*)v;
  4338. dst->data = src.raw_data;
  4339. dst->size = src.raw_length;
  4340. return 1;
  4341. } else return 0;
  4342. default:
  4343. ufbx_assert(0 && "Bad format char");
  4344. return 0;
  4345. }
  4346. }
  4347. ufbxi_nodiscard ufbxi_noinline static ufbxi_value_array *ufbxi_get_array(ufbxi_node *node, char fmt)
  4348. {
  4349. if (node->value_type_mask != UFBXI_VALUE_ARRAY) return NULL;
  4350. ufbxi_value_array *array = node->array;
  4351. if (fmt != '?') {
  4352. fmt = ufbxi_normalize_array_type(fmt);
  4353. if (array->type != fmt) return NULL;
  4354. }
  4355. return array;
  4356. }
  4357. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val1(ufbxi_node *node, const char *fmt, void *v0)
  4358. {
  4359. if (!ufbxi_get_val_at(node, 0, fmt[0], v0)) return 0;
  4360. return 1;
  4361. }
  4362. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val2(ufbxi_node *node, const char *fmt, void *v0, void *v1)
  4363. {
  4364. if (!ufbxi_get_val_at(node, 0, fmt[0], v0)) return 0;
  4365. if (!ufbxi_get_val_at(node, 1, fmt[1], v1)) return 0;
  4366. return 1;
  4367. }
  4368. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val3(ufbxi_node *node, const char *fmt, void *v0, void *v1, void *v2)
  4369. {
  4370. if (!ufbxi_get_val_at(node, 0, fmt[0], v0)) return 0;
  4371. if (!ufbxi_get_val_at(node, 1, fmt[1], v1)) return 0;
  4372. if (!ufbxi_get_val_at(node, 2, fmt[2], v2)) return 0;
  4373. return 1;
  4374. }
  4375. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val4(ufbxi_node *node, const char *fmt, void *v0, void *v1, void *v2, void *v3)
  4376. {
  4377. if (!ufbxi_get_val_at(node, 0, fmt[0], v0)) return 0;
  4378. if (!ufbxi_get_val_at(node, 1, fmt[1], v1)) return 0;
  4379. if (!ufbxi_get_val_at(node, 2, fmt[2], v2)) return 0;
  4380. if (!ufbxi_get_val_at(node, 3, fmt[3], v3)) return 0;
  4381. return 1;
  4382. }
  4383. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_get_val5(ufbxi_node *node, const char *fmt, void *v0, void *v1, void *v2, void *v3, void *v4)
  4384. {
  4385. if (!ufbxi_get_val_at(node, 0, fmt[0], v0)) return 0;
  4386. if (!ufbxi_get_val_at(node, 1, fmt[1], v1)) return 0;
  4387. if (!ufbxi_get_val_at(node, 2, fmt[2], v2)) return 0;
  4388. if (!ufbxi_get_val_at(node, 3, fmt[3], v3)) return 0;
  4389. if (!ufbxi_get_val_at(node, 4, fmt[4], v4)) return 0;
  4390. return 1;
  4391. }
  4392. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_find_val1(ufbxi_node *node, const char *name, const char *fmt, void *v0)
  4393. {
  4394. ufbxi_node *child = ufbxi_find_child(node, name);
  4395. if (!child) return 0;
  4396. if (!ufbxi_get_val_at(child, 0, fmt[0], v0)) return 0;
  4397. return 1;
  4398. }
  4399. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_find_val2(ufbxi_node *node, const char *name, const char *fmt, void *v0, void *v1)
  4400. {
  4401. ufbxi_node *child = ufbxi_find_child(node, name);
  4402. if (!child) return 0;
  4403. if (!ufbxi_get_val_at(child, 0, fmt[0], v0)) return 0;
  4404. if (!ufbxi_get_val_at(child, 1, fmt[1], v1)) return 0;
  4405. return 1;
  4406. }
  4407. ufbxi_nodiscard static ufbxi_noinline ufbxi_value_array *ufbxi_find_array(ufbxi_node *node, const char *name, char fmt)
  4408. {
  4409. ufbxi_node *child = ufbxi_find_child(node, name);
  4410. if (!child) return NULL;
  4411. return ufbxi_get_array(child, fmt);
  4412. }
  4413. static ufbxi_node *ufbxi_find_child_strcmp(ufbxi_node *node, const char *name)
  4414. {
  4415. char leading = name[0];
  4416. ufbxi_for(ufbxi_node, c, node->children, node->num_children) {
  4417. if (c->name[0] != leading) continue;
  4418. if (!strcmp(c->name, name)) return c;
  4419. }
  4420. return NULL;
  4421. }
  4422. // -- Element extra data allocation
  4423. ufbxi_nodiscard static ufbxi_noinline void *ufbxi_push_element_extra_size(ufbxi_context *uc, uint32_t id, size_t size)
  4424. {
  4425. void *extra = ufbxi_push_size_zero(&uc->tmp, size, 1);
  4426. ufbxi_check_return(extra, NULL);
  4427. if (uc->element_extra_cap <= id) {
  4428. size_t old_cap = uc->element_extra_cap;
  4429. ufbxi_check_return(ufbxi_grow_array(&uc->ator_tmp, &uc->element_extra_arr, &uc->element_extra_cap, id + 1), NULL);
  4430. memset(uc->element_extra_arr + old_cap, 0, (uc->element_extra_cap - old_cap) * sizeof(void*));
  4431. }
  4432. ufbx_assert(uc->element_extra_arr[id] == NULL);
  4433. uc->element_extra_arr[id] = extra;
  4434. return extra;
  4435. }
  4436. static ufbxi_noinline void *ufbxi_get_element_extra(ufbxi_context *uc, uint32_t id)
  4437. {
  4438. if (id < uc->element_extra_cap) {
  4439. return uc->element_extra_arr[id];
  4440. } else {
  4441. return NULL;
  4442. }
  4443. }
  4444. #define ufbxi_push_element_extra(uc, id, type) (type*)ufbxi_push_element_extra_size((uc), (id), sizeof(type))
  4445. // -- Parsing state machine
  4446. //
  4447. // When reading the file we maintain a coarse representation of the structure so
  4448. // that we can resolve array info (type, included in result, etc). Using this info
  4449. // we can often read/decompress the contents directly into the right memory area.
  4450. typedef enum {
  4451. UFBXI_PARSE_ROOT,
  4452. UFBXI_PARSE_FBX_HEADER_EXTENSION,
  4453. UFBXI_PARSE_DEFINITIONS,
  4454. UFBXI_PARSE_OBJECTS,
  4455. UFBXI_PARSE_CONNECTIONS,
  4456. UFBXI_PARSE_RELATIONS,
  4457. UFBXI_PARSE_TAKES,
  4458. UFBXI_PARSE_FBX_VERSION,
  4459. UFBXI_PARSE_MODEL,
  4460. UFBXI_PARSE_GEOMETRY,
  4461. UFBXI_PARSE_NODE_ATTRIBUTE,
  4462. UFBXI_PARSE_LEGACY_MODEL,
  4463. UFBXI_PARSE_LEGACY_SWITCHER,
  4464. UFBXI_PARSE_LEGACY_SCENE_PERSISTENCE,
  4465. UFBXI_PARSE_REFERENCES,
  4466. UFBXI_PARSE_REFERENCE,
  4467. UFBXI_PARSE_ANIMATION_CURVE,
  4468. UFBXI_PARSE_DEFORMER,
  4469. UFBXI_PARSE_ASSOCIATE_MODEL,
  4470. UFBXI_PARSE_LEGACY_LINK,
  4471. UFBXI_PARSE_POSE,
  4472. UFBXI_PARSE_POSE_NODE,
  4473. UFBXI_PARSE_TEXTURE,
  4474. UFBXI_PARSE_VIDEO,
  4475. UFBXI_PARSE_LAYERED_TEXTURE,
  4476. UFBXI_PARSE_SELECTION_NODE,
  4477. UFBXI_PARSE_COLLECTION,
  4478. UFBXI_PARSE_UNKNOWN_OBJECT,
  4479. UFBXI_PARSE_LAYER_ELEMENT_NORMAL,
  4480. UFBXI_PARSE_LAYER_ELEMENT_BINORMAL,
  4481. UFBXI_PARSE_LAYER_ELEMENT_TANGENT,
  4482. UFBXI_PARSE_LAYER_ELEMENT_UV,
  4483. UFBXI_PARSE_LAYER_ELEMENT_COLOR,
  4484. UFBXI_PARSE_LAYER_ELEMENT_VERTEX_CREASE,
  4485. UFBXI_PARSE_LAYER_ELEMENT_EDGE_CREASE,
  4486. UFBXI_PARSE_LAYER_ELEMENT_SMOOTHING,
  4487. UFBXI_PARSE_LAYER_ELEMENT_VISIBILITY,
  4488. UFBXI_PARSE_LAYER_ELEMENT_POLYGON_GROUP,
  4489. UFBXI_PARSE_LAYER_ELEMENT_HOLE,
  4490. UFBXI_PARSE_LAYER_ELEMENT_MATERIAL,
  4491. UFBXI_PARSE_LAYER_ELEMENT_OTHER,
  4492. UFBXI_PARSE_GEOMETRY_UV_INFO,
  4493. UFBXI_PARSE_SHAPE,
  4494. UFBXI_PARSE_TAKE,
  4495. UFBXI_PARSE_TAKE_OBJECT,
  4496. UFBXI_PARSE_CHANNEL,
  4497. UFBXI_PARSE_UNKNOWN,
  4498. } ufbxi_parse_state;
  4499. typedef enum {
  4500. UFBXI_ARRAY_FLAG_RESULT = 0x1, // < Alloacte the array from the result buffer
  4501. UFBXI_ARRAY_FLAG_TMP_BUF = 0x2, // < Alloacte the array from the result buffer
  4502. UFBXI_ARRAY_FLAG_PAD_BEGIN = 0x4, // < Pad the begin of the array with 4 zero elements to guard from invalid -1 index accesses
  4503. } ufbxi_array_flags;
  4504. typedef struct {
  4505. char type; // < FBX type code of the array: b,i,l,f,d (or 'r' meaning ufbx_real '-' ignore, 's'/'S' for strings, 'C' for content)
  4506. uint8_t flags; // < Combination of `ufbxi_array_flags`
  4507. } ufbxi_array_info;
  4508. static ufbxi_noinline ufbxi_parse_state ufbxi_update_parse_state(ufbxi_parse_state parent, const char *name)
  4509. {
  4510. switch (parent) {
  4511. case UFBXI_PARSE_ROOT:
  4512. if (name == ufbxi_FBXHeaderExtension) return UFBXI_PARSE_FBX_HEADER_EXTENSION;
  4513. if (name == ufbxi_Definitions) return UFBXI_PARSE_DEFINITIONS;
  4514. if (name == ufbxi_Objects) return UFBXI_PARSE_OBJECTS;
  4515. if (name == ufbxi_Connections) return UFBXI_PARSE_CONNECTIONS;
  4516. if (name == ufbxi_Takes) return UFBXI_PARSE_TAKES;
  4517. if (name == ufbxi_Model) return UFBXI_PARSE_LEGACY_MODEL;
  4518. if (!strcmp(name, "References")) return UFBXI_PARSE_REFERENCES;
  4519. if (!strcmp(name, "Relations")) return UFBXI_PARSE_RELATIONS;
  4520. if (!strcmp(name, "Switcher")) return UFBXI_PARSE_LEGACY_SWITCHER;
  4521. if (!strcmp(name, "SceneGenericPersistence")) return UFBXI_PARSE_LEGACY_SCENE_PERSISTENCE;
  4522. break;
  4523. case UFBXI_PARSE_FBX_HEADER_EXTENSION:
  4524. if (name == ufbxi_FBXVersion) return UFBXI_PARSE_FBX_VERSION;
  4525. break;
  4526. case UFBXI_PARSE_OBJECTS:
  4527. if (name == ufbxi_Model) return UFBXI_PARSE_MODEL;
  4528. if (name == ufbxi_Geometry) return UFBXI_PARSE_GEOMETRY;
  4529. if (name == ufbxi_NodeAttribute) return UFBXI_PARSE_NODE_ATTRIBUTE;
  4530. if (name == ufbxi_AnimationCurve) return UFBXI_PARSE_ANIMATION_CURVE;
  4531. if (name == ufbxi_Deformer) return UFBXI_PARSE_DEFORMER;
  4532. if (name == ufbxi_Pose) return UFBXI_PARSE_POSE;
  4533. if (name == ufbxi_Texture) return UFBXI_PARSE_TEXTURE;
  4534. if (name == ufbxi_Video) return UFBXI_PARSE_VIDEO;
  4535. if (name == ufbxi_LayeredTexture) return UFBXI_PARSE_LAYERED_TEXTURE;
  4536. if (name == ufbxi_SelectionNode) return UFBXI_PARSE_SELECTION_NODE;
  4537. if (name == ufbxi_Collection) return UFBXI_PARSE_COLLECTION;
  4538. return UFBXI_PARSE_UNKNOWN_OBJECT;
  4539. case UFBXI_PARSE_MODEL:
  4540. case UFBXI_PARSE_GEOMETRY:
  4541. if (name[0] == 'L') {
  4542. if (name == ufbxi_LayerElementNormal) return UFBXI_PARSE_LAYER_ELEMENT_NORMAL;
  4543. if (name == ufbxi_LayerElementBinormal) return UFBXI_PARSE_LAYER_ELEMENT_BINORMAL;
  4544. if (name == ufbxi_LayerElementTangent) return UFBXI_PARSE_LAYER_ELEMENT_TANGENT;
  4545. if (name == ufbxi_LayerElementUV) return UFBXI_PARSE_LAYER_ELEMENT_UV;
  4546. if (name == ufbxi_LayerElementColor) return UFBXI_PARSE_LAYER_ELEMENT_COLOR;
  4547. if (name == ufbxi_LayerElementVertexCrease) return UFBXI_PARSE_LAYER_ELEMENT_VERTEX_CREASE;
  4548. if (name == ufbxi_LayerElementEdgeCrease) return UFBXI_PARSE_LAYER_ELEMENT_EDGE_CREASE;
  4549. if (name == ufbxi_LayerElementSmoothing) return UFBXI_PARSE_LAYER_ELEMENT_SMOOTHING;
  4550. if (name == ufbxi_LayerElementVisibility) return UFBXI_PARSE_LAYER_ELEMENT_VISIBILITY;
  4551. if (name == ufbxi_LayerElementPolygonGroup) return UFBXI_PARSE_LAYER_ELEMENT_POLYGON_GROUP;
  4552. if (name == ufbxi_LayerElementHole) return UFBXI_PARSE_LAYER_ELEMENT_HOLE;
  4553. if (name == ufbxi_LayerElementMaterial) return UFBXI_PARSE_LAYER_ELEMENT_MATERIAL;
  4554. if (!strncmp(name, "LayerElement", 12)) return UFBXI_PARSE_LAYER_ELEMENT_OTHER;
  4555. }
  4556. if (name == ufbxi_Shape) return UFBXI_PARSE_SHAPE;
  4557. break;
  4558. case UFBXI_PARSE_DEFORMER:
  4559. if (!strcmp(name, "AssociateModel")) return UFBXI_PARSE_ASSOCIATE_MODEL;
  4560. break;
  4561. case UFBXI_PARSE_LEGACY_MODEL:
  4562. if (name == ufbxi_GeometryUVInfo) return UFBXI_PARSE_GEOMETRY_UV_INFO;
  4563. if (name == ufbxi_Link) return UFBXI_PARSE_LEGACY_LINK;
  4564. if (name == ufbxi_Channel) return UFBXI_PARSE_CHANNEL;
  4565. if (name == ufbxi_Shape) return UFBXI_PARSE_SHAPE;
  4566. break;
  4567. case UFBXI_PARSE_POSE:
  4568. if (name == ufbxi_PoseNode) return UFBXI_PARSE_POSE_NODE;
  4569. break;
  4570. case UFBXI_PARSE_TAKES:
  4571. if (name == ufbxi_Take) return UFBXI_PARSE_TAKE;
  4572. break;
  4573. case UFBXI_PARSE_TAKE:
  4574. return UFBXI_PARSE_TAKE_OBJECT;
  4575. case UFBXI_PARSE_TAKE_OBJECT:
  4576. if (name == ufbxi_Channel) return UFBXI_PARSE_CHANNEL;
  4577. break;
  4578. case UFBXI_PARSE_CHANNEL:
  4579. if (name == ufbxi_Channel) return UFBXI_PARSE_CHANNEL;
  4580. break;
  4581. case UFBXI_PARSE_REFERENCES:
  4582. return UFBXI_PARSE_REFERENCE;
  4583. default:
  4584. break;
  4585. }
  4586. return UFBXI_PARSE_UNKNOWN;
  4587. }
  4588. static bool ufbxi_is_array_node(ufbxi_context *uc, ufbxi_parse_state parent, const char *name, ufbxi_array_info *info)
  4589. {
  4590. info->flags = 0;
  4591. // Retain all arrays if user wants the DOM representation
  4592. if (uc->opts.retain_dom) {
  4593. info->flags |= UFBXI_ARRAY_FLAG_RESULT;
  4594. }
  4595. switch (parent) {
  4596. case UFBXI_PARSE_GEOMETRY:
  4597. case UFBXI_PARSE_MODEL:
  4598. if (name == ufbxi_Vertices) {
  4599. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4600. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4601. return true;
  4602. } else if (name == ufbxi_PolygonVertexIndex) {
  4603. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4604. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4605. return true;
  4606. } else if (name == ufbxi_Edges) {
  4607. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4608. return true;
  4609. } else if (name == ufbxi_Indexes) {
  4610. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4611. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4612. return true;
  4613. } else if (name == ufbxi_Points) {
  4614. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4615. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4616. return true;
  4617. } else if (name == ufbxi_KnotVector) {
  4618. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4619. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4620. return true;
  4621. } else if (name == ufbxi_KnotVectorU) {
  4622. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4623. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4624. return true;
  4625. } else if (name == ufbxi_KnotVectorV) {
  4626. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4627. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4628. return true;
  4629. } else if (name == ufbxi_PointsIndex) {
  4630. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4631. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4632. return true;
  4633. } else if (name == ufbxi_Normals) {
  4634. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4635. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4636. return true;
  4637. }
  4638. break;
  4639. case UFBXI_PARSE_LEGACY_MODEL:
  4640. if (name == ufbxi_Vertices) {
  4641. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4642. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4643. return true;
  4644. } else if (name == ufbxi_Normals) {
  4645. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4646. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4647. return true;
  4648. } else if (name == ufbxi_Materials) {
  4649. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4650. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4651. return true;
  4652. } else if (name == ufbxi_PolygonVertexIndex) {
  4653. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4654. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4655. return true;
  4656. } else if (name == ufbxi_Children) {
  4657. info->type = 's';
  4658. return true;
  4659. }
  4660. break;
  4661. case UFBXI_PARSE_ANIMATION_CURVE:
  4662. if (name == ufbxi_KeyTime) {
  4663. info->type = uc->opts.ignore_animation ? '-' : 'l';
  4664. return true;
  4665. } else if (name == ufbxi_KeyValueFloat) {
  4666. info->type = uc->opts.ignore_animation ? '-' : 'r';
  4667. return true;
  4668. } else if (name == ufbxi_KeyAttrFlags) {
  4669. info->type = uc->opts.ignore_animation ? '-' : 'i';
  4670. return true;
  4671. } else if (name == ufbxi_KeyAttrDataFloat) {
  4672. // The float data in a keyframe attribute array is represented as integers
  4673. // in versions >= 7200 as some of the elements aren't actually floats (!)
  4674. info->type = uc->from_ascii && uc->version >= 7200 ? 'i' : 'f';
  4675. if (uc->opts.ignore_animation) info->type = '-';
  4676. return true;
  4677. } else if (name == ufbxi_KeyAttrRefCount) {
  4678. info->type = uc->opts.ignore_animation ? '-' : 'i';
  4679. return true;
  4680. }
  4681. break;
  4682. case UFBXI_PARSE_TEXTURE:
  4683. if (!strcmp(name, "ModelUVTranslation") || !strcmp(name, "ModelUVScaling") || !strcmp(name, "Cropping")) {
  4684. info->type = uc->opts.retain_dom ? 'r' : '-';
  4685. return true;
  4686. }
  4687. break;
  4688. case UFBXI_PARSE_VIDEO:
  4689. if (name == ufbxi_Content) {
  4690. info->type = uc->opts.ignore_embedded ? '-' : 'C';
  4691. return true;
  4692. }
  4693. break;
  4694. case UFBXI_PARSE_LAYERED_TEXTURE:
  4695. if (name == ufbxi_BlendModes) {
  4696. info->type = 'i';
  4697. info->flags |= UFBXI_ARRAY_FLAG_TMP_BUF;
  4698. return true;
  4699. } else if (name == ufbxi_Alphas) {
  4700. info->type = 'r';
  4701. info->flags |= UFBXI_ARRAY_FLAG_TMP_BUF;
  4702. return true;
  4703. }
  4704. break;
  4705. case UFBXI_PARSE_SELECTION_NODE:
  4706. if (name == ufbxi_VertexIndexArray) {
  4707. info->type = 'i';
  4708. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4709. return true;
  4710. } else if (name == ufbxi_EdgeIndexArray) {
  4711. info->type = 'i';
  4712. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4713. return true;
  4714. } else if (name == ufbxi_PolygonIndexArray) {
  4715. info->type = 'i';
  4716. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4717. return true;
  4718. }
  4719. break;
  4720. case UFBXI_PARSE_LAYER_ELEMENT_NORMAL:
  4721. if (name == ufbxi_Normals) {
  4722. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4723. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4724. return true;
  4725. } else if (name == ufbxi_NormalsIndex) {
  4726. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4727. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4728. return true;
  4729. } else if (name == ufbxi_NormalsW) {
  4730. info->type = uc->opts.retain_dom ? 'r' : '-';
  4731. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4732. return true;
  4733. }
  4734. break;
  4735. case UFBXI_PARSE_LAYER_ELEMENT_BINORMAL:
  4736. if (name == ufbxi_Binormals) {
  4737. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4738. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4739. return true;
  4740. } else if (name == ufbxi_BinormalsIndex) {
  4741. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4742. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4743. return true;
  4744. } else if (name == ufbxi_BinormalsW) {
  4745. info->type = uc->opts.retain_dom ? 'r' : '-';
  4746. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4747. return true;
  4748. }
  4749. break;
  4750. case UFBXI_PARSE_LAYER_ELEMENT_TANGENT:
  4751. if (name == ufbxi_Tangents) {
  4752. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4753. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4754. return true;
  4755. } else if (name == ufbxi_TangentsIndex) {
  4756. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4757. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4758. return true;
  4759. } else if (name == ufbxi_TangentsW) {
  4760. info->type = uc->opts.retain_dom ? 'r' : '-';
  4761. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4762. return true;
  4763. }
  4764. break;
  4765. case UFBXI_PARSE_LAYER_ELEMENT_UV:
  4766. if (name == ufbxi_UV) {
  4767. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4768. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4769. return true;
  4770. } else if (name == ufbxi_UVIndex) {
  4771. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4772. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4773. return true;
  4774. }
  4775. break;
  4776. case UFBXI_PARSE_LAYER_ELEMENT_COLOR:
  4777. if (name == ufbxi_Colors) {
  4778. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4779. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4780. return true;
  4781. } else if (name == ufbxi_ColorIndex) {
  4782. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4783. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4784. return true;
  4785. }
  4786. break;
  4787. case UFBXI_PARSE_LAYER_ELEMENT_VERTEX_CREASE:
  4788. if (name == ufbxi_VertexCrease) {
  4789. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4790. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4791. return true;
  4792. } else if (name == ufbxi_VertexCreaseIndex) {
  4793. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4794. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4795. return true;
  4796. }
  4797. break;
  4798. case UFBXI_PARSE_LAYER_ELEMENT_EDGE_CREASE:
  4799. if (name == ufbxi_EdgeCrease) {
  4800. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4801. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4802. return true;
  4803. }
  4804. break;
  4805. case UFBXI_PARSE_LAYER_ELEMENT_SMOOTHING:
  4806. if (name == ufbxi_Smoothing) {
  4807. info->type = uc->opts.ignore_geometry ? '-' : 'b';
  4808. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4809. return true;
  4810. }
  4811. break;
  4812. case UFBXI_PARSE_LAYER_ELEMENT_VISIBILITY:
  4813. if (name == ufbxi_Visibility) {
  4814. info->type = uc->opts.ignore_geometry ? '-' : 'b';
  4815. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4816. return true;
  4817. }
  4818. break;
  4819. case UFBXI_PARSE_LAYER_ELEMENT_POLYGON_GROUP:
  4820. if (name == ufbxi_PolygonGroup) {
  4821. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4822. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4823. return true;
  4824. }
  4825. break;
  4826. case UFBXI_PARSE_LAYER_ELEMENT_HOLE:
  4827. if (name == ufbxi_Hole) {
  4828. info->type = uc->opts.ignore_geometry ? '-' : 'b';
  4829. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4830. return true;
  4831. }
  4832. break;
  4833. case UFBXI_PARSE_LAYER_ELEMENT_MATERIAL:
  4834. if (name == ufbxi_Materials) {
  4835. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4836. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4837. return true;
  4838. }
  4839. break;
  4840. case UFBXI_PARSE_LAYER_ELEMENT_OTHER:
  4841. if (name == ufbxi_TextureId) {
  4842. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4843. info->flags |= UFBXI_ARRAY_FLAG_TMP_BUF;
  4844. return true;
  4845. } else if (name == ufbxi_UV) {
  4846. info->type = uc->opts.retain_dom ? 'r' : '-';
  4847. return true;
  4848. } else if (name == ufbxi_UVIndex) {
  4849. info->type = uc->opts.retain_dom ? 'i' : '-';
  4850. return true;
  4851. }
  4852. break;
  4853. case UFBXI_PARSE_GEOMETRY_UV_INFO:
  4854. if (name == ufbxi_TextureUV) {
  4855. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4856. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4857. return true;
  4858. } else if (name == ufbxi_TextureUVVerticeIndex) {
  4859. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4860. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4861. return true;
  4862. }
  4863. break;
  4864. case UFBXI_PARSE_SHAPE:
  4865. if (name == ufbxi_Indexes) {
  4866. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4867. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4868. return true;
  4869. }
  4870. if (name == ufbxi_Vertices) {
  4871. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4872. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4873. return true;
  4874. }
  4875. if (name == ufbxi_Normals) {
  4876. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4877. info->flags = UFBXI_ARRAY_FLAG_RESULT | UFBXI_ARRAY_FLAG_PAD_BEGIN;
  4878. return true;
  4879. }
  4880. break;
  4881. case UFBXI_PARSE_DEFORMER:
  4882. if (name == ufbxi_Transform) {
  4883. info->type = 'r';
  4884. return true;
  4885. } else if (name == ufbxi_TransformLink) {
  4886. info->type = 'r';
  4887. return true;
  4888. } else if (name == ufbxi_Indexes) {
  4889. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4890. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4891. return true;
  4892. } else if (name == ufbxi_Weights) {
  4893. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4894. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4895. return true;
  4896. } else if (name == ufbxi_BlendWeights) {
  4897. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4898. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4899. return true;
  4900. } else if (name == ufbxi_FullWeights) {
  4901. // Ignore blend shape FullWeights as it's used in Blender for vertex groups
  4902. // which we don't currently handle. https://developer.blender.org/T90382
  4903. // TODO: Should we present this to users anyway somehow?
  4904. info->type = 'd';
  4905. if (!uc->opts.disable_quirks && uc->exporter == UFBX_EXPORTER_BLENDER_BINARY) {
  4906. info->type = '-';
  4907. }
  4908. info->flags |= UFBXI_ARRAY_FLAG_TMP_BUF;
  4909. return true;
  4910. } else if (!strcmp(name, "TransformAssociateModel")) {
  4911. info->type = uc->opts.retain_dom ? 'r' : '-';
  4912. return true;
  4913. }
  4914. break;
  4915. case UFBXI_PARSE_ASSOCIATE_MODEL:
  4916. if (name == ufbxi_Transform) {
  4917. info->type = uc->opts.retain_dom ? 'r' : '-';
  4918. return true;
  4919. }
  4920. break;
  4921. case UFBXI_PARSE_LEGACY_LINK:
  4922. if (name == ufbxi_Transform) {
  4923. info->type = 'r';
  4924. return true;
  4925. } else if (name == ufbxi_TransformLink) {
  4926. info->type = 'r';
  4927. return true;
  4928. } else if (name == ufbxi_Indexes) {
  4929. info->type = uc->opts.ignore_geometry ? '-' : 'i';
  4930. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4931. return true;
  4932. } else if (name == ufbxi_Weights) {
  4933. info->type = uc->opts.ignore_geometry ? '-' : 'r';
  4934. info->flags = UFBXI_ARRAY_FLAG_RESULT;
  4935. return true;
  4936. }
  4937. break;
  4938. case UFBXI_PARSE_POSE_NODE:
  4939. if (name == ufbxi_Matrix) {
  4940. info->type = 'r';
  4941. return true;
  4942. }
  4943. break;
  4944. case UFBXI_PARSE_CHANNEL:
  4945. if (name == ufbxi_Key) {
  4946. info->type = uc->opts.ignore_animation ? '-' : 'd';
  4947. return true;
  4948. }
  4949. break;
  4950. default:
  4951. if (name == ufbxi_BinaryData) {
  4952. info->type = uc->opts.ignore_embedded ? '-' : 'C';
  4953. return true;
  4954. }
  4955. break;
  4956. }
  4957. return false;
  4958. }
  4959. static ufbxi_noinline bool ufbxi_is_raw_string(ufbxi_context *uc, ufbxi_parse_state parent, const char *name, size_t index)
  4960. {
  4961. (void)index;
  4962. switch (parent) {
  4963. case UFBXI_PARSE_ROOT:
  4964. if (name == ufbxi_Model) return true;
  4965. if (!strcmp(name, "FileId")) return true;
  4966. break;
  4967. case UFBXI_PARSE_FBX_HEADER_EXTENSION:
  4968. if (name == ufbxi_SceneInfo) return true;
  4969. break;
  4970. case UFBXI_PARSE_OBJECTS:
  4971. return true;
  4972. case UFBXI_PARSE_CONNECTIONS:
  4973. case UFBXI_PARSE_RELATIONS:
  4974. // Pre-7000 needs raw strings for "Name\x00\x01Type" pairs, post-7000 uses it only
  4975. // for properties that are non-raw by default.
  4976. return uc->version < 7000;
  4977. case UFBXI_PARSE_MODEL:
  4978. if (name == ufbxi_NodeAttributeName) return true;
  4979. if (name == ufbxi_Name) return true;
  4980. break;
  4981. case UFBXI_PARSE_VIDEO:
  4982. if (name == ufbxi_Content) return true;
  4983. break;
  4984. case UFBXI_PARSE_TEXTURE:
  4985. if (!strcmp(name, "TextureName")) return true;
  4986. if (!strcmp(name, "Media")) return true;
  4987. break;
  4988. case UFBXI_PARSE_GEOMETRY:
  4989. if (name == ufbxi_NodeAttributeName) return true;
  4990. if (name == ufbxi_Name) return true;
  4991. break;
  4992. case UFBXI_PARSE_NODE_ATTRIBUTE:
  4993. if (name == ufbxi_NodeAttributeName) return true;
  4994. if (name == ufbxi_Name) return true;
  4995. break;
  4996. case UFBXI_PARSE_POSE_NODE:
  4997. if (name == ufbxi_Node) return true;
  4998. break;
  4999. case UFBXI_PARSE_SELECTION_NODE:
  5000. if (name == ufbxi_Node) return true;
  5001. break;
  5002. case UFBXI_PARSE_UNKNOWN_OBJECT:
  5003. if (name == ufbxi_NodeAttributeName) return true;
  5004. if (name == ufbxi_Name) return true;
  5005. break;
  5006. case UFBXI_PARSE_COLLECTION:
  5007. if (!strcmp(name, "Member")) return true;
  5008. break;
  5009. case UFBXI_PARSE_LEGACY_MODEL:
  5010. if (name == ufbxi_Material) return true;
  5011. if (name == ufbxi_Link) return true;
  5012. if (name == ufbxi_Name) return true;
  5013. break;
  5014. case UFBXI_PARSE_LEGACY_SWITCHER:
  5015. if (!strcmp(name, "CameraIndexName")) return true;
  5016. break;
  5017. case UFBXI_PARSE_LEGACY_SCENE_PERSISTENCE:
  5018. if (name == ufbxi_SceneInfo) return true;
  5019. break;
  5020. case UFBXI_PARSE_REFERENCE:
  5021. if (!strcmp(name, "Object")) return true;
  5022. break;
  5023. case UFBXI_PARSE_TAKE:
  5024. if (name == ufbxi_Model) return true;
  5025. break;
  5026. default:
  5027. break;
  5028. }
  5029. return false;
  5030. }
  5031. // -- Binary parsing
  5032. ufbxi_nodiscard static ufbxi_noinline char *ufbxi_swap_endian(ufbxi_context *uc, const void *src, size_t count, size_t elem_size)
  5033. {
  5034. size_t total_size = count * elem_size;
  5035. ufbxi_check_return(!ufbxi_does_overflow(total_size, count, elem_size), NULL);
  5036. if (uc->swap_arr_size < total_size) {
  5037. ufbxi_check_return(ufbxi_grow_array(&uc->ator_tmp, &uc->swap_arr, &uc->swap_arr_size, total_size), NULL);
  5038. }
  5039. char *dst = uc->swap_arr, *d = dst;
  5040. const char *s = (const char*)src;
  5041. switch (elem_size) {
  5042. case 1:
  5043. for (size_t i = 0; i < count; i++) {
  5044. d[0] = s[0];
  5045. d += 1; s += 1;
  5046. }
  5047. break;
  5048. case 2:
  5049. for (size_t i = 0; i < count; i++) {
  5050. d[0] = s[1]; d[1] = s[0];
  5051. d += 2; s += 2;
  5052. }
  5053. break;
  5054. case 4:
  5055. for (size_t i = 0; i < count; i++) {
  5056. d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; d[3] = s[0];
  5057. d += 4; s += 4;
  5058. }
  5059. break;
  5060. case 8:
  5061. for (size_t i = 0; i < count; i++) {
  5062. d[0] = s[7]; d[1] = s[6]; d[2] = s[5]; d[3] = s[4];
  5063. d[4] = s[3]; d[5] = s[2]; d[6] = s[1]; d[7] = s[0];
  5064. d += 8; s += 8;
  5065. }
  5066. break;
  5067. default:
  5068. ufbx_assert(0 && "Bad endian swap size");
  5069. }
  5070. return dst;
  5071. }
  5072. // Swap the endianness of an array typed with a lowercase letter
  5073. ufbxi_nodiscard static ufbxi_noinline const char *ufbxi_swap_endian_array(ufbxi_context *uc, const void *src, size_t count, char type)
  5074. {
  5075. switch (type) {
  5076. case 'i': case 'f': return ufbxi_swap_endian(uc, src, count, 4); break;
  5077. case 'l': case 'd': return ufbxi_swap_endian(uc, src, count, 8); break;
  5078. default: return (const char*)src;
  5079. }
  5080. }
  5081. // Swap the endianness of a single value (shallow, swaps string/array header words)
  5082. ufbxi_nodiscard static ufbxi_noinline const char *ufbxi_swap_endian_value(ufbxi_context *uc, const void *src, char type)
  5083. {
  5084. switch (type) {
  5085. case 'Y': return ufbxi_swap_endian(uc, src, 1, 2); break;
  5086. case 'I': case 'F': return ufbxi_swap_endian(uc, src, 1, 4); break;
  5087. case 'L': case 'D': return ufbxi_swap_endian(uc, src, 1, 8); break;
  5088. case 'S': case 'R': return ufbxi_swap_endian(uc, src, 1, 4); break;
  5089. case 'i': case 'l': case 'f': case 'd': case 'b': return ufbxi_swap_endian(uc, src, 3, 4); break;
  5090. default: return (const char*)src;
  5091. }
  5092. }
  5093. // Read and convert a post-7000 FBX data array into a different format. `src_type` may be equal to `dst_type`
  5094. // if the platform is not binary compatible with the FBX data representation.
  5095. ufbxi_nodiscard static ufbxi_noinline int ufbxi_binary_convert_array(ufbxi_context *uc, char src_type, char dst_type, const void *src, void *dst, size_t size)
  5096. {
  5097. // TODO: We might want to use the slow path if the machine float/double doesn't match IEEE 754!
  5098. // Convert commented out lines under some `#if UFBX_NON_IEE754` define or something.
  5099. if (src_type == dst_type) {
  5100. src = ufbxi_swap_endian_array(uc, src, size, src_type);
  5101. ufbxi_check(src);
  5102. memcpy(dst, src, size * ufbxi_array_type_size(dst_type));
  5103. return 1;
  5104. }
  5105. if (uc->file_big_endian) {
  5106. src = ufbxi_swap_endian_array(uc, src, size, src_type);
  5107. ufbxi_check(src);
  5108. }
  5109. switch (dst_type)
  5110. {
  5111. #define ufbxi_convert_loop_fast(m_dst, m_cast, m_size, m_expr) { \
  5112. const char *val = (const char*)src, *val_end = val + size*m_size; \
  5113. m_dst *d = (m_dst*)dst; \
  5114. while (val != val_end) { *d++ = m_cast(m_expr); val += m_size; } }
  5115. #define ufbxi_convert_loop_slow(m_dst, m_cast, m_size, m_expr) { \
  5116. const char *val = (const char*)src, *val_end = val + size*m_size; \
  5117. m_dst *d = (m_dst*)dst; \
  5118. ufbxi_nounroll while (val != val_end) { *d++ = m_cast(m_expr); val += m_size; } }
  5119. case 'c':
  5120. switch (src_type) {
  5121. // case 'c': ufbxi_convert_loop_fast(char, (char), 1, *val != 0); break;
  5122. case 'i': ufbxi_convert_loop_slow(uint8_t, (uint8_t), 4, (uint8_t)ufbxi_read_i32(val)); break;
  5123. case 'l': ufbxi_convert_loop_slow(uint8_t, (uint8_t), 8, (uint8_t)ufbxi_read_i64(val)); break;
  5124. case 'f': ufbxi_convert_loop_slow(uint8_t, (uint8_t), 4, (uint8_t)ufbxi_read_f32(val)); break;
  5125. case 'd': ufbxi_convert_loop_slow(uint8_t, (uint8_t), 8, (uint8_t)ufbxi_read_f64(val)); break;
  5126. default: ufbxi_fail("Bad array source type");
  5127. }
  5128. break;
  5129. case 'i':
  5130. switch (src_type) {
  5131. case 'c': ufbxi_convert_loop_slow(int32_t, (int32_t), 1, *val); break;
  5132. // case 'i': ufbxi_convert_loop_slow(int32_t, (int32_t), 4, ufbxi_read_i32(val)); break;
  5133. case 'l': ufbxi_convert_loop_fast(int32_t, (int32_t), 8, ufbxi_read_i64(val)); break;
  5134. case 'f': ufbxi_convert_loop_slow(int32_t, ufbxi_f64_to_i32, 4, ufbxi_read_f32(val)); break;
  5135. case 'd': ufbxi_convert_loop_slow(int32_t, ufbxi_f64_to_i32, 8, ufbxi_read_f64(val)); break;
  5136. default: ufbxi_fail("Bad array source type");
  5137. }
  5138. break;
  5139. case 'l':
  5140. switch (src_type) {
  5141. case 'c': ufbxi_convert_loop_slow(int64_t, (int64_t), 1, *val); break;
  5142. case 'i': ufbxi_convert_loop_fast(int64_t, (int64_t), 4, ufbxi_read_i32(val)); break;
  5143. // case 'l': ufbxi_convert_loop_slow(int64_t, (int64_t), 8, ufbxi_read_i64(val)); break;
  5144. case 'f': ufbxi_convert_loop_slow(int64_t, ufbxi_f64_to_i64, 4, ufbxi_read_f32(val)); break;
  5145. case 'd': ufbxi_convert_loop_slow(int64_t, ufbxi_f64_to_i64, 8, ufbxi_read_f64(val)); break;
  5146. default: ufbxi_fail("Bad array source type");
  5147. }
  5148. break;
  5149. case 'f':
  5150. switch (src_type) {
  5151. case 'c': ufbxi_convert_loop_slow(float, (float), 1, *val); break;
  5152. case 'i': ufbxi_convert_loop_slow(float, (float), 4, ufbxi_read_i32(val)); break;
  5153. case 'l': ufbxi_convert_loop_slow(float, (float), 8, ufbxi_read_i64(val)); break;
  5154. // case 'f': ufbxi_convert_loop_slow(float, (float), 4, ufbxi_read_f32(val)); break;
  5155. case 'd': ufbxi_convert_loop_fast(float, (float), 8, ufbxi_read_f64(val)); break;
  5156. default: ufbxi_fail("Bad array source type");
  5157. }
  5158. break;
  5159. case 'd':
  5160. switch (src_type) {
  5161. case 'c': ufbxi_convert_loop_slow(double, (double), 1, *val); break;
  5162. case 'i': ufbxi_convert_loop_slow(double, (double), 4, ufbxi_read_i32(val)); break;
  5163. case 'l': ufbxi_convert_loop_slow(double, (double), 8, ufbxi_read_i64(val)); break;
  5164. case 'f': ufbxi_convert_loop_fast(double, (double), 4, ufbxi_read_f32(val)); break;
  5165. // case 'd': ufbxi_convert_loop_slow(double, (double), 8, ufbxi_read_f64(val)); break;
  5166. default: ufbxi_fail("Bad array source type");
  5167. }
  5168. break;
  5169. default: return 0;
  5170. }
  5171. return 1;
  5172. }
  5173. // Read pre-7000 separate properties as an array.
  5174. ufbxi_nodiscard static ufbxi_noinline int ufbxi_binary_parse_multivalue_array(ufbxi_context *uc, char dst_type, void *dst, size_t size, ufbxi_buf *tmp_buf)
  5175. {
  5176. if (size == 0) return 1;
  5177. const char *val;
  5178. size_t val_size;
  5179. bool file_big_endian = uc->file_big_endian;
  5180. #define ufbxi_convert_parse_fast(m_dst, m_type, m_expr) { \
  5181. m_dst *d = (m_dst*)dst; \
  5182. for (; base < size; base++) { \
  5183. val = ufbxi_peek_bytes(uc, 13); \
  5184. ufbxi_check(val); \
  5185. if (*val != m_type) break; \
  5186. val++; \
  5187. *d++ = (m_dst)(m_expr); \
  5188. ufbxi_consume_bytes(uc, 1 + sizeof(m_dst)); \
  5189. } \
  5190. }
  5191. // String array special case
  5192. if (dst_type == 's' || dst_type == 'S' || dst_type == 'C') {
  5193. bool raw = dst_type == 's';
  5194. ufbx_string *d = (ufbx_string*)dst;
  5195. for (size_t i = 0; i < size; i++) {
  5196. val = ufbxi_peek_bytes(uc, 13);
  5197. ufbxi_check(val);
  5198. char type = *val++;
  5199. ufbxi_check(type == 'S' || type == 'R');
  5200. if (file_big_endian) {
  5201. val = ufbxi_swap_endian_value(uc, val, type);
  5202. ufbxi_check(val);
  5203. }
  5204. size_t len = ufbxi_read_u32(val);
  5205. ufbxi_consume_bytes(uc, 5);
  5206. d->data = ufbxi_read_bytes(uc, len);
  5207. d->length = len;
  5208. ufbxi_check(d->data);
  5209. if (dst_type == 'C') {
  5210. ufbxi_buf *buf = size == 1 || uc->opts.retain_dom ? &uc->result : tmp_buf;
  5211. d->data = ufbxi_push_copy(buf, char, len, d->data);
  5212. ufbxi_check(d->data);
  5213. } else {
  5214. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, d, raw));
  5215. }
  5216. d++;
  5217. }
  5218. return 1;
  5219. }
  5220. // Optimize a couple of common cases
  5221. size_t base = 0;
  5222. if (!file_big_endian) {
  5223. switch (dst_type) {
  5224. case 'i': ufbxi_convert_parse_fast(int32_t, 'I', ufbxi_read_i32(val)); break;
  5225. case 'l': ufbxi_convert_parse_fast(int64_t, 'L', ufbxi_read_i64(val)); break;
  5226. case 'f': ufbxi_convert_parse_fast(float, 'F', ufbxi_read_f32(val)); break;
  5227. case 'd': ufbxi_convert_parse_fast(double, 'D', ufbxi_read_f64(val)); break;
  5228. }
  5229. // Early return if we handled everything
  5230. if (base == size) return 1;
  5231. }
  5232. switch (dst_type)
  5233. {
  5234. #define ufbxi_convert_parse(m_cast, m_size, m_expr) \
  5235. *d++ = m_cast(m_expr); val_size = m_size + 1; \
  5236. #define ufbxi_convert_parse_switch(m_dst, m_cast_int, m_cast_float) { \
  5237. m_dst *d = (m_dst*)dst + base; \
  5238. for (size_t i = base; i < size; i++) { \
  5239. val = ufbxi_peek_bytes(uc, 13); \
  5240. ufbxi_check(val); \
  5241. char type = *val++; \
  5242. if (file_big_endian) { \
  5243. val = ufbxi_swap_endian_value(uc, val, type); \
  5244. ufbxi_check(val); \
  5245. } \
  5246. switch (type) { \
  5247. case 'C': \
  5248. case 'B': ufbxi_convert_parse(m_cast_int, 1, *val); break; \
  5249. case 'Y': ufbxi_convert_parse(m_cast_int, 2, ufbxi_read_i16(val)); break; \
  5250. case 'I': ufbxi_convert_parse(m_cast_int, 4, ufbxi_read_i32(val)); break; \
  5251. case 'L': ufbxi_convert_parse(m_cast_int, 8, ufbxi_read_i64(val)); break; \
  5252. case 'F': ufbxi_convert_parse(m_cast_float, 4, ufbxi_read_f32(val)); break; \
  5253. case 'D': ufbxi_convert_parse(m_cast_float, 8, ufbxi_read_f64(val)); break; \
  5254. default: ufbxi_fail("Bad multivalue array type"); \
  5255. } \
  5256. ufbxi_consume_bytes(uc, val_size); \
  5257. } \
  5258. } \
  5259. case 'c': ufbxi_convert_parse_switch(uint8_t, (uint8_t), (uint8_t)); break;
  5260. case 'i': ufbxi_convert_parse_switch(int32_t, (int32_t), ufbxi_f64_to_i32); break;
  5261. case 'l': ufbxi_convert_parse_switch(int64_t, (int64_t), ufbxi_f64_to_i64); break;
  5262. case 'f': ufbxi_convert_parse_switch(float, (float), (float)); break;
  5263. case 'd': ufbxi_convert_parse_switch(double, (double), (double)); break;
  5264. default: return 0;
  5265. }
  5266. return 1;
  5267. }
  5268. ufbxi_nodiscard ufbxi_noinline static void *ufbxi_push_array_data(ufbxi_context *uc, const ufbxi_array_info *info, size_t size, ufbxi_buf *tmp_buf)
  5269. {
  5270. char type = ufbxi_normalize_array_type(info->type);
  5271. size_t elem_size = ufbxi_array_type_size(type);
  5272. uint32_t flags = info->flags;
  5273. if (flags & UFBXI_ARRAY_FLAG_PAD_BEGIN) size += 4;
  5274. // The array may be pushed either to the result or temporary buffer depending
  5275. // if it's already in the right format
  5276. ufbxi_buf *arr_buf = tmp_buf;
  5277. if (flags & UFBXI_ARRAY_FLAG_RESULT) arr_buf = &uc->result;
  5278. else if (flags & UFBXI_ARRAY_FLAG_TMP_BUF) arr_buf = &uc->tmp;
  5279. char *data = (char*)ufbxi_push_size(arr_buf, elem_size, size);
  5280. ufbxi_check_return(data, NULL);
  5281. if (flags & UFBXI_ARRAY_FLAG_PAD_BEGIN) {
  5282. memset(data, 0, elem_size * 4);
  5283. data += elem_size * 4;
  5284. }
  5285. return data;
  5286. }
  5287. ufbxi_nodiscard ufbxi_noinline static int ufbxi_binary_parse_node(ufbxi_context *uc, uint32_t depth, ufbxi_parse_state parent_state, bool *p_end, ufbxi_buf *tmp_buf, bool recursive)
  5288. {
  5289. // https://code.blender.org/2013/08/fbx-binary-file-format-specification
  5290. // Parse an FBX document node in the binary format
  5291. ufbxi_check(depth < UFBXI_MAX_NODE_DEPTH);
  5292. // Parse the node header, post-7500 versions use 64-bit values for most
  5293. // header fields.
  5294. uint64_t end_offset, num_values64, values_len;
  5295. uint8_t name_len;
  5296. size_t header_size = (uc->version >= 7500) ? 25 : 13;
  5297. const char *header = ufbxi_read_bytes(uc, header_size), *header_words = header;
  5298. ufbxi_check(header);
  5299. if (uc->version >= 7500) {
  5300. if (uc->file_big_endian) {
  5301. header_words = ufbxi_swap_endian(uc, header_words, 3, 8);
  5302. ufbxi_check(header_words);
  5303. }
  5304. end_offset = ufbxi_read_u64(header_words + 0);
  5305. num_values64 = ufbxi_read_u64(header_words + 8);
  5306. values_len = ufbxi_read_u64(header_words + 16);
  5307. name_len = ufbxi_read_u8(header + 24);
  5308. } else {
  5309. if (uc->file_big_endian) {
  5310. header_words = ufbxi_swap_endian(uc, header_words, 3, 4);
  5311. ufbxi_check(header_words);
  5312. }
  5313. end_offset = ufbxi_read_u32(header_words + 0);
  5314. num_values64 = ufbxi_read_u32(header_words + 4);
  5315. values_len = ufbxi_read_u32(header_words + 8);
  5316. name_len = ufbxi_read_u8(header + 12);
  5317. }
  5318. ufbxi_check(num_values64 <= UINT32_MAX);
  5319. uint32_t num_values = (uint32_t)num_values64;
  5320. // If `end_offset` and `name_len` is zero we treat as the node as a NULL-sentinel
  5321. // that terminates a node list.
  5322. if (end_offset == 0 && name_len == 0) {
  5323. *p_end = true;
  5324. return 1;
  5325. }
  5326. // Update estimated end offset if possible
  5327. if (end_offset > uc->progress_bytes_total) {
  5328. uc->progress_bytes_total = end_offset;
  5329. }
  5330. // Push the parsed node into the `tmp_stack` buffer, the nodes will be popped by
  5331. // calling code after its done parsing all of it's children.
  5332. ufbxi_node *node = ufbxi_push_zero(&uc->tmp_stack, ufbxi_node, 1);
  5333. ufbxi_check(node);
  5334. // Parse and intern the name to the string pool.
  5335. const char *name = ufbxi_read_bytes(uc, name_len);
  5336. ufbxi_check(name);
  5337. name = ufbxi_push_string(&uc->string_pool, name, name_len, NULL, true);
  5338. ufbxi_check(name);
  5339. node->name_len = name_len;
  5340. node->name = name;
  5341. uint64_t values_end_offset = ufbxi_get_read_offset(uc) + values_len;
  5342. // Check if the values of the node we're parsing currently should be
  5343. // treated as an array.
  5344. ufbxi_array_info arr_info;
  5345. if (ufbxi_is_array_node(uc, parent_state, name, &arr_info)) {
  5346. // Normalize the array type (eg. 'r' to 'f'/'d' depending on the build)
  5347. // and get the per-element size of the array.
  5348. char dst_type = ufbxi_normalize_array_type(arr_info.type);
  5349. ufbxi_value_array *arr = ufbxi_push(tmp_buf, ufbxi_value_array, 1);
  5350. ufbxi_check(arr);
  5351. node->value_type_mask = UFBXI_VALUE_ARRAY;
  5352. node->array = arr;
  5353. arr->type = dst_type;
  5354. // Peek the first bytes of the array. We can always look at least 13 bytes
  5355. // ahead safely as valid FBX files must end in a 13/25 byte NULL record.
  5356. const char *data = ufbxi_peek_bytes(uc, 13);
  5357. ufbxi_check(data);
  5358. // Check if the data type is one of the explicit array types (post-7000).
  5359. // Otherwise we form the array by concatenating all the normal values of the
  5360. // node (pre-7000)
  5361. char c = data[0];
  5362. // HACK: Override the "type" if either the array is empty or we want to
  5363. // specifically ignore the contents.
  5364. if (num_values == 0) c = '0';
  5365. if (dst_type == '-') c = '-';
  5366. if (c=='c' || c=='b' || c=='i' || c=='l' || c =='f' || c=='d') {
  5367. const char *arr_words = data + 1;
  5368. if (uc->file_big_endian) {
  5369. arr_words = ufbxi_swap_endian(uc, arr_words, 3, 4);
  5370. ufbxi_check(arr_words);
  5371. }
  5372. // Parse the array header from the prefix we already peeked above.
  5373. char src_type = data[0];
  5374. uint32_t size = ufbxi_read_u32(arr_words + 0);
  5375. uint32_t encoding = ufbxi_read_u32(arr_words + 4);
  5376. uint32_t encoded_size = ufbxi_read_u32(arr_words + 8);
  5377. ufbxi_consume_bytes(uc, 13);
  5378. // Normalize the source type as well, but don't convert UFBX-specific
  5379. // 'r' to 'f'/'d', but fail later instead.
  5380. if (src_type != 'r') src_type = ufbxi_normalize_array_type(src_type);
  5381. size_t src_elem_size = ufbxi_array_type_size(src_type);
  5382. size_t decoded_data_size = src_elem_size * size;
  5383. // Allocate `size` elements for the array.
  5384. char *arr_data = (char*)ufbxi_push_array_data(uc, &arr_info, size, tmp_buf);
  5385. ufbxi_check(arr_data);
  5386. // If the source and destination types are equal and our build is binary-compatible
  5387. // with the FBX format we can read the decoded data directly into the array buffer.
  5388. // Otherwise we need a temporary buffer to decode the array into before conversion.
  5389. void *decoded_data = arr_data;
  5390. if (src_type != dst_type || uc->local_big_endian != uc->file_big_endian) {
  5391. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, decoded_data_size));
  5392. decoded_data = uc->tmp_arr;
  5393. }
  5394. uint64_t arr_begin = ufbxi_get_read_offset(uc);
  5395. ufbxi_check(UINT64_MAX - encoded_size > arr_begin);
  5396. uint64_t arr_end = arr_begin + encoded_size;
  5397. if (arr_end > uc->progress_bytes_total) {
  5398. uc->progress_bytes_total = arr_end;
  5399. }
  5400. if (encoding == 0) {
  5401. // Encoding 0: Plain binary data.
  5402. ufbxi_check(encoded_size == decoded_data_size);
  5403. // If the array is contained in the current read buffer and we need to convert
  5404. // the data anyway we can use the read buffer as the decoded array source, otherwise
  5405. // do a plain byte copy to the array/conversion buffer.
  5406. if (uc->yield_size + uc->data_size >= encoded_size && decoded_data != arr_data) {
  5407. // Yield right after this if we crossed the yield threshold
  5408. if (encoded_size > uc->yield_size) {
  5409. uc->data_size += uc->yield_size;
  5410. uc->yield_size = encoded_size;
  5411. uc->data_size -= uc->yield_size;
  5412. }
  5413. decoded_data = (void*)uc->data;
  5414. ufbxi_consume_bytes(uc, encoded_size);
  5415. } else {
  5416. ufbxi_check(ufbxi_read_to(uc, decoded_data, encoded_size));
  5417. }
  5418. } else if (encoding == 1) {
  5419. // Encoding 1: DEFLATE
  5420. uc->data_size += uc->yield_size;
  5421. uc->yield_size = 0;
  5422. // Inflate the data from the user-provided IO buffer / read callbacks
  5423. ufbx_inflate_input input;
  5424. input.total_size = encoded_size;
  5425. input.data = uc->data;
  5426. input.data_size = uc->data_size;
  5427. input.no_header = false;
  5428. input.no_checksum = false;
  5429. if (uc->opts.progress_cb.fn) {
  5430. input.progress_cb = uc->opts.progress_cb;
  5431. input.progress_size_before = arr_begin;
  5432. input.progress_size_after = uc->progress_bytes_total - arr_end;
  5433. input.progress_interval_hint = uc->progress_interval;
  5434. } else {
  5435. input.progress_cb.fn = NULL;
  5436. input.progress_cb.user = NULL;
  5437. input.progress_size_before = 0;
  5438. input.progress_size_after = 0;
  5439. input.progress_interval_hint = 0;
  5440. }
  5441. // If the encoded array is larger than the data we have currently buffered
  5442. // we need to allow `ufbxi_inflate()` to read from the IO callback. We can
  5443. // let `ufbxi_inflate()` freely clobber our `read_buffer` as all the data
  5444. // in the buffer will be consumed. `ufbxi_inflate()` always reads exactly
  5445. // the amount of bytes needed so we can continue reading from `read_fn` as
  5446. // usual (given that we clear the `uc->data/_size` buffer below).
  5447. // NOTE: We _cannot_ share `read_buffer` if we plan to read later from it
  5448. // as `ufbxi_inflate()` overwrites parts of it with zeroes.
  5449. if (encoded_size > input.data_size) {
  5450. input.buffer = uc->read_buffer;
  5451. input.buffer_size = uc->read_buffer_size;
  5452. input.read_fn = uc->read_fn;
  5453. input.read_user = uc->read_user;
  5454. uc->data_offset += encoded_size - input.data_size;
  5455. uc->data += input.data_size;
  5456. uc->data_size = 0;
  5457. } else {
  5458. input.buffer = NULL;
  5459. input.buffer_size = 0;
  5460. input.read_fn = NULL;
  5461. input.read_user = 0;
  5462. uc->data += encoded_size;
  5463. uc->data_size -= encoded_size;
  5464. uc->yield_size = ufbxi_min_sz(uc->data_size, uc->progress_interval);
  5465. uc->data_size -= uc->yield_size;
  5466. }
  5467. ptrdiff_t res = ufbx_inflate(decoded_data, decoded_data_size, &input, uc->inflate_retain);
  5468. ufbxi_check_msg(res != -28, "Cancelled");
  5469. ufbxi_check_msg(res == (ptrdiff_t)decoded_data_size, "Bad DEFLATE data");
  5470. } else {
  5471. ufbxi_fail("Bad array encoding");
  5472. }
  5473. // Convert the decoded array if necessary.
  5474. if (decoded_data != arr_data) {
  5475. ufbxi_check(ufbxi_binary_convert_array(uc, src_type, dst_type, decoded_data, arr_data, size));
  5476. }
  5477. arr->data = arr_data;
  5478. arr->size = size;
  5479. } else if (c == '0' || c == '-') {
  5480. // Ignore the array
  5481. arr->type = c == '-' ? '-' : dst_type;
  5482. arr->data = (char*)ufbxi_zero_size_buffer + 32;
  5483. arr->size = 0;
  5484. } else {
  5485. // Allocate `num_values` elements for the array and parse single values into it.
  5486. char *arr_data = (char*)ufbxi_push_array_data(uc, &arr_info, num_values, tmp_buf);
  5487. ufbxi_check(arr_data);
  5488. ufbxi_check(ufbxi_binary_parse_multivalue_array(uc, dst_type, arr_data, num_values, tmp_buf));
  5489. arr->data = arr_data;
  5490. arr->size = num_values;
  5491. }
  5492. // Post-process boolean arrays
  5493. if (arr_info.type == 'b') {
  5494. ufbxi_for(char, b, (char*)arr->data, arr->size) {
  5495. *b = (char)(*b != 0);
  5496. }
  5497. }
  5498. } else {
  5499. // Parse up to UFBXI_MAX_NON_ARRAY_VALUES as plain values
  5500. num_values = ufbxi_min32(num_values, UFBXI_MAX_NON_ARRAY_VALUES);
  5501. ufbxi_value *vals = ufbxi_push(tmp_buf, ufbxi_value, num_values);
  5502. ufbxi_check(vals);
  5503. node->vals = vals;
  5504. uint32_t type_mask = 0;
  5505. for (size_t i = 0; i < (size_t)num_values; i++) {
  5506. // The file must end in a 13/25 byte NULL record, so we can peek
  5507. // up to 13 bytes safely here.
  5508. const char *data = ufbxi_peek_bytes(uc, 13);
  5509. ufbxi_check(data);
  5510. const char *value = data + 1;
  5511. char type = data[0];
  5512. if (uc->file_big_endian) {
  5513. value = ufbxi_swap_endian_value(uc, value, type);
  5514. ufbxi_check(value);
  5515. }
  5516. switch (type) {
  5517. case 'C': case 'B':
  5518. type_mask |= (uint32_t)UFBXI_VALUE_NUMBER << (i*2);
  5519. vals[i].f = (double)(vals[i].i = (int64_t)value[0]);
  5520. ufbxi_consume_bytes(uc, 2);
  5521. break;
  5522. case 'Y':
  5523. type_mask |= (uint32_t)UFBXI_VALUE_NUMBER << (i*2);
  5524. vals[i].f = (double)(vals[i].i = ufbxi_read_i16(value));
  5525. ufbxi_consume_bytes(uc, 3);
  5526. break;
  5527. case 'I':
  5528. type_mask |= (uint32_t)UFBXI_VALUE_NUMBER << (i*2);
  5529. vals[i].f = (double)(vals[i].i = ufbxi_read_i32(value));
  5530. ufbxi_consume_bytes(uc, 5);
  5531. break;
  5532. case 'L':
  5533. type_mask |= (uint32_t)UFBXI_VALUE_NUMBER << (i*2);
  5534. vals[i].f = (double)(vals[i].i = ufbxi_read_i64(value));
  5535. ufbxi_consume_bytes(uc, 9);
  5536. break;
  5537. case 'F':
  5538. type_mask |= (uint32_t)UFBXI_VALUE_NUMBER << (i*2);
  5539. vals[i].i = ufbxi_f64_to_i64(vals[i].f = ufbxi_read_f32(value));
  5540. ufbxi_consume_bytes(uc, 5);
  5541. break;
  5542. case 'D':
  5543. type_mask |= (uint32_t)UFBXI_VALUE_NUMBER << (i*2);
  5544. vals[i].i = ufbxi_f64_to_i64(vals[i].f = ufbxi_read_f64(value));
  5545. ufbxi_consume_bytes(uc, 9);
  5546. break;
  5547. case 'S': case 'R':
  5548. {
  5549. uint32_t length = ufbxi_read_u32(value);
  5550. ufbxi_consume_bytes(uc, 5);
  5551. const char *str = ufbxi_read_bytes(uc, length);
  5552. ufbxi_check(str);
  5553. if (length == 0) {
  5554. vals[i].s.raw_data = ufbxi_empty_char;
  5555. vals[i].s.raw_length = 0;
  5556. vals[i].s.utf8_length = 0;
  5557. } else {
  5558. bool non_ascii = false;
  5559. uint32_t hash = ufbxi_hash_string_check_ascii(str, length, &non_ascii);
  5560. bool raw = !non_ascii || ufbxi_is_raw_string(uc, parent_state, name, i);
  5561. ufbxi_check(ufbxi_push_sanitized_string(&uc->string_pool, &vals[i].s, str, length, hash, raw));
  5562. // Mark the data as invalid UTF-8
  5563. if (non_ascii && raw) vals[i].s.utf8_length = UINT32_MAX;
  5564. }
  5565. type_mask |= (uint32_t)UFBXI_VALUE_STRING << (i*2);
  5566. }
  5567. break;
  5568. // Treat arrays as non-values and skip them
  5569. case 'c': case 'b': case 'i': case 'l': case 'f': case 'd':
  5570. {
  5571. uint32_t encoded_size = ufbxi_read_u32(value + 8);
  5572. ufbxi_consume_bytes(uc, 13);
  5573. ufbxi_check(ufbxi_skip_bytes(uc, encoded_size));
  5574. }
  5575. break;
  5576. default:
  5577. ufbxi_fail("Bad value type");
  5578. }
  5579. }
  5580. node->value_type_mask = (uint16_t)type_mask;
  5581. }
  5582. // Skip over remaining values if necessary if we for example truncated
  5583. // the list of values or if there are values after an array
  5584. uint64_t offset = ufbxi_get_read_offset(uc);
  5585. ufbxi_check(offset <= values_end_offset);
  5586. if (offset < values_end_offset) {
  5587. ufbxi_check(ufbxi_skip_bytes(uc, values_end_offset - offset));
  5588. }
  5589. if (recursive) {
  5590. // Recursively parse the children of this node. Update the parse state
  5591. // to provide context for child node parsing.
  5592. ufbxi_parse_state parse_state = ufbxi_update_parse_state(parent_state, node->name);
  5593. uint32_t num_children = 0;
  5594. for (;;) {
  5595. // Stop at end offset
  5596. uint64_t current_offset = ufbxi_get_read_offset(uc);
  5597. if (current_offset >= end_offset) {
  5598. ufbxi_check(current_offset == end_offset || end_offset == 0);
  5599. break;
  5600. }
  5601. bool end = false;
  5602. ufbxi_check(ufbxi_binary_parse_node(uc, depth + 1, parse_state, &end, tmp_buf, true));
  5603. if (end) break;
  5604. num_children++;
  5605. }
  5606. // Pop children from `tmp_stack` to a contiguous array
  5607. node->num_children = num_children;
  5608. if (num_children > 0) {
  5609. node->children = ufbxi_push_pop(tmp_buf, &uc->tmp_stack, ufbxi_node, num_children);
  5610. ufbxi_check(node->children);
  5611. }
  5612. } else {
  5613. uint64_t current_offset = ufbxi_get_read_offset(uc);
  5614. uc->has_next_child = (current_offset < end_offset);
  5615. }
  5616. return 1;
  5617. }
  5618. #define UFBXI_BINARY_MAGIC_SIZE 22
  5619. #define UFBXI_BINARY_HEADER_SIZE 27
  5620. static const char ufbxi_binary_magic[] = "Kaydara FBX Binary \x00\x1a";
  5621. // -- ASCII parsing
  5622. #define UFBXI_ASCII_END '\0'
  5623. #define UFBXI_ASCII_NAME 'N'
  5624. #define UFBXI_ASCII_BARE_WORD 'B'
  5625. #define UFBXI_ASCII_INT 'I'
  5626. #define UFBXI_ASCII_FLOAT 'F'
  5627. #define UFBXI_ASCII_STRING 'S'
  5628. static ufbxi_noinline char ufbxi_ascii_refill(ufbxi_context *uc)
  5629. {
  5630. ufbxi_ascii *ua = &uc->ascii;
  5631. uc->data_offset += ufbxi_to_size(ua->src - uc->data_begin);
  5632. if (uc->read_fn) {
  5633. // Grow the read buffer if necessary
  5634. if (uc->read_buffer_size < uc->opts.read_buffer_size) {
  5635. size_t new_size = uc->opts.read_buffer_size;
  5636. ufbxi_check_return(ufbxi_grow_array(&uc->ator_tmp, &uc->read_buffer, &uc->read_buffer_size, new_size), '\0');
  5637. }
  5638. // Read user data, return '\0' on EOF
  5639. size_t num_read = uc->read_fn(uc->read_user, uc->read_buffer, uc->read_buffer_size);
  5640. ufbxi_check_return_msg(num_read != SIZE_MAX, '\0', "IO error");
  5641. ufbxi_check_return(num_read <= uc->read_buffer_size, '\0');
  5642. if (num_read == 0) return '\0';
  5643. uc->data = uc->data_begin = ua->src = uc->read_buffer;
  5644. ua->src_end = uc->read_buffer + num_read;
  5645. return *ua->src;
  5646. } else {
  5647. // If the user didn't specify a `read_fn()` treat anything
  5648. // past the initial data buffer as EOF.
  5649. uc->data = uc->data_begin = ua->src = "";
  5650. ua->src_end = ua->src + 1;
  5651. return '\0';
  5652. }
  5653. }
  5654. static ufbxi_noinline char ufbxi_ascii_yield(ufbxi_context *uc)
  5655. {
  5656. ufbxi_ascii *ua = &uc->ascii;
  5657. char ret;
  5658. if (ua->src == ua->src_end) {
  5659. ret = ufbxi_ascii_refill(uc);
  5660. } else {
  5661. ret = *ua->src;
  5662. }
  5663. if (ufbxi_to_size(ua->src_end - ua->src) < uc->progress_interval) {
  5664. ua->src_yield = ua->src_end;
  5665. } else {
  5666. ua->src_yield = ua->src + uc->progress_interval;
  5667. }
  5668. // TODO: Unify these properly
  5669. uc->data = ua->src;
  5670. ufbxi_check_return(ufbxi_report_progress(uc), '\0');
  5671. return ret;
  5672. }
  5673. static ufbxi_forceinline char ufbxi_ascii_peek(ufbxi_context *uc)
  5674. {
  5675. ufbxi_ascii *ua = &uc->ascii;
  5676. if (ua->src == ua->src_yield) return ufbxi_ascii_yield(uc);
  5677. return *ua->src;
  5678. }
  5679. static ufbxi_forceinline char ufbxi_ascii_next(ufbxi_context *uc)
  5680. {
  5681. ufbxi_ascii *ua = &uc->ascii;
  5682. if (ua->src == ua->src_yield) return ufbxi_ascii_yield(uc);
  5683. ua->src++;
  5684. if (ua->src == ua->src_yield) return ufbxi_ascii_yield(uc);
  5685. return *ua->src;
  5686. }
  5687. static ufbxi_noinline uint32_t ufbxi_ascii_parse_version(ufbxi_context *uc)
  5688. {
  5689. uint8_t digits[3];
  5690. uint32_t num_digits = 0;
  5691. char c = ufbxi_ascii_next(uc);
  5692. const char fmt[] = " FBX ?.?.?";
  5693. uint32_t ix = 0;
  5694. while (num_digits < 3) {
  5695. char ref = fmt[ix++];
  5696. switch (ref) {
  5697. // Digit
  5698. case '?':
  5699. if (c < '0' || c > '9') return 0;
  5700. digits[num_digits++] = (uint8_t)(c - '0');
  5701. c = ufbxi_ascii_next(uc);
  5702. break;
  5703. // Whitespace
  5704. case ' ':
  5705. while (c == ' ' || c == '\t') {
  5706. c = ufbxi_ascii_next(uc);
  5707. }
  5708. break;
  5709. // Literal character
  5710. default:
  5711. if (c != ref) return 0;
  5712. c = ufbxi_ascii_next(uc);
  5713. break;
  5714. }
  5715. }
  5716. if (num_digits != 3) return 0;
  5717. return 1000u*(uint32_t)digits[0] + 100u*(uint32_t)digits[1] + 10u*(uint32_t)digits[2];
  5718. }
  5719. static ufbxi_noinline char ufbxi_ascii_skip_whitespace(ufbxi_context *uc)
  5720. {
  5721. ufbxi_ascii *ua = &uc->ascii;
  5722. // Ignore whitespace
  5723. char c = ufbxi_ascii_peek(uc);
  5724. for (;;) {
  5725. while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
  5726. c = ufbxi_ascii_next(uc);
  5727. }
  5728. // Line comment
  5729. if (c == ';') {
  5730. bool read_magic = false;
  5731. // FBX ASCII files begin with a magic comment of form "; FBX 7.7.0 project file"
  5732. // Try to extract the version number from the magic comment
  5733. if (!ua->read_first_comment) {
  5734. ua->read_first_comment = true;
  5735. uint32_t version = ufbxi_ascii_parse_version(uc);
  5736. if (version) {
  5737. uc->version = version;
  5738. ua->found_version = true;
  5739. read_magic = true;
  5740. }
  5741. }
  5742. c = ufbxi_ascii_next(uc);
  5743. while (c != '\n' && c != '\0') {
  5744. c = ufbxi_ascii_next(uc);
  5745. }
  5746. c = ufbxi_ascii_next(uc);
  5747. // Try to determine if this is a Blender 6100 ASCII file
  5748. if (read_magic) {
  5749. if (c == ';') {
  5750. char line[32];
  5751. size_t line_len = 0;
  5752. c = ufbxi_ascii_next(uc);
  5753. while (c != '\n' && c != '\0') {
  5754. if (line_len < sizeof(line)) {
  5755. line[line_len++] = c;
  5756. }
  5757. c = ufbxi_ascii_next(uc);
  5758. }
  5759. if (line_len >= 19 && !memcmp(line, " Created by Blender", 19)) {
  5760. uc->exporter = UFBX_EXPORTER_BLENDER_ASCII;
  5761. }
  5762. }
  5763. }
  5764. } else {
  5765. break;
  5766. }
  5767. }
  5768. return c;
  5769. }
  5770. ufbxi_nodiscard static ufbxi_forceinline int ufbxi_ascii_push_token_char(ufbxi_context *uc, ufbxi_ascii_token *token, char c)
  5771. {
  5772. // Grow the string data buffer if necessary
  5773. if (token->str_len == token->str_cap) {
  5774. size_t len = ufbxi_max_sz(token->str_len + 1, 256);
  5775. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &token->str_data, &token->str_cap, len));
  5776. }
  5777. token->str_data[token->str_len++] = c;
  5778. return 1;
  5779. }
  5780. ufbxi_nodiscard ufbxi_noinline static int ufbxi_ascii_skip_until(ufbxi_context *uc, char dst)
  5781. {
  5782. ufbxi_ascii *ua = &uc->ascii;
  5783. for (;;) {
  5784. size_t buffered = ufbxi_to_size(ua->src_yield - ua->src);
  5785. const char *match = (const char*)memchr(ua->src, dst, buffered);
  5786. if (match) {
  5787. ua->src = match;
  5788. break;
  5789. } else {
  5790. ua->src += buffered;
  5791. }
  5792. if (buffered == 0) {
  5793. char c = ufbxi_ascii_yield(uc);
  5794. ufbxi_check(c != '\0');
  5795. }
  5796. }
  5797. return 1;
  5798. }
  5799. ufbxi_nodiscard ufbxi_noinline static int ufbxi_ascii_try_ignore_string(ufbxi_context *uc, ufbxi_ascii_token *token)
  5800. {
  5801. ufbxi_ascii *ua = &uc->ascii;
  5802. char c = ufbxi_ascii_skip_whitespace(uc);
  5803. token->str_len = 0;
  5804. if (c == '"') {
  5805. // Replace `prev_token` with `token` but swap the buffers so `token` uses
  5806. // the now-unused string buffer of the old `prev_token`.
  5807. char *swap_data = ua->prev_token.str_data;
  5808. size_t swap_cap = ua->prev_token.str_cap;
  5809. ua->prev_token = ua->token;
  5810. ua->token.str_data = swap_data;
  5811. ua->token.str_cap = swap_cap;
  5812. token->type = UFBXI_ASCII_STRING;
  5813. // Skip opening quote
  5814. ufbxi_ascii_next(uc);
  5815. ufbxi_check(ufbxi_ascii_skip_until(uc, '"'));
  5816. // Skip closing quote
  5817. ufbxi_ascii_next(uc);
  5818. return true;
  5819. }
  5820. return false;
  5821. }
  5822. ufbxi_nodiscard ufbxi_noinline static int ufbxi_ascii_next_token(ufbxi_context *uc, ufbxi_ascii_token *token)
  5823. {
  5824. ufbxi_ascii *ua = &uc->ascii;
  5825. // Replace `prev_token` with `token` but swap the buffers so `token` uses
  5826. // the now-unused string buffer of the old `prev_token`.
  5827. char *swap_data = ua->prev_token.str_data;
  5828. size_t swap_cap = ua->prev_token.str_cap;
  5829. ua->prev_token = ua->token;
  5830. ua->token.str_data = swap_data;
  5831. ua->token.str_cap = swap_cap;
  5832. char c = ufbxi_ascii_skip_whitespace(uc);
  5833. token->str_len = 0;
  5834. if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') {
  5835. token->type = UFBXI_ASCII_BARE_WORD;
  5836. while ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
  5837. || (c >= '0' && c <= '9') || c == '_') {
  5838. ufbxi_check(ufbxi_ascii_push_token_char(uc, token, c));
  5839. c = ufbxi_ascii_next(uc);
  5840. }
  5841. // Skip whitespace to find if there's a following ':'
  5842. c = ufbxi_ascii_skip_whitespace(uc);
  5843. if (c == ':') {
  5844. token->value.name_len = token->str_len;
  5845. token->type = UFBXI_ASCII_NAME;
  5846. ufbxi_ascii_next(uc);
  5847. }
  5848. } else if ((c >= '0' && c <= '9') || c == '-' || c == '+' || c == '.') {
  5849. token->type = UFBXI_ASCII_INT;
  5850. while ((c >= '0' && c <= '9') || c == '-' || c == '+' || c == '.' || c == 'e' || c == 'E') {
  5851. if (c == '.' || c == 'e' || c == 'E') {
  5852. token->type = UFBXI_ASCII_FLOAT;
  5853. }
  5854. ufbxi_check(ufbxi_ascii_push_token_char(uc, token, c));
  5855. c = ufbxi_ascii_next(uc);
  5856. }
  5857. if (c == '#') {
  5858. ufbxi_check(token->type == UFBXI_ASCII_FLOAT);
  5859. ufbxi_check(ufbxi_ascii_push_token_char(uc, token, c));
  5860. c = ufbxi_ascii_next(uc);
  5861. bool is_inf = c == 'I' || c == 'i';
  5862. while ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
  5863. ufbxi_check(ufbxi_ascii_push_token_char(uc, token, c));
  5864. c = ufbxi_ascii_next(uc);
  5865. }
  5866. ufbxi_check(ufbxi_ascii_push_token_char(uc, token, '\0'));
  5867. if (is_inf) {
  5868. token->value.f64 = token->str_data[0] == '-' ? -UFBX_INFINITY : UFBX_INFINITY;
  5869. } else {
  5870. token->value.f64 = UFBX_NAN;
  5871. }
  5872. } else {
  5873. ufbxi_check(ufbxi_ascii_push_token_char(uc, token, '\0'));
  5874. char *end;
  5875. if (token->type == UFBXI_ASCII_INT) {
  5876. token->value.i64 = strtoll(token->str_data, &end, 10);
  5877. ufbxi_check(end == token->str_data + token->str_len - 1);
  5878. } else if (token->type == UFBXI_ASCII_FLOAT) {
  5879. if (ua->parse_as_f32) {
  5880. token->value.f64 = strtof(token->str_data, &end);
  5881. } else {
  5882. token->value.f64 = strtod(token->str_data, &end);
  5883. }
  5884. ufbxi_check(end == token->str_data + token->str_len - 1);
  5885. }
  5886. }
  5887. } else if (c == '"') {
  5888. token->type = UFBXI_ASCII_STRING;
  5889. c = ufbxi_ascii_next(uc);
  5890. while (c != '"') {
  5891. // Escape XML-like elements, funny enough there is no way to escape '&' itself, there is no `&amp`.
  5892. // '&quot;' -> '"'
  5893. // '&cr;' -> '\r'
  5894. // '&lf;' -> '\n'
  5895. if (c == '&') {
  5896. const char *entity = NULL;
  5897. char replacement = '\0';
  5898. c = ufbxi_ascii_next(uc);
  5899. switch (c) {
  5900. case 'q':
  5901. entity = "&quot;";
  5902. replacement = '"';
  5903. break;
  5904. case 'c':
  5905. entity = "&cr;";
  5906. replacement = '\r';
  5907. break;
  5908. case 'l':
  5909. entity = "&lf;";
  5910. replacement = '\n';
  5911. break;
  5912. default:
  5913. // As '&' is not escaped in any way just map '&' -> '&'
  5914. entity = "&";
  5915. replacement = '&';
  5916. break;
  5917. }
  5918. size_t step = 1;
  5919. for (; entity[step]; step++) {
  5920. if (c != entity[step]) break;
  5921. c = ufbxi_ascii_next(uc);
  5922. }
  5923. if (entity[step] == '\0') {
  5924. // Full match: Push the replacement character
  5925. ufbxi_check(ufbxi_ascii_push_token_char(uc, token, replacement));
  5926. } else {
  5927. // Partial match: Push the prefix we have skipped already
  5928. for (size_t i = 0; i < step; i++) {
  5929. ufbxi_check(ufbxi_ascii_push_token_char(uc, token, entity[i]));
  5930. }
  5931. }
  5932. continue;
  5933. }
  5934. ufbxi_check(c != '\0');
  5935. ufbxi_check(ufbxi_ascii_push_token_char(uc, token, c));
  5936. c = ufbxi_ascii_next(uc);
  5937. }
  5938. // Skip closing quote
  5939. ufbxi_ascii_next(uc);
  5940. } else {
  5941. // Single character token
  5942. token->type = c;
  5943. ufbxi_ascii_next(uc);
  5944. }
  5945. return 1;
  5946. }
  5947. ufbxi_nodiscard static int ufbxi_ascii_accept(ufbxi_context *uc, char type)
  5948. {
  5949. ufbxi_ascii *ua = &uc->ascii;
  5950. if (ua->token.type == type) {
  5951. ufbxi_check(ufbxi_ascii_next_token(uc, &ua->token));
  5952. return 1;
  5953. } else {
  5954. return 0;
  5955. }
  5956. }
  5957. ufbxi_nodiscard ufbxi_noinline static int ufbxi_ascii_parse_node(ufbxi_context *uc, uint32_t depth, ufbxi_parse_state parent_state, bool *p_end, ufbxi_buf *tmp_buf, bool recursive)
  5958. {
  5959. ufbxi_ascii *ua = &uc->ascii;
  5960. if (ua->token.type == '}') {
  5961. ufbxi_check(ufbxi_ascii_next_token(uc, &ua->token));
  5962. *p_end = true;
  5963. return 1;
  5964. }
  5965. if (ua->token.type == UFBXI_ASCII_END) {
  5966. ufbxi_check_msg(depth == 0, "Truncated file");
  5967. *p_end = true;
  5968. return 1;
  5969. }
  5970. // Parse the name eg. "Node:" token and intern the name
  5971. ufbxi_check(depth < UFBXI_MAX_NODE_DEPTH);
  5972. if (!uc->sure_fbx && depth == 0 && ua->token.type != UFBXI_ASCII_NAME) {
  5973. ufbxi_fail_msg("Expected a 'Name:' token", "Not an FBX file");
  5974. }
  5975. ufbxi_check(ufbxi_ascii_accept(uc, UFBXI_ASCII_NAME));
  5976. size_t name_len = ua->prev_token.value.name_len;
  5977. ufbxi_check(name_len <= 0xff);
  5978. const char *name = ufbxi_push_string(&uc->string_pool, ua->prev_token.str_data, ua->prev_token.str_len, NULL, true);
  5979. ufbxi_check(name);
  5980. // Push the parsed node into the `tmp_stack` buffer, the nodes will be popped by
  5981. // calling code after its done parsing all of it's children.
  5982. ufbxi_node *node = ufbxi_push_zero(&uc->tmp_stack, ufbxi_node, 1);
  5983. ufbxi_check(node);
  5984. node->name = name;
  5985. node->name_len = (uint8_t)name_len;
  5986. bool in_ascii_array = false;
  5987. uint32_t num_values = 0;
  5988. uint32_t type_mask = 0;
  5989. int arr_type = 0;
  5990. ufbxi_buf *arr_buf = NULL;
  5991. size_t arr_elem_size = 0;
  5992. // Check if the values of the node we're parsing currently should be
  5993. // treated as an array.
  5994. ufbxi_array_info arr_info;
  5995. if (ufbxi_is_array_node(uc, parent_state, name, &arr_info)) {
  5996. uint32_t flags = arr_info.flags;
  5997. arr_type = ufbxi_normalize_array_type(arr_info.type);
  5998. arr_buf = tmp_buf;
  5999. if (flags & UFBXI_ARRAY_FLAG_RESULT) arr_buf = &uc->result;
  6000. else if (flags & UFBXI_ARRAY_FLAG_TMP_BUF) arr_buf = &uc->tmp;
  6001. ufbxi_value_array *arr = ufbxi_push(tmp_buf, ufbxi_value_array, 1);
  6002. ufbxi_check(arr);
  6003. node->value_type_mask = UFBXI_VALUE_ARRAY;
  6004. node->array = arr;
  6005. arr->type = (char)arr_type;
  6006. // Parse array values using strtof() if the array destination is 32-bit float
  6007. // since KeyAttrDataFloat packs integer data (!) into floating point values so we
  6008. // should try to be as exact as possible.
  6009. if (arr->type == 'f') {
  6010. ua->parse_as_f32 = true;
  6011. }
  6012. arr_elem_size = ufbxi_array_type_size((char)arr_type);
  6013. // Pad with 4 zero elements to make indexing with `-1` safe.
  6014. if ((flags & UFBXI_ARRAY_FLAG_PAD_BEGIN) != 0 && arr_type != '-') {
  6015. ufbxi_check(ufbxi_push_size_zero(&uc->tmp_stack, arr_elem_size, 4));
  6016. num_values += 4;
  6017. }
  6018. }
  6019. // Some fields in ASCII may have leading commas eg. `Content: , "base64-string"`
  6020. if (ua->token.type == ',') {
  6021. // HACK: If we are parsing an "array" that should be ignored, ie. `Content` when
  6022. // `opts.ignore_embedded == true` try to skip the next token string if possible.
  6023. if (arr_type == '-') {
  6024. if (!ufbxi_ascii_try_ignore_string(uc, &ua->token)) {
  6025. ufbxi_check(ufbxi_ascii_next_token(uc, &ua->token));
  6026. }
  6027. } else {
  6028. ufbxi_check(ufbxi_ascii_next_token(uc, &ua->token));
  6029. }
  6030. }
  6031. ufbxi_parse_state parse_state = ufbxi_update_parse_state(parent_state, node->name);
  6032. ufbxi_value vals[UFBXI_MAX_NON_ARRAY_VALUES];
  6033. // NOTE: Infinite loop to allow skipping the comma parsing via `continue`.
  6034. for (;;) {
  6035. ufbxi_ascii_token *tok = &ua->prev_token;
  6036. if (ufbxi_ascii_accept(uc, UFBXI_ASCII_STRING)) {
  6037. if (arr_type) {
  6038. if (arr_type == 's' || arr_type == 'S' || arr_type == 'C') {
  6039. bool raw = arr_type == 's';
  6040. ufbx_string *v = ufbxi_push(&uc->tmp_stack, ufbx_string, 1);
  6041. ufbxi_check(v);
  6042. v->data = tok->str_data;
  6043. v->length = tok->str_len;
  6044. if (arr_type == 'C') {
  6045. ufbxi_buf *buf = uc->opts.retain_dom ? &uc->result : tmp_buf;
  6046. v->data = ufbxi_push_copy(buf, char, v->length, v->data);
  6047. ufbxi_check(v->data);
  6048. } else {
  6049. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, v, raw));
  6050. }
  6051. } else {
  6052. // Ignore strings in non-string arrays, decrement `num_values` as it will be
  6053. // incremented after the loop iteration is done to ignore it.
  6054. num_values--;
  6055. }
  6056. } else if (num_values < UFBXI_MAX_NON_ARRAY_VALUES) {
  6057. type_mask |= (uint32_t)UFBXI_VALUE_STRING << (num_values*2);
  6058. ufbxi_value *v = &vals[num_values];
  6059. const char *str = tok->str_data;
  6060. size_t length = tok->str_len;
  6061. ufbxi_check(str);
  6062. if (length == 0) {
  6063. v->s.raw_data = ufbxi_empty_char;
  6064. v->s.raw_length = 0;
  6065. v->s.utf8_length = 0;
  6066. } else {
  6067. bool non_ascii = false;
  6068. uint32_t hash = ufbxi_hash_string_check_ascii(str, length, &non_ascii);
  6069. bool raw = !non_ascii || ufbxi_is_raw_string(uc, parent_state, name, num_values);
  6070. ufbxi_check(ufbxi_push_sanitized_string(&uc->string_pool, &v->s, str, length, hash, raw));
  6071. if (non_ascii && raw) v->s.utf8_length = UINT32_MAX;
  6072. }
  6073. }
  6074. } else if (ufbxi_ascii_accept(uc, UFBXI_ASCII_INT)) {
  6075. int64_t val = tok->value.i64;
  6076. switch (arr_type) {
  6077. case 0:
  6078. // Parse version from comment if there was no magic comment
  6079. if (!ua->found_version && parse_state == UFBXI_PARSE_FBX_VERSION && num_values == 0) {
  6080. if (val >= 6000 && val <= 10000) {
  6081. ua->found_version = true;
  6082. uc->version = (uint32_t)val;
  6083. }
  6084. }
  6085. if (num_values < UFBXI_MAX_NON_ARRAY_VALUES) {
  6086. type_mask |= (uint32_t)UFBXI_VALUE_NUMBER << (num_values*2);
  6087. ufbxi_value *v = &vals[num_values];
  6088. v->f = (double)(v->i = val);
  6089. }
  6090. break;
  6091. case 'b': { bool *v = ufbxi_push(&uc->tmp_stack, bool, 1); ufbxi_check(v); *v = val != 0; } break;
  6092. case 'c': { uint8_t *v = ufbxi_push(&uc->tmp_stack, uint8_t, 1); ufbxi_check(v); *v = (uint8_t)val; } break;
  6093. case 'i': { int32_t *v = ufbxi_push(&uc->tmp_stack, int32_t, 1); ufbxi_check(v); *v = (int32_t)val; } break;
  6094. case 'l': { int64_t *v = ufbxi_push(&uc->tmp_stack, int64_t, 1); ufbxi_check(v); *v = (int64_t)val; } break;
  6095. case 'f': { float *v = ufbxi_push(&uc->tmp_stack, float, 1); ufbxi_check(v); *v = (float)val; } break;
  6096. case 'd': { double *v = ufbxi_push(&uc->tmp_stack, double, 1); ufbxi_check(v); *v = (double)val; } break;
  6097. case '-': num_values--; break;
  6098. default:
  6099. ufbxi_fail("Bad array dst type");
  6100. }
  6101. } else if (ufbxi_ascii_accept(uc, UFBXI_ASCII_FLOAT)) {
  6102. double val = tok->value.f64;
  6103. switch (arr_type) {
  6104. case 0:
  6105. if (num_values < UFBXI_MAX_NON_ARRAY_VALUES) {
  6106. type_mask |= (uint32_t)UFBXI_VALUE_NUMBER << (num_values*2);
  6107. ufbxi_value *v = &vals[num_values];
  6108. v->i = ufbxi_f64_to_i64(v->f = val);
  6109. }
  6110. break;
  6111. case 'b': { bool *v = ufbxi_push(&uc->tmp_stack, bool, 1); ufbxi_check(v); *v = val != 0; } break;
  6112. case 'c': { uint8_t *v = ufbxi_push(&uc->tmp_stack, uint8_t, 1); ufbxi_check(v); *v = (uint8_t)val; } break;
  6113. case 'i': { int32_t *v = ufbxi_push(&uc->tmp_stack, int32_t, 1); ufbxi_check(v); *v = (int32_t)val; } break;
  6114. case 'l': { int64_t *v = ufbxi_push(&uc->tmp_stack, int64_t, 1); ufbxi_check(v); *v = (int64_t)val; } break;
  6115. case 'f': { float *v = ufbxi_push(&uc->tmp_stack, float, 1); ufbxi_check(v); *v = (float)val; } break;
  6116. case 'd': { double *v = ufbxi_push(&uc->tmp_stack, double, 1); ufbxi_check(v); *v = (double)val; } break;
  6117. case '-': num_values--; break;
  6118. default:
  6119. ufbxi_fail("Bad array dst type");
  6120. }
  6121. } else if (ufbxi_ascii_accept(uc, UFBXI_ASCII_BARE_WORD)) {
  6122. int64_t val = 0;
  6123. if (tok->str_len >= 1) {
  6124. val = (int64_t)tok->str_data[0];
  6125. }
  6126. switch (arr_type) {
  6127. case 0:
  6128. if (num_values < UFBXI_MAX_NON_ARRAY_VALUES) {
  6129. type_mask |= (uint32_t)UFBXI_VALUE_NUMBER << (num_values*2);
  6130. ufbxi_value *v = &vals[num_values];
  6131. v->f = (double)(v->i = val);
  6132. }
  6133. break;
  6134. case 'b': { bool *v = ufbxi_push(&uc->tmp_stack, bool, 1); ufbxi_check(v); *v = val != 0; } break;
  6135. case 'c': { uint8_t *v = ufbxi_push(&uc->tmp_stack, uint8_t, 1); ufbxi_check(v); *v = (uint8_t)val; } break;
  6136. case 'i': { int32_t *v = ufbxi_push(&uc->tmp_stack, int32_t, 1); ufbxi_check(v); *v = (int32_t)val; } break;
  6137. case 'l': { int64_t *v = ufbxi_push(&uc->tmp_stack, int64_t, 1); ufbxi_check(v); *v = (int64_t)val; } break;
  6138. case 'f': { float *v = ufbxi_push(&uc->tmp_stack, float, 1); ufbxi_check(v); *v = (float)val; } break;
  6139. case 'd': { double *v = ufbxi_push(&uc->tmp_stack, double, 1); ufbxi_check(v); *v = (double)val; } break;
  6140. case '-': num_values--; break;
  6141. }
  6142. } else if (ufbxi_ascii_accept(uc, '*')) {
  6143. // Parse a post-7000 ASCII array eg. "*3 { 1,2,3 }"
  6144. ufbxi_check(!in_ascii_array);
  6145. ufbxi_check(ufbxi_ascii_accept(uc, UFBXI_ASCII_INT));
  6146. if (ufbxi_ascii_accept(uc, '{')) {
  6147. ufbxi_check(ufbxi_ascii_accept(uc, UFBXI_ASCII_NAME));
  6148. // NOTE: This `continue` skips incrementing `num_values` and parsing
  6149. // a comma, continuing to parse the values in the array.
  6150. in_ascii_array = true;
  6151. // Optimized array skipping
  6152. if (arr_type == '-') {
  6153. ufbxi_check(ufbxi_ascii_skip_until(uc, '}'));
  6154. }
  6155. }
  6156. continue;
  6157. } else {
  6158. break;
  6159. }
  6160. // Add value and keep parsing if there's a comma. This part may be
  6161. // skipped if we enter an array block.
  6162. num_values++;
  6163. ufbxi_check(num_values < UINT32_MAX);
  6164. if (!ufbxi_ascii_accept(uc, ',')) break;
  6165. }
  6166. // Close the ASCII array if we are in one
  6167. if (in_ascii_array) {
  6168. ufbxi_check(ufbxi_ascii_accept(uc, '}'));
  6169. }
  6170. ua->parse_as_f32 = false;
  6171. if (arr_type) {
  6172. if (arr_type == '-') {
  6173. node->array->data = NULL;
  6174. node->array->size = 0;
  6175. } else {
  6176. void *arr_data = ufbxi_push_pop_size(arr_buf, &uc->tmp_stack, arr_elem_size, num_values);
  6177. ufbxi_check(arr_data);
  6178. if (arr_info.flags & UFBXI_ARRAY_FLAG_PAD_BEGIN) {
  6179. node->array->data = (char*)arr_data + 4*arr_elem_size;
  6180. node->array->size = num_values - 4;
  6181. } else {
  6182. node->array->data = arr_data;
  6183. node->array->size = num_values;
  6184. }
  6185. }
  6186. } else {
  6187. num_values = ufbxi_min32(num_values, UFBXI_MAX_NON_ARRAY_VALUES);
  6188. node->value_type_mask = (uint16_t)type_mask;
  6189. node->vals = ufbxi_push_copy(tmp_buf, ufbxi_value, num_values, vals);
  6190. ufbxi_check(node->vals);
  6191. }
  6192. // Recursively parse the children of this node. Update the parse state
  6193. // to provide context for child node parsing.
  6194. if (ufbxi_ascii_accept(uc, '{')) {
  6195. if (recursive) {
  6196. size_t num_children = 0;
  6197. for (;;) {
  6198. bool end = false;
  6199. ufbxi_check(ufbxi_ascii_parse_node(uc, depth + 1, parse_state, &end, tmp_buf, recursive));
  6200. if (end) break;
  6201. num_children++;
  6202. }
  6203. // Pop children from `tmp_stack` to a contiguous array
  6204. node->children = ufbxi_push_pop(tmp_buf, &uc->tmp_stack, ufbxi_node, num_children);
  6205. ufbxi_check(node->children);
  6206. node->num_children = (uint32_t)num_children;
  6207. }
  6208. uc->has_next_child = true;
  6209. } else {
  6210. uc->has_next_child = false;
  6211. }
  6212. return 1;
  6213. }
  6214. // -- DOM retention
  6215. typedef struct {
  6216. uintptr_t node_ptr;
  6217. ufbx_dom_node *dom_node;
  6218. } ufbxi_dom_mapping;
  6219. ufbxi_nodiscard static ufbxi_noinline ufbx_dom_node *ufbxi_get_dom_node_imp(ufbxi_context *uc, ufbxi_node *node)
  6220. {
  6221. if (!node) return NULL;
  6222. ufbxi_dom_mapping mapping = { (uintptr_t)node, NULL };
  6223. uint32_t hash = ufbxi_hash_uptr(mapping.node_ptr);
  6224. ufbxi_dom_mapping *result = ufbxi_map_find(&uc->dom_node_map, ufbxi_dom_mapping, hash, &mapping);
  6225. return result ? result->dom_node : NULL;
  6226. }
  6227. ufbxi_nodiscard static ufbxi_forceinline ufbx_dom_node *ufbxi_get_dom_node(ufbxi_context *uc, ufbxi_node *node)
  6228. {
  6229. if (!uc->opts.retain_dom) return NULL;
  6230. return ufbxi_get_dom_node_imp(uc, node);
  6231. }
  6232. ufbxi_nodiscard static ufbxi_noinline int ufbxi_retain_dom_node(ufbxi_context *uc, ufbxi_node *node, ufbx_dom_node **p_dom_node)
  6233. {
  6234. ufbx_dom_node *dst = ufbxi_push_zero(&uc->result, ufbx_dom_node, 1);
  6235. ufbxi_check(dst);
  6236. ufbxi_check(ufbxi_push_copy(&uc->tmp_dom_nodes, ufbx_dom_node*, 1, &dst));
  6237. if (p_dom_node) {
  6238. *p_dom_node = dst;
  6239. }
  6240. dst->name.data = node->name;
  6241. dst->name.length = node->name_len;
  6242. {
  6243. ufbxi_dom_mapping mapping = { (uintptr_t)node, NULL };
  6244. uint32_t hash = ufbxi_hash_uptr(mapping.node_ptr);
  6245. ufbxi_dom_mapping *result = ufbxi_map_find(&uc->dom_node_map, ufbxi_dom_mapping, hash, &mapping);
  6246. if (!result) {
  6247. result = ufbxi_map_insert(&uc->dom_node_map, ufbxi_dom_mapping, hash, &mapping);
  6248. ufbxi_check(result);
  6249. }
  6250. result->node_ptr = (uintptr_t)node;
  6251. result->dom_node = dst;
  6252. }
  6253. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &dst->name, false));
  6254. if (node->value_type_mask == UFBXI_VALUE_ARRAY) {
  6255. ufbxi_value_array *arr = node->array;
  6256. ufbx_dom_value *val = ufbxi_push_zero(&uc->result, ufbx_dom_value, 1);
  6257. ufbxi_check(val);
  6258. dst->values.data = val;
  6259. dst->values.count = 1;
  6260. size_t elem_size = ufbxi_array_type_size(arr->type);
  6261. val->value_str.data = ufbxi_empty_char;
  6262. val->value_blob.data = arr->data;
  6263. val->value_blob.size = arr->size * elem_size;
  6264. val->value_float = (double)(val->value_int = (int64_t)arr->size);
  6265. switch (arr->type) {
  6266. case 'c': val->type = UFBX_DOM_VALUE_ARRAY_I8; break;
  6267. case 'i': val->type = UFBX_DOM_VALUE_ARRAY_I32; break;
  6268. case 'l': val->type = UFBX_DOM_VALUE_ARRAY_I64; break;
  6269. case 'f': val->type = UFBX_DOM_VALUE_ARRAY_F32; break;
  6270. case 'd': val->type = UFBX_DOM_VALUE_ARRAY_F64; break;
  6271. case 's': val->type = UFBX_DOM_VALUE_ARRAY_RAW_STRING; break;
  6272. case 'C': val->type = UFBX_DOM_VALUE_ARRAY_RAW_STRING; break;
  6273. case '-': val->type = UFBX_DOM_VALUE_ARRAY_IGNORED; break;
  6274. default: ufbxi_fail("Bad array type"); break;
  6275. }
  6276. } else {
  6277. size_t ix;
  6278. for (ix = 0; ix < UFBXI_MAX_NON_ARRAY_VALUES; ix++) {
  6279. uint32_t mask = (node->value_type_mask >> (2*ix)) & 0x3;
  6280. if (!mask) break;
  6281. ufbx_dom_value *val = ufbxi_push_zero(&uc->tmp_stack, ufbx_dom_value, 1);
  6282. ufbxi_check(val);
  6283. val->value_str.data = ufbxi_empty_char;
  6284. if (mask == UFBXI_VALUE_STRING) {
  6285. val->type = UFBX_DOM_VALUE_STRING;
  6286. ufbxi_ignore(ufbxi_get_val_at(node, ix, 'S', &val->value_str));
  6287. ufbxi_ignore(ufbxi_get_val_at(node, ix, 'b', &val->value_blob));
  6288. } else {
  6289. ufbx_assert(mask == UFBXI_VALUE_NUMBER);
  6290. val->type = UFBX_DOM_VALUE_NUMBER;
  6291. val->value_int = node->vals[ix].i;
  6292. val->value_float = node->vals[ix].f;
  6293. }
  6294. }
  6295. dst->values.count = ix;
  6296. dst->values.data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_dom_value, ix);
  6297. ufbxi_check(dst->values.data);
  6298. }
  6299. if (node->num_children > 0) {
  6300. ufbxi_for(ufbxi_node, child, node->children, node->num_children) {
  6301. ufbxi_check(ufbxi_retain_dom_node(uc, child, NULL));
  6302. }
  6303. dst->children.count = node->num_children;
  6304. dst->children.data = ufbxi_push_pop(&uc->result, &uc->tmp_dom_nodes, ufbx_dom_node*, node->num_children);
  6305. ufbxi_check(dst->children.data);
  6306. }
  6307. return 1;
  6308. }
  6309. ufbxi_nodiscard static ufbxi_noinline int ufbxi_retain_toplevel(ufbxi_context *uc, ufbxi_node *node)
  6310. {
  6311. if (uc->dom_parse_num_children > 0) {
  6312. ufbx_dom_node **children = ufbxi_push_pop(&uc->result, &uc->tmp_dom_nodes, ufbx_dom_node*, uc->dom_parse_num_children);
  6313. ufbxi_check(children);
  6314. uc->dom_parse_toplevel->children.data = children;
  6315. uc->dom_parse_toplevel->children.count = uc->dom_parse_num_children;
  6316. uc->dom_parse_num_children = 0;
  6317. }
  6318. if (node) {
  6319. ufbxi_check(ufbxi_retain_dom_node(uc, node, &uc->dom_parse_toplevel));
  6320. } else {
  6321. uc->dom_parse_toplevel = NULL;
  6322. // Called with NULL argument to finish retaining DOM, collect the final nodes to `ufbx_scene`.
  6323. size_t num_top_nodes = uc->tmp_dom_nodes.num_items;
  6324. ufbx_dom_node **nodes = ufbxi_push_pop(&uc->result, &uc->tmp_dom_nodes, ufbx_dom_node*, num_top_nodes);
  6325. ufbxi_check(nodes);
  6326. ufbx_dom_node *dom_root = ufbxi_push_zero(&uc->result, ufbx_dom_node, 1);
  6327. ufbxi_check(dom_root);
  6328. dom_root->name.data = ufbxi_empty_char;
  6329. dom_root->children.data = nodes;
  6330. dom_root->children.count = num_top_nodes;
  6331. uc->scene.dom_root = dom_root;
  6332. }
  6333. return 1;
  6334. }
  6335. ufbxi_nodiscard static ufbxi_noinline int ufbxi_retain_toplevel_child(ufbxi_context *uc, ufbxi_node *child)
  6336. {
  6337. ufbx_assert(uc->dom_parse_toplevel);
  6338. ufbxi_check(ufbxi_retain_dom_node(uc, child, NULL));
  6339. uc->dom_parse_num_children++;
  6340. return 1;
  6341. }
  6342. // -- General parsing
  6343. ufbxi_nodiscard static ufbxi_noinline int ufbxi_begin_parse(ufbxi_context *uc)
  6344. {
  6345. const char *header = ufbxi_peek_bytes(uc, UFBXI_BINARY_HEADER_SIZE);
  6346. ufbxi_check(header);
  6347. // If the file starts with the binary magic parse it as binary, otherwise
  6348. // treat it as an ASCII file.
  6349. if (!memcmp(header, ufbxi_binary_magic, UFBXI_BINARY_MAGIC_SIZE)) {
  6350. // The byte after the magic indicates endianness
  6351. char endian = header[UFBXI_BINARY_MAGIC_SIZE + 0];
  6352. uc->file_big_endian = endian != 0;
  6353. // Read the version directly from the header
  6354. const char *version_word = header + UFBXI_BINARY_MAGIC_SIZE + 1;
  6355. if (uc->file_big_endian) {
  6356. version_word = ufbxi_swap_endian(uc, version_word, 1, 4);
  6357. ufbxi_check(version_word);
  6358. }
  6359. uc->version = ufbxi_read_u32(version_word);
  6360. // This is quite probably an FBX file..
  6361. uc->sure_fbx = true;
  6362. ufbxi_consume_bytes(uc, UFBXI_BINARY_HEADER_SIZE);
  6363. } else {
  6364. uc->from_ascii = true;
  6365. // Use the current read buffer as the initial parse buffer
  6366. memset(&uc->ascii, 0, sizeof(uc->ascii));
  6367. uc->ascii.src = uc->data;
  6368. uc->ascii.src_yield = uc->data + uc->yield_size;
  6369. uc->ascii.src_end = uc->data + uc->data_size + uc->yield_size;
  6370. // Initialize the first token
  6371. ufbxi_check(ufbxi_ascii_next_token(uc, &uc->ascii.token));
  6372. // Default to version 7400 if not found in header
  6373. if (uc->version > 0) {
  6374. uc->sure_fbx = true;
  6375. } else {
  6376. if (!uc->opts.strict) uc->version = 7400;
  6377. ufbxi_check_msg(uc->version > 0, "Not an FBX file");
  6378. }
  6379. }
  6380. // Initialize the scene
  6381. uc->scene.metadata.creator = ufbx_empty_string;
  6382. return 1;
  6383. }
  6384. ufbxi_nodiscard static int ufbxi_parse_toplevel_child_imp(ufbxi_context *uc, ufbxi_parse_state state, ufbxi_buf *buf, bool *p_end)
  6385. {
  6386. if (uc->from_ascii) {
  6387. ufbxi_check(ufbxi_ascii_parse_node(uc, 0, state, p_end, buf, true));
  6388. } else {
  6389. ufbxi_check(ufbxi_binary_parse_node(uc, 0, state, p_end, buf, true));
  6390. }
  6391. return 1;
  6392. }
  6393. ufbxi_nodiscard ufbxi_noinline static int ufbxi_parse_toplevel(ufbxi_context *uc, const char *name)
  6394. {
  6395. ufbxi_for(ufbxi_node, node, uc->top_nodes, uc->top_nodes_len) {
  6396. if (node->name == name) {
  6397. uc->top_node = node;
  6398. uc->top_child_index = 0;
  6399. return 1;
  6400. }
  6401. }
  6402. // Reached end and not found in cache
  6403. if (uc->parsed_to_end) {
  6404. uc->top_node = NULL;
  6405. uc->top_child_index = 0;
  6406. return 1;
  6407. }
  6408. for (;;) {
  6409. // Parse the next top-level node
  6410. bool end = false;
  6411. if (uc->from_ascii) {
  6412. ufbxi_check(ufbxi_ascii_parse_node(uc, 0, UFBXI_PARSE_ROOT, &end, &uc->tmp, false));
  6413. } else {
  6414. ufbxi_check(ufbxi_binary_parse_node(uc, 0, UFBXI_PARSE_ROOT, &end, &uc->tmp, false));
  6415. }
  6416. // Top-level node not found
  6417. if (end) {
  6418. uc->top_node = NULL;
  6419. uc->top_child_index = 0;
  6420. uc->parsed_to_end = true;
  6421. if (uc->opts.retain_dom) {
  6422. ufbxi_check(ufbxi_retain_toplevel(uc, NULL));
  6423. }
  6424. // Not needed anymore
  6425. ufbxi_buf_free(&uc->tmp_parse);
  6426. return 1;
  6427. }
  6428. uc->top_nodes_len++;
  6429. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->top_nodes, &uc->top_nodes_cap, uc->top_nodes_len));
  6430. ufbxi_node *node = &uc->top_nodes[uc->top_nodes_len - 1];
  6431. ufbxi_pop(&uc->tmp_stack, ufbxi_node, 1, node);
  6432. if (uc->opts.retain_dom) {
  6433. ufbxi_check(ufbxi_retain_toplevel(uc, node));
  6434. }
  6435. // Return if we parsed the right one
  6436. if (node->name == name) {
  6437. uc->top_node = node;
  6438. uc->top_child_index = SIZE_MAX;
  6439. return 1;
  6440. }
  6441. // If not we need to parse all the children of the node for later
  6442. uint32_t num_children = 0;
  6443. ufbxi_parse_state state = ufbxi_update_parse_state(UFBXI_PARSE_ROOT, node->name);
  6444. if (uc->has_next_child) {
  6445. for (;;) {
  6446. ufbxi_check(ufbxi_parse_toplevel_child_imp(uc, state, &uc->tmp, &end));
  6447. if (end) break;
  6448. num_children++;
  6449. }
  6450. }
  6451. node->num_children = num_children;
  6452. node->children = ufbxi_push_pop(&uc->tmp, &uc->tmp_stack, ufbxi_node, num_children);
  6453. ufbxi_check(node->children);
  6454. if (uc->opts.retain_dom) {
  6455. for (size_t i = 0; i < num_children; i++) {
  6456. ufbxi_check(ufbxi_retain_toplevel_child(uc, &node->children[i]));
  6457. }
  6458. }
  6459. }
  6460. }
  6461. ufbxi_nodiscard ufbxi_noinline static int ufbxi_parse_toplevel_child(ufbxi_context *uc, ufbxi_node **p_node)
  6462. {
  6463. // Top-level node not found
  6464. if (!uc->top_node) {
  6465. *p_node = NULL;
  6466. return 1;
  6467. }
  6468. if (uc->top_child_index == SIZE_MAX) {
  6469. // Parse children on demand
  6470. ufbxi_buf_clear(&uc->tmp_parse);
  6471. bool end = false;
  6472. ufbxi_parse_state state = ufbxi_update_parse_state(UFBXI_PARSE_ROOT, uc->top_node->name);
  6473. ufbxi_check(ufbxi_parse_toplevel_child_imp(uc, state, &uc->tmp_parse, &end));
  6474. if (end) {
  6475. *p_node = NULL;
  6476. } else {
  6477. ufbxi_pop(&uc->tmp_stack, ufbxi_node, 1, &uc->top_child);
  6478. *p_node = &uc->top_child;
  6479. if (uc->opts.retain_dom) {
  6480. ufbxi_check(ufbxi_retain_toplevel_child(uc, &uc->top_child));
  6481. }
  6482. }
  6483. } else {
  6484. // Iterate already parsed nodes
  6485. size_t child_index = uc->top_child_index;
  6486. if (child_index == uc->top_node->num_children) {
  6487. *p_node = NULL;
  6488. } else {
  6489. uc->top_child_index++;
  6490. *p_node = &uc->top_node->children[child_index];
  6491. }
  6492. }
  6493. return 1;
  6494. }
  6495. ufbxi_nodiscard ufbxi_noinline static int ufbxi_parse_legacy_toplevel(ufbxi_context *uc)
  6496. {
  6497. ufbx_assert(uc->top_nodes_len == 0);
  6498. bool end = false;
  6499. if (uc->from_ascii) {
  6500. ufbxi_check(ufbxi_ascii_parse_node(uc, 0, UFBXI_PARSE_ROOT, &end, &uc->tmp, true));
  6501. } else {
  6502. ufbxi_check(ufbxi_binary_parse_node(uc, 0, UFBXI_PARSE_ROOT, &end, &uc->tmp, true));
  6503. }
  6504. // Top-level node not found
  6505. if (end) {
  6506. uc->top_node = NULL;
  6507. uc->top_child_index = 0;
  6508. uc->parsed_to_end = true;
  6509. return 1;
  6510. }
  6511. ufbxi_pop(&uc->tmp_stack, ufbxi_node, 1, &uc->legacy_node);
  6512. uc->top_child_index = 0;
  6513. uc->top_node = &uc->legacy_node;
  6514. if (uc->opts.retain_dom) {
  6515. ufbxi_check(ufbxi_retain_toplevel(uc, &uc->legacy_node));
  6516. }
  6517. return 1;
  6518. }
  6519. // -- Setup
  6520. ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_strings(ufbxi_context *uc)
  6521. {
  6522. #if defined(UFBX_REGRESSION)
  6523. ufbx_string reg_prev = ufbx_empty_string;
  6524. #endif
  6525. // Push all the global 'ufbxi_*' strings into the pool without copying them
  6526. // This allows us to compare name pointers to the global values
  6527. ufbxi_for(ufbx_string, str, ufbxi_strings, ufbxi_arraycount(ufbxi_strings)) {
  6528. #if defined(UFBX_REGRESSION)
  6529. ufbx_assert(strlen(str->data) == str->length);
  6530. ufbx_assert(ufbxi_str_less(reg_prev, *str));
  6531. reg_prev = *str;
  6532. #endif
  6533. ufbxi_check(ufbxi_push_string_imp(&uc->string_pool, str->data, str->length, NULL, false, true));
  6534. }
  6535. return 1;
  6536. }
  6537. typedef struct {
  6538. const char *name;
  6539. ufbx_prop_type type;
  6540. } ufbxi_prop_type_name;
  6541. static const ufbxi_prop_type_name ufbxi_prop_type_names[] = {
  6542. { "Boolean", UFBX_PROP_BOOLEAN },
  6543. { "bool", UFBX_PROP_BOOLEAN },
  6544. { "Bool", UFBX_PROP_BOOLEAN },
  6545. { "Integer", UFBX_PROP_INTEGER },
  6546. { "int", UFBX_PROP_INTEGER },
  6547. { "enum", UFBX_PROP_INTEGER },
  6548. { "Visibility", UFBX_PROP_INTEGER },
  6549. { "Visibility Inheritance", UFBX_PROP_INTEGER },
  6550. { "KTime", UFBX_PROP_INTEGER },
  6551. { "Number", UFBX_PROP_NUMBER },
  6552. { "double", UFBX_PROP_NUMBER },
  6553. { "Real", UFBX_PROP_NUMBER },
  6554. { "Float", UFBX_PROP_NUMBER },
  6555. { "Intensity", UFBX_PROP_NUMBER },
  6556. { "Vector", UFBX_PROP_VECTOR },
  6557. { "Vector3D", UFBX_PROP_VECTOR },
  6558. { "Color", UFBX_PROP_COLOR },
  6559. { "ColorAndAlpha", UFBX_PROP_COLOR_WITH_ALPHA },
  6560. { "ColorRGB", UFBX_PROP_COLOR },
  6561. { "String", UFBX_PROP_STRING },
  6562. { "KString", UFBX_PROP_STRING },
  6563. { "object", UFBX_PROP_STRING },
  6564. { "DateTime", UFBX_PROP_DATE_TIME },
  6565. { "Lcl Translation", UFBX_PROP_TRANSLATION },
  6566. { "Lcl Rotation", UFBX_PROP_ROTATION },
  6567. { "Lcl Scaling", UFBX_PROP_SCALING },
  6568. { "Distance", UFBX_PROP_DISTANCE },
  6569. { "Compound", UFBX_PROP_COMPOUND },
  6570. { "Blob", UFBX_PROP_BLOB },
  6571. { "Reference", UFBX_PROP_REFERENCE },
  6572. };
  6573. static ufbx_prop_type ufbxi_get_prop_type(ufbxi_context *uc, const char *name)
  6574. {
  6575. uint32_t hash = ufbxi_hash_ptr(name);
  6576. ufbxi_prop_type_name *entry = ufbxi_map_find(&uc->prop_type_map, ufbxi_prop_type_name, hash, &name);
  6577. if (entry) {
  6578. return entry->type;
  6579. }
  6580. return UFBX_PROP_UNKNOWN;
  6581. }
  6582. static ufbxi_noinline ufbx_prop *ufbxi_find_prop_with_key(const ufbx_props *props, const char *name, uint32_t key)
  6583. {
  6584. do {
  6585. ufbx_prop *prop_data = props->props.data;
  6586. size_t begin = 0;
  6587. size_t end = props->props.count;
  6588. while (end - begin >= 16) {
  6589. size_t mid = (begin + end) >> 1;
  6590. const ufbx_prop *p = &prop_data[mid];
  6591. if (p->_internal_key < key) {
  6592. begin = mid + 1;
  6593. } else {
  6594. end = mid;
  6595. }
  6596. }
  6597. end = props->props.count;
  6598. for (; begin < end; begin++) {
  6599. const ufbx_prop *p = &prop_data[begin];
  6600. if (p->_internal_key > key) break;
  6601. if (p->name.data == name && (p->flags & UFBX_PROP_FLAG_NO_VALUE) == 0) {
  6602. return (ufbx_prop*)p;
  6603. }
  6604. }
  6605. props = props->defaults;
  6606. } while (props);
  6607. return NULL;
  6608. }
  6609. #define ufbxi_find_prop(props, name) ufbxi_find_prop_with_key((props), (name), \
  6610. ((uint32_t)(uint8_t)name[0] << 24u) | ((uint32_t)(uint8_t)name[1] << 16u) | \
  6611. ((uint32_t)(uint8_t)name[2] << 8u) | (uint32_t)(uint8_t)name[3])
  6612. static ufbxi_forceinline uint32_t ufbxi_get_name_key(const char *name, size_t len)
  6613. {
  6614. uint32_t key = 0;
  6615. if (len >= 4) {
  6616. key = (uint32_t)(uint8_t)name[0]<<24 | (uint32_t)(uint8_t)name[1]<<16
  6617. | (uint32_t)(uint8_t)name[2]<<8 | (uint32_t)(uint8_t)name[3];
  6618. } else {
  6619. for (size_t i = 0; i < 4; i++) {
  6620. key <<= 8;
  6621. if (i < len) key |= (uint8_t)name[i];
  6622. }
  6623. }
  6624. return key;
  6625. }
  6626. static ufbxi_forceinline uint32_t ufbxi_get_name_key_c(const char *name)
  6627. {
  6628. if (name[0] == '\0') return 0;
  6629. if (name[1] == '\0') return (uint32_t)(uint8_t)name[0]<<24;
  6630. if (name[2] == '\0') return (uint32_t)(uint8_t)name[0]<<24 | (uint32_t)(uint8_t)name[1]<<16;
  6631. return (uint32_t)(uint8_t)name[0]<<24 | (uint32_t)(uint8_t)name[1]<<16
  6632. | (uint32_t)(uint8_t)name[2]<<8 | (uint32_t)(uint8_t)name[3];
  6633. }
  6634. static ufbxi_forceinline bool ufbxi_name_key_less(ufbx_prop *prop, const char *data, size_t name_len, uint32_t key)
  6635. {
  6636. if (prop->_internal_key < key) return true;
  6637. if (prop->_internal_key > key) return false;
  6638. size_t prop_len = prop->name.length;
  6639. size_t len = ufbxi_min_sz(prop_len, name_len);
  6640. int cmp = memcmp(prop->name.data, data, len);
  6641. if (cmp != 0) return cmp < 0;
  6642. return prop_len < name_len;
  6643. }
  6644. static const char *ufbxi_node_prop_names[] = {
  6645. "AxisLen",
  6646. "DefaultAttributeIndex",
  6647. "Freeze",
  6648. "GeometricRotation",
  6649. "GeometricScaling",
  6650. "GeometricTranslation",
  6651. "InheritType",
  6652. "LODBox",
  6653. "Lcl Rotation",
  6654. "Lcl Scaling",
  6655. "Lcl Translation",
  6656. "LookAtProperty",
  6657. "MaxDampRangeX",
  6658. "MaxDampRangeY",
  6659. "MaxDampRangeZ",
  6660. "MaxDampStrengthX",
  6661. "MaxDampStrengthY",
  6662. "MaxDampStrengthZ",
  6663. "MinDampRangeX",
  6664. "MinDampRangeY",
  6665. "MinDampRangeZ",
  6666. "MinDampStrengthX",
  6667. "MinDampStrengthY",
  6668. "MinDampStrengthZ",
  6669. "NegativePercentShapeSupport",
  6670. "PostRotation",
  6671. "PreRotation",
  6672. "PreferedAngleX",
  6673. "PreferedAngleY",
  6674. "PreferedAngleZ",
  6675. "QuaternionInterpolate",
  6676. "RotationActive",
  6677. "RotationMax",
  6678. "RotationMaxX",
  6679. "RotationMaxY",
  6680. "RotationMaxZ",
  6681. "RotationMin",
  6682. "RotationMinX",
  6683. "RotationMinY",
  6684. "RotationMinZ",
  6685. "RotationOffset",
  6686. "RotationOrder",
  6687. "RotationPivot",
  6688. "RotationSpaceForLimitOnly",
  6689. "RotationStiffnessX",
  6690. "RotationStiffnessY",
  6691. "RotationStiffnessZ",
  6692. "ScalingActive",
  6693. "ScalingMax",
  6694. "ScalingMaxX",
  6695. "ScalingMaxY",
  6696. "ScalingMaxZ",
  6697. "ScalingMin",
  6698. "ScalingMinX",
  6699. "ScalingMinY",
  6700. "ScalingMinZ",
  6701. "ScalingOffset",
  6702. "ScalingPivot",
  6703. "Show",
  6704. "TranslationActive",
  6705. "TranslationMax",
  6706. "TranslationMaxX",
  6707. "TranslationMaxY",
  6708. "TranslationMaxZ",
  6709. "TranslationMin",
  6710. "TranslationMinX",
  6711. "TranslationMinY",
  6712. "TranslationMinZ",
  6713. "UpVectorProperty",
  6714. "Visibility Inheritance",
  6715. "Visibility",
  6716. };
  6717. ufbxi_nodiscard static ufbxi_noinline int ufbxi_init_node_prop_names(ufbxi_context *uc)
  6718. {
  6719. ufbxi_check(ufbxi_map_grow(&uc->node_prop_set, const char*, ufbxi_arraycount(ufbxi_node_prop_names)));
  6720. ufbxi_for_ptr(const char, p_name, ufbxi_node_prop_names, ufbxi_arraycount(ufbxi_node_prop_names)) {
  6721. const char *name = *p_name;
  6722. const char *pooled = ufbxi_push_string_imp(&uc->string_pool, name, strlen(name), NULL, false, true);
  6723. ufbxi_check(pooled);
  6724. uint32_t hash = ufbxi_hash_ptr(pooled);
  6725. const char **entry = ufbxi_map_insert(&uc->node_prop_set, const char*, hash, &pooled);
  6726. ufbxi_check(entry);
  6727. *entry = pooled;
  6728. }
  6729. return 1;
  6730. }
  6731. static bool ufbxi_is_node_property(ufbxi_context *uc, const char *name)
  6732. {
  6733. // You need to call `ufbxi_init_node_prop_names()` before calling this
  6734. ufbx_assert(uc->node_prop_set.size > 0);
  6735. uint32_t hash = ufbxi_hash_ptr(name);
  6736. const char **entry = ufbxi_map_find(&uc->node_prop_set, const char*, hash, &name);
  6737. return entry != NULL;
  6738. }
  6739. ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_maps(ufbxi_context *uc)
  6740. {
  6741. ufbxi_check(ufbxi_map_grow(&uc->prop_type_map, ufbxi_prop_type_name, ufbxi_arraycount(ufbxi_prop_type_names)));
  6742. ufbxi_for(const ufbxi_prop_type_name, name, ufbxi_prop_type_names, ufbxi_arraycount(ufbxi_prop_type_names)) {
  6743. const char *pooled = ufbxi_push_string_imp(&uc->string_pool, name->name, strlen(name->name), NULL, false, true);
  6744. ufbxi_check(pooled);
  6745. uint32_t hash = ufbxi_hash_ptr(pooled);
  6746. ufbxi_prop_type_name *entry = ufbxi_map_insert(&uc->prop_type_map, ufbxi_prop_type_name, hash, &pooled);
  6747. ufbxi_check(entry);
  6748. entry->type = name->type;
  6749. entry->name = pooled;
  6750. }
  6751. return 1;
  6752. }
  6753. // -- Reading the parsed data
  6754. ufbxi_noinline static void ufbxi_decode_base64(char *dst, const char *src, size_t src_length)
  6755. {
  6756. uint8_t table[256] = { 0 };
  6757. for (char c = 'A'; c <= 'Z'; c++) table[(size_t)c] = (uint8_t)(c - 'A');
  6758. for (char c = 'a'; c <= 'z'; c++) table[(size_t)c] = (uint8_t)(26 + (c - 'a'));
  6759. for (char c = '0'; c <= '9'; c++) table[(size_t)c] = (uint8_t)(52 + (c - '0'));
  6760. table[(size_t)'+'] = 62;
  6761. table[(size_t)'/'] = 63;
  6762. for (size_t i = 0; i + 4 <= src_length; i += 4) {
  6763. uint32_t a = table[(size_t)(uint8_t)src[i + 0]];
  6764. uint32_t b = table[(size_t)(uint8_t)src[i + 1]];
  6765. uint32_t c = table[(size_t)(uint8_t)src[i + 2]];
  6766. uint32_t d = table[(size_t)(uint8_t)src[i + 3]];
  6767. dst[0] = (char)(uint8_t)(a << 2 | b >> 4);
  6768. dst[1] = (char)(uint8_t)(b << 4 | c >> 2);
  6769. dst[2] = (char)(uint8_t)(c << 6 | d);
  6770. dst += 3;
  6771. }
  6772. }
  6773. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_embedded_blob(ufbxi_context *uc, ufbx_blob *dst_blob, ufbxi_node *node)
  6774. {
  6775. if (!node) return 1;
  6776. ufbxi_value_array *content_arr = ufbxi_get_array(node, 'C');
  6777. if (content_arr && content_arr->size > 0) {
  6778. ufbx_string content;
  6779. size_t num_parts = content_arr->size;
  6780. ufbx_string *parts = (ufbx_string*)content_arr->data;
  6781. if (num_parts == 1) {
  6782. content = parts[0];
  6783. } else {
  6784. size_t total_size = 0;
  6785. ufbxi_for(ufbx_string, part, parts, num_parts) {
  6786. total_size += part->length;
  6787. }
  6788. ufbxi_buf *dst_buf = uc->from_ascii ? &uc->tmp_parse : &uc->result;
  6789. char *dst = ufbxi_push(dst_buf, char, total_size);
  6790. ufbxi_check(dst);
  6791. content.data = dst;
  6792. content.length = total_size;
  6793. ufbxi_for(ufbx_string, part, parts, num_parts) {
  6794. memcpy(dst, part->data, part->length);
  6795. dst += part->length;
  6796. }
  6797. }
  6798. if (uc->from_ascii) {
  6799. if (content.length % 4 == 0) {
  6800. size_t padding = 0;
  6801. while (padding < 2 && padding < content.length && content.data[content.length - 1 - padding] == '=') {
  6802. padding++;
  6803. }
  6804. dst_blob->size = content.length / 4 * 3 - padding;
  6805. dst_blob->data = ufbxi_push(&uc->result, char, dst_blob->size + 3);
  6806. ufbxi_check(dst_blob->data);
  6807. ufbxi_decode_base64((char*)dst_blob->data, content.data, content.length);
  6808. }
  6809. } else {
  6810. dst_blob->data = content.data;
  6811. dst_blob->size = content.length;
  6812. }
  6813. }
  6814. return 1;
  6815. }
  6816. ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_property(ufbxi_context *uc, ufbxi_node *node, ufbx_prop *prop, int version)
  6817. {
  6818. const char *type_str = NULL, *subtype_str = NULL;
  6819. ufbxi_check(ufbxi_get_val2(node, "SC", &prop->name, (char**)&type_str));
  6820. uint32_t val_ix = 2;
  6821. if (version == 70) {
  6822. ufbxi_check(ufbxi_get_val_at(node, val_ix++, 'C', (char**)&subtype_str));
  6823. }
  6824. prop->_internal_key = ufbxi_get_name_key(prop->name.data, prop->name.length);
  6825. ufbx_string flags_str;
  6826. if (ufbxi_get_val_at(node, val_ix++, 'S', &flags_str)) {
  6827. uint32_t flags = 0;
  6828. for (size_t i = 0; i < flags_str.length; i++) {
  6829. char next = i + 1 < flags_str.length ? flags_str.data[i + 1] : '0';
  6830. switch (flags_str.data[i]) {
  6831. case 'A': flags |= UFBX_PROP_FLAG_ANIMATABLE; break;
  6832. case 'U': flags |= UFBX_PROP_FLAG_USER_DEFINED; break;
  6833. case 'H': flags |= UFBX_PROP_FLAG_HIDDEN; break;
  6834. case 'L': flags |= ((uint32_t)(next - '0') & 0xf) << 4; break; // UFBX_PROP_FLAG_LOCK_*
  6835. case 'M': flags |= ((uint32_t)(next - '0') & 0xf) << 8; break; // UFBX_PROP_FLAG_MUTE_*
  6836. }
  6837. }
  6838. prop->flags = (ufbx_prop_flags)flags;
  6839. }
  6840. prop->type = ufbxi_get_prop_type(uc, type_str);
  6841. if (prop->type == UFBX_PROP_UNKNOWN && subtype_str) {
  6842. prop->type = ufbxi_get_prop_type(uc, subtype_str);
  6843. }
  6844. ufbxi_ignore(ufbxi_get_val_at(node, val_ix, 'L', &prop->value_int));
  6845. for (size_t i = 0; i < 4; i++) {
  6846. if (!ufbxi_get_val_at(node, val_ix + i, 'R', &prop->value_real_arr[i])) break;
  6847. }
  6848. // Distance properties have a string unit _after_ the real value, eg. `10, "cm"`
  6849. if (prop->type == UFBX_PROP_DISTANCE) {
  6850. val_ix++;
  6851. }
  6852. if (ufbxi_get_val_at(node, val_ix, 'S', &prop->value_str)) {
  6853. if (prop->value_str.length > 0) {
  6854. ufbxi_ignore(ufbxi_get_val_at(node, val_ix, 'b', &prop->value_blob));
  6855. }
  6856. } else {
  6857. prop->value_str = ufbx_empty_string;
  6858. }
  6859. // Very unlikely, seems to only exist in some "non standard" FBX files
  6860. if (node->num_children > 0) {
  6861. ufbxi_node *binary = ufbxi_find_child(node, ufbxi_BinaryData);
  6862. ufbxi_check(ufbxi_read_embedded_blob(uc, &prop->value_blob, binary));
  6863. }
  6864. return 1;
  6865. }
  6866. static ufbxi_forceinline bool ufbxi_prop_less(ufbx_prop *a, ufbx_prop *b)
  6867. {
  6868. if (a->_internal_key < b->_internal_key) return true;
  6869. if (a->_internal_key > b->_internal_key) return false;
  6870. return strcmp(a->name.data, b->name.data) < 0;
  6871. }
  6872. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_properties(ufbxi_context *uc, ufbx_prop *props, size_t count)
  6873. {
  6874. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_prop)));
  6875. ufbxi_macro_stable_sort(ufbx_prop, 32, props, uc->tmp_arr, count, ( ufbxi_prop_less(a, b) ));
  6876. return 1;
  6877. }
  6878. ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_properties(ufbxi_context *uc, ufbxi_node *parent, ufbx_props *props)
  6879. {
  6880. props->defaults = NULL;
  6881. int version = 70;
  6882. ufbxi_node *node = ufbxi_find_child(parent, ufbxi_Properties70);
  6883. if (!node) {
  6884. node = ufbxi_find_child(parent, ufbxi_Properties60);
  6885. if (!node) {
  6886. // No properties found, not an error
  6887. props->props.data = NULL;
  6888. props->props.count = 0;
  6889. return 1;
  6890. }
  6891. version = 60;
  6892. }
  6893. props->props.data = ufbxi_push_zero(&uc->result, ufbx_prop, node->num_children);
  6894. props->props.count = node->num_children;
  6895. ufbxi_check(props->props.data);
  6896. for (size_t i = 0; i < props->props.count; i++) {
  6897. ufbxi_check(ufbxi_read_property(uc, &node->children[i], &props->props.data[i], version));
  6898. }
  6899. // Sort the properties
  6900. ufbxi_check(ufbxi_sort_properties(uc, props->props.data, props->props.count));
  6901. // Remove duplicates, the last one wins
  6902. if (props->props.count >= 2) {
  6903. ufbx_prop *ps = props->props.data;
  6904. size_t dst = 0, src = 0, end = props->props.count;
  6905. while (src < end) {
  6906. if (src + 1 < end && ps[src].name.data == ps[src + 1].name.data) {
  6907. src++;
  6908. } else if (dst != src) {
  6909. ps[dst++] = ps[src++];
  6910. } else {
  6911. dst++; src++;
  6912. }
  6913. }
  6914. props->props.count = dst;
  6915. }
  6916. return 1;
  6917. }
  6918. ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_scene_info(ufbxi_context *uc, ufbxi_node *node)
  6919. {
  6920. ufbxi_check(ufbxi_read_properties(uc, node, &uc->scene.metadata.scene_props));
  6921. return 1;
  6922. }
  6923. ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_header_extension(ufbxi_context *uc)
  6924. {
  6925. // TODO: Read TCDefinition and adjust timestamps
  6926. uc->ktime_to_sec = (1.0 / 46186158000.0);
  6927. for (;;) {
  6928. ufbxi_node *child;
  6929. ufbxi_check(ufbxi_parse_toplevel_child(uc, &child));
  6930. if (!child) break;
  6931. if (child->name == ufbxi_Creator) {
  6932. ufbxi_ignore(ufbxi_get_val1(child, "S", &uc->scene.metadata.creator));
  6933. }
  6934. if (uc->version < 6000 && child->name == ufbxi_FBXVersion) {
  6935. int32_t version;
  6936. if (ufbxi_get_val1(child, "I", &version)) {
  6937. if (version > 0 && (uint32_t)version > uc->version) {
  6938. uc->version = (uint32_t)version;
  6939. }
  6940. }
  6941. }
  6942. if (child->name == ufbxi_SceneInfo) {
  6943. ufbxi_check(ufbxi_read_scene_info(uc, child));
  6944. }
  6945. }
  6946. return 1;
  6947. }
  6948. static bool ufbxi_match_version_string(const char *fmt, ufbx_string str, uint32_t *p_version)
  6949. {
  6950. size_t num_ix = 0;
  6951. size_t pos = 0;
  6952. while (*fmt) {
  6953. char c = *fmt++;
  6954. if (c >= 'a' && c <= 'z') {
  6955. if (pos >= str.length) return false;
  6956. char s = str.data[pos];
  6957. if (s != c && (int)s + (int)('a' - 'A') != (int)c) return false;
  6958. pos++;
  6959. } else if (c == ' ') {
  6960. while (pos < str.length) {
  6961. char s = str.data[pos];
  6962. if (s != ' ' && s != '\t') break;
  6963. pos++;
  6964. }
  6965. } else if (c == '-') {
  6966. while (pos < str.length) {
  6967. char s = str.data[pos];
  6968. if (s == '-') break;
  6969. pos++;
  6970. }
  6971. if (pos >= str.length) return false;
  6972. pos++;
  6973. } else if (c == '/' || c == '.' || c == '(' || c == ')') {
  6974. if (pos >= str.length) return false;
  6975. if (str.data[pos] != c) return false;
  6976. pos++;
  6977. } else if (c == '?') {
  6978. uint32_t num = 0;
  6979. size_t len = 0;
  6980. while (pos < str.length) {
  6981. char s = str.data[pos];
  6982. if (!(s >= '0' && s <= '9')) break;
  6983. num = num*10 + (uint32_t)(s - '0');
  6984. pos++;
  6985. len++;
  6986. }
  6987. if (len == 0) return false;
  6988. p_version[num_ix++] = num;
  6989. } else {
  6990. ufbx_assert(0 && "Unhandled match character");
  6991. }
  6992. }
  6993. return true;
  6994. }
  6995. ufbxi_nodiscard static int ufbxi_match_exporter(ufbxi_context *uc)
  6996. {
  6997. ufbx_string creator = uc->scene.metadata.creator;
  6998. uint32_t version[3] = { 0 };
  6999. if (ufbxi_match_version_string("blender-- ?.?.?", creator, version)) {
  7000. uc->exporter = UFBX_EXPORTER_BLENDER_BINARY;
  7001. uc->exporter_version = ufbx_pack_version(version[0], version[1], version[2]);
  7002. } else if (ufbxi_match_version_string("blender- ?.?", creator, version)) {
  7003. uc->exporter = UFBX_EXPORTER_BLENDER_BINARY;
  7004. uc->exporter_version = ufbx_pack_version(version[0], version[1], 0);
  7005. } else if (ufbxi_match_version_string("blender version ?.?", creator, version)) {
  7006. uc->exporter = UFBX_EXPORTER_BLENDER_ASCII;
  7007. uc->exporter_version = ufbx_pack_version(version[0], version[1], 0);
  7008. } else if (ufbxi_match_version_string("fbx sdk/fbx plugins version ?.?", creator, version)) {
  7009. uc->exporter = UFBX_EXPORTER_FBX_SDK;
  7010. uc->exporter_version = ufbx_pack_version(version[0], version[1], 0);
  7011. } else if (ufbxi_match_version_string("fbx sdk/fbx plugins build ?", creator, version)) {
  7012. uc->exporter = UFBX_EXPORTER_FBX_SDK;
  7013. uc->exporter_version = ufbx_pack_version(version[0]/10000u, version[0]/100u%100u, version[0]%100u);
  7014. } else if (ufbxi_match_version_string("motionbuilder version ?.?", creator, version)) {
  7015. uc->exporter = UFBX_EXPORTER_MOTION_BUILDER;
  7016. uc->exporter_version = ufbx_pack_version(version[0], version[1], 0);
  7017. } else if (ufbxi_match_version_string("motionbuilder/mocap/online version ?.?", creator, version)) {
  7018. uc->exporter = UFBX_EXPORTER_MOTION_BUILDER;
  7019. uc->exporter_version = ufbx_pack_version(version[0], version[1], 0);
  7020. } else if (ufbxi_match_version_string("fbx unity export version ?.?", creator, version)) {
  7021. uc->exporter = UFBX_EXPORTER_BC_UNITY_EXPORTER;
  7022. uc->exporter_version = ufbx_pack_version(version[0], version[1], 0);
  7023. } else if (ufbxi_match_version_string("fbx unity export version ?.?.?", creator, version)) {
  7024. uc->exporter = UFBX_EXPORTER_BC_UNITY_EXPORTER;
  7025. uc->exporter_version = ufbx_pack_version(version[0], version[1], version[2]);
  7026. } else if (ufbxi_match_version_string("made using asset forge", creator, version)) {
  7027. uc->exporter = UFBX_EXPORTER_BC_UNITY_EXPORTER;
  7028. } else if (ufbxi_match_version_string("model created by kenney", creator, version)) {
  7029. uc->exporter = UFBX_EXPORTER_BC_UNITY_EXPORTER;
  7030. }
  7031. uc->scene.metadata.exporter = uc->exporter;
  7032. uc->scene.metadata.exporter_version = uc->exporter_version;
  7033. // Un-detect the exporter in `ufbxi_context` to disable special cases
  7034. if (uc->opts.disable_quirks) {
  7035. uc->exporter = UFBX_EXPORTER_UNKNOWN;
  7036. uc->exporter_version = 0;
  7037. }
  7038. return 1;
  7039. }
  7040. ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_document(ufbxi_context *uc)
  7041. {
  7042. bool found_root_id = 0;
  7043. for (;;) {
  7044. ufbxi_node *child;
  7045. ufbxi_check(ufbxi_parse_toplevel_child(uc, &child));
  7046. if (!child) break;
  7047. if (child->name == ufbxi_Document && !found_root_id) {
  7048. // Post-7000: Try to find the first document node and root ID.
  7049. // TODO: Multiple documents / roots?
  7050. if (ufbxi_find_val1(child, ufbxi_RootNode, "L", &uc->root_id)) {
  7051. found_root_id = true;
  7052. }
  7053. }
  7054. }
  7055. return 1;
  7056. }
  7057. ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_definitions(ufbxi_context *uc)
  7058. {
  7059. for (;;) {
  7060. ufbxi_node *object;
  7061. ufbxi_check(ufbxi_parse_toplevel_child(uc, &object));
  7062. if (!object) break;
  7063. if (object->name != ufbxi_ObjectType) continue;
  7064. ufbxi_template *tmpl = ufbxi_push_zero(&uc->tmp_stack, ufbxi_template, 1);
  7065. uc->num_templates++;
  7066. ufbxi_check(tmpl);
  7067. ufbxi_check(ufbxi_get_val1(object, "C", (char**)&tmpl->type));
  7068. // Pre-7000 FBX versions don't have property templates, they just have
  7069. // the object counts by themselves.
  7070. ufbxi_node *props = ufbxi_find_child(object, ufbxi_PropertyTemplate);
  7071. if (props) {
  7072. ufbxi_check(ufbxi_get_val1(props, "S", &tmpl->sub_type));
  7073. // Remove the "Fbx" prefix from sub-types, remember to re-intern!
  7074. if (tmpl->sub_type.length > 3 && !strncmp(tmpl->sub_type.data, "Fbx", 3)) {
  7075. tmpl->sub_type.data += 3;
  7076. tmpl->sub_type.length -= 3;
  7077. // HACK: LOD groups use LODGroup for Template, LodGroup for Object?
  7078. if (tmpl->sub_type.length == 8 && !memcmp(tmpl->sub_type.data, "LODGroup", 8)) {
  7079. tmpl->sub_type.data = "LodGroup";
  7080. }
  7081. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &tmpl->sub_type, false));
  7082. }
  7083. ufbxi_check(ufbxi_read_properties(uc, props, &tmpl->props));
  7084. }
  7085. }
  7086. // TODO: Preserve only the `props` part of the templates
  7087. uc->templates = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbxi_template, uc->num_templates);
  7088. ufbxi_check(uc->templates);
  7089. return 1;
  7090. }
  7091. ufbxi_nodiscard static ufbx_props *ufbxi_find_template(ufbxi_context *uc, const char *name, const char *sub_type)
  7092. {
  7093. // TODO: Binary search
  7094. ufbxi_for(ufbxi_template, tmpl, uc->templates, uc->num_templates) {
  7095. if (tmpl->type == name) {
  7096. // Check that sub_type matches unless the type is Material, Model, AnimationStack, AnimationLayer.
  7097. // Those match to all sub-types.
  7098. if (tmpl->type != ufbxi_Material && tmpl->type != ufbxi_Model
  7099. && tmpl->type != ufbxi_AnimationStack && tmpl->type != ufbxi_AnimationLayer) {
  7100. if (tmpl->sub_type.data != sub_type) {
  7101. return NULL;
  7102. }
  7103. }
  7104. if (tmpl->props.props.count > 0) {
  7105. return &tmpl->props;
  7106. } else {
  7107. return NULL;
  7108. }
  7109. }
  7110. }
  7111. return NULL;
  7112. }
  7113. // Name ID categories
  7114. #define UFBXI_SYNTHETIC_ID_BIT UINT64_C(0x8000000000000000)
  7115. ufbx_static_assert(uptr_size, sizeof(uintptr_t) <= sizeof(uint64_t));
  7116. static ufbxi_forceinline uint64_t ufbxi_synthetic_id_from_pointer(const void *ptr)
  7117. {
  7118. uintptr_t uptr = (uintptr_t)ptr;
  7119. ufbx_assert((uptr & 0x1) == 0);
  7120. return (uptr >> 1u) | UFBXI_SYNTHETIC_ID_BIT;
  7121. }
  7122. static ufbxi_forceinline uint64_t ufbxi_synthetic_id_from_string(const char *str)
  7123. {
  7124. uintptr_t uptr = (uintptr_t)str;
  7125. uptr &= ~(uintptr_t)1;
  7126. return (uptr >> 1u) | UFBXI_SYNTHETIC_ID_BIT;
  7127. }
  7128. static ufbxi_noinline int ufbxi_push_synthetic_id(ufbxi_context *uc, uint64_t *p_dst)
  7129. {
  7130. void *ptr = ufbxi_push_size(&uc->tmp, 8, 1);
  7131. ufbxi_check(ptr);
  7132. *p_dst = ufbxi_synthetic_id_from_pointer(ptr);
  7133. return 1;
  7134. }
  7135. ufbxi_nodiscard static int ufbxi_split_type_and_name(ufbxi_context *uc, ufbx_string type_and_name, ufbx_string *type, ufbx_string *name)
  7136. {
  7137. // Name and type are packed in a single property as Type::Name (in ASCII)
  7138. // or Name\x00\x01Type (in binary)
  7139. const char *sep = uc->from_ascii ? "::" : "\x00\x01";
  7140. size_t type_end = 2;
  7141. for (; type_end <= type_and_name.length; type_end++) {
  7142. const char *ch = type_and_name.data + type_end - 2;
  7143. if (ch[0] == sep[0] && ch[1] == sep[1]) break;
  7144. }
  7145. // ???: ASCII and binary store type and name in different order
  7146. if (type_end <= type_and_name.length) {
  7147. if (uc->from_ascii) {
  7148. name->data = type_and_name.data + type_end;
  7149. name->length = type_and_name.length - type_end;
  7150. type->data = type_and_name.data;
  7151. type->length = type_end - 2;
  7152. } else {
  7153. name->data = type_and_name.data;
  7154. name->length = type_end - 2;
  7155. type->data = type_and_name.data + type_end;
  7156. type->length = type_and_name.length - type_end;
  7157. }
  7158. } else {
  7159. *name = type_and_name;
  7160. type->data = ufbxi_empty_char;
  7161. type->length = 0;
  7162. }
  7163. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, type, false));
  7164. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, name, false));
  7165. return 1;
  7166. }
  7167. ufbxi_nodiscard ufbxi_noinline static int ufbxi_insert_fbx_id(ufbxi_context *uc, uint64_t fbx_id, uint32_t element_id)
  7168. {
  7169. uint32_t hash = ufbxi_hash64(fbx_id);
  7170. ufbxi_fbx_id_entry *entry = ufbxi_map_find(&uc->fbx_id_map, ufbxi_fbx_id_entry, hash, &fbx_id);
  7171. // TODO: Strict / warn about duplicate objects
  7172. if (!entry) {
  7173. entry = ufbxi_map_insert(&uc->fbx_id_map, ufbxi_fbx_id_entry, hash, &fbx_id);
  7174. ufbxi_check(entry);
  7175. entry->fbx_id = fbx_id;
  7176. entry->element_id = element_id;
  7177. }
  7178. return 1;
  7179. }
  7180. static ufbxi_noinline bool ufbxi_fbx_id_exists(ufbxi_context *uc, uint64_t fbx_id)
  7181. {
  7182. uint32_t hash = ufbxi_hash64(fbx_id);
  7183. ufbxi_fbx_id_entry *entry = ufbxi_map_find(&uc->fbx_id_map, ufbxi_fbx_id_entry, hash, &fbx_id);
  7184. return entry != NULL;
  7185. }
  7186. ufbxi_nodiscard ufbxi_noinline static int ufbxi_insert_fbx_attr(ufbxi_context *uc, uint64_t fbx_id, uint64_t attrib_fbx_id)
  7187. {
  7188. uint32_t hash = ufbxi_hash64(fbx_id);
  7189. ufbxi_fbx_attr_entry *entry = ufbxi_map_find(&uc->fbx_attr_map, ufbxi_fbx_attr_entry, hash, &fbx_id);
  7190. // TODO: Strict / warn about duplicate objects
  7191. if (!entry) {
  7192. entry = ufbxi_map_insert(&uc->fbx_attr_map, ufbxi_fbx_attr_entry, hash, &fbx_id);
  7193. ufbxi_check(entry);
  7194. entry->node_fbx_id = fbx_id;
  7195. entry->attr_fbx_id = attrib_fbx_id;
  7196. }
  7197. return 1;
  7198. }
  7199. ufbxi_nodiscard ufbxi_noinline static ufbx_element *ufbxi_push_element_size(ufbxi_context *uc, ufbxi_element_info *info, size_t size, ufbx_element_type type)
  7200. {
  7201. size_t aligned_size = (size + 7u) & ~0x7u;
  7202. uint32_t typed_id = (uint32_t)uc->tmp_typed_element_offsets[type].num_items;
  7203. ufbxi_check_return(ufbxi_push_copy(&uc->tmp_typed_element_offsets[type], size_t, 1, &uc->tmp_element_byte_offset), NULL);
  7204. ufbxi_check_return(ufbxi_push_copy(&uc->tmp_element_offsets, size_t, 1, &uc->tmp_element_byte_offset), NULL);
  7205. uc->tmp_element_byte_offset += aligned_size;
  7206. ufbx_element *elem = (ufbx_element*)ufbxi_push_zero(&uc->tmp_elements, uint64_t, aligned_size/8);
  7207. ufbxi_check_return(elem, NULL);
  7208. elem->type = type;
  7209. elem->element_id = uc->num_elements++;
  7210. elem->typed_id = typed_id;
  7211. elem->name = info->name;
  7212. elem->props = info->props;
  7213. elem->dom_node = info->dom_node;
  7214. ufbxi_check_return(ufbxi_insert_fbx_id(uc, info->fbx_id, elem->element_id), NULL);
  7215. return elem;
  7216. }
  7217. ufbxi_nodiscard ufbxi_noinline static ufbx_element *ufbxi_push_synthetic_element_size(ufbxi_context *uc, uint64_t *p_fbx_id, ufbxi_node *node, const char *name, size_t size, ufbx_element_type type)
  7218. {
  7219. size_t aligned_size = (size + 7u) & ~0x7u;
  7220. uint32_t typed_id = (uint32_t)uc->tmp_typed_element_offsets[type].num_items;
  7221. ufbxi_check_return(ufbxi_push_copy(&uc->tmp_typed_element_offsets[type], size_t, 1, &uc->tmp_element_byte_offset), NULL);
  7222. ufbxi_check_return(ufbxi_push_copy(&uc->tmp_element_offsets, size_t, 1, &uc->tmp_element_byte_offset), NULL);
  7223. uc->tmp_element_byte_offset += aligned_size;
  7224. ufbx_element *elem = (ufbx_element*)ufbxi_push_zero(&uc->tmp_elements, uint64_t, aligned_size/8);
  7225. ufbxi_check_return(elem, NULL);
  7226. elem->type = type;
  7227. elem->element_id = uc->num_elements++;
  7228. elem->typed_id = typed_id;
  7229. elem->dom_node = ufbxi_get_dom_node(uc, node);
  7230. if (name) {
  7231. elem->name.data = name;
  7232. elem->name.length = strlen(name);
  7233. }
  7234. uint64_t fbx_id = ufbxi_synthetic_id_from_pointer(elem);
  7235. *p_fbx_id = fbx_id;
  7236. ufbxi_check_return(ufbxi_insert_fbx_id(uc, fbx_id, elem->element_id), NULL);
  7237. return elem;
  7238. }
  7239. #define ufbxi_push_element(uc, info, type_name, type_enum) ufbxi_maybe_null((type_name*)ufbxi_push_element_size((uc), (info), sizeof(type_name), (type_enum)))
  7240. #define ufbxi_push_synthetic_element(uc, p_fbx_id, node, name, type_name, type_enum) ufbxi_maybe_null((type_name*)ufbxi_push_synthetic_element_size((uc), (p_fbx_id), (node), (name), sizeof(type_name), (type_enum)))
  7241. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_model(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  7242. {
  7243. (void)node;
  7244. ufbx_node *elem_node = ufbxi_push_element(uc, info, ufbx_node, UFBX_ELEMENT_NODE);
  7245. ufbxi_check(elem_node);
  7246. ufbxi_check(ufbxi_push_copy(&uc->tmp_node_ids, uint32_t, 1, &elem_node->element.element_id));
  7247. return 1;
  7248. }
  7249. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_element(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, size_t size, ufbx_element_type type)
  7250. {
  7251. (void)node;
  7252. ufbx_element *elem = ufbxi_push_element_size(uc, info, size, type);
  7253. ufbxi_check(elem);
  7254. return 1;
  7255. }
  7256. ufbxi_nodiscard ufbxi_noinline static int ufbxi_connect_oo(ufbxi_context *uc, uint64_t src, uint64_t dst)
  7257. {
  7258. ufbxi_tmp_connection *conn = ufbxi_push(&uc->tmp_connections, ufbxi_tmp_connection, 1);
  7259. ufbxi_check(conn);
  7260. conn->src = src;
  7261. conn->dst = dst;
  7262. conn->src_prop = conn->dst_prop = ufbx_empty_string;
  7263. return 1;
  7264. }
  7265. ufbxi_nodiscard ufbxi_noinline static int ufbxi_connect_op(ufbxi_context *uc, uint64_t src, uint64_t dst, ufbx_string prop)
  7266. {
  7267. ufbxi_tmp_connection *conn = ufbxi_push(&uc->tmp_connections, ufbxi_tmp_connection, 1);
  7268. ufbxi_check(conn);
  7269. conn->src = src;
  7270. conn->dst = dst;
  7271. conn->src_prop = ufbx_empty_string;
  7272. conn->dst_prop = prop;
  7273. return 1;
  7274. }
  7275. ufbxi_nodiscard ufbxi_noinline static int ufbxi_connect_pp(ufbxi_context *uc, uint64_t src, uint64_t dst, ufbx_string src_prop, ufbx_string dst_prop)
  7276. {
  7277. ufbxi_tmp_connection *conn = ufbxi_push(&uc->tmp_connections, ufbxi_tmp_connection, 1);
  7278. ufbxi_check(conn);
  7279. conn->src = src;
  7280. conn->dst = dst;
  7281. conn->src_prop = src_prop;
  7282. conn->dst_prop = dst_prop;
  7283. return 1;
  7284. }
  7285. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_unknown(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *element, ufbx_string type, ufbx_string sub_type, const char *node_name)
  7286. {
  7287. (void)node;
  7288. ufbx_unknown *unknown = ufbxi_push_element(uc, element, ufbx_unknown, UFBX_ELEMENT_UNKNOWN);
  7289. ufbxi_check(unknown);
  7290. unknown->type = type;
  7291. unknown->sub_type = sub_type;
  7292. unknown->super_type.data = node_name;
  7293. unknown->super_type.length = strlen(node_name);
  7294. // `type`, `sub_type` and `node_name` are raw strings so they may need to be sanitized.
  7295. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &unknown->type, false));
  7296. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &unknown->sub_type, false));
  7297. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &unknown->super_type, false));
  7298. return 1;
  7299. }
  7300. typedef struct {
  7301. ufbx_vertex_vec3 elem;
  7302. uint32_t index;
  7303. } ufbxi_tangent_layer;
  7304. static ufbx_real ufbxi_zero_element[8] = { 0 };
  7305. // Sentinel pointers used for zero/sequential index buffers
  7306. static const uint32_t ufbxi_sentinel_index_zero[1] = { 100000000 };
  7307. static const uint32_t ufbxi_sentinel_index_consecutive[1] = { 123456789 };
  7308. ufbxi_noinline static int ufbxi_fix_index(ufbxi_context *uc, uint32_t *p_dst, uint32_t index, uint32_t clamped)
  7309. {
  7310. switch (uc->opts.index_error_handling) {
  7311. case UFBX_INDEX_ERROR_HANDLING_CLAMP:
  7312. *p_dst = clamped;
  7313. break;
  7314. case UFBX_INDEX_ERROR_HANDLING_NO_INDEX:
  7315. *p_dst = UFBX_NO_INDEX;
  7316. break;
  7317. case UFBX_INDEX_ERROR_HANDLING_ABORT_LOADING:
  7318. ufbxi_fail_msg("UFBX_INDEX_ERROR_HANDLING_ABORT_LOADING", "Bad index");
  7319. break;
  7320. case UFBX_INDEX_ERROR_HANDLING_UNSAFE_IGNORE:
  7321. *p_dst = index;
  7322. break;
  7323. default:
  7324. ufbx_assert(0 && "Unhandled index_error_handling");
  7325. return 0;
  7326. }
  7327. return 1;
  7328. }
  7329. ufbxi_nodiscard ufbxi_noinline static int ufbxi_check_indices(ufbxi_context *uc, uint32_t **p_dst, uint32_t *indices, bool owns_indices, size_t num_indices, size_t num_indexers, size_t num_elems)
  7330. {
  7331. // If the indices are truncated extend them with `UFBX_NO_INDEX`, the following normalization pass
  7332. // will handle them the same way as other out-of-bounds indices.
  7333. if (num_indices < num_indexers) {
  7334. uint32_t *new_indices = ufbxi_push(&uc->result, uint32_t, num_indexers);
  7335. ufbxi_check(new_indices);
  7336. memcpy(new_indices, indices, sizeof(uint32_t) * num_indices);
  7337. for (size_t i = num_indices; i < num_indexers; i++) {
  7338. new_indices[i] = UFBX_NO_INDEX;
  7339. }
  7340. indices = new_indices;
  7341. num_indices = num_indexers;
  7342. owns_indices = true;
  7343. }
  7344. // Normalize out-of-bounds indices to `invalid_index`
  7345. for (size_t i = 0; i < num_indices; i++) {
  7346. uint32_t ix = indices[i];
  7347. if (ix >= num_elems) {
  7348. // If the indices refer to an external buffer we need to
  7349. // allocate a separate buffer for them
  7350. if (!owns_indices) {
  7351. uint32_t *new_indices = ufbxi_push(&uc->result, uint32_t, num_indices);
  7352. ufbxi_check(new_indices);
  7353. memcpy(new_indices, indices, sizeof(uint32_t) * num_indices);
  7354. indices = new_indices;
  7355. owns_indices = true;
  7356. }
  7357. ufbxi_check(ufbxi_fix_index(uc, &indices[i], ix, (uint32_t)(num_elems - 1)));
  7358. }
  7359. }
  7360. *p_dst = indices;
  7361. return 1;
  7362. }
  7363. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_vertex_element(ufbxi_context *uc, ufbx_mesh *mesh, ufbxi_node *node,
  7364. ufbx_vertex_attrib *attrib, const char *data_name, const char *index_name, char data_type, size_t num_components)
  7365. {
  7366. ufbx_real **p_dst_data = (ufbx_real**)&attrib->values.data;
  7367. ufbxi_value_array *data = ufbxi_find_array(node, data_name, data_type);
  7368. ufbxi_value_array *indices = ufbxi_find_array(node, index_name, 'i');
  7369. if (!uc->opts.strict) {
  7370. if (!data) return 1;
  7371. }
  7372. ufbxi_check(data);
  7373. ufbxi_check(data->size % num_components == 0);
  7374. size_t num_elems = data->size / num_components;
  7375. // HACK: If there's no elements at all keep the attribute as NULL
  7376. // TODO: Strict mode for this?
  7377. if (num_elems == 0) {
  7378. return 1;
  7379. }
  7380. ufbxi_check(num_elems > 0 && num_elems < INT32_MAX);
  7381. attrib->exists = true;
  7382. attrib->indices.count = mesh->num_indices;
  7383. const char *mapping;
  7384. ufbxi_check(ufbxi_find_val1(node, ufbxi_MappingInformationType, "C", (char**)&mapping));
  7385. attrib->values.count = num_elems ? num_elems : 1;
  7386. // Data array is always used as-is, if empty set the data to a global
  7387. // zero buffer so invalid zero index can point to some valid data.
  7388. // The zero data is offset by 4 elements to accomodate for invalid index (-1)
  7389. if (num_elems > 0) {
  7390. *p_dst_data = (ufbx_real*)data->data;
  7391. } else {
  7392. *p_dst_data = ufbxi_zero_element + 4;
  7393. }
  7394. if (indices) {
  7395. size_t num_indices = indices->size;
  7396. uint32_t *index_data = (uint32_t*)indices->data;
  7397. if (mapping == ufbxi_ByPolygonVertex || mapping == ufbxi_ByPolygon) {
  7398. // Indexed by polygon vertex: We can use the provided indices directly.
  7399. ufbxi_check(ufbxi_check_indices(uc, &attrib->indices.data, index_data, true, num_indices, mesh->num_indices, num_elems));
  7400. } else if (mapping == ufbxi_ByVertex || mapping == ufbxi_ByVertice) {
  7401. // Indexed by vertex: Follow through the position index mapping to get the final indices.
  7402. uint32_t *new_index_data = ufbxi_push(&uc->result, uint32_t, mesh->num_indices);
  7403. ufbxi_check(new_index_data);
  7404. uint32_t *vert_ix = mesh->vertex_indices.data;
  7405. for (size_t i = 0; i < mesh->num_indices; i++) {
  7406. uint32_t ix = vert_ix[i];
  7407. if (ix < num_indices) {
  7408. new_index_data[i] = index_data[ix];
  7409. } else {
  7410. ufbxi_check(ufbxi_fix_index(uc, &new_index_data[i], ix, (uint32_t)(num_elems - 1)));
  7411. }
  7412. }
  7413. ufbxi_check(ufbxi_check_indices(uc, &attrib->indices.data, new_index_data, true, mesh->num_indices, mesh->num_indices, num_elems));
  7414. attrib->unique_per_vertex = true;
  7415. } else if (mapping == ufbxi_AllSame) {
  7416. // Indexed by all same: ??? This could be possibly used for making
  7417. // holes with invalid indices, but that seems really fringe.
  7418. // Just use the shared zero index buffer for this.
  7419. uc->max_zero_indices = ufbxi_max_sz(uc->max_zero_indices, mesh->num_indices);
  7420. attrib->indices.data = (uint32_t*)ufbxi_sentinel_index_zero;
  7421. attrib->unique_per_vertex = true;
  7422. } else {
  7423. ufbxi_fail("Invalid mapping");
  7424. }
  7425. } else {
  7426. if (mapping == ufbxi_ByPolygonVertex || mapping == ufbxi_ByPolygon) {
  7427. // Direct by polygon index: Use shared consecutive array if there's enough
  7428. // elements, otherwise use a unique truncated consecutive index array.
  7429. if (num_elems >= mesh->num_indices) {
  7430. uc->max_consecutive_indices = ufbxi_max_sz(uc->max_consecutive_indices, mesh->num_indices);
  7431. attrib->indices.data = (uint32_t*)ufbxi_sentinel_index_consecutive;
  7432. } else {
  7433. uint32_t *index_data = ufbxi_push(&uc->result, uint32_t, mesh->num_indices);
  7434. ufbxi_check(index_data);
  7435. for (size_t i = 0; i < mesh->num_indices; i++) {
  7436. index_data[i] = (uint32_t)i;
  7437. }
  7438. ufbxi_check(ufbxi_check_indices(uc, &attrib->indices.data, index_data, true, mesh->num_indices, mesh->num_indices, num_elems));
  7439. }
  7440. } else if (mapping == ufbxi_ByVertex || mapping == ufbxi_ByVertice) {
  7441. // Direct by vertex: We can re-use the position indices..
  7442. ufbxi_check(ufbxi_check_indices(uc, &attrib->indices.data, mesh->vertex_position.indices.data, false, mesh->num_indices, mesh->num_indices, num_elems));
  7443. attrib->unique_per_vertex = true;
  7444. } else if (mapping == ufbxi_AllSame) {
  7445. // Direct by all same: This cannot fail as the index list is just zero.
  7446. uc->max_zero_indices = ufbxi_max_sz(uc->max_zero_indices, mesh->num_indices);
  7447. attrib->indices.data = (uint32_t*)ufbxi_sentinel_index_zero;
  7448. attrib->unique_per_vertex = true;
  7449. } else {
  7450. ufbxi_fail("Invalid mapping");
  7451. }
  7452. }
  7453. return 1;
  7454. }
  7455. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_truncated_array(ufbxi_context *uc, void *p_data, size_t *p_count, ufbxi_node *node, const char *name, char fmt, size_t size)
  7456. {
  7457. ufbxi_value_array *arr = ufbxi_find_array(node, name, fmt);
  7458. ufbxi_check(arr);
  7459. *p_count = size;
  7460. void *data = arr->data;
  7461. if (arr->size < size) {
  7462. size_t elem_size = ufbxi_array_type_size(fmt);
  7463. void *new_data = ufbxi_push_size(&uc->result, elem_size, size);
  7464. ufbxi_check(new_data);
  7465. memcpy(new_data, data, arr->size * elem_size);
  7466. // Extend the array with the last element if possible
  7467. if (arr->size > 0) {
  7468. char *first_elem = (char*)data + (arr->size - 1) * elem_size;
  7469. for (size_t i = arr->size; i < size; i++) {
  7470. memcpy((char*)new_data + i * elem_size, first_elem, elem_size);
  7471. }
  7472. } else {
  7473. memset((char*)new_data + arr->size * elem_size, 0, (size - arr->size) * elem_size);
  7474. }
  7475. data = new_data;
  7476. }
  7477. *(void**)p_data = data;
  7478. return 1;
  7479. }
  7480. ufbxi_noinline static bool ufbxi_uv_set_less(void *user, const void *va, const void *vb)
  7481. {
  7482. (void)user;
  7483. const ufbx_uv_set *a = (const ufbx_uv_set *)va, *b = (const ufbx_uv_set *)vb;
  7484. return a->index < b->index;
  7485. }
  7486. ufbxi_noinline static bool ufbxi_color_set_less(void *user, const void *va, const void *vb)
  7487. {
  7488. (void)user;
  7489. const ufbx_color_set *a = (const ufbx_color_set *)va, *b = (const ufbx_color_set *)vb;
  7490. return a->index < b->index;
  7491. }
  7492. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_uv_sets(ufbxi_context *uc, ufbx_uv_set *sets, size_t count)
  7493. {
  7494. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_uv_set)));
  7495. ufbxi_stable_sort(sizeof(ufbx_uv_set), 32, sets, uc->tmp_arr, count, &ufbxi_uv_set_less, NULL);
  7496. return 1;
  7497. }
  7498. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_color_sets(ufbxi_context *uc, ufbx_color_set *sets, size_t count)
  7499. {
  7500. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_color_set)));
  7501. ufbxi_stable_sort(sizeof(ufbx_color_set), 32, sets, uc->tmp_arr, count, &ufbxi_color_set_less, NULL);
  7502. return 1;
  7503. }
  7504. typedef struct ufbxi_blend_offset {
  7505. uint32_t vertex;
  7506. ufbx_vec3 position_offset;
  7507. ufbx_vec3 normal_offset;
  7508. } ufbxi_blend_offset;
  7509. static ufbxi_noinline bool ufbxi_blend_offset_less(void *user, const void *va, const void *vb)
  7510. {
  7511. (void)user;
  7512. const ufbxi_blend_offset *a = (const ufbxi_blend_offset*)va, *b = (const ufbxi_blend_offset*)vb;
  7513. return a->vertex < b->vertex;
  7514. }
  7515. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_blend_offsets(ufbxi_context *uc, ufbxi_blend_offset *offsets, size_t count)
  7516. {
  7517. // Practically always ordered
  7518. while (count >= 2 && offsets[0].vertex <= offsets[1].vertex) {
  7519. offsets += 1;
  7520. count -= 1;
  7521. }
  7522. if (count <= 1) return 1;
  7523. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbxi_blend_offset)));
  7524. ufbxi_stable_sort(sizeof(ufbxi_blend_offset), 16, offsets, uc->tmp_arr, count, &ufbxi_blend_offset_less, NULL);
  7525. return 1;
  7526. }
  7527. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_shape(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  7528. {
  7529. ufbxi_node *node_vertices = ufbxi_find_child(node, ufbxi_Vertices);
  7530. ufbxi_node *node_indices = ufbxi_find_child(node, ufbxi_Indexes);
  7531. ufbxi_node *node_normals = ufbxi_find_child(node, ufbxi_Normals);
  7532. if (!node_vertices || !node_indices) return 1;
  7533. ufbx_blend_shape *shape = ufbxi_push_element(uc, info, ufbx_blend_shape, UFBX_ELEMENT_BLEND_SHAPE);
  7534. ufbxi_check(shape);
  7535. if (uc->opts.ignore_geometry) return 1;
  7536. ufbxi_value_array *vertices = ufbxi_get_array(node_vertices, 'r');
  7537. ufbxi_value_array *indices = ufbxi_get_array(node_indices, 'i');
  7538. ufbxi_check(vertices && indices);
  7539. ufbxi_check(vertices->size % 3 == 0);
  7540. ufbxi_check(indices->size == vertices->size / 3);
  7541. size_t num_offsets = indices->size;
  7542. uint32_t *vertex_indices = (uint32_t*)indices->data;
  7543. shape->num_offsets = num_offsets;
  7544. shape->position_offsets.data = (ufbx_vec3*)vertices->data;
  7545. shape->offset_vertices.data = vertex_indices;
  7546. shape->position_offsets.count = num_offsets;
  7547. shape->offset_vertices.count = num_offsets;
  7548. if (node_normals) {
  7549. ufbxi_value_array *normals = ufbxi_get_array(node_normals, 'r');
  7550. ufbxi_check(normals && normals->size == vertices->size);
  7551. shape->normal_offsets.data = (ufbx_vec3*)normals->data;
  7552. shape->normal_offsets.count = num_offsets;
  7553. }
  7554. // Sort the blend shape vertices only if absolutely necessary
  7555. bool sorted = true;
  7556. for (size_t i = 1; i < num_offsets; i++) {
  7557. if (vertex_indices[i - 1] > vertex_indices[i]) {
  7558. sorted = false;
  7559. break;
  7560. }
  7561. }
  7562. if (!sorted) {
  7563. ufbxi_blend_offset *offsets = ufbxi_push(&uc->tmp_stack, ufbxi_blend_offset, num_offsets);
  7564. ufbxi_check(offsets);
  7565. for (size_t i = 0; i < num_offsets; i++) {
  7566. offsets[i].vertex = shape->offset_vertices.data[i];
  7567. offsets[i].position_offset = shape->position_offsets.data[i];
  7568. if (node_normals) offsets[i].normal_offset = shape->normal_offsets.data[i];
  7569. }
  7570. ufbxi_check(ufbxi_sort_blend_offsets(uc, offsets, num_offsets));
  7571. for (size_t i = 0; i < num_offsets; i++) {
  7572. shape->offset_vertices.data[i] = offsets[i].vertex;
  7573. shape->position_offsets.data[i] = offsets[i].position_offset;
  7574. if (node_normals) shape->normal_offsets.data[i] = offsets[i].normal_offset;
  7575. }
  7576. ufbxi_pop(&uc->tmp_stack, ufbxi_blend_offset, num_offsets, NULL);
  7577. }
  7578. return 1;
  7579. }
  7580. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_synthetic_blend_shapes(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  7581. {
  7582. ufbx_blend_deformer *deformer = NULL;
  7583. uint64_t deformer_fbx_id = 0;
  7584. ufbxi_for (ufbxi_node, n, node->children, node->num_children) {
  7585. if (n->name != ufbxi_Shape) continue;
  7586. ufbx_string name;
  7587. ufbxi_check(ufbxi_get_val1(n, "S", &name));
  7588. if (deformer == NULL) {
  7589. deformer = ufbxi_push_synthetic_element(uc, &deformer_fbx_id, n, name.data, ufbx_blend_deformer, UFBX_ELEMENT_BLEND_DEFORMER);
  7590. ufbxi_check(deformer);
  7591. ufbxi_check(ufbxi_connect_oo(uc, deformer_fbx_id, info->fbx_id));
  7592. }
  7593. uint64_t channel_fbx_id = 0;
  7594. ufbx_blend_channel *channel = ufbxi_push_synthetic_element(uc, &channel_fbx_id, n, name.data, ufbx_blend_channel, UFBX_ELEMENT_BLEND_CHANNEL);
  7595. ufbxi_check(channel);
  7596. ufbx_real_list weight_list = { NULL, 0 };
  7597. ufbxi_check(ufbxi_push_copy(&uc->tmp_full_weights, ufbx_real_list, 1, &weight_list));
  7598. size_t num_shape_props = 1;
  7599. ufbx_prop *shape_props = ufbxi_push_zero(&uc->result, ufbx_prop, num_shape_props);
  7600. ufbxi_check(shape_props);
  7601. shape_props[0].name.data = ufbxi_DeformPercent;
  7602. shape_props[0].name.length = sizeof(ufbxi_DeformPercent) - 1;
  7603. shape_props[0]._internal_key = ufbxi_get_name_key_c(ufbxi_DeformPercent);
  7604. shape_props[0].type = UFBX_PROP_NUMBER;
  7605. shape_props[0].value_real = (ufbx_real)0.0;
  7606. shape_props[0].value_str = ufbx_empty_string;
  7607. shape_props[0].value_blob = ufbx_empty_blob;
  7608. ufbx_prop *self_prop = ufbx_find_prop_len(&info->props, name.data, name.length);
  7609. if (self_prop && (self_prop->type == UFBX_PROP_NUMBER || self_prop->type == UFBX_PROP_INTEGER)) {
  7610. shape_props[0].value_real = self_prop->value_real;
  7611. ufbxi_check(ufbxi_connect_pp(uc, info->fbx_id, channel_fbx_id, name, shape_props[0].name));
  7612. } else if (uc->version < 6000) {
  7613. ufbxi_check(ufbxi_connect_pp(uc, info->fbx_id, channel_fbx_id, name, shape_props[0].name));
  7614. }
  7615. channel->name = name;
  7616. channel->props.props.data = shape_props;
  7617. channel->props.props.count = num_shape_props;
  7618. ufbxi_element_info shape_info = { 0 };
  7619. ufbxi_check(ufbxi_push_synthetic_id(uc, &shape_info.fbx_id));
  7620. shape_info.name = name;
  7621. shape_info.dom_node = ufbxi_get_dom_node(uc, n);
  7622. ufbxi_check(ufbxi_read_shape(uc, n, &shape_info));
  7623. ufbxi_check(ufbxi_connect_oo(uc, channel_fbx_id, deformer_fbx_id));
  7624. ufbxi_check(ufbxi_connect_oo(uc, shape_info.fbx_id, channel_fbx_id));
  7625. }
  7626. return 1;
  7627. }
  7628. ufbxi_nodiscard ufbxi_noinline static int ufbxi_process_indices(ufbxi_context *uc, ufbx_mesh *mesh, uint32_t *index_data)
  7629. {
  7630. // Count the number of faces and allocate the index list
  7631. // Indices less than zero (~actual_index) ends a polygon
  7632. size_t num_total_faces = 0;
  7633. ufbxi_for (uint32_t, p_ix, index_data, mesh->num_indices) {
  7634. num_total_faces += ((int32_t)*p_ix < 0) ? 1u : 0u;
  7635. }
  7636. mesh->faces.data = ufbxi_push(&uc->result, ufbx_face, num_total_faces);
  7637. ufbxi_check(mesh->faces.data);
  7638. size_t num_triangles = 0;
  7639. size_t num_bad_faces = 0;
  7640. size_t max_face_triangles = 0;
  7641. ufbx_face *dst_face = mesh->faces.data;
  7642. uint32_t *p_face_begin = index_data;
  7643. ufbxi_for (uint32_t, p_ix, index_data, mesh->num_indices) {
  7644. uint32_t ix = *p_ix;
  7645. // Un-negate final indices of polygons
  7646. if ((int32_t)ix < 0) {
  7647. ix = ~ix;
  7648. *p_ix = ix;
  7649. uint32_t num_indices = (uint32_t)((p_ix - p_face_begin) + 1);
  7650. dst_face->index_begin = (uint32_t)(p_face_begin - index_data);
  7651. dst_face->num_indices = num_indices;
  7652. if (num_indices >= 3) {
  7653. num_triangles += num_indices - 2;
  7654. max_face_triangles = ufbxi_max_sz(max_face_triangles, num_indices - 2);
  7655. } else {
  7656. num_bad_faces++;
  7657. }
  7658. dst_face++;
  7659. p_face_begin = p_ix + 1;
  7660. }
  7661. ufbxi_check((size_t)ix < mesh->num_vertices);
  7662. }
  7663. mesh->vertex_position.indices.data = index_data;
  7664. mesh->num_faces = ufbxi_to_size(dst_face - mesh->faces.data);
  7665. mesh->faces.count = mesh->num_faces;
  7666. mesh->num_triangles = num_triangles;
  7667. mesh->max_face_triangles = max_face_triangles;
  7668. mesh->num_bad_faces = num_bad_faces;
  7669. mesh->vertex_first_index.count = mesh->num_vertices;
  7670. mesh->vertex_first_index.data = ufbxi_push(&uc->result, uint32_t, mesh->num_vertices);
  7671. ufbxi_check(mesh->vertex_first_index.data);
  7672. ufbxi_for_list(uint32_t, p_vx_ix, mesh->vertex_first_index) {
  7673. *p_vx_ix = UFBX_NO_INDEX;
  7674. }
  7675. for (size_t ix = 0; ix < mesh->num_indices; ix++) {
  7676. uint32_t vx = mesh->vertex_indices.data[ix];
  7677. if (vx < mesh->num_vertices) {
  7678. if (mesh->vertex_first_index.data[vx] == UFBX_NO_INDEX) {
  7679. mesh->vertex_first_index.data[vx] = (uint32_t)ix;
  7680. }
  7681. } else {
  7682. ufbxi_check(ufbxi_fix_index(uc, &mesh->vertex_indices.data[ix], vx, (uint32_t)mesh->num_vertices - 1));
  7683. }
  7684. }
  7685. // HACK(consecutive-faces): Prepare for finalize to re-use a consecutive/zero
  7686. // index buffer for face materials..
  7687. uc->max_zero_indices = ufbxi_max_sz(uc->max_zero_indices, mesh->num_faces);
  7688. uc->max_consecutive_indices = ufbxi_max_sz(uc->max_consecutive_indices, mesh->num_faces);
  7689. return 1;
  7690. }
  7691. ufbxi_noinline static void ufbxi_patch_mesh_reals(ufbx_mesh *mesh)
  7692. {
  7693. mesh->vertex_position.value_reals = 3;
  7694. mesh->vertex_normal.value_reals = 3;
  7695. mesh->vertex_uv.value_reals = 2;
  7696. mesh->vertex_tangent.value_reals = 3;
  7697. mesh->vertex_bitangent.value_reals = 3;
  7698. mesh->vertex_color.value_reals = 4;
  7699. mesh->vertex_crease.value_reals = 1;
  7700. mesh->skinned_position.value_reals = 3;
  7701. mesh->skinned_normal.value_reals = 3;
  7702. ufbxi_nounroll ufbxi_for_list(ufbx_uv_set, set, mesh->uv_sets) {
  7703. set->vertex_uv.value_reals = 2;
  7704. set->vertex_tangent.value_reals = 3;
  7705. set->vertex_bitangent.value_reals = 3;
  7706. }
  7707. ufbxi_nounroll ufbxi_for_list(ufbx_color_set, set, mesh->color_sets) {
  7708. set->vertex_color.value_reals = 4;
  7709. }
  7710. }
  7711. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_mesh(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  7712. {
  7713. ufbx_mesh *ufbxi_restrict mesh = ufbxi_push_element(uc, info, ufbx_mesh, UFBX_ELEMENT_MESH);
  7714. ufbxi_check(mesh);
  7715. // In up to version 7100 FBX files blend shapes are contained within the same geometry node
  7716. if (uc->version <= 7100) {
  7717. ufbxi_check(ufbxi_read_synthetic_blend_shapes(uc, node, info));
  7718. }
  7719. ufbxi_patch_mesh_reals(mesh);
  7720. // Sometimes there are empty meshes in FBX files?
  7721. // TODO: Should these be included in output? option? strict mode?
  7722. ufbxi_node *node_vertices = ufbxi_find_child(node, ufbxi_Vertices);
  7723. ufbxi_node *node_indices = ufbxi_find_child(node, ufbxi_PolygonVertexIndex);
  7724. if (!node_vertices || !node_indices) return 1;
  7725. if (uc->opts.ignore_geometry) return 1;
  7726. ufbxi_value_array *vertices = ufbxi_get_array(node_vertices, 'r');
  7727. ufbxi_value_array *indices = ufbxi_get_array(node_indices, 'i');
  7728. ufbxi_value_array *edge_indices = ufbxi_find_array(node, ufbxi_Edges, 'i');
  7729. ufbxi_check(vertices && indices);
  7730. ufbxi_check(vertices->size % 3 == 0);
  7731. mesh->num_vertices = vertices->size / 3;
  7732. mesh->num_indices = indices->size;
  7733. uint32_t *index_data = (uint32_t*)indices->data;
  7734. // Duplicate `index_data` for modification if we retain DOM
  7735. if (uc->opts.retain_dom) {
  7736. index_data = ufbxi_push_copy(&uc->result, uint32_t, indices->size, index_data);
  7737. ufbxi_check(index_data);
  7738. }
  7739. mesh->vertices.data = (ufbx_vec3*)vertices->data;
  7740. mesh->vertices.count = mesh->num_vertices;
  7741. mesh->vertex_indices.data = index_data;
  7742. mesh->vertex_indices.count = mesh->num_indices;
  7743. mesh->vertex_position.exists = true;
  7744. mesh->vertex_position.values.data = (ufbx_vec3*)vertices->data;
  7745. mesh->vertex_position.values.count = mesh->num_vertices;
  7746. mesh->vertex_position.indices.data = index_data;
  7747. mesh->vertex_position.indices.count = mesh->num_indices;
  7748. // Check/make sure that the last index is negated (last of polygon)
  7749. if (mesh->num_indices > 0) {
  7750. if ((int32_t)index_data[mesh->num_indices - 1] >= 0) {
  7751. if (uc->opts.strict) ufbxi_fail("Non-negated last index");
  7752. index_data[mesh->num_indices - 1] = ~index_data[mesh->num_indices - 1];
  7753. }
  7754. }
  7755. // Read edges before un-negating the indices
  7756. if (edge_indices) {
  7757. size_t num_edges = edge_indices->size;
  7758. ufbx_edge *edges = ufbxi_push(&uc->result, ufbx_edge, num_edges);
  7759. ufbxi_check(edges);
  7760. size_t dst_ix = 0;
  7761. // Edges are represented using a single index into PolygonVertexIndex.
  7762. // The edge is between two consecutive vertices in the polygon.
  7763. uint32_t *edge_data = (uint32_t*)edge_indices->data;
  7764. for (size_t i = 0; i < num_edges; i++) {
  7765. uint32_t index_ix = edge_data[i];
  7766. if (index_ix >= mesh->num_indices) {
  7767. if (uc->opts.strict) ufbxi_fail("Edge index out of bounds");
  7768. continue;
  7769. }
  7770. edges[dst_ix].a = index_ix;
  7771. if ((int32_t)index_data[index_ix] < 0) {
  7772. // Previous index is the last one of this polygon, rewind to first index.
  7773. while (index_ix > 0 && (int32_t)index_data[index_ix - 1] >= 0) {
  7774. index_ix--;
  7775. }
  7776. } else {
  7777. // Connect to the next index in the same polygon
  7778. index_ix++;
  7779. }
  7780. ufbxi_check(index_ix < mesh->num_indices);
  7781. edges[dst_ix].b = index_ix;
  7782. dst_ix++;
  7783. }
  7784. mesh->edges.data = edges;
  7785. mesh->edges.count = dst_ix;
  7786. mesh->num_edges = mesh->edges.count;
  7787. }
  7788. ufbxi_check(ufbxi_process_indices(uc, mesh, index_data));
  7789. // Count the number of UV/color sets
  7790. size_t num_uv = 0, num_color = 0, num_bitangents = 0, num_tangents = 0;
  7791. ufbxi_for (ufbxi_node, n, node->children, node->num_children) {
  7792. if (n->name == ufbxi_LayerElementUV) num_uv++;
  7793. if (n->name == ufbxi_LayerElementColor) num_color++;
  7794. if (n->name == ufbxi_LayerElementBinormal) num_bitangents++;
  7795. if (n->name == ufbxi_LayerElementTangent) num_tangents++;
  7796. }
  7797. size_t num_textures = 0;
  7798. ufbxi_tangent_layer *bitangents = ufbxi_push_zero(&uc->tmp_stack, ufbxi_tangent_layer, num_bitangents);
  7799. ufbxi_tangent_layer *tangents = ufbxi_push_zero(&uc->tmp_stack, ufbxi_tangent_layer, num_tangents);
  7800. ufbxi_check(bitangents);
  7801. ufbxi_check(tangents);
  7802. mesh->uv_sets.data = ufbxi_push_zero(&uc->result, ufbx_uv_set, num_uv);
  7803. mesh->color_sets.data = ufbxi_push_zero(&uc->result, ufbx_color_set, num_color);
  7804. ufbxi_check(mesh->uv_sets.data);
  7805. ufbxi_check(mesh->color_sets.data);
  7806. size_t num_bitangents_read = 0, num_tangents_read = 0;
  7807. ufbxi_for (ufbxi_node, n, node->children, node->num_children) {
  7808. if (n->name[0] != 'L') continue; // All names start with 'LayerElement*'
  7809. if (n->name == ufbxi_LayerElementNormal) {
  7810. if (mesh->vertex_normal.exists) continue;
  7811. ufbxi_check(ufbxi_read_vertex_element(uc, mesh, n, (ufbx_vertex_attrib*)&mesh->vertex_normal,
  7812. ufbxi_Normals, ufbxi_NormalsIndex, 'r', 3));
  7813. } else if (n->name == ufbxi_LayerElementBinormal) {
  7814. ufbxi_tangent_layer *layer = &bitangents[num_bitangents_read++];
  7815. ufbxi_ignore(ufbxi_get_val1(n, "I", &layer->index));
  7816. ufbxi_check(ufbxi_read_vertex_element(uc, mesh, n, (ufbx_vertex_attrib*)&layer->elem,
  7817. ufbxi_Binormals, ufbxi_BinormalsIndex, 'r', 3));
  7818. if (!layer->elem.exists) num_bitangents_read--;
  7819. } else if (n->name == ufbxi_LayerElementTangent) {
  7820. ufbxi_tangent_layer *layer = &tangents[num_tangents_read++];
  7821. ufbxi_ignore(ufbxi_get_val1(n, "I", &layer->index));
  7822. ufbxi_check(ufbxi_read_vertex_element(uc, mesh, n, (ufbx_vertex_attrib*)&layer->elem,
  7823. ufbxi_Tangents, ufbxi_TangentsIndex, 'r', 3));
  7824. if (!layer->elem.exists) num_tangents_read--;
  7825. } else if (n->name == ufbxi_LayerElementUV) {
  7826. ufbx_uv_set *set = &mesh->uv_sets.data[mesh->uv_sets.count++];
  7827. ufbxi_ignore(ufbxi_get_val1(n, "I", &set->index));
  7828. if (!ufbxi_find_val1(n, ufbxi_Name, "S", &set->name)) {
  7829. set->name = ufbx_empty_string;
  7830. }
  7831. ufbxi_check(ufbxi_read_vertex_element(uc, mesh, n, (ufbx_vertex_attrib*)&set->vertex_uv,
  7832. ufbxi_UV, ufbxi_UVIndex, 'r', 2));
  7833. if (!set->vertex_uv.exists) mesh->uv_sets.count--;
  7834. } else if (n->name == ufbxi_LayerElementColor) {
  7835. ufbx_color_set *set = &mesh->color_sets.data[mesh->color_sets.count++];
  7836. ufbxi_ignore(ufbxi_get_val1(n, "I", &set->index));
  7837. if (!ufbxi_find_val1(n, ufbxi_Name, "S", &set->name)) {
  7838. set->name = ufbx_empty_string;
  7839. }
  7840. ufbxi_check(ufbxi_read_vertex_element(uc, mesh, n, (ufbx_vertex_attrib*)&set->vertex_color,
  7841. ufbxi_Colors, ufbxi_ColorIndex, 'r', 4));
  7842. if (!set->vertex_color.exists) mesh->color_sets.count--;
  7843. } else if (n->name == ufbxi_LayerElementVertexCrease) {
  7844. ufbxi_check(ufbxi_read_vertex_element(uc, mesh, n, (ufbx_vertex_attrib*)&mesh->vertex_crease,
  7845. ufbxi_VertexCrease, ufbxi_VertexCreaseIndex, 'r', 1));
  7846. } else if (n->name == ufbxi_LayerElementEdgeCrease) {
  7847. const char *mapping;
  7848. ufbxi_check(ufbxi_find_val1(n, ufbxi_MappingInformationType, "c", (char**)&mapping));
  7849. if (mapping == ufbxi_ByEdge) {
  7850. if (mesh->edge_crease.count) continue;
  7851. ufbxi_check(ufbxi_read_truncated_array(uc, &mesh->edge_crease.data, &mesh->edge_crease.count, n, ufbxi_EdgeCrease, 'r', mesh->num_edges));
  7852. }
  7853. } else if (n->name == ufbxi_LayerElementSmoothing) {
  7854. const char *mapping;
  7855. ufbxi_check(ufbxi_find_val1(n, ufbxi_MappingInformationType, "c", (char**)&mapping));
  7856. if (mapping == ufbxi_ByEdge) {
  7857. if (mesh->edge_smoothing.count) continue;
  7858. ufbxi_check(ufbxi_read_truncated_array(uc, &mesh->edge_smoothing.data, &mesh->edge_smoothing.count, n, ufbxi_Smoothing, 'b', mesh->num_edges));
  7859. } else if (mapping == ufbxi_ByPolygon) {
  7860. if (mesh->face_smoothing.count) continue;
  7861. ufbxi_check(ufbxi_read_truncated_array(uc, &mesh->face_smoothing.data, &mesh->face_smoothing.count, n, ufbxi_Smoothing, 'b', mesh->num_faces));
  7862. }
  7863. } else if (n->name == ufbxi_LayerElementVisibility) {
  7864. const char *mapping;
  7865. ufbxi_check(ufbxi_find_val1(n, ufbxi_MappingInformationType, "c", (char**)&mapping));
  7866. if (mapping == ufbxi_ByEdge) {
  7867. if (mesh->edge_visibility.count) continue;
  7868. ufbxi_check(ufbxi_read_truncated_array(uc, &mesh->edge_visibility.data, &mesh->edge_visibility.count, n, ufbxi_Visibility, 'b', mesh->num_edges));
  7869. }
  7870. } else if (n->name == ufbxi_LayerElementMaterial) {
  7871. if (mesh->face_material.count) continue;
  7872. const char *mapping;
  7873. ufbxi_check(ufbxi_find_val1(n, ufbxi_MappingInformationType, "c", (char**)&mapping));
  7874. if (mapping == ufbxi_ByPolygon) {
  7875. ufbxi_check(ufbxi_read_truncated_array(uc, &mesh->face_material.data, &mesh->face_material.count, n, ufbxi_Materials, 'i', mesh->num_faces));
  7876. } else if (mapping == ufbxi_AllSame) {
  7877. ufbxi_value_array *arr = ufbxi_find_array(n, ufbxi_Materials, 'i');
  7878. ufbxi_check(arr && arr->size >= 1);
  7879. uint32_t material = *(uint32_t*)arr->data;
  7880. mesh->face_material.count = mesh->num_faces;
  7881. if (material == 0) {
  7882. mesh->face_material.data = (uint32_t*)ufbxi_sentinel_index_zero;
  7883. } else {
  7884. mesh->face_material.data = ufbxi_push(&uc->result, uint32_t, mesh->num_faces);
  7885. ufbxi_check(mesh->face_material.data);
  7886. ufbxi_for_list(uint32_t, p_mat, mesh->face_material) {
  7887. *p_mat = material;
  7888. }
  7889. }
  7890. }
  7891. } else if (n->name == ufbxi_LayerElementPolygonGroup) {
  7892. if (mesh->face_group.count) continue;
  7893. const char *mapping;
  7894. ufbxi_check(ufbxi_find_val1(n, ufbxi_MappingInformationType, "c", (char**)&mapping));
  7895. if (mapping == ufbxi_ByPolygon) {
  7896. ufbxi_check(ufbxi_read_truncated_array(uc, &mesh->face_group.data, &mesh->face_group.count, n, ufbxi_PolygonGroup, 'i', mesh->num_faces));
  7897. }
  7898. } else if (n->name == ufbxi_LayerElementHole) {
  7899. if (mesh->face_group.count) continue;
  7900. const char *mapping;
  7901. ufbxi_check(ufbxi_find_val1(n, ufbxi_MappingInformationType, "c", (char**)&mapping));
  7902. if (mapping == ufbxi_ByPolygon) {
  7903. ufbxi_check(ufbxi_read_truncated_array(uc, &mesh->face_hole.data, &mesh->face_hole.count, n, ufbxi_Hole, 'b', mesh->num_faces));
  7904. }
  7905. } else if (!strncmp(n->name, "LayerElement", 12)) {
  7906. // Make sure the name has no internal zero bytes
  7907. ufbxi_check(!memchr(n->name, '\0', n->name_len));
  7908. // What?! 6x00 stores textures in mesh geometry, eg. "LayerElementTexture",
  7909. // "LayerElementDiffuseFactorTextures", "LayerElementEmissive_Textures"...
  7910. ufbx_string prop_name = ufbx_empty_string;
  7911. if (n->name_len > 20 && !strcmp(n->name + n->name_len - 8, "Textures")) {
  7912. prop_name.data = n->name + 12;
  7913. prop_name.length = (size_t)n->name_len - 20;
  7914. if (prop_name.data[prop_name.length - 1] == '_') {
  7915. prop_name.length -= 1;
  7916. }
  7917. } else if (!strcmp(n->name, "LayerElementTexture")) {
  7918. prop_name.data = "Diffuse";
  7919. prop_name.length = 7;
  7920. }
  7921. if (prop_name.length > 0) {
  7922. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &prop_name, false));
  7923. const char *mapping;
  7924. if (ufbxi_find_val1(n, ufbxi_MappingInformationType, "c", (char**)&mapping)) {
  7925. ufbxi_value_array *arr = ufbxi_find_array(n, ufbxi_TextureId, 'i');
  7926. ufbxi_tmp_mesh_texture *tex = ufbxi_push_zero(&uc->tmp_mesh_textures, ufbxi_tmp_mesh_texture, 1);
  7927. ufbxi_check(tex);
  7928. if (arr) {
  7929. tex->face_texture = (uint32_t*)arr->data;
  7930. tex->num_faces = arr->size;
  7931. }
  7932. tex->prop_name = prop_name;
  7933. tex->all_same = (mapping == ufbxi_AllSame);
  7934. num_textures++;
  7935. }
  7936. }
  7937. }
  7938. }
  7939. // Always use a default zero material, this will be removed if no materials are found
  7940. if (!mesh->face_material.count) {
  7941. uc->max_zero_indices = ufbxi_max_sz(uc->max_zero_indices, mesh->num_faces);
  7942. mesh->face_material.data = (uint32_t*)ufbxi_sentinel_index_zero;
  7943. mesh->face_material.count = mesh->num_faces;
  7944. }
  7945. if (uc->opts.strict) {
  7946. ufbxi_check(mesh->uv_sets.count == num_uv);
  7947. ufbxi_check(mesh->color_sets.count == num_color);
  7948. ufbxi_check(num_bitangents_read == num_bitangents);
  7949. ufbxi_check(num_tangents_read == num_tangents);
  7950. }
  7951. // Connect bitangents/tangents to UV sets
  7952. ufbxi_for (ufbxi_node, n, node->children, node->num_children) {
  7953. if (n->name != ufbxi_Layer) continue;
  7954. ufbx_uv_set *uv_set = NULL;
  7955. ufbxi_tangent_layer *bitangent_layer = NULL;
  7956. ufbxi_tangent_layer *tangent_layer = NULL;
  7957. ufbxi_for (ufbxi_node, c, n->children, n->num_children) {
  7958. uint32_t index;
  7959. const char *type;
  7960. if (c->name != ufbxi_LayerElement) continue;
  7961. if (!ufbxi_find_val1(c, ufbxi_TypedIndex, "I", &index)) continue;
  7962. if (!ufbxi_find_val1(c, ufbxi_Type, "C", (char**)&type)) continue;
  7963. if (type == ufbxi_LayerElementUV) {
  7964. ufbxi_for(ufbx_uv_set, set, mesh->uv_sets.data, mesh->uv_sets.count) {
  7965. if (set->index == index) {
  7966. uv_set = set;
  7967. break;
  7968. }
  7969. }
  7970. } else if (type == ufbxi_LayerElementBinormal) {
  7971. ufbxi_for(ufbxi_tangent_layer, layer, bitangents, num_bitangents_read) {
  7972. if (layer->index == index) {
  7973. bitangent_layer = layer;
  7974. break;
  7975. }
  7976. }
  7977. } else if (type == ufbxi_LayerElementTangent) {
  7978. ufbxi_for(ufbxi_tangent_layer, layer, tangents, num_tangents_read) {
  7979. if (layer->index == index) {
  7980. tangent_layer = layer;
  7981. break;
  7982. }
  7983. }
  7984. }
  7985. }
  7986. if (uv_set) {
  7987. if (bitangent_layer) {
  7988. uv_set->vertex_bitangent = bitangent_layer->elem;
  7989. }
  7990. if (tangent_layer) {
  7991. uv_set->vertex_tangent = tangent_layer->elem;
  7992. }
  7993. }
  7994. }
  7995. mesh->skinned_is_local = true;
  7996. mesh->skinned_position = mesh->vertex_position;
  7997. mesh->skinned_normal = mesh->vertex_normal;
  7998. ufbxi_patch_mesh_reals(mesh);
  7999. // Sort UV and color sets by set index
  8000. ufbxi_check(ufbxi_sort_uv_sets(uc, mesh->uv_sets.data, mesh->uv_sets.count));
  8001. ufbxi_check(ufbxi_sort_color_sets(uc, mesh->color_sets.data, mesh->color_sets.count));
  8002. if (num_textures > 0) {
  8003. ufbxi_mesh_extra *extra = ufbxi_push_element_extra(uc, mesh->element.element_id, ufbxi_mesh_extra);
  8004. ufbxi_check(extra);
  8005. extra->texture_count = num_textures;
  8006. extra->texture_arr = ufbxi_push_pop(&uc->tmp, &uc->tmp_mesh_textures, ufbxi_tmp_mesh_texture, num_textures);
  8007. ufbxi_check(extra->texture_arr);
  8008. }
  8009. // Subdivision
  8010. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_PreviewDivisionLevels, "I", &mesh->subdivision_preview_levels));
  8011. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_RenderDivisionLevels, "I", &mesh->subdivision_render_levels));
  8012. int32_t smoothness, boundary;
  8013. if (ufbxi_find_val1(node, ufbxi_Smoothness, "I", &smoothness)) {
  8014. if (smoothness >= 0 && smoothness <= UFBX_SUBDIVISION_DISPLAY_SMOOTH) {
  8015. mesh->subdivision_display_mode = (ufbx_subdivision_display_mode)smoothness;
  8016. }
  8017. }
  8018. if (ufbxi_find_val1(node, ufbxi_BoundaryRule, "I", &boundary)) {
  8019. if (boundary >= 0 && boundary <= UFBX_SUBDIVISION_BOUNDARY_SHARP_CORNERS - 1) {
  8020. mesh->subdivision_boundary = (ufbx_subdivision_boundary)(boundary + 1);
  8021. }
  8022. }
  8023. return 1;
  8024. }
  8025. ufbxi_noinline static ufbx_nurbs_topology ufbxi_read_nurbs_topology(const char *form)
  8026. {
  8027. if (!strcmp(form, "Open")) {
  8028. return UFBX_NURBS_TOPOLOGY_OPEN;
  8029. } else if (!strcmp(form, "Closed")) {
  8030. return UFBX_NURBS_TOPOLOGY_CLOSED;
  8031. } else if (!strcmp(form, "Periodic")) {
  8032. return UFBX_NURBS_TOPOLOGY_PERIODIC;
  8033. }
  8034. return UFBX_NURBS_TOPOLOGY_OPEN;
  8035. }
  8036. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_nurbs_curve(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8037. {
  8038. ufbx_nurbs_curve *nurbs = ufbxi_push_element(uc, info, ufbx_nurbs_curve, UFBX_ELEMENT_NURBS_CURVE);
  8039. ufbxi_check(nurbs);
  8040. int32_t dimension = 3;
  8041. const char *form = NULL;
  8042. ufbxi_check(ufbxi_find_val1(node, ufbxi_Order, "I", &nurbs->basis.order));
  8043. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_Dimension, "I", &dimension));
  8044. ufbxi_check(ufbxi_find_val1(node, ufbxi_Form, "C", (char**)&form));
  8045. nurbs->basis.topology = ufbxi_read_nurbs_topology(form);
  8046. nurbs->basis.is_2d = dimension == 2;
  8047. if (!uc->opts.ignore_geometry) {
  8048. ufbxi_value_array *points = ufbxi_find_array(node, ufbxi_Points, 'r');
  8049. ufbxi_value_array *knot = ufbxi_find_array(node, ufbxi_KnotVector, 'r');
  8050. ufbxi_check(points);
  8051. ufbxi_check(knot);
  8052. ufbxi_check(points->size % 4 == 0);
  8053. nurbs->control_points.count = points->size / 4;
  8054. nurbs->control_points.data = (ufbx_vec4*)points->data;
  8055. nurbs->basis.knot_vector.data = (ufbx_real*)knot->data;
  8056. nurbs->basis.knot_vector.count = knot->size;
  8057. }
  8058. return 1;
  8059. }
  8060. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_nurbs_surface(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8061. {
  8062. ufbx_nurbs_surface *nurbs = ufbxi_push_element(uc, info, ufbx_nurbs_surface, UFBX_ELEMENT_NURBS_SURFACE);
  8063. ufbxi_check(nurbs);
  8064. const char *form_u = NULL, *form_v = NULL;
  8065. size_t dimension_u = 0, dimension_v = 0;
  8066. int32_t step_u = 0, step_v = 0;
  8067. ufbxi_check(ufbxi_find_val2(node, ufbxi_NurbsSurfaceOrder, "II", &nurbs->basis_u.order, &nurbs->basis_v.order));
  8068. ufbxi_check(ufbxi_find_val2(node, ufbxi_Dimensions, "ZZ", &dimension_u, &dimension_v));
  8069. ufbxi_check(ufbxi_find_val2(node, ufbxi_Step, "II", &step_u, &step_v));
  8070. ufbxi_check(ufbxi_find_val2(node, ufbxi_Form, "CC", (char**)&form_u, (char**)&form_v));
  8071. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_FlipNormals, "B", &nurbs->flip_normals));
  8072. nurbs->basis_u.topology = ufbxi_read_nurbs_topology(form_u);
  8073. nurbs->basis_v.topology = ufbxi_read_nurbs_topology(form_v);
  8074. nurbs->num_control_points_u = dimension_u;
  8075. nurbs->num_control_points_v = dimension_v;
  8076. nurbs->span_subdivision_u = step_u > 0 ? (uint32_t)step_u : 4u;
  8077. nurbs->span_subdivision_v = step_v > 0 ? (uint32_t)step_v : 4u;
  8078. if (!uc->opts.ignore_geometry) {
  8079. ufbxi_value_array *points = ufbxi_find_array(node, ufbxi_Points, 'r');
  8080. ufbxi_value_array *knot_u = ufbxi_find_array(node, ufbxi_KnotVectorU, 'r');
  8081. ufbxi_value_array *knot_v = ufbxi_find_array(node, ufbxi_KnotVectorV, 'r');
  8082. ufbxi_check(points);
  8083. ufbxi_check(knot_u);
  8084. ufbxi_check(knot_v);
  8085. ufbxi_check(points->size % 4 == 0);
  8086. ufbxi_check(points->size / 4 == (size_t)dimension_u * (size_t)dimension_v);
  8087. nurbs->control_points.count = points->size / 4;
  8088. nurbs->control_points.data = (ufbx_vec4*)points->data;
  8089. nurbs->basis_u.knot_vector.data = (ufbx_real*)knot_u->data;
  8090. nurbs->basis_u.knot_vector.count = knot_u->size;
  8091. nurbs->basis_v.knot_vector.data = (ufbx_real*)knot_v->data;
  8092. nurbs->basis_v.knot_vector.count = knot_v->size;
  8093. }
  8094. return 1;
  8095. }
  8096. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_line(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8097. {
  8098. ufbx_line_curve *line = ufbxi_push_element(uc, info, ufbx_line_curve, UFBX_ELEMENT_LINE_CURVE);
  8099. ufbxi_check(line);
  8100. if (!uc->opts.ignore_geometry) {
  8101. ufbxi_value_array *points = ufbxi_find_array(node, ufbxi_Points, 'r');
  8102. ufbxi_value_array *points_index = ufbxi_find_array(node, ufbxi_PointsIndex, 'i');
  8103. ufbxi_check(points);
  8104. ufbxi_check(points_index);
  8105. ufbxi_check(points->size % 3 == 0);
  8106. if (points->size > 0) {
  8107. line->control_points.count = points->size / 3;
  8108. line->control_points.data = (ufbx_vec3*)points->data;
  8109. line->point_indices.count = points_index->size;
  8110. line->point_indices.data = (uint32_t*)points_index->data;
  8111. ufbxi_check(line->control_points.count < INT32_MAX);
  8112. // Count end points
  8113. size_t num_segments = 1;
  8114. if (line->point_indices.count > 0) {
  8115. for (size_t i = 0; i < line->point_indices.count - 1; i++) {
  8116. uint32_t ix = line->point_indices.data[i];
  8117. num_segments += (int32_t)ix < 0 ? 1u : 0u;
  8118. }
  8119. }
  8120. size_t prev_end = 0;
  8121. line->segments.data = ufbxi_push(&uc->result, ufbx_line_segment, num_segments);
  8122. ufbxi_check(line->segments.data);
  8123. for (size_t i = 0; i < line->point_indices.count; i++) {
  8124. uint32_t ix = line->point_indices.data[i];
  8125. if ((int32_t)ix < 0) {
  8126. ix = ~ix;
  8127. if (i + 1 < line->point_indices.count) {
  8128. ufbx_line_segment *segment = &line->segments.data[line->segments.count++];
  8129. segment->index_begin = (uint32_t)prev_end;
  8130. segment->num_indices = (uint32_t)(i - prev_end);
  8131. prev_end = i;
  8132. }
  8133. }
  8134. if (ix < line->control_points.count) {
  8135. line->point_indices.data[i] = ix;
  8136. } else {
  8137. ufbxi_check(ufbxi_fix_index(uc, &line->point_indices.data[i], ix, (uint32_t)line->control_points.count - 1));
  8138. }
  8139. }
  8140. ufbx_line_segment *segment = &line->segments.data[line->segments.count++];
  8141. segment->index_begin = (uint32_t)prev_end;
  8142. segment->num_indices = (uint32_t)ufbxi_to_size(line->point_indices.count - prev_end);
  8143. ufbx_assert(line->segments.count == num_segments);
  8144. }
  8145. }
  8146. return 1;
  8147. }
  8148. ufbxi_noinline static void ufbxi_read_transform_matrix(ufbx_matrix *m, ufbx_real *data)
  8149. {
  8150. m->m00 = data[ 0]; m->m10 = data[ 1]; m->m20 = data[ 2];
  8151. m->m01 = data[ 4]; m->m11 = data[ 5]; m->m21 = data[ 6];
  8152. m->m02 = data[ 8]; m->m12 = data[ 9]; m->m22 = data[10];
  8153. m->m03 = data[12]; m->m13 = data[13]; m->m23 = data[14];
  8154. }
  8155. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_bone(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, const char *sub_type)
  8156. {
  8157. (void)node;
  8158. ufbx_bone *bone = ufbxi_push_element(uc, info, ufbx_bone, UFBX_ELEMENT_BONE);
  8159. ufbxi_check(bone);
  8160. if (sub_type == ufbxi_Root) {
  8161. bone->is_root = true;
  8162. }
  8163. return 1;
  8164. }
  8165. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_marker(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, const char *sub_type, ufbx_marker_type type)
  8166. {
  8167. (void)node;
  8168. (void)sub_type;
  8169. ufbx_marker *marker = ufbxi_push_element(uc, info, ufbx_marker, UFBX_ELEMENT_MARKER);
  8170. ufbxi_check(marker);
  8171. marker->type = type;
  8172. return 1;
  8173. }
  8174. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_skin(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8175. {
  8176. ufbx_skin_deformer *skin = ufbxi_push_element(uc, info, ufbx_skin_deformer, UFBX_ELEMENT_SKIN_DEFORMER);
  8177. ufbxi_check(skin);
  8178. const char *skinning_type = NULL;
  8179. if (ufbxi_find_val1(node, ufbxi_SkinningType, "C", (char**)&skinning_type)) {
  8180. if (!strcmp(skinning_type, "Rigid")) {
  8181. skin->skinning_method = UFBX_SKINNING_METHOD_RIGID;
  8182. } else if (!strcmp(skinning_type, "Linear")) {
  8183. skin->skinning_method = UFBX_SKINNING_METHOD_LINEAR;
  8184. } else if (!strcmp(skinning_type, "DualQuaternion")) {
  8185. skin->skinning_method = UFBX_SKINNING_METHOD_DUAL_QUATERNION;
  8186. } else if (!strcmp(skinning_type, "Blend")) {
  8187. skin->skinning_method = UFBX_SKINNING_METHOD_BLENDED_DQ_LINEAR;
  8188. }
  8189. }
  8190. ufbxi_value_array *indices = ufbxi_find_array(node, ufbxi_Indexes, 'i');
  8191. ufbxi_value_array *weights = ufbxi_find_array(node, ufbxi_BlendWeights, 'r');
  8192. if (indices && weights) {
  8193. // TODO strict: ufbxi_check(indices->size == weights->size);
  8194. skin->num_dq_weights = ufbxi_min_sz(indices->size, weights->size);
  8195. skin->dq_vertices.data = (uint32_t*)indices->data;
  8196. skin->dq_weights.data = (ufbx_real*)weights->data;
  8197. skin->dq_vertices.count = skin->num_dq_weights;
  8198. skin->dq_weights.count = skin->num_dq_weights;
  8199. }
  8200. return 1;
  8201. }
  8202. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_skin_cluster(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8203. {
  8204. ufbx_skin_cluster *cluster = ufbxi_push_element(uc, info, ufbx_skin_cluster, UFBX_ELEMENT_SKIN_CLUSTER);
  8205. ufbxi_check(cluster);
  8206. ufbxi_value_array *indices = ufbxi_find_array(node, ufbxi_Indexes, 'i');
  8207. ufbxi_value_array *weights = ufbxi_find_array(node, ufbxi_Weights, 'r');
  8208. if (indices && weights) {
  8209. ufbxi_check(indices->size == weights->size);
  8210. cluster->num_weights = indices->size;
  8211. cluster->vertices.data = (uint32_t*)indices->data;
  8212. cluster->weights.data = (ufbx_real*)weights->data;
  8213. cluster->vertices.count = cluster->num_weights;
  8214. cluster->weights.count = cluster->num_weights;
  8215. }
  8216. ufbxi_value_array *transform = ufbxi_find_array(node, ufbxi_Transform, 'r');
  8217. ufbxi_value_array *transform_link = ufbxi_find_array(node, ufbxi_TransformLink, 'r');
  8218. if (transform && transform_link) {
  8219. ufbxi_check(transform->size >= 16);
  8220. ufbxi_check(transform_link->size >= 16);
  8221. ufbxi_read_transform_matrix(&cluster->mesh_node_to_bone, (ufbx_real*)transform->data);
  8222. ufbxi_read_transform_matrix(&cluster->bind_to_world, (ufbx_real*)transform_link->data);
  8223. }
  8224. return 1;
  8225. }
  8226. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_blend_channel(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8227. {
  8228. ufbx_blend_channel *channel = ufbxi_push_element(uc, info, ufbx_blend_channel, UFBX_ELEMENT_BLEND_CHANNEL);
  8229. ufbxi_check(channel);
  8230. ufbx_real_list list = { NULL, 0 };
  8231. ufbxi_value_array *full_weights = ufbxi_find_array(node, ufbxi_FullWeights, 'd');
  8232. if (full_weights) {
  8233. list.data = (ufbx_real*)full_weights->data;
  8234. list.count = full_weights->size;
  8235. }
  8236. ufbxi_check(ufbxi_push_copy(&uc->tmp_full_weights, ufbx_real_list, 1, &list));
  8237. return 1;
  8238. }
  8239. static ufbxi_forceinline float ufbxi_solve_auto_tangent(double prev_time, double time, double next_time, ufbx_real prev_value, ufbx_real value, ufbx_real next_value, float weight_left, float weight_right)
  8240. {
  8241. // In between two keyframes: Set the initial slope to be the difference between
  8242. // the two keyframes. Prevent overshooting by clamping the slope in case either
  8243. // tangent goes above/below the endpoints.
  8244. double slope = (next_value - prev_value) / (next_time - prev_time);
  8245. // Split the slope to sign and a non-negative absolute value
  8246. double slope_sign = slope >= 0.0 ? 1.0 : -1.0;
  8247. double abs_slope = slope_sign * slope;
  8248. // Find limits for the absolute value of the slope
  8249. double range_left = weight_left * (time - prev_time);
  8250. double range_right = weight_right * (next_time - time);
  8251. double max_left = range_left > 0.0 ? slope_sign * (value - prev_value) / range_left : 0.0;
  8252. double max_right = range_right > 0.0 ? slope_sign * (next_value - value) / range_right : 0.0;
  8253. // Clamp negative values and NaNs to zero
  8254. if (!(max_left > 0.0)) max_left = 0.0;
  8255. if (!(max_right > 0.0)) max_right = 0.0;
  8256. // Clamp the absolute slope from both sides
  8257. if (abs_slope > max_left) abs_slope = max_left;
  8258. if (abs_slope > max_right) abs_slope = max_right;
  8259. return (float)(slope_sign * abs_slope);
  8260. }
  8261. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_animation_curve(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8262. {
  8263. ufbx_anim_curve *curve = ufbxi_push_element(uc, info, ufbx_anim_curve, UFBX_ELEMENT_ANIM_CURVE);
  8264. ufbxi_check(curve);
  8265. if (uc->opts.ignore_animation) return 1;
  8266. ufbxi_value_array *times, *values, *attr_flags, *attrs, *refs;
  8267. ufbxi_check(times = ufbxi_find_array(node, ufbxi_KeyTime, 'l'));
  8268. ufbxi_check(values = ufbxi_find_array(node, ufbxi_KeyValueFloat, 'r'));
  8269. ufbxi_check(attr_flags = ufbxi_find_array(node, ufbxi_KeyAttrFlags, 'i'));
  8270. ufbxi_check(attrs = ufbxi_find_array(node, ufbxi_KeyAttrDataFloat, '?'));
  8271. ufbxi_check(refs = ufbxi_find_array(node, ufbxi_KeyAttrRefCount, 'i'));
  8272. // Time and value arrays that define the keyframes should be parallel
  8273. ufbxi_check(times->size == values->size);
  8274. // Flags and attributes are run-length encoded where KeyAttrRefCount (refs)
  8275. // is an array that describes how many times to repeat a given flag/attribute.
  8276. // Attributes consist of 4 32-bit floating point values per key.
  8277. ufbxi_check(attr_flags->size == refs->size);
  8278. ufbxi_check(attrs->size == refs->size * 4u);
  8279. size_t num_keys = times->size;
  8280. ufbx_keyframe *keys = ufbxi_push(&uc->result, ufbx_keyframe, num_keys);
  8281. ufbxi_check(keys);
  8282. curve->keyframes.data = keys;
  8283. curve->keyframes.count = num_keys;
  8284. int64_t *p_time = (int64_t*)times->data;
  8285. ufbx_real *p_value = (ufbx_real*)values->data;
  8286. int32_t *p_flag = (int32_t*)attr_flags->data;
  8287. float *p_attr = (float*)attrs->data;
  8288. int32_t *p_ref = (int32_t*)refs->data, *p_ref_end = p_ref + refs->size;
  8289. // The previous key defines the weight/slope of the left tangent
  8290. float slope_left = 0.0f;
  8291. float weight_left = 0.333333f;
  8292. double prev_time = 0.0;
  8293. double next_time = 0.0;
  8294. if (num_keys > 0) {
  8295. next_time = (double)p_time[0] * uc->ktime_to_sec;
  8296. }
  8297. for (size_t i = 0; i < num_keys; i++) {
  8298. ufbx_keyframe *key = &keys[i];
  8299. ufbxi_check(p_ref < p_ref_end);
  8300. key->time = next_time;
  8301. key->value = *p_value;
  8302. if (i + 1 < num_keys) {
  8303. next_time = (double)p_time[1] * uc->ktime_to_sec;
  8304. }
  8305. uint32_t flags = (uint32_t)*p_flag;
  8306. float slope_right = p_attr[0];
  8307. float weight_right = 0.333333f;
  8308. float next_slope_left = p_attr[1];
  8309. float next_weight_left = 0.333333f;
  8310. if (flags & 0x3000000) {
  8311. // At least one of the tangents is weighted. The weights are encoded as
  8312. // two 0.4 _decimal_ fixed point values that are packed into 32 bits and
  8313. // interpreted as a 32-bit float.
  8314. uint32_t packed_weights;
  8315. memcpy(&packed_weights, &p_attr[2], sizeof(uint32_t));
  8316. if (flags & 0x1000000) {
  8317. // Right tangent is weighted
  8318. weight_right = (float)(packed_weights & 0xffff) * 0.0001f;
  8319. }
  8320. if (flags & 0x2000000) {
  8321. // Next left tangent is weighted
  8322. next_weight_left = (float)(packed_weights >> 16) * 0.0001f;
  8323. }
  8324. }
  8325. if (flags & 0x2) {
  8326. // Constant interpolation: Set cubic tangents to flat.
  8327. if (flags & 0x100) {
  8328. // Take constant value from next key
  8329. key->interpolation = UFBX_INTERPOLATION_CONSTANT_NEXT;
  8330. } else {
  8331. // Take constant value from the previous key
  8332. key->interpolation = UFBX_INTERPOLATION_CONSTANT_PREV;
  8333. }
  8334. weight_right = next_weight_left = 0.333333f;
  8335. slope_right = next_slope_left = 0.0f;
  8336. } else if (flags & 0x8) {
  8337. // Cubic interpolation
  8338. key->interpolation = UFBX_INTERPOLATION_CUBIC;
  8339. if (flags & 0x400) {
  8340. // User tangents
  8341. if (flags & 0x800) {
  8342. // Broken tangents: No need to modify slopes
  8343. } else {
  8344. // Unified tangents: Use right slope for both sides
  8345. // TODO: ??? slope_left = slope_right;
  8346. }
  8347. } else {
  8348. // Automatic (0x100) or unknown tangents
  8349. // TODO: TCB tangents (0x200)
  8350. // TODO: Auto break (0x800)
  8351. if (i > 0 && i + 1 < num_keys && key->time > prev_time && next_time > key->time) {
  8352. slope_left = slope_right = ufbxi_solve_auto_tangent(
  8353. prev_time, key->time, next_time,
  8354. p_value[-1], key->value, p_value[1],
  8355. weight_left, weight_right);
  8356. } else {
  8357. // Endpoint / invalid keyframe: Set both slopes to zero
  8358. slope_left = slope_right = 0.0f;
  8359. }
  8360. }
  8361. } else {
  8362. // Linear (0x4) or unknown interpolation: Set cubic tangents to match
  8363. // the linear interpolation with weights of 1/3.
  8364. key->interpolation = UFBX_INTERPOLATION_LINEAR;
  8365. weight_right = 0.333333f;
  8366. next_weight_left = 0.333333f;
  8367. if (next_time > key->time) {
  8368. double delta_time = next_time - key->time;
  8369. if (delta_time > 0.0) {
  8370. double slope = (p_value[1] - key->value) / delta_time;
  8371. slope_right = next_slope_left = (float)slope;
  8372. } else {
  8373. slope_right = next_slope_left = 0.0f;
  8374. }
  8375. } else {
  8376. slope_right = next_slope_left = 0.0f;
  8377. }
  8378. }
  8379. // Set the tangents based on weights (dx relative to the time difference
  8380. // between the previous/next key) and slope (simply d = slope * dx)
  8381. if (key->time > prev_time) {
  8382. double delta = key->time - prev_time;
  8383. key->left.dx = (float)(weight_left * delta);
  8384. key->left.dy = key->left.dx * slope_left;
  8385. } else {
  8386. key->left.dx = 0.0f;
  8387. key->left.dy = 0.0f;
  8388. }
  8389. if (next_time > key->time) {
  8390. double delta = next_time - key->time;
  8391. key->right.dx = (float)(weight_right * delta);
  8392. key->right.dy = key->right.dx * slope_right;
  8393. } else {
  8394. key->right.dx = 0.0f;
  8395. key->right.dy = 0.0f;
  8396. }
  8397. slope_left = next_slope_left;
  8398. weight_left = next_weight_left;
  8399. prev_time = key->time;
  8400. // Decrement attribute refcount and potentially move to the next one.
  8401. int32_t refs_left = --*p_ref;
  8402. ufbxi_check(refs_left >= 0);
  8403. if (refs_left == 0) {
  8404. p_flag++;
  8405. p_attr += 4;
  8406. p_ref++;
  8407. }
  8408. p_time++;
  8409. p_value++;
  8410. }
  8411. return 1;
  8412. }
  8413. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_material(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8414. {
  8415. ufbx_material *material = ufbxi_push_element(uc, info, ufbx_material, UFBX_ELEMENT_MATERIAL);
  8416. ufbxi_check(material);
  8417. if (!ufbxi_find_val1(node, ufbxi_ShadingModel, "S", &material->shading_model_name)) {
  8418. material->shading_model_name = ufbx_empty_string;
  8419. }
  8420. material->shader_prop_prefix = ufbx_empty_string;
  8421. return 1;
  8422. }
  8423. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_texture(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8424. {
  8425. ufbx_texture *texture = ufbxi_push_element(uc, info, ufbx_texture, UFBX_ELEMENT_TEXTURE);
  8426. ufbxi_check(texture);
  8427. texture->type = UFBX_TEXTURE_FILE;
  8428. texture->filename = ufbx_empty_string;
  8429. texture->absolute_filename = ufbx_empty_string;
  8430. texture->relative_filename = ufbx_empty_string;
  8431. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_FileName, "S", &texture->absolute_filename));
  8432. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_Filename, "S", &texture->absolute_filename));
  8433. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_RelativeFileName, "S", &texture->relative_filename));
  8434. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_RelativeFilename, "S", &texture->relative_filename));
  8435. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_FileName, "b", &texture->raw_absolute_filename));
  8436. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_Filename, "b", &texture->raw_absolute_filename));
  8437. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_RelativeFileName, "b", &texture->raw_relative_filename));
  8438. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_RelativeFilename, "b", &texture->raw_relative_filename));
  8439. return 1;
  8440. }
  8441. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_layered_texture(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8442. {
  8443. ufbx_texture *texture = ufbxi_push_element(uc, info, ufbx_texture, UFBX_ELEMENT_TEXTURE);
  8444. ufbxi_check(texture);
  8445. texture->type = UFBX_TEXTURE_LAYERED;
  8446. texture->filename = ufbx_empty_string;
  8447. texture->absolute_filename = ufbx_empty_string;
  8448. texture->relative_filename = ufbx_empty_string;
  8449. ufbxi_texture_extra *extra = ufbxi_push_element_extra(uc, texture->element.element_id, ufbxi_texture_extra);
  8450. ufbxi_check(extra);
  8451. ufbxi_value_array *alphas = ufbxi_find_array(node, ufbxi_Alphas, 'r');
  8452. if (alphas) {
  8453. extra->alphas = (ufbx_real*)alphas->data;
  8454. extra->num_alphas = alphas->size;
  8455. }
  8456. ufbxi_value_array *blend_modes = ufbxi_find_array(node, ufbxi_BlendModes, 'i');
  8457. if (blend_modes) {
  8458. extra->blend_modes = (int32_t*)blend_modes->data;
  8459. extra->num_blend_modes = blend_modes->size;
  8460. }
  8461. return 1;
  8462. }
  8463. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_video(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8464. {
  8465. ufbx_video *video = ufbxi_push_element(uc, info, ufbx_video, UFBX_ELEMENT_VIDEO);
  8466. ufbxi_check(video);
  8467. video->filename = ufbx_empty_string;
  8468. video->absolute_filename = ufbx_empty_string;
  8469. video->relative_filename = ufbx_empty_string;
  8470. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_FileName, "S", &video->absolute_filename));
  8471. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_Filename, "S", &video->absolute_filename));
  8472. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_RelativeFileName, "S", &video->relative_filename));
  8473. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_RelativeFilename, "S", &video->relative_filename));
  8474. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_FileName, "b", &video->raw_absolute_filename));
  8475. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_Filename, "b", &video->raw_absolute_filename));
  8476. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_RelativeFileName, "b", &video->raw_relative_filename));
  8477. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_RelativeFilename, "b", &video->raw_relative_filename));
  8478. ufbxi_node *content_node = ufbxi_find_child(node, ufbxi_Content);
  8479. ufbxi_check(ufbxi_read_embedded_blob(uc, &video->content, content_node));
  8480. return 1;
  8481. }
  8482. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_pose(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, const char *sub_type)
  8483. {
  8484. ufbx_pose *pose = ufbxi_push_element(uc, info, ufbx_pose, UFBX_ELEMENT_POSE);
  8485. ufbxi_check(pose);
  8486. // TODO: What are the actual other types?
  8487. pose->bind_pose = sub_type == ufbxi_BindPose;
  8488. size_t num_bones = 0;
  8489. ufbxi_for(ufbxi_node, n, node->children, node->num_children) {
  8490. if (n->name != ufbxi_PoseNode) continue;
  8491. // Bones are linked with FBX names/IDs bypassing the connection system (!?)
  8492. uint64_t fbx_id = 0;
  8493. if (uc->version < 7000) {
  8494. char *name = NULL;
  8495. if (!ufbxi_find_val1(n, ufbxi_Node, "c", &name)) continue;
  8496. fbx_id = ufbxi_synthetic_id_from_string(name);
  8497. } else {
  8498. if (!ufbxi_find_val1(n, ufbxi_Node, "L", &fbx_id)) continue;
  8499. }
  8500. ufbxi_value_array *matrix = ufbxi_find_array(n, ufbxi_Matrix, 'r');
  8501. if (!matrix) continue;
  8502. ufbxi_check(matrix->size >= 16);
  8503. ufbxi_tmp_bone_pose *tmp_pose = ufbxi_push(&uc->tmp_stack, ufbxi_tmp_bone_pose, 1);
  8504. ufbxi_check(tmp_pose);
  8505. num_bones++;
  8506. tmp_pose->bone_fbx_id = fbx_id;
  8507. ufbxi_read_transform_matrix(&tmp_pose->bone_to_world, (ufbx_real*)matrix->data);
  8508. }
  8509. // HACK: Transport `ufbxi_tmp_bone_pose` array through the `ufbx_bone_pose` pointer
  8510. pose->bone_poses.count = num_bones;
  8511. pose->bone_poses.data = (ufbx_bone_pose*)ufbxi_push_pop(&uc->tmp, &uc->tmp_stack, ufbxi_tmp_bone_pose, num_bones);
  8512. ufbxi_check(pose->bone_poses.data);
  8513. return 1;
  8514. }
  8515. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_shader_prop_bindings(ufbxi_context *uc, ufbx_shader_prop_binding *bindings, size_t count)
  8516. {
  8517. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_shader_prop_binding)));
  8518. ufbxi_macro_stable_sort(ufbx_shader_prop_binding, 32, bindings, uc->tmp_arr, count,
  8519. ( ufbxi_str_less(a->shader_prop, b->shader_prop) ) );
  8520. return 1;
  8521. }
  8522. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_binding_table(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8523. {
  8524. ufbx_shader_binding *bindings = ufbxi_push_element(uc, info, ufbx_shader_binding, UFBX_ELEMENT_SHADER_BINDING);
  8525. ufbxi_check(bindings);
  8526. size_t num_entries = 0;
  8527. ufbxi_for (ufbxi_node, n, node->children, node->num_children) {
  8528. if (n->name != ufbxi_Entry) continue;
  8529. ufbx_string src, dst;
  8530. const char *src_type = NULL, *dst_type = NULL;
  8531. if (!ufbxi_get_val4(n, "SCSC", &src, (char**)&src_type, &dst, (char**)&dst_type)) {
  8532. continue;
  8533. }
  8534. if (src_type == ufbxi_FbxPropertyEntry && dst_type == ufbxi_FbxSemanticEntry) {
  8535. ufbx_shader_prop_binding *bind = ufbxi_push(&uc->tmp_stack, ufbx_shader_prop_binding, 1);
  8536. ufbxi_check(bind);
  8537. bind->material_prop = src;
  8538. bind->shader_prop = dst;
  8539. num_entries++;
  8540. } else if (src_type == ufbxi_FbxSemanticEntry && dst_type == ufbxi_FbxPropertyEntry) {
  8541. ufbx_shader_prop_binding *bind = ufbxi_push(&uc->tmp_stack, ufbx_shader_prop_binding, 1);
  8542. ufbxi_check(bind);
  8543. bind->material_prop = dst;
  8544. bind->shader_prop = src;
  8545. num_entries++;
  8546. }
  8547. }
  8548. bindings->prop_bindings.count = num_entries;
  8549. bindings->prop_bindings.data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_shader_prop_binding, num_entries);
  8550. ufbxi_check(bindings->prop_bindings.data);
  8551. ufbxi_check(ufbxi_sort_shader_prop_bindings(uc, bindings->prop_bindings.data, bindings->prop_bindings.count));
  8552. return 1;
  8553. }
  8554. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_selection_set(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8555. {
  8556. (void)node;
  8557. ufbx_selection_set *set = ufbxi_push_element(uc, info, ufbx_selection_set, UFBX_ELEMENT_SELECTION_SET);
  8558. ufbxi_check(set);
  8559. return 1;
  8560. }
  8561. ufbxi_noinline static void ufbxi_find_uint32_list(ufbx_uint32_list *dst, ufbxi_node *node, const char *name)
  8562. {
  8563. ufbxi_value_array *arr = ufbxi_find_array(node, name, 'i');
  8564. if (arr) {
  8565. dst->data = (uint32_t*)arr->data;
  8566. dst->count = arr->size;
  8567. }
  8568. }
  8569. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_selection_node(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8570. {
  8571. ufbx_selection_node *sel = ufbxi_push_element(uc, info, ufbx_selection_node, UFBX_ELEMENT_SELECTION_NODE);
  8572. ufbxi_check(sel);
  8573. int32_t in_set = 0;
  8574. if (ufbxi_find_val1(node, ufbxi_IsTheNodeInSet, "I", &in_set) && in_set) {
  8575. sel->include_node = true;
  8576. }
  8577. ufbxi_find_uint32_list(&sel->vertices, node, ufbxi_VertexIndexArray);
  8578. ufbxi_find_uint32_list(&sel->edges, node, ufbxi_EdgeIndexArray);
  8579. ufbxi_find_uint32_list(&sel->faces, node, ufbxi_PolygonIndexArray);
  8580. return 1;
  8581. }
  8582. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_character(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8583. {
  8584. (void)node;
  8585. ufbx_character *character = ufbxi_push_element(uc, info, ufbx_character, UFBX_ELEMENT_CHARACTER);
  8586. ufbxi_check(character);
  8587. // TODO: There's some extremely cursed all-caps data in characters
  8588. return 1;
  8589. }
  8590. typedef struct {
  8591. ufbx_constraint_type type;
  8592. const char *name;
  8593. } ufbxi_constraint_type;
  8594. static const ufbxi_constraint_type ufbxi_constraint_types[] = {
  8595. { UFBX_CONSTRAINT_AIM, "Aim" },
  8596. { UFBX_CONSTRAINT_PARENT, "Parent-Child" },
  8597. { UFBX_CONSTRAINT_POSITION, "Position From Positions" },
  8598. { UFBX_CONSTRAINT_ROTATION, "Rotation From Rotations" },
  8599. { UFBX_CONSTRAINT_SCALE, "Scale From Scales" },
  8600. { UFBX_CONSTRAINT_SINGLE_CHAIN_IK, "Single Chain IK" },
  8601. };
  8602. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_constraint(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  8603. {
  8604. (void)node;
  8605. ufbx_constraint *constraint = ufbxi_push_element(uc, info, ufbx_constraint, UFBX_ELEMENT_CONSTRAINT);
  8606. ufbxi_check(constraint);
  8607. if (!ufbxi_find_val1(node, ufbxi_Type, "S", &constraint->type_name)) {
  8608. constraint->type_name = ufbx_empty_string;
  8609. }
  8610. ufbxi_for(const ufbxi_constraint_type, ctype, ufbxi_constraint_types, ufbxi_arraycount(ufbxi_constraint_types)) {
  8611. if (!strcmp(constraint->type_name.data, ctype->name)) {
  8612. constraint->type = ctype->type;
  8613. break;
  8614. }
  8615. }
  8616. // TODO: There's some extremely cursed all-caps data in characters
  8617. return 1;
  8618. }
  8619. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_synthetic_attribute(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info, ufbx_string type_str, const char *sub_type, const char *super_type)
  8620. {
  8621. if ((sub_type == ufbxi_empty_char || sub_type == ufbxi_Model) && type_str.data == ufbxi_Model) {
  8622. // Plain model
  8623. return 1;
  8624. }
  8625. ufbxi_element_info attrib_info = *info;
  8626. ufbxi_check(ufbxi_push_synthetic_id(uc, &attrib_info.fbx_id));
  8627. // Use type and name from NodeAttributeName if it exists *uniquely*
  8628. ufbx_string type_and_name;
  8629. if (ufbxi_find_val1(node, ufbxi_NodeAttributeName, "s", &type_and_name)) {
  8630. ufbx_string attrib_type_str, attrib_name_str;
  8631. ufbxi_check(ufbxi_split_type_and_name(uc, type_and_name, &attrib_type_str, &attrib_name_str));
  8632. if (attrib_name_str.length > 0) {
  8633. attrib_info.name = attrib_name_str;
  8634. uint64_t attrib_id = ufbxi_synthetic_id_from_string(type_and_name.data);
  8635. if (info->fbx_id != attrib_id && !ufbxi_fbx_id_exists(uc, attrib_id)) {
  8636. attrib_info.fbx_id = attrib_id;
  8637. }
  8638. }
  8639. }
  8640. // 6x00: Link the node to the node attribute so property connections can be
  8641. // redirected from connections if necessary.
  8642. if (uc->version < 7000) {
  8643. ufbxi_check(ufbxi_insert_fbx_attr(uc, info->fbx_id, attrib_info.fbx_id));
  8644. // Split properties between the node and the attribute
  8645. ufbx_prop *ps = info->props.props.data;
  8646. size_t dst = 0, src = 0, end = info->props.props.count;
  8647. while (src < end) {
  8648. if (!ufbxi_is_node_property(uc, ps[src].name.data)) {
  8649. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_prop, 1, &ps[src]));
  8650. src++;
  8651. } else if (dst != src) {
  8652. ps[dst++] = ps[src++];
  8653. } else {
  8654. dst++; src++;
  8655. }
  8656. }
  8657. attrib_info.props.props.count = end - dst;
  8658. attrib_info.props.props.data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_prop, attrib_info.props.props.count);
  8659. ufbxi_check(attrib_info.props.props.data);
  8660. info->props.props.count = dst;
  8661. }
  8662. if (sub_type == ufbxi_Mesh) {
  8663. ufbxi_check(ufbxi_read_mesh(uc, node, &attrib_info));
  8664. } else if (sub_type == ufbxi_Light) {
  8665. ufbxi_check(ufbxi_read_element(uc, node, &attrib_info, sizeof(ufbx_light), UFBX_ELEMENT_LIGHT));
  8666. } else if (sub_type == ufbxi_Camera) {
  8667. ufbxi_check(ufbxi_read_element(uc, node, &attrib_info, sizeof(ufbx_camera), UFBX_ELEMENT_CAMERA));
  8668. } else if (sub_type == ufbxi_LimbNode || sub_type == ufbxi_Limb || sub_type == ufbxi_Root) {
  8669. ufbxi_check(ufbxi_read_bone(uc, node, &attrib_info, sub_type));
  8670. } else if (sub_type == ufbxi_Null || sub_type == ufbxi_Marker) {
  8671. ufbxi_check(ufbxi_read_element(uc, node, &attrib_info, sizeof(ufbx_empty), UFBX_ELEMENT_EMPTY));
  8672. } else if (sub_type == ufbxi_NurbsCurve) {
  8673. if (!ufbxi_find_child(node, ufbxi_KnotVector)) return 1;
  8674. ufbxi_check(ufbxi_read_nurbs_curve(uc, node, &attrib_info));
  8675. } else if (sub_type == ufbxi_NurbsSurface) {
  8676. if (!ufbxi_find_child(node, ufbxi_KnotVectorU)) return 1;
  8677. if (!ufbxi_find_child(node, ufbxi_KnotVectorV)) return 1;
  8678. ufbxi_check(ufbxi_read_nurbs_surface(uc, node, &attrib_info));
  8679. } else if (sub_type == ufbxi_Line) {
  8680. if (!ufbxi_find_child(node, ufbxi_Points)) return 1;
  8681. if (!ufbxi_find_child(node, ufbxi_PointsIndex)) return 1;
  8682. ufbxi_check(ufbxi_read_line(uc, node, &attrib_info));
  8683. } else if (sub_type == ufbxi_TrimNurbsSurface) {
  8684. if (!ufbxi_find_child(node, ufbxi_Layer)) return 1;
  8685. ufbxi_check(ufbxi_read_element(uc, node, &attrib_info, sizeof(ufbx_nurbs_trim_surface), UFBX_ELEMENT_NURBS_TRIM_SURFACE));
  8686. } else if (sub_type == ufbxi_Boundary) {
  8687. ufbxi_check(ufbxi_read_element(uc, node, &attrib_info, sizeof(ufbx_nurbs_trim_boundary), UFBX_ELEMENT_NURBS_TRIM_BOUNDARY));
  8688. } else if (sub_type == ufbxi_CameraStereo) {
  8689. ufbxi_check(ufbxi_read_element(uc, node, &attrib_info, sizeof(ufbx_stereo_camera), UFBX_ELEMENT_STEREO_CAMERA));
  8690. } else if (sub_type == ufbxi_CameraSwitcher) {
  8691. ufbxi_check(ufbxi_read_element(uc, node, &attrib_info, sizeof(ufbx_camera_switcher), UFBX_ELEMENT_CAMERA_SWITCHER));
  8692. } else if (sub_type == ufbxi_FKEffector) {
  8693. ufbxi_check(ufbxi_read_marker(uc, node, &attrib_info, sub_type, UFBX_MARKER_FK_EFFECTOR));
  8694. } else if (sub_type == ufbxi_IKEffector) {
  8695. ufbxi_check(ufbxi_read_marker(uc, node, &attrib_info, sub_type, UFBX_MARKER_IK_EFFECTOR));
  8696. } else if (sub_type == ufbxi_LodGroup) {
  8697. ufbxi_check(ufbxi_read_element(uc, node, &attrib_info, sizeof(ufbx_lod_group), UFBX_ELEMENT_LOD_GROUP));
  8698. } else {
  8699. ufbx_string sub_type_str = { sub_type, strlen(sub_type) };
  8700. ufbxi_check(ufbxi_read_unknown(uc, node, &attrib_info, type_str, sub_type_str, super_type));
  8701. }
  8702. ufbxi_check(ufbxi_connect_oo(uc, attrib_info.fbx_id, info->fbx_id));
  8703. return 1;
  8704. }
  8705. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_global_settings(ufbxi_context *uc, ufbxi_node *node)
  8706. {
  8707. ufbxi_check(ufbxi_read_properties(uc, node, &uc->scene.settings.props));
  8708. return 1;
  8709. }
  8710. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_objects(ufbxi_context *uc)
  8711. {
  8712. ufbxi_element_info info = { 0 };
  8713. for (;;) {
  8714. ufbxi_node *node;
  8715. ufbxi_check(ufbxi_parse_toplevel_child(uc, &node));
  8716. if (!node) break;
  8717. info.dom_node = ufbxi_get_dom_node(uc, node);
  8718. if (node->name == ufbxi_GlobalSettings) {
  8719. ufbxi_check(ufbxi_read_global_settings(uc, node));
  8720. continue;
  8721. }
  8722. ufbx_string type_and_name, sub_type_str;
  8723. // Failing to parse the object properties is not an error since
  8724. // there's some weird objects mixed in every now and then.
  8725. // FBX version 7000 and up uses 64-bit unique IDs per object,
  8726. // older FBX versions just use name/type pairs, which we can
  8727. // use as IDs since all strings are interned into a string pool.
  8728. if (uc->version >= 7000) {
  8729. if (!ufbxi_get_val3(node, "Lss", &info.fbx_id, &type_and_name, &sub_type_str)) continue;
  8730. ufbxi_check((info.fbx_id & UFBXI_SYNTHETIC_ID_BIT) == 0);
  8731. } else {
  8732. if (!ufbxi_get_val2(node, "ss", &type_and_name, &sub_type_str)) continue;
  8733. info.fbx_id = ufbxi_synthetic_id_from_string(type_and_name.data);
  8734. }
  8735. // Remove the "Fbx" prefix from sub-types, remember to re-intern!
  8736. if (sub_type_str.length > 3 && !memcmp(sub_type_str.data, "Fbx", 3)) {
  8737. sub_type_str.data += 3;
  8738. sub_type_str.length -= 3;
  8739. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &sub_type_str, false));
  8740. }
  8741. ufbx_string type_str;
  8742. ufbxi_check(ufbxi_split_type_and_name(uc, type_and_name, &type_str, &info.name));
  8743. const char *name = node->name, *sub_type = sub_type_str.data;
  8744. ufbxi_check(ufbxi_read_properties(uc, node, &info.props));
  8745. info.props.defaults = ufbxi_find_template(uc, name, sub_type);
  8746. if (name == ufbxi_Model) {
  8747. if (uc->version < 7000) {
  8748. ufbxi_check(ufbxi_read_synthetic_attribute(uc, node, &info, type_str, sub_type, name));
  8749. }
  8750. ufbxi_check(ufbxi_read_model(uc, node, &info));
  8751. } else if (name == ufbxi_NodeAttribute) {
  8752. if (sub_type == ufbxi_Light) {
  8753. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_light), UFBX_ELEMENT_LIGHT));
  8754. } else if (sub_type == ufbxi_Camera) {
  8755. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_camera), UFBX_ELEMENT_CAMERA));
  8756. } else if (sub_type == ufbxi_LimbNode || sub_type == ufbxi_Limb || sub_type == ufbxi_Root) {
  8757. ufbxi_check(ufbxi_read_bone(uc, node, &info, sub_type));
  8758. } else if (sub_type == ufbxi_Null || sub_type == ufbxi_Marker) {
  8759. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_empty), UFBX_ELEMENT_EMPTY));
  8760. } else if (sub_type == ufbxi_CameraStereo) {
  8761. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_stereo_camera), UFBX_ELEMENT_STEREO_CAMERA));
  8762. } else if (sub_type == ufbxi_CameraSwitcher) {
  8763. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_camera_switcher), UFBX_ELEMENT_CAMERA_SWITCHER));
  8764. } else if (sub_type == ufbxi_FKEffector) {
  8765. ufbxi_check(ufbxi_read_marker(uc, node, &info, sub_type, UFBX_MARKER_FK_EFFECTOR));
  8766. } else if (sub_type == ufbxi_IKEffector) {
  8767. ufbxi_check(ufbxi_read_marker(uc, node, &info, sub_type, UFBX_MARKER_IK_EFFECTOR));
  8768. } else if (sub_type == ufbxi_LodGroup) {
  8769. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_lod_group), UFBX_ELEMENT_LOD_GROUP));
  8770. } else {
  8771. ufbxi_check(ufbxi_read_unknown(uc, node, &info, type_str, sub_type_str, name));
  8772. }
  8773. } else if (name == ufbxi_Geometry) {
  8774. if (sub_type == ufbxi_Mesh) {
  8775. ufbxi_check(ufbxi_read_mesh(uc, node, &info));
  8776. } else if (sub_type == ufbxi_Shape) {
  8777. ufbxi_check(ufbxi_read_shape(uc, node, &info));
  8778. } else if (sub_type == ufbxi_NurbsCurve) {
  8779. ufbxi_check(ufbxi_read_nurbs_curve(uc, node, &info));
  8780. } else if (sub_type == ufbxi_NurbsSurface) {
  8781. ufbxi_check(ufbxi_read_nurbs_surface(uc, node, &info));
  8782. } else if (sub_type == ufbxi_Line) {
  8783. ufbxi_check(ufbxi_read_line(uc, node, &info));
  8784. } else if (sub_type == ufbxi_TrimNurbsSurface) {
  8785. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_nurbs_trim_surface), UFBX_ELEMENT_NURBS_TRIM_SURFACE));
  8786. } else if (sub_type == ufbxi_Boundary) {
  8787. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_nurbs_trim_boundary), UFBX_ELEMENT_NURBS_TRIM_BOUNDARY));
  8788. } else {
  8789. ufbxi_check(ufbxi_read_unknown(uc, node, &info, type_str, sub_type_str, name));
  8790. }
  8791. } else if (name == ufbxi_Deformer) {
  8792. if (sub_type == ufbxi_Skin) {
  8793. ufbxi_check(ufbxi_read_skin(uc, node, &info));
  8794. } else if (sub_type == ufbxi_Cluster) {
  8795. ufbxi_check(ufbxi_read_skin_cluster(uc, node, &info));
  8796. } else if (sub_type == ufbxi_BlendShape) {
  8797. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_blend_deformer), UFBX_ELEMENT_BLEND_DEFORMER));
  8798. } else if (sub_type == ufbxi_BlendShapeChannel) {
  8799. ufbxi_check(ufbxi_read_blend_channel(uc, node, &info));
  8800. } else if (sub_type == ufbxi_VertexCacheDeformer) {
  8801. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_cache_deformer), UFBX_ELEMENT_CACHE_DEFORMER));
  8802. } else {
  8803. ufbxi_check(ufbxi_read_unknown(uc, node, &info, type_str, sub_type_str, name));
  8804. }
  8805. } else if (name == ufbxi_Material) {
  8806. ufbxi_check(ufbxi_read_material(uc, node, &info));
  8807. } else if (name == ufbxi_Texture) {
  8808. ufbxi_check(ufbxi_read_texture(uc, node, &info));
  8809. } else if (name == ufbxi_LayeredTexture) {
  8810. ufbxi_check(ufbxi_read_layered_texture(uc, node, &info));
  8811. } else if (name == ufbxi_Video) {
  8812. ufbxi_check(ufbxi_read_video(uc, node, &info));
  8813. } else if (name == ufbxi_AnimationStack) {
  8814. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_anim_stack), UFBX_ELEMENT_ANIM_STACK));
  8815. } else if (name == ufbxi_AnimationLayer) {
  8816. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_anim_layer), UFBX_ELEMENT_ANIM_LAYER));
  8817. } else if (name == ufbxi_AnimationCurveNode) {
  8818. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_anim_value), UFBX_ELEMENT_ANIM_VALUE));
  8819. } else if (name == ufbxi_AnimationCurve) {
  8820. ufbxi_check(ufbxi_read_animation_curve(uc, node, &info));
  8821. } else if (name == ufbxi_Pose) {
  8822. ufbxi_check(ufbxi_read_pose(uc, node, &info, sub_type));
  8823. } else if (name == ufbxi_Implementation) {
  8824. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_shader), UFBX_ELEMENT_SHADER));
  8825. } else if (name == ufbxi_BindingTable) {
  8826. ufbxi_check(ufbxi_read_binding_table(uc, node, &info));
  8827. } else if (name == ufbxi_Collection) {
  8828. if (sub_type == ufbxi_SelectionSet) {
  8829. ufbxi_check(ufbxi_read_selection_set(uc, node, &info));
  8830. }
  8831. } else if (name == ufbxi_CollectionExclusive) {
  8832. if (sub_type == ufbxi_DisplayLayer) {
  8833. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_display_layer), UFBX_ELEMENT_DISPLAY_LAYER));
  8834. }
  8835. } else if (name == ufbxi_SelectionNode) {
  8836. ufbxi_check(ufbxi_read_selection_node(uc, node, &info));
  8837. } else if (name == ufbxi_Constraint) {
  8838. if (sub_type == ufbxi_Character) {
  8839. ufbxi_check(ufbxi_read_character(uc, node, &info));
  8840. } else {
  8841. ufbxi_check(ufbxi_read_constraint(uc, node, &info));
  8842. }
  8843. } else if (name == ufbxi_SceneInfo) {
  8844. ufbxi_check(ufbxi_read_scene_info(uc, node));
  8845. } else if (name == ufbxi_Cache) {
  8846. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_cache_file), UFBX_ELEMENT_CACHE_FILE));
  8847. } else if (name == ufbxi_ObjectMetaData) {
  8848. ufbxi_check(ufbxi_read_element(uc, node, &info, sizeof(ufbx_metadata_object), UFBX_ELEMENT_METADATA_OBJECT));
  8849. } else {
  8850. ufbxi_check(ufbxi_read_unknown(uc, node, &info, type_str, sub_type_str, name));
  8851. }
  8852. }
  8853. return 1;
  8854. }
  8855. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_connections(ufbxi_context *uc)
  8856. {
  8857. // Read the connections to the list first
  8858. for (;;) {
  8859. ufbxi_node *node;
  8860. ufbxi_check(ufbxi_parse_toplevel_child(uc, &node));
  8861. if (!node) break;
  8862. char *type;
  8863. uint64_t src_id = 0, dst_id = 0;
  8864. ufbx_string src_prop = ufbx_empty_string, dst_prop = ufbx_empty_string;
  8865. if (uc->version < 7000) {
  8866. char *src_name = NULL, *dst_name = NULL;
  8867. // Pre-7000 versions use Type::Name pairs as identifiers
  8868. if (!ufbxi_get_val1(node, "c", &type)) continue;
  8869. if (type == ufbxi_OO) {
  8870. if (!ufbxi_get_val3(node, "_cc", NULL, &src_name, &dst_name)) continue;
  8871. } else if (type == ufbxi_OP) {
  8872. if (!ufbxi_get_val4(node, "_ccs", NULL, &src_name, &dst_name, &dst_prop)) continue;
  8873. } else if (type == ufbxi_PO) {
  8874. if (!ufbxi_get_val4(node, "_csc", NULL, &src_name, &src_prop, &dst_name)) continue;
  8875. } else if (type == ufbxi_PP) {
  8876. if (!ufbxi_get_val5(node, "_cscs", NULL, &src_name, &src_prop, &dst_name, &dst_prop)) continue;
  8877. } else {
  8878. // TODO: Strict mode?
  8879. continue;
  8880. }
  8881. if (src_prop.length > 0) {
  8882. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &src_prop, false));
  8883. }
  8884. if (dst_prop.length > 0) {
  8885. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &dst_prop, false));
  8886. }
  8887. src_id = ufbxi_synthetic_id_from_string(src_name);
  8888. dst_id = ufbxi_synthetic_id_from_string(dst_name);
  8889. } else {
  8890. // Post-7000 versions use proper unique 64-bit IDs
  8891. if (!ufbxi_get_val1(node, "C", &type)) continue;
  8892. if (type == ufbxi_OO) {
  8893. if (!ufbxi_get_val3(node, "_LL", NULL, &src_id, &dst_id)) continue;
  8894. } else if (type == ufbxi_OP) {
  8895. if (!ufbxi_get_val4(node, "_LLS", NULL, &src_id, &dst_id, &dst_prop)) continue;
  8896. } else if (type == ufbxi_PO) {
  8897. if (!ufbxi_get_val4(node, "_LSL", NULL, &src_id, &src_prop, &dst_id)) continue;
  8898. } else if (type == ufbxi_PP) {
  8899. if (!ufbxi_get_val5(node, "_LSLS", NULL, &src_id, &src_prop, &dst_id, &dst_prop)) continue;
  8900. } else {
  8901. // TODO: Strict mode?
  8902. continue;
  8903. }
  8904. }
  8905. ufbxi_tmp_connection *conn = ufbxi_push(&uc->tmp_connections, ufbxi_tmp_connection, 1);
  8906. ufbxi_check(conn);
  8907. conn->src = src_id;
  8908. conn->dst = dst_id;
  8909. conn->src_prop = src_prop;
  8910. conn->dst_prop = dst_prop;
  8911. }
  8912. return 1;
  8913. }
  8914. // -- Pre-7000 "Take" based animation
  8915. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_take_anim_channel(ufbxi_context *uc, ufbxi_node *node, uint64_t value_fbx_id, const char *name, ufbx_real *p_default)
  8916. {
  8917. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_Default, "R", p_default));
  8918. // Find the key array, early return with success if not found as we may have only a default
  8919. ufbxi_value_array *keys = ufbxi_find_array(node, ufbxi_Key, 'd');
  8920. if (!keys) return 1;
  8921. uint64_t curve_fbx_id = 0;
  8922. ufbx_anim_curve *curve = ufbxi_push_synthetic_element(uc, &curve_fbx_id, node, name, ufbx_anim_curve, UFBX_ELEMENT_ANIM_CURVE);
  8923. ufbxi_check(curve);
  8924. ufbxi_check(ufbxi_connect_op(uc, curve_fbx_id, value_fbx_id, curve->name));
  8925. if (uc->opts.ignore_animation) return 1;
  8926. size_t num_keys;
  8927. ufbxi_check(ufbxi_find_val1(node, ufbxi_KeyCount, "Z", &num_keys));
  8928. curve->keyframes.data = ufbxi_push(&uc->result, ufbx_keyframe, num_keys);
  8929. curve->keyframes.count = num_keys;
  8930. ufbxi_check(curve->keyframes.data);
  8931. float slope_left = 0.0f;
  8932. float weight_left = 0.333333f;
  8933. double next_time = 0.0;
  8934. double next_value = 0.0;
  8935. double prev_time = 0.0;
  8936. // The pre-7000 keyframe data is stored as a _heterogenous_ array containing 64-bit integers,
  8937. // floating point values, and _bare characters_. We cast all values to double and interpret them.
  8938. double *data = (double*)keys->data, *data_end = data + keys->size;
  8939. if (num_keys > 0) {
  8940. ufbxi_check(data_end - data >= 2);
  8941. // TODO: This could break with large times...
  8942. next_time = data[0] * uc->ktime_to_sec;
  8943. next_value = data[1];
  8944. }
  8945. for (size_t i = 0; i < num_keys; i++) {
  8946. ufbx_keyframe *key = &curve->keyframes.data[i];
  8947. // First three values: Time, Value, InterpolationMode
  8948. ufbxi_check(data_end - data >= 3);
  8949. key->time = next_time;
  8950. key->value = (ufbx_real)next_value;
  8951. char mode = (char)data[2];
  8952. data += 3;
  8953. float slope_right = 0.0f;
  8954. float weight_right = 0.333333f;
  8955. float next_slope_left = 0.0f;
  8956. float next_weight_left = 0.333333f;
  8957. bool auto_slope = false;
  8958. if (mode == 'U') {
  8959. // Cubic interpolation
  8960. key->interpolation = UFBX_INTERPOLATION_CUBIC;
  8961. ufbxi_check(data_end - data >= 1);
  8962. char slope_mode = (char)data[0];
  8963. data += 1;
  8964. size_t num_weights = 1;
  8965. if (slope_mode == 's' || slope_mode == 'b') {
  8966. // Slope mode 's'/'b' (standard? broken?) always have two explicit slopes
  8967. // TODO: `b` might actually be some kind of TCB curve
  8968. ufbxi_check(data_end - data >= 2);
  8969. slope_right = (float)data[0];
  8970. next_slope_left = (float)data[1];
  8971. data += 2;
  8972. } else if (slope_mode == 'a') {
  8973. // Parameterless slope mode 'a' seems to appear in baked animations. Let's just assume
  8974. // automatic tangents for now as they're the least likely to break with
  8975. // objectionable artifacts. We need to defer the automatic tangent resolve
  8976. // until we have read the next time/value.
  8977. // TODO: Solve what this is more throroughly
  8978. auto_slope = true;
  8979. if (uc->version == 5000) {
  8980. num_weights = 0;
  8981. }
  8982. } else if (slope_mode == 'p') {
  8983. // TODO: What is this mode? It seems to have negative values sometimes?
  8984. // Also it seems to have _two_ trailing weights values, currently observed:
  8985. // `n,n` and `a,X,Y,n`...
  8986. // Ignore unknown values for now
  8987. ufbxi_check(data_end - data >= 2);
  8988. data += 2;
  8989. num_weights = 2;
  8990. } else if (slope_mode == 't') {
  8991. // TODO: What is this mode? It seems that it does not have any weights and the
  8992. // third value seems _tiny_ (around 1e-30?)
  8993. ufbxi_check(data_end - data >= 3);
  8994. data += 3;
  8995. num_weights = 0;
  8996. } else {
  8997. ufbxi_fail("Unknown slope mode");
  8998. }
  8999. for (; num_weights > 0; num_weights--) {
  9000. ufbxi_check(data_end - data >= 1);
  9001. char weight_mode = (char)data[0];
  9002. data += 1;
  9003. if (weight_mode == 'n') {
  9004. // Automatic weights (0.3333...)
  9005. } else if (weight_mode == 'a') {
  9006. // Manual weights: RightWeight, NextLeftWeight
  9007. ufbxi_check(data_end - data >= 2);
  9008. weight_right = (float)data[0];
  9009. next_weight_left = (float)data[1];
  9010. data += 2;
  9011. } else if (weight_mode == 'l') {
  9012. // Next left tangent is weighted
  9013. ufbxi_check(data_end - data >= 1);
  9014. next_weight_left = (float)data[0];
  9015. data += 1;
  9016. } else if (weight_mode == 'r') {
  9017. // Right tangent is weighted
  9018. ufbxi_check(data_end - data >= 1);
  9019. weight_right = (float)data[0];
  9020. data += 1;
  9021. } else if (weight_mode == 'c') {
  9022. // TODO: What is this mode? At least it has no parameters so let's
  9023. // just assume automatic weights for the time being (0.3333...)
  9024. } else {
  9025. ufbxi_fail("Unknown weight mode");
  9026. }
  9027. }
  9028. } else if (mode == 'L') {
  9029. // Linear interpolation: No parameters
  9030. key->interpolation = UFBX_INTERPOLATION_LINEAR;
  9031. } else if (mode == 'C') {
  9032. // Constant interpolation: Single parameter (use prev/next)
  9033. ufbxi_check(data_end - data >= 1);
  9034. key->interpolation = (char)data[0] == 'n' ? UFBX_INTERPOLATION_CONSTANT_NEXT : UFBX_INTERPOLATION_CONSTANT_PREV;
  9035. data += 1;
  9036. } else {
  9037. ufbxi_fail("Unknown key mode");
  9038. }
  9039. // Retrieve next key and value
  9040. if (i + 1 < num_keys) {
  9041. ufbxi_check(data_end - data >= 2);
  9042. next_time = data[0] * uc->ktime_to_sec;
  9043. next_value = data[1];
  9044. }
  9045. if (auto_slope) {
  9046. if (i > 0) {
  9047. slope_left = slope_right = ufbxi_solve_auto_tangent(
  9048. prev_time, key->time, next_time,
  9049. key[-1].value, key->value, (ufbx_real)next_value,
  9050. weight_left, weight_right);
  9051. } else {
  9052. slope_left = slope_right = 0.0f;
  9053. }
  9054. }
  9055. // Set up linear cubic tangents if necessary
  9056. if (key->interpolation == UFBX_INTERPOLATION_LINEAR) {
  9057. if (next_time > key->time) {
  9058. double slope = (next_value - key->value) / (next_time - key->time);
  9059. slope_right = next_slope_left = (float)slope;
  9060. } else {
  9061. slope_right = next_slope_left = 0.0f;
  9062. }
  9063. }
  9064. if (key->time > prev_time) {
  9065. double delta = key->time - prev_time;
  9066. key->left.dx = (float)(weight_left * delta);
  9067. key->left.dy = key->left.dx * slope_left;
  9068. } else {
  9069. key->left.dx = 0.0f;
  9070. key->left.dy = 0.0f;
  9071. }
  9072. if (next_time > key->time) {
  9073. double delta = next_time - key->time;
  9074. key->right.dx = (float)(weight_right * delta);
  9075. key->right.dy = key->right.dx * slope_right;
  9076. } else {
  9077. key->right.dx = 0.0f;
  9078. key->right.dy = 0.0f;
  9079. }
  9080. slope_left = next_slope_left;
  9081. weight_left = next_weight_left;
  9082. prev_time = key->time;
  9083. }
  9084. ufbxi_check(data == data_end);
  9085. return 1;
  9086. }
  9087. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_take_prop_channel(ufbxi_context *uc, ufbxi_node *node, uint64_t target_fbx_id, uint64_t layer_fbx_id, ufbx_string name)
  9088. {
  9089. if (name.data == ufbxi_Transform) {
  9090. // Pre-7000 have transform keyframes in a deeply nested structure,
  9091. // flatten it to make it resemble post-7000 structure a bit closer:
  9092. // old: Model: { Channel: "Transform" { Channel: "T" { Channel "X": { ... } } } }
  9093. // new: Model: { Channel: "Lcl Translation" { Channel "X": { ... } } }
  9094. ufbxi_for(ufbxi_node, child, node->children, node->num_children) {
  9095. if (child->name != ufbxi_Channel) continue;
  9096. const char *old_name;
  9097. ufbxi_check(ufbxi_get_val1(child, "C", (char**)&old_name));
  9098. ufbx_string new_name;
  9099. if (old_name == ufbxi_T) { new_name.data = ufbxi_Lcl_Translation; new_name.length = sizeof(ufbxi_Lcl_Translation) - 1; }
  9100. else if (old_name == ufbxi_R) { new_name.data = ufbxi_Lcl_Rotation; new_name.length = sizeof(ufbxi_Lcl_Rotation) - 1; }
  9101. else if (old_name == ufbxi_S) { new_name.data = ufbxi_Lcl_Scaling; new_name.length = sizeof(ufbxi_Lcl_Scaling) - 1; }
  9102. else {
  9103. continue;
  9104. }
  9105. // Read child as a top-level property channel
  9106. ufbxi_check(ufbxi_read_take_prop_channel(uc, child, target_fbx_id, layer_fbx_id, new_name));
  9107. }
  9108. } else {
  9109. // Pre-6000 FBX files store blend shape keys with a " (Shape)" suffix
  9110. if (uc->version < 6000) {
  9111. const char *const suffix = " (Shape)";
  9112. size_t suffix_len = strlen(suffix);
  9113. if (name.length > suffix_len && !memcmp(name.data + name.length - suffix_len, suffix, suffix_len)) {
  9114. name.length -= suffix_len;
  9115. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &name, false));
  9116. }
  9117. }
  9118. // Find 1-3 channel nodes thast contain a `Key:` node
  9119. ufbxi_node *channel_nodes[3] = { 0 };
  9120. const char *channel_names[3] = { 0 };
  9121. size_t num_channel_nodes = 0;
  9122. if (ufbxi_find_child(node, ufbxi_Key) || ufbxi_find_child(node, ufbxi_Default)) {
  9123. // Channel has only a single curve
  9124. channel_nodes[0] = node;
  9125. channel_names[0] = name.data;
  9126. num_channel_nodes = 1;
  9127. } else {
  9128. // Channel is a compound of multiple curves
  9129. ufbxi_for(ufbxi_node, child, node->children, node->num_children) {
  9130. if (child->name != ufbxi_Channel) continue;
  9131. if (!ufbxi_find_child(child, ufbxi_Key) && !ufbxi_find_child(child, ufbxi_Default)) continue;
  9132. if (!ufbxi_get_val1(child, "C", (char**)&channel_names[num_channel_nodes])) continue;
  9133. channel_nodes[num_channel_nodes] = child;
  9134. if (++num_channel_nodes == 3) break;
  9135. }
  9136. }
  9137. // Early return: No valid channels found, not an error
  9138. if (num_channel_nodes == 0) return 1;
  9139. uint64_t value_fbx_id = 0;
  9140. ufbx_anim_value *value = ufbxi_push_synthetic_element(uc, &value_fbx_id, node, name.data, ufbx_anim_value, UFBX_ELEMENT_ANIM_VALUE);
  9141. // Add a "virtual" connection between the animated property and the layer/target
  9142. ufbxi_check(ufbxi_connect_oo(uc, value_fbx_id, layer_fbx_id));
  9143. ufbxi_check(ufbxi_connect_op(uc, value_fbx_id, target_fbx_id, name));
  9144. for (size_t i = 0; i < num_channel_nodes; i++) {
  9145. ufbxi_check(ufbxi_read_take_anim_channel(uc, channel_nodes[i], value_fbx_id, channel_names[i], &value->default_value.v[i]));
  9146. }
  9147. }
  9148. return 1;
  9149. }
  9150. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_take_object(ufbxi_context *uc, ufbxi_node *node, uint64_t layer_fbx_id)
  9151. {
  9152. // Takes are used only in pre-7000 FBX versions so objects are identified
  9153. // by their unique Type::Name pair that we use as unique IDs through the
  9154. // pooled interned string pointers.
  9155. const char *type_and_name;
  9156. ufbxi_check(ufbxi_get_val1(node, "c", (char**)&type_and_name));
  9157. uint64_t target_fbx_id = ufbxi_synthetic_id_from_string(type_and_name);
  9158. // Add all suitable Channels as animated properties
  9159. ufbxi_for(ufbxi_node, child, node->children, node->num_children) {
  9160. ufbx_string name;
  9161. if (child->name != ufbxi_Channel) continue;
  9162. if (!ufbxi_get_val1(child, "S", &name)) continue;
  9163. ufbxi_check(ufbxi_read_take_prop_channel(uc, child, target_fbx_id, layer_fbx_id, name));
  9164. }
  9165. return 1;
  9166. }
  9167. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_take(ufbxi_context *uc, ufbxi_node *node)
  9168. {
  9169. uint64_t stack_fbx_id = 0, layer_fbx_id = 0;
  9170. // Treat the Take as a post-7000 version animation stack and layer.
  9171. ufbx_anim_stack *stack = ufbxi_push_synthetic_element(uc, &stack_fbx_id, node, NULL, ufbx_anim_stack, UFBX_ELEMENT_ANIM_STACK);
  9172. ufbxi_check(stack);
  9173. ufbxi_check(ufbxi_get_val1(node, "S", &stack->name));
  9174. ufbx_anim_layer *layer = ufbxi_push_synthetic_element(uc, &layer_fbx_id, node, ufbxi_BaseLayer, ufbx_anim_layer, UFBX_ELEMENT_ANIM_LAYER);
  9175. ufbxi_check(layer);
  9176. ufbxi_check(ufbxi_connect_oo(uc, layer_fbx_id, stack_fbx_id));
  9177. // Read stack properties from node
  9178. int64_t begin = 0, end = 0;
  9179. if (!ufbxi_find_val2(node, ufbxi_LocalTime, "LL", &begin, &end)) {
  9180. ufbxi_check(ufbxi_find_val2(node, ufbxi_ReferenceTime, "LL", &begin, &end));
  9181. }
  9182. stack->time_begin = (double)begin * uc->ktime_to_sec;
  9183. stack->time_end = (double)end * uc->ktime_to_sec;
  9184. // Read all properties of objects included in the take
  9185. ufbxi_for(ufbxi_node, child, node->children, node->num_children) {
  9186. // TODO: Do some object types have another name?
  9187. if (child->name != ufbxi_Model) continue;
  9188. ufbxi_check(ufbxi_read_take_object(uc, child, layer_fbx_id));
  9189. }
  9190. return 1;
  9191. }
  9192. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_takes(ufbxi_context *uc)
  9193. {
  9194. for (;;) {
  9195. ufbxi_node *node;
  9196. ufbxi_check(ufbxi_parse_toplevel_child(uc, &node));
  9197. if (!node) break;
  9198. if (node->name == ufbxi_Take) {
  9199. ufbxi_check(ufbxi_read_take(uc, node));
  9200. }
  9201. }
  9202. return 1;
  9203. }
  9204. ufbxi_noinline static void ufbxi_setup_root_node(ufbxi_context *uc, ufbx_node *root)
  9205. {
  9206. if (uc->opts.use_root_transform) {
  9207. root->local_transform = uc->opts.root_transform;
  9208. root->node_to_parent = ufbx_transform_to_matrix(&uc->opts.root_transform);
  9209. } else {
  9210. root->local_transform = ufbx_identity_transform;
  9211. root->node_to_parent = ufbx_identity_matrix;
  9212. }
  9213. root->is_root = true;
  9214. }
  9215. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_root(ufbxi_context *uc)
  9216. {
  9217. // FBXHeaderExtension: Some metadata (optional)
  9218. ufbxi_check(ufbxi_parse_toplevel(uc, ufbxi_FBXHeaderExtension));
  9219. ufbxi_check(ufbxi_read_header_extension(uc));
  9220. // The ASCII exporter version is stored in top-level
  9221. if (uc->exporter == UFBX_EXPORTER_BLENDER_ASCII) {
  9222. ufbxi_check(ufbxi_parse_toplevel(uc, ufbxi_Creator));
  9223. if (uc->top_node) {
  9224. ufbxi_ignore(ufbxi_get_val1(uc->top_node, "S", &uc->scene.metadata.creator));
  9225. }
  9226. }
  9227. // Resolve the exporter before continuing
  9228. ufbxi_check(ufbxi_match_exporter(uc));
  9229. if (uc->version < 7000) {
  9230. ufbxi_check(ufbxi_init_node_prop_names(uc));
  9231. }
  9232. // Document: Read root ID
  9233. if (uc->version >= 7000) {
  9234. ufbxi_check(ufbxi_parse_toplevel(uc, ufbxi_Documents));
  9235. ufbxi_check(ufbxi_read_document(uc));
  9236. } else {
  9237. // Pre-7000: Root node has a specific type-name pair "Model::Scene"
  9238. // (or reversed in binary). Use the interned name as ID as usual.
  9239. const char *root_name = uc->from_ascii ? "Model::Scene" : "Scene\x00\x01Model";
  9240. root_name = ufbxi_push_string_imp(&uc->string_pool, root_name, 12, NULL, false, true);
  9241. ufbxi_check(root_name);
  9242. uc->root_id = ufbxi_synthetic_id_from_string(root_name);
  9243. }
  9244. // Add a nameless root node with the root ID
  9245. {
  9246. ufbxi_element_info root_info = { uc->root_id };
  9247. root_info.name = ufbx_empty_string;
  9248. ufbx_node *root = ufbxi_push_element(uc, &root_info, ufbx_node, UFBX_ELEMENT_NODE);
  9249. ufbxi_check(root);
  9250. ufbxi_setup_root_node(uc, root);
  9251. ufbxi_check(ufbxi_push_copy(&uc->tmp_node_ids, uint32_t, 1, &root->element.element_id));
  9252. }
  9253. // Definitions: Object type counts and property templates (optional)
  9254. ufbxi_check(ufbxi_parse_toplevel(uc, ufbxi_Definitions));
  9255. ufbxi_check(ufbxi_read_definitions(uc));
  9256. // Objects: Actual scene data
  9257. ufbxi_check(ufbxi_parse_toplevel(uc, ufbxi_Objects));
  9258. if (!uc->sure_fbx) {
  9259. // If the file is a bit iffy about being a real FBX file reject it if
  9260. // even the objects are not found.
  9261. ufbxi_check_msg(uc->top_node, "Not an FBX file");
  9262. }
  9263. ufbxi_check(ufbxi_read_objects(uc));
  9264. // Connections: Relationships between nodes
  9265. ufbxi_check(ufbxi_parse_toplevel(uc, ufbxi_Connections));
  9266. ufbxi_check(ufbxi_read_connections(uc));
  9267. // Takes: Pre-7000 animations, don't even try to read them in
  9268. // post-7000 versions as the code has some assumptions about the version.
  9269. if (uc->version < 7000) {
  9270. ufbxi_check(ufbxi_parse_toplevel(uc, ufbxi_Takes));
  9271. ufbxi_check(ufbxi_read_takes(uc));
  9272. }
  9273. // Check if there's a top-level GlobalSettings that we skimmed over
  9274. ufbxi_check(ufbxi_parse_toplevel(uc, ufbxi_GlobalSettings));
  9275. if (uc->top_node) {
  9276. ufbxi_check(ufbxi_read_global_settings(uc, uc->top_node));
  9277. }
  9278. // Force parsing all the nodes by parsing a toplevel that cannot be found
  9279. if (uc->opts.retain_dom) {
  9280. ufbxi_check(ufbxi_parse_toplevel(uc, NULL));
  9281. }
  9282. return 1;
  9283. }
  9284. typedef struct {
  9285. const char *prop_name;
  9286. ufbx_prop_type prop_type;
  9287. const char *node_name;
  9288. const char *node_fmt;
  9289. } ufbxi_legacy_prop;
  9290. // Must be alphabetically sorted!
  9291. static const ufbxi_legacy_prop ufbxi_legacy_light_props[] = {
  9292. { ufbxi_CastLight, UFBX_PROP_BOOLEAN, ufbxi_CastLight, "L" },
  9293. { ufbxi_CastShadows, UFBX_PROP_BOOLEAN, ufbxi_CastShadows, "L" },
  9294. { ufbxi_Color, UFBX_PROP_COLOR, ufbxi_Color, "RRR" },
  9295. { ufbxi_ConeAngle, UFBX_PROP_NUMBER, ufbxi_ConeAngle, "R" },
  9296. { ufbxi_HotSpot, UFBX_PROP_NUMBER, ufbxi_HotSpot, "R" },
  9297. { ufbxi_Intensity, UFBX_PROP_NUMBER, ufbxi_Intensity, "R" },
  9298. { ufbxi_LightType, UFBX_PROP_INTEGER, ufbxi_LightType, "L" },
  9299. };
  9300. // Must be alphabetically sorted!
  9301. static const ufbxi_legacy_prop ufbxi_legacy_camera_props[] = {
  9302. { ufbxi_ApertureMode, UFBX_PROP_INTEGER, ufbxi_ApertureMode, "L" },
  9303. { ufbxi_AspectH, UFBX_PROP_NUMBER, ufbxi_AspectH, "R" },
  9304. { ufbxi_AspectRatioMode, UFBX_PROP_INTEGER, "AspectType", "L" },
  9305. { ufbxi_AspectW, UFBX_PROP_NUMBER, ufbxi_AspectW, "R" },
  9306. { ufbxi_FieldOfView, UFBX_PROP_NUMBER, "Aperture", "R" },
  9307. { ufbxi_FieldOfViewX, UFBX_PROP_NUMBER, "FieldOfViewXProperty", "R" },
  9308. { ufbxi_FieldOfViewY, UFBX_PROP_NUMBER, "FieldOfViewYProperty", "R" },
  9309. { ufbxi_FilmHeight, UFBX_PROP_NUMBER, "CameraAperture", "_R" },
  9310. { ufbxi_FilmSqueezeRatio, UFBX_PROP_NUMBER, "SqueezeRatio", "R" },
  9311. { ufbxi_FilmWidth, UFBX_PROP_NUMBER, "CameraAperture", "R_" },
  9312. { ufbxi_FocalLength, UFBX_PROP_NUMBER, ufbxi_FocalLength, "R" },
  9313. };
  9314. // Must be alphabetically sorted!
  9315. static const ufbxi_legacy_prop ufbxi_legacy_bone_props[] = {
  9316. { ufbxi_Size, UFBX_PROP_NUMBER, ufbxi_Size, "R" },
  9317. };
  9318. // Must be alphabetically sorted!
  9319. static const ufbxi_legacy_prop ufbxi_legacy_material_props[] = {
  9320. { ufbxi_AmbientColor, UFBX_PROP_COLOR, "Ambient", "RRR" },
  9321. { ufbxi_DiffuseColor, UFBX_PROP_COLOR, "Diffuse", "RRR" },
  9322. { ufbxi_EmissiveColor, UFBX_PROP_COLOR, "Emissive", "RRR" },
  9323. { ufbxi_ShadingModel, UFBX_PROP_COLOR, ufbxi_ShadingModel, "S" },
  9324. { ufbxi_Shininess, UFBX_PROP_NUMBER, "Shininess", "R" },
  9325. { ufbxi_SpecularColor, UFBX_PROP_COLOR, "Specular", "RRR" },
  9326. };
  9327. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_prop(ufbxi_node *node, ufbx_prop *prop, const ufbxi_legacy_prop *legacy_prop)
  9328. {
  9329. size_t value_ix = 0;
  9330. const char *fmt = legacy_prop->node_fmt;
  9331. for (size_t fmt_ix = 0; fmt[fmt_ix]; fmt_ix++) {
  9332. char c = fmt[fmt_ix];
  9333. switch (c) {
  9334. case 'L':
  9335. ufbx_assert(value_ix == 0);
  9336. if (!ufbxi_get_val_at(node, fmt_ix, 'L', &prop->value_int)) return 0;
  9337. prop->value_real = (ufbx_real)prop->value_int;
  9338. prop->value_real_arr[1] = 0.0f;
  9339. prop->value_real_arr[2] = 0.0f;
  9340. prop->value_real_arr[3] = 0.0f;
  9341. prop->value_str = ufbx_empty_string;
  9342. prop->value_blob = ufbx_empty_blob;
  9343. value_ix++;
  9344. break;
  9345. case 'R':
  9346. ufbx_assert(value_ix < 4);
  9347. if (!ufbxi_get_val_at(node, fmt_ix, 'R', &prop->value_real_arr[value_ix])) return 0;
  9348. if (value_ix == 0) {
  9349. prop->value_int = ufbxi_f64_to_i64(prop->value_real);
  9350. prop->value_real_arr[1] = 0.0f;
  9351. prop->value_real_arr[2] = 0.0f;
  9352. prop->value_real_arr[3] = 0.0f;
  9353. prop->value_str = ufbx_empty_string;
  9354. prop->value_blob = ufbx_empty_blob;
  9355. }
  9356. value_ix++;
  9357. break;
  9358. case 'S':
  9359. ufbx_assert(value_ix == 0);
  9360. if (!ufbxi_get_val_at(node, fmt_ix, 'S', &prop->value_str)) return 0;
  9361. if (prop->value_str.length > 0) {
  9362. int found = ufbxi_get_val_at(node, fmt_ix, 'b', &prop->value_blob);
  9363. ufbxi_ignore(found);
  9364. ufbx_assert(found);
  9365. } else {
  9366. prop->value_blob = ufbx_empty_blob;
  9367. }
  9368. prop->value_real = 0.0f;
  9369. prop->value_real_arr[1] = 0.0f;
  9370. prop->value_real_arr[2] = 0.0f;
  9371. prop->value_real_arr[3] = 0.0f;
  9372. prop->value_int = 0;
  9373. value_ix++;
  9374. break;
  9375. case '_':
  9376. break;
  9377. default:
  9378. ufbx_assert(0 && "Unhandled legacy fmt");
  9379. break;
  9380. }
  9381. }
  9382. return 1;
  9383. }
  9384. ufbxi_nodiscard ufbxi_noinline static size_t ufbxi_read_legacy_props(ufbxi_node *node, ufbx_prop *props, const ufbxi_legacy_prop *legacy_props, size_t num_legacy)
  9385. {
  9386. size_t num_props = 0;
  9387. for (size_t legacy_ix = 0; legacy_ix < num_legacy; legacy_ix++) {
  9388. const ufbxi_legacy_prop *legacy_prop = &legacy_props[legacy_ix];
  9389. ufbx_prop *prop = &props[num_props];
  9390. ufbxi_node *n = ufbxi_find_child_strcmp(node, legacy_prop->node_name);
  9391. if (!n) continue;
  9392. if (!ufbxi_read_legacy_prop(n, prop, legacy_prop)) continue;
  9393. prop->name.data = legacy_prop->prop_name;
  9394. prop->name.length = strlen(legacy_prop->prop_name);
  9395. prop->_internal_key = ufbxi_get_name_key(prop->name.data, prop->name.length);
  9396. prop->flags = (ufbx_prop_flags)0;
  9397. prop->type = legacy_prop->prop_type;
  9398. num_props++;
  9399. }
  9400. return num_props;
  9401. }
  9402. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_material(ufbxi_context *uc, ufbxi_node *node, uint64_t *p_fbx_id, const char *name)
  9403. {
  9404. ufbx_material *ufbxi_restrict material = ufbxi_push_synthetic_element(uc, p_fbx_id, node, name, ufbx_material, UFBX_ELEMENT_MATERIAL);
  9405. ufbxi_check(material);
  9406. ufbx_prop tmp_props[ufbxi_arraycount(ufbxi_legacy_material_props)];
  9407. size_t num_props = ufbxi_read_legacy_props(node, tmp_props, ufbxi_legacy_material_props, ufbxi_arraycount(ufbxi_legacy_material_props));
  9408. material->shading_model_name = ufbx_empty_string;
  9409. material->props.props.count = num_props;
  9410. material->props.props.data = ufbxi_push_copy(&uc->result, ufbx_prop, num_props, tmp_props);
  9411. ufbxi_check(material->props.props.data);
  9412. material->shader_prop_prefix = ufbx_empty_string;
  9413. return 1;
  9414. }
  9415. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_link(ufbxi_context *uc, ufbxi_node *node, uint64_t *p_fbx_id, const char *name)
  9416. {
  9417. ufbx_skin_cluster *ufbxi_restrict cluster = ufbxi_push_synthetic_element(uc, p_fbx_id, node, name, ufbx_skin_cluster, UFBX_ELEMENT_SKIN_CLUSTER);
  9418. ufbxi_check(cluster);
  9419. // TODO: Merge with ufbxi_read_skin_cluster(), at least partially?
  9420. ufbxi_value_array *indices = ufbxi_find_array(node, ufbxi_Indexes, 'i');
  9421. ufbxi_value_array *weights = ufbxi_find_array(node, ufbxi_Weights, 'r');
  9422. if (indices && weights) {
  9423. ufbxi_check(indices->size == weights->size);
  9424. cluster->num_weights = indices->size;
  9425. cluster->vertices.data = (uint32_t*)indices->data;
  9426. cluster->weights.data = (ufbx_real*)weights->data;
  9427. cluster->vertices.count = cluster->num_weights;
  9428. cluster->weights.count = cluster->num_weights;
  9429. }
  9430. ufbxi_value_array *transform = ufbxi_find_array(node, ufbxi_Transform, 'r');
  9431. ufbxi_value_array *transform_link = ufbxi_find_array(node, ufbxi_TransformLink, 'r');
  9432. if (transform && transform_link) {
  9433. ufbxi_check(transform->size >= 16);
  9434. ufbxi_check(transform_link->size >= 16);
  9435. ufbxi_read_transform_matrix(&cluster->mesh_node_to_bone, (ufbx_real*)transform->data);
  9436. ufbxi_read_transform_matrix(&cluster->bind_to_world, (ufbx_real*)transform_link->data);
  9437. }
  9438. return 1;
  9439. }
  9440. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_light(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  9441. {
  9442. ufbx_light *ufbxi_restrict light = ufbxi_push_element(uc, info, ufbx_light, UFBX_ELEMENT_LIGHT);
  9443. ufbxi_check(light);
  9444. ufbx_prop tmp_props[ufbxi_arraycount(ufbxi_legacy_light_props)];
  9445. size_t num_props = ufbxi_read_legacy_props(node, tmp_props, ufbxi_legacy_light_props, ufbxi_arraycount(ufbxi_legacy_light_props));
  9446. light->props.props.count = num_props;
  9447. light->props.props.data = ufbxi_push_copy(&uc->result, ufbx_prop, num_props, tmp_props);
  9448. ufbxi_check(light->props.props.data);
  9449. return 1;
  9450. }
  9451. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_camera(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  9452. {
  9453. ufbx_camera *ufbxi_restrict camera = ufbxi_push_element(uc, info, ufbx_camera, UFBX_ELEMENT_CAMERA);
  9454. ufbxi_check(camera);
  9455. ufbx_prop tmp_props[ufbxi_arraycount(ufbxi_legacy_camera_props)];
  9456. size_t num_props = ufbxi_read_legacy_props(node, tmp_props, ufbxi_legacy_camera_props, ufbxi_arraycount(ufbxi_legacy_camera_props));
  9457. camera->props.props.count = num_props;
  9458. camera->props.props.data = ufbxi_push_copy(&uc->result, ufbx_prop, num_props, tmp_props);
  9459. ufbxi_check(camera->props.props.data);
  9460. return 1;
  9461. }
  9462. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_limb_node(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  9463. {
  9464. ufbx_bone *ufbxi_restrict bone = ufbxi_push_element(uc, info, ufbx_bone, UFBX_ELEMENT_BONE);
  9465. ufbxi_check(bone);
  9466. ufbx_prop tmp_props[ufbxi_arraycount(ufbxi_legacy_bone_props)];
  9467. size_t num_props = 0;
  9468. ufbxi_node *prop_node = ufbxi_find_child_strcmp(node, "Properties");
  9469. if (prop_node) {
  9470. num_props = ufbxi_read_legacy_props(prop_node, tmp_props, ufbxi_legacy_bone_props, ufbxi_arraycount(ufbxi_legacy_bone_props));
  9471. }
  9472. bone->props.props.count = num_props;
  9473. bone->props.props.data = ufbxi_push_copy(&uc->result, ufbx_prop, num_props, tmp_props);
  9474. ufbxi_check(bone->props.props.data);
  9475. return 1;
  9476. }
  9477. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_mesh(ufbxi_context *uc, ufbxi_node *node, ufbxi_element_info *info)
  9478. {
  9479. // Only read polygon meshes, ignore eg. NURBS without error
  9480. ufbxi_node *node_vertices = ufbxi_find_child(node, ufbxi_Vertices);
  9481. ufbxi_node *node_indices = ufbxi_find_child(node, ufbxi_PolygonVertexIndex);
  9482. if (!node_vertices || !node_indices) return 1;
  9483. ufbx_mesh *ufbxi_restrict mesh = ufbxi_push_element(uc, info, ufbx_mesh, UFBX_ELEMENT_MESH);
  9484. ufbxi_check(mesh);
  9485. ufbxi_check(ufbxi_read_synthetic_blend_shapes(uc, node, info));
  9486. ufbxi_patch_mesh_reals(mesh);
  9487. if (uc->opts.ignore_geometry) return 1;
  9488. ufbxi_value_array *vertices = ufbxi_get_array(node_vertices, 'r');
  9489. ufbxi_value_array *indices = ufbxi_get_array(node_indices, 'i');
  9490. ufbxi_check(vertices && indices);
  9491. ufbxi_check(vertices->size % 3 == 0);
  9492. mesh->num_vertices = vertices->size / 3;
  9493. mesh->num_indices = indices->size;
  9494. uint32_t *index_data = (uint32_t*)indices->data;
  9495. // Duplicate `index_data` for modification if we retain DOM
  9496. if (uc->opts.retain_dom) {
  9497. index_data = ufbxi_push_copy(&uc->result, uint32_t, indices->size, index_data);
  9498. ufbxi_check(index_data);
  9499. }
  9500. mesh->vertices.data = (ufbx_vec3*)vertices->data;
  9501. mesh->vertex_indices.data = index_data;
  9502. mesh->vertices.count = mesh->num_vertices;
  9503. mesh->vertex_indices.count = mesh->num_indices;
  9504. mesh->vertex_position.exists = true;
  9505. mesh->vertex_position.values.data = (ufbx_vec3*)vertices->data;
  9506. mesh->vertex_position.values.count = mesh->num_vertices;
  9507. mesh->vertex_position.indices.data = index_data;
  9508. mesh->vertex_position.indices.count = mesh->num_indices;
  9509. // Check/make sure that the last index is negated (last of polygon)
  9510. if (mesh->num_indices > 0) {
  9511. if ((int32_t)index_data[mesh->num_indices - 1] >= 0) {
  9512. if (uc->opts.strict) ufbxi_fail("Non-negated last index");
  9513. index_data[mesh->num_indices - 1] = ~index_data[mesh->num_indices - 1];
  9514. }
  9515. }
  9516. ufbxi_check(ufbxi_process_indices(uc, mesh, index_data));
  9517. // Normals are either per-vertex or per-index in legacy FBX files?
  9518. // If the version is 5000 prefer per-vertex, otherwise per-index...
  9519. ufbxi_value_array *normals = ufbxi_find_array(node, ufbxi_Normals, 'r');
  9520. if (normals) {
  9521. size_t num_normals = normals->size / 3;
  9522. bool per_vertex = num_normals == mesh->num_vertices;
  9523. bool per_index = num_normals == mesh->num_indices;
  9524. if (per_vertex && (!per_index || uc->version == 5000)) {
  9525. mesh->vertex_normal.exists = true;
  9526. mesh->vertex_normal.values.count = num_normals;
  9527. mesh->vertex_normal.indices.count = mesh->num_indices;
  9528. mesh->vertex_normal.unique_per_vertex = true;
  9529. mesh->vertex_normal.values.data = (ufbx_vec3*)normals->data;
  9530. mesh->vertex_normal.indices.data = mesh->vertex_indices.data;
  9531. } else if (per_index) {
  9532. uc->max_consecutive_indices = ufbxi_max_sz(uc->max_consecutive_indices, mesh->num_indices);
  9533. mesh->vertex_normal.exists = true;
  9534. mesh->vertex_normal.values.count = num_normals;
  9535. mesh->vertex_normal.indices.count = mesh->num_indices;
  9536. mesh->vertex_normal.unique_per_vertex = false;
  9537. mesh->vertex_normal.values.data = (ufbx_vec3*)normals->data;
  9538. mesh->vertex_normal.indices.data = (uint32_t*)ufbxi_sentinel_index_consecutive;
  9539. }
  9540. }
  9541. // Optional UV values are stored pretty much like a modern vertex element
  9542. ufbxi_node *uv_info = ufbxi_find_child(node, ufbxi_GeometryUVInfo);
  9543. if (uv_info) {
  9544. ufbx_uv_set *set = ufbxi_push_zero(&uc->result, ufbx_uv_set, 1);
  9545. ufbxi_check(set);
  9546. set->index = 0;
  9547. set->name = ufbx_empty_string;
  9548. ufbxi_check(ufbxi_read_vertex_element(uc, mesh, uv_info, (ufbx_vertex_attrib*)&set->vertex_uv,
  9549. ufbxi_TextureUV, ufbxi_TextureUVVerticeIndex, 'r', 2));
  9550. mesh->vertex_uv = set->vertex_uv;
  9551. }
  9552. // Material indices
  9553. {
  9554. const char *mapping;
  9555. ufbxi_check(ufbxi_find_val1(node, ufbxi_MaterialAssignation, "C", (char**)&mapping));
  9556. if (mapping == ufbxi_ByPolygon) {
  9557. ufbxi_check(ufbxi_read_truncated_array(uc, &mesh->face_material.data, &mesh->face_material.count, node, ufbxi_Materials, 'i', mesh->num_faces));
  9558. } else if (mapping == ufbxi_AllSame) {
  9559. ufbxi_value_array *arr = ufbxi_find_array(node, ufbxi_Materials, 'i');
  9560. uint32_t material = 0;
  9561. if (arr && arr->size >= 1) {
  9562. material = ((uint32_t*)arr->data)[0];
  9563. }
  9564. mesh->face_material.count = mesh->num_indices;
  9565. if (material == 0) {
  9566. mesh->face_material.data = (uint32_t*)ufbxi_sentinel_index_zero;
  9567. } else {
  9568. mesh->face_material.data = ufbxi_push(&uc->result, uint32_t, mesh->num_faces);
  9569. ufbxi_check(mesh->face_material.data);
  9570. ufbxi_for_list(uint32_t, p_mat, mesh->face_material) {
  9571. *p_mat = material;
  9572. }
  9573. }
  9574. }
  9575. }
  9576. uint64_t skin_fbx_id = 0;
  9577. ufbx_skin_deformer *skin = NULL;
  9578. // Materials, Skin Clusters
  9579. ufbxi_for(ufbxi_node, child, node->children, node->num_children) {
  9580. if (child->name == ufbxi_Material) {
  9581. uint64_t fbx_id = 0;
  9582. ufbx_string type_and_name, type, name;
  9583. ufbxi_check(ufbxi_get_val1(child, "s", &type_and_name));
  9584. ufbxi_check(ufbxi_split_type_and_name(uc, type_and_name, &type, &name));
  9585. ufbxi_check(ufbxi_read_legacy_material(uc, child, &fbx_id, name.data));
  9586. ufbxi_check(ufbxi_connect_oo(uc, fbx_id, info->fbx_id));
  9587. } else if (child->name == ufbxi_Link) {
  9588. uint64_t fbx_id = 0;
  9589. ufbx_string type_and_name, type, name;
  9590. ufbxi_check(ufbxi_get_val1(child, "s", &type_and_name));
  9591. ufbxi_check(ufbxi_split_type_and_name(uc, type_and_name, &type, &name));
  9592. ufbxi_check(ufbxi_read_legacy_link(uc, child, &fbx_id, name.data));
  9593. uint64_t node_fbx_id = ufbxi_synthetic_id_from_string(type_and_name.data);
  9594. ufbxi_check(ufbxi_connect_oo(uc, node_fbx_id, fbx_id));
  9595. if (!skin) {
  9596. skin = ufbxi_push_synthetic_element(uc, &skin_fbx_id, NULL, info->name.data, ufbx_skin_deformer, UFBX_ELEMENT_SKIN_DEFORMER);
  9597. ufbxi_check(skin);
  9598. ufbxi_check(ufbxi_connect_oo(uc, skin_fbx_id, info->fbx_id));
  9599. }
  9600. ufbxi_check(ufbxi_connect_oo(uc, fbx_id, skin_fbx_id));
  9601. }
  9602. }
  9603. mesh->skinned_is_local = true;
  9604. mesh->skinned_position = mesh->vertex_position;
  9605. mesh->skinned_normal = mesh->vertex_normal;
  9606. ufbxi_patch_mesh_reals(mesh);
  9607. return 1;
  9608. }
  9609. ufbxi_nodiscard ufbxi_noinline static int ufbxi_read_legacy_model(ufbxi_context *uc, ufbxi_node *node)
  9610. {
  9611. ufbx_string type_and_name, type, name;
  9612. ufbxi_check(ufbxi_get_val1(node, "s", &type_and_name));
  9613. ufbxi_check(ufbxi_split_type_and_name(uc, type_and_name, &type, &name));
  9614. ufbxi_element_info info = { 0 };
  9615. info.fbx_id = ufbxi_synthetic_id_from_string(type_and_name.data);
  9616. info.name = name;
  9617. info.dom_node = ufbxi_get_dom_node(uc, node);
  9618. ufbx_node *elem_node = ufbxi_push_element(uc, &info, ufbx_node, UFBX_ELEMENT_NODE);
  9619. ufbxi_check(elem_node);
  9620. ufbxi_check(ufbxi_push_copy(&uc->tmp_node_ids, uint32_t, 1, &elem_node->element.element_id));
  9621. ufbxi_element_info attrib_info = { 0 };
  9622. ufbxi_check(ufbxi_push_synthetic_id(uc, &attrib_info.fbx_id));
  9623. attrib_info.name = name;
  9624. attrib_info.dom_node = info.dom_node;
  9625. // If we make unused connections it doesn't matter..
  9626. ufbxi_check(ufbxi_connect_oo(uc, attrib_info.fbx_id, info.fbx_id));
  9627. const char *attrib_type = ufbxi_empty_char;
  9628. ufbxi_ignore(ufbxi_find_val1(node, ufbxi_Type, "C", (char**)&attrib_type));
  9629. bool has_attrib = true;
  9630. if (attrib_type == ufbxi_Light) {
  9631. ufbxi_check(ufbxi_read_legacy_light(uc, node, &attrib_info));
  9632. } else if (attrib_type == ufbxi_Camera) {
  9633. ufbxi_check(ufbxi_read_legacy_camera(uc, node, &attrib_info));
  9634. } else if (attrib_type == ufbxi_LimbNode) {
  9635. ufbxi_check(ufbxi_read_legacy_limb_node(uc, node, &attrib_info));
  9636. } else if (ufbxi_find_child(node, ufbxi_Vertices)) {
  9637. ufbxi_check(ufbxi_read_legacy_mesh(uc, node, &attrib_info));
  9638. } else {
  9639. has_attrib = false;
  9640. }
  9641. // Mark the node as having an attribute so property connections can be forwarded
  9642. if (has_attrib) {
  9643. ufbxi_check(ufbxi_insert_fbx_attr(uc, info.fbx_id, attrib_info.fbx_id));
  9644. }
  9645. // Children are represented as an array of strings
  9646. ufbxi_value_array *children = ufbxi_find_array(node, ufbxi_Children, 's');
  9647. if (children) {
  9648. ufbx_string *names = (ufbx_string*)children->data;
  9649. for (size_t i = 0; i < children->size; i++) {
  9650. uint64_t child_fbx_id = ufbxi_synthetic_id_from_string(names[i].data);
  9651. ufbxi_check(ufbxi_connect_oo(uc, child_fbx_id, info.fbx_id));
  9652. }
  9653. }
  9654. // Non-take animation channels
  9655. ufbxi_for(ufbxi_node, child, node->children, node->num_children) {
  9656. if (child->name == ufbxi_Channel) {
  9657. ufbx_string channel_name;
  9658. if (ufbxi_get_val1(child, "S", &channel_name)) {
  9659. if (uc->legacy_implicit_anim_layer_id == 0) {
  9660. // Defer creation so we won't be the first animation stack..
  9661. ufbxi_check(ufbxi_push_synthetic_id(uc, &uc->legacy_implicit_anim_layer_id));
  9662. }
  9663. ufbxi_check(ufbxi_read_take_prop_channel(uc, child, info.fbx_id, uc->legacy_implicit_anim_layer_id, channel_name));
  9664. }
  9665. }
  9666. }
  9667. return 1;
  9668. }
  9669. // Read a pre-6000 FBX file where everything is stored at the root level
  9670. ufbxi_nodiscard static ufbxi_noinline int ufbxi_read_legacy_root(ufbxi_context *uc)
  9671. {
  9672. ufbxi_check(ufbxi_init_node_prop_names(uc));
  9673. // Some legacy FBX files have an `Fbx_Root` node that could be used as the
  9674. // root node. However no other formats have root node with transforms so it
  9675. // might be better to leave it as-is and create an empty one.
  9676. {
  9677. ufbx_node *root = ufbxi_push_synthetic_element(uc, &uc->root_id, NULL, ufbxi_empty_char, ufbx_node, UFBX_ELEMENT_NODE);
  9678. ufbxi_check(root);
  9679. ufbxi_setup_root_node(uc, root);
  9680. ufbxi_check(ufbxi_push_copy(&uc->tmp_node_ids, uint32_t, 1, &root->element.element_id));
  9681. }
  9682. for (;;) {
  9683. ufbxi_check(ufbxi_parse_legacy_toplevel(uc));
  9684. if (!uc->top_node) break;
  9685. ufbxi_node *node = uc->top_node;
  9686. if (node->name == ufbxi_FBXHeaderExtension) {
  9687. ufbxi_check(ufbxi_read_header_extension(uc));
  9688. } else if (node->name == ufbxi_Takes) {
  9689. ufbxi_check(ufbxi_read_takes(uc));
  9690. } else if (node->name == ufbxi_Takes) {
  9691. ufbxi_check(ufbxi_read_takes(uc));
  9692. } else if (node->name == ufbxi_Model) {
  9693. ufbxi_check(ufbxi_read_legacy_model(uc, node));
  9694. }
  9695. }
  9696. if (uc->opts.retain_dom) {
  9697. ufbxi_check(ufbxi_retain_toplevel(uc, NULL));
  9698. }
  9699. // Create the implicit animation stack if necessary
  9700. if (uc->legacy_implicit_anim_layer_id) {
  9701. ufbxi_element_info layer_info = { 0 };
  9702. layer_info.fbx_id = uc->legacy_implicit_anim_layer_id;
  9703. layer_info.name.data = "(internal)";
  9704. layer_info.name.length = strlen(layer_info.name.data);
  9705. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &layer_info.name, true));
  9706. ufbx_anim_layer *layer = ufbxi_push_element(uc, &layer_info, ufbx_anim_layer, UFBX_ELEMENT_ANIM_LAYER);
  9707. ufbxi_check(layer);
  9708. ufbxi_element_info stack_info = layer_info;
  9709. ufbxi_check(ufbxi_push_synthetic_id(uc, &stack_info.fbx_id));
  9710. ufbx_anim_stack *stack = ufbxi_push_element(uc, &stack_info, ufbx_anim_stack, UFBX_ELEMENT_ANIM_STACK);
  9711. ufbxi_check(stack);
  9712. ufbxi_check(ufbxi_connect_oo(uc, layer_info.fbx_id, stack_info.fbx_id));
  9713. }
  9714. return 1;
  9715. }
  9716. static ufbxi_noinline ufbx_element *ufbxi_find_element_by_fbx_id(ufbxi_context *uc, uint64_t fbx_id)
  9717. {
  9718. uint32_t hash = ufbxi_hash64(fbx_id);
  9719. ufbxi_fbx_id_entry *entry = ufbxi_map_find(&uc->fbx_id_map, ufbxi_fbx_id_entry, hash, &fbx_id);
  9720. if (entry) {
  9721. return uc->scene.elements.data[entry->element_id];
  9722. }
  9723. return NULL;
  9724. }
  9725. ufbxi_forceinline static bool ufbxi_cmp_name_element_less(const ufbx_name_element *a, const ufbx_name_element *b)
  9726. {
  9727. if (a->_internal_key != b->_internal_key) return a->_internal_key < b->_internal_key;
  9728. int cmp = strcmp(a->name.data, b->name.data);
  9729. if (cmp != 0) return cmp < 0;
  9730. return a->type < b->type;
  9731. }
  9732. ufbxi_forceinline static bool ufbxi_cmp_name_element_less_ref(const ufbx_name_element *a, ufbx_string name, ufbx_element_type type, uint32_t key)
  9733. {
  9734. if (a->_internal_key != key) return a->_internal_key < key;
  9735. int cmp = ufbxi_str_cmp(a->name, name);
  9736. if (cmp != 0) return cmp < 0;
  9737. return a->type < type;
  9738. }
  9739. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_name_elements(ufbxi_context *uc, ufbx_name_element *name_elems, size_t count)
  9740. {
  9741. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_name_element)));
  9742. ufbxi_macro_stable_sort(ufbx_name_element, 32, name_elems, uc->tmp_arr, count,
  9743. ( ufbxi_cmp_name_element_less(a, b) ) );
  9744. return 1;
  9745. }
  9746. ufbxi_noinline static bool ufbxi_cmp_node_less(ufbx_node *a, ufbx_node *b)
  9747. {
  9748. if (a->node_depth != b->node_depth) return a->node_depth < b->node_depth;
  9749. if (a->parent && b->parent) {
  9750. uint32_t a_pid = a->parent->element.element_id, b_pid = b->parent->element.element_id;
  9751. if (a_pid != b_pid) return a_pid < b_pid;
  9752. } else {
  9753. ufbx_assert(a->parent == NULL && b->parent == NULL);
  9754. }
  9755. return a->element.element_id < b->element.element_id;
  9756. }
  9757. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_node_ptrs(ufbxi_context *uc, ufbx_node **nodes, size_t count)
  9758. {
  9759. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_node*)));
  9760. ufbxi_macro_stable_sort(ufbx_node*, 32, nodes, uc->tmp_arr, count,
  9761. ( ufbxi_cmp_node_less(*a, *b) ) );
  9762. return 1;
  9763. }
  9764. ufbxi_nodiscard ufbxi_noinline static int ufbxi_cmp_tmp_material_texture_less(const ufbxi_tmp_material_texture *a, const ufbxi_tmp_material_texture *b)
  9765. {
  9766. if (a->material_id != b->material_id) return a->material_id < b->material_id;
  9767. if (a->texture_id != b->texture_id) return a->texture_id < b->texture_id;
  9768. return ufbxi_str_less(a->prop_name, b->prop_name);
  9769. }
  9770. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_tmp_material_textures(ufbxi_context *uc, ufbxi_tmp_material_texture *mat_texs, size_t count)
  9771. {
  9772. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbxi_tmp_material_texture)));
  9773. ufbxi_macro_stable_sort(ufbxi_tmp_material_texture, 32, mat_texs, uc->tmp_arr, count,
  9774. ( ufbxi_cmp_tmp_material_texture_less(a, b) ));
  9775. return 1;
  9776. }
  9777. // We need to be able to assume no padding!
  9778. ufbx_static_assert(connection_size, sizeof(ufbx_connection) == sizeof(ufbx_element*)*2 + sizeof(ufbx_string)*2);
  9779. ufbxi_forceinline static bool ufbxi_cmp_connection_less(ufbx_connection *a, ufbx_connection *b, size_t index)
  9780. {
  9781. ufbx_element *a_elem = (&a->src)[index], *b_elem = (&b->src)[index];
  9782. if (a_elem != b_elem) return a_elem < b_elem;
  9783. int cmp = strcmp((&a->src_prop)[index].data, (&b->src_prop)[index].data);
  9784. if (cmp != 0) return cmp < 0;
  9785. cmp = strcmp((&a->src_prop)[index ^ 1].data, (&b->src_prop)[index ^ 1].data);
  9786. return cmp < 0;
  9787. }
  9788. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_connections(ufbxi_context *uc, ufbx_connection *connections, size_t count, size_t index)
  9789. {
  9790. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_connection)));
  9791. ufbxi_macro_stable_sort(ufbx_connection, 32, connections, uc->tmp_arr, count, ( ufbxi_cmp_connection_less(a, b, index) ));
  9792. return 1;
  9793. }
  9794. static uint64_t ufbxi_find_attribute_fbx_id(ufbxi_context *uc, uint64_t node_fbx_id)
  9795. {
  9796. uint32_t hash = ufbxi_hash64(node_fbx_id);
  9797. ufbxi_fbx_attr_entry *entry = ufbxi_map_find(&uc->fbx_attr_map, ufbxi_fbx_attr_entry, hash, &node_fbx_id);
  9798. if (entry) {
  9799. return entry->attr_fbx_id;
  9800. }
  9801. return node_fbx_id;
  9802. }
  9803. static ufbxi_forceinline ufbx_real ufbxi_find_real(const ufbx_props *props, const char *name, ufbx_real def)
  9804. {
  9805. ufbx_prop *prop = ufbxi_find_prop(props, name);
  9806. if (prop) {
  9807. return prop->value_real;
  9808. } else {
  9809. return def;
  9810. }
  9811. }
  9812. static ufbxi_forceinline ufbx_vec3 ufbxi_find_vec3(const ufbx_props *props, const char *name, ufbx_real def_x, ufbx_real def_y, ufbx_real def_z)
  9813. {
  9814. ufbx_prop *prop = ufbxi_find_prop(props, name);
  9815. if (prop) {
  9816. return prop->value_vec3;
  9817. } else {
  9818. ufbx_vec3 def = { def_x, def_y, def_z };
  9819. return def;
  9820. }
  9821. }
  9822. static ufbxi_forceinline int64_t ufbxi_find_int(const ufbx_props *props, const char *name, int64_t def)
  9823. {
  9824. ufbx_prop *prop = ufbxi_find_prop(props, name);
  9825. if (prop) {
  9826. return prop->value_int;
  9827. } else {
  9828. return def;
  9829. }
  9830. }
  9831. static ufbxi_forceinline int64_t ufbxi_find_enum(const ufbx_props *props, const char *name, int64_t def, int64_t max_value)
  9832. {
  9833. ufbx_prop *prop = ufbxi_find_prop(props, name);
  9834. if (prop) {
  9835. int64_t value = prop->value_int;
  9836. if (value >= 0 && value <= max_value) {
  9837. return value;
  9838. } else {
  9839. return def;
  9840. }
  9841. } else {
  9842. return def;
  9843. }
  9844. }
  9845. ufbxi_nodiscard ufbxi_noinline static int ufbxi_resolve_connections(ufbxi_context *uc)
  9846. {
  9847. size_t num_connections = uc->tmp_connections.num_items;
  9848. ufbxi_tmp_connection *tmp_connections = ufbxi_push_pop(&uc->tmp, &uc->tmp_connections, ufbxi_tmp_connection, num_connections);
  9849. ufbxi_buf_free(&uc->tmp_connections);
  9850. ufbxi_check(tmp_connections);
  9851. // NOTE: We truncate this array in case not all connections are resolved
  9852. uc->scene.connections_src.data = ufbxi_push(&uc->result, ufbx_connection, num_connections);
  9853. ufbxi_check(uc->scene.connections_src.data);
  9854. // HACK: Translate property connections from node to attribute if
  9855. // the property name is not included in the known node properties.
  9856. if (uc->version < 7000) {
  9857. ufbxi_for(ufbxi_tmp_connection, tmp_conn, tmp_connections, num_connections) {
  9858. if (tmp_conn->src_prop.length > 0 && !ufbxi_is_node_property(uc, tmp_conn->src_prop.data)) {
  9859. tmp_conn->src = ufbxi_find_attribute_fbx_id(uc, tmp_conn->src);
  9860. }
  9861. if (tmp_conn->dst_prop.length > 0 && !ufbxi_is_node_property(uc, tmp_conn->dst_prop.data)) {
  9862. tmp_conn->dst = ufbxi_find_attribute_fbx_id(uc, tmp_conn->dst);
  9863. }
  9864. }
  9865. }
  9866. ufbxi_for(ufbxi_tmp_connection, tmp_conn, tmp_connections, num_connections) {
  9867. ufbx_element *src = ufbxi_find_element_by_fbx_id(uc, tmp_conn->src);
  9868. ufbx_element *dst = ufbxi_find_element_by_fbx_id(uc, tmp_conn->dst);
  9869. if (!src || !dst) continue;
  9870. ufbx_connection *conn = &uc->scene.connections_src.data[uc->scene.connections_src.count++];
  9871. conn->src = src;
  9872. conn->dst = dst;
  9873. conn->src_prop = tmp_conn->src_prop;
  9874. conn->dst_prop = tmp_conn->dst_prop;
  9875. }
  9876. uc->scene.connections_dst.count = uc->scene.connections_src.count;
  9877. uc->scene.connections_dst.data = ufbxi_push_copy(&uc->result, ufbx_connection,
  9878. uc->scene.connections_src.count, uc->scene.connections_src.data);
  9879. ufbxi_check(uc->scene.connections_dst.data);
  9880. ufbxi_check(ufbxi_sort_connections(uc, uc->scene.connections_src.data, uc->scene.connections_src.count, 0));
  9881. ufbxi_check(ufbxi_sort_connections(uc, uc->scene.connections_dst.data, uc->scene.connections_dst.count, 1));
  9882. // We don't need the temporary connections at this point anymore
  9883. ufbxi_buf_free(&uc->tmp_connections);
  9884. return 1;
  9885. }
  9886. ufbxi_nodiscard ufbxi_noinline static int ufbxi_add_connections_to_elements(ufbxi_context *uc)
  9887. {
  9888. ufbx_connection *conn_src = uc->scene.connections_src.data;
  9889. ufbx_connection *conn_src_end = ufbxi_add_ptr(conn_src, uc->scene.connections_src.count);
  9890. ufbx_connection *conn_dst = uc->scene.connections_dst.data;
  9891. ufbx_connection *conn_dst_end = ufbxi_add_ptr(conn_dst, uc->scene.connections_dst.count);
  9892. ufbxi_for_ptr(ufbx_element, p_elem, uc->scene.elements.data, uc->scene.elements.count) {
  9893. ufbx_element *elem = *p_elem;
  9894. uint32_t id = elem->element_id;
  9895. while (conn_src < conn_src_end && conn_src->src->element_id < id) conn_src++;
  9896. while (conn_dst < conn_dst_end && conn_dst->dst->element_id < id) conn_dst++;
  9897. ufbx_connection *src_end = conn_src, *dst_end = conn_dst;
  9898. while (src_end < conn_src_end && src_end->src->element_id == id) src_end++;
  9899. while (dst_end < conn_dst_end && dst_end->dst->element_id == id) dst_end++;
  9900. elem->connections_src.data = conn_src;
  9901. elem->connections_src.count = ufbxi_to_size(src_end - conn_src);
  9902. elem->connections_dst.data = conn_dst;
  9903. elem->connections_dst.count = ufbxi_to_size(dst_end - conn_dst);
  9904. // Setup animated properties
  9905. // TODO: It seems we're invalidating a lot of properties here actually, maybe they
  9906. // should be initially pushed to `tmp` instead of result if this happens so much..
  9907. {
  9908. ufbx_prop *prop = elem->props.props.data, *prop_end = ufbxi_add_ptr(prop, elem->props.props.count);
  9909. ufbx_prop *copy_start = prop;
  9910. bool needs_copy = false;
  9911. size_t num_animated = 0, num_synthetic = 0;
  9912. for (;;) {
  9913. // Scan to the next animation connection
  9914. for (; conn_dst < dst_end; conn_dst++) {
  9915. if (conn_dst->dst_prop.length == 0) continue;
  9916. if (conn_dst->src_prop.length > 0) break;
  9917. if (conn_dst->src->type == UFBX_ELEMENT_ANIM_VALUE) break;
  9918. }
  9919. ufbx_string name = ufbx_empty_string;
  9920. if (conn_dst < dst_end) {
  9921. name = conn_dst->dst_prop;
  9922. }
  9923. if (name.length == 0) break;
  9924. // NOTE: "Animated" properties also include connected ones as we need
  9925. // to resolve them during evaluation
  9926. num_animated++;
  9927. ufbx_anim_value *anim_value = NULL;
  9928. uint32_t flags = 0;
  9929. for (; conn_dst < dst_end && conn_dst->dst_prop.data == name.data; conn_dst++) {
  9930. if (conn_dst->src_prop.length > 0) {
  9931. flags |= UFBX_PROP_FLAG_CONNECTED;
  9932. } else if (conn_dst->src->type == UFBX_ELEMENT_ANIM_VALUE) {
  9933. anim_value = (ufbx_anim_value*)conn_dst->src;
  9934. flags |= UFBX_PROP_FLAG_ANIMATED;
  9935. }
  9936. }
  9937. uint32_t key = ufbxi_get_name_key(name.data, name.length);
  9938. while (prop != prop_end && ufbxi_name_key_less(prop, name.data, name.length, key)) prop++;
  9939. if (prop != prop_end && prop->name.data == name.data) {
  9940. prop->flags = (ufbx_prop_flags)((uint32_t)prop->flags | flags);
  9941. } else {
  9942. // Animated property that is not in the element property list
  9943. // Copy the preceeding properties to the stack, then push a
  9944. // synthetic property for the animated property.
  9945. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_prop, ufbxi_to_size(prop - copy_start), copy_start));
  9946. copy_start = prop;
  9947. needs_copy = true;
  9948. // Let's hope we can find the property in the defaults at least
  9949. ufbx_prop anim_def_prop;
  9950. ufbx_prop *def_prop = NULL;
  9951. if (elem->props.defaults) {
  9952. def_prop = ufbxi_find_prop_with_key(elem->props.defaults, name.data, key);
  9953. } else if (anim_value) {
  9954. memset(&anim_def_prop, 0, sizeof(anim_def_prop));
  9955. // Hack a couple of common types
  9956. ufbx_prop_type type = UFBX_PROP_UNKNOWN;
  9957. if (name.data == ufbxi_Lcl_Translation) type = UFBX_PROP_TRANSLATION;
  9958. else if (name.data == ufbxi_Lcl_Rotation) type = UFBX_PROP_ROTATION;
  9959. else if (name.data == ufbxi_Lcl_Scaling) type = UFBX_PROP_SCALING;
  9960. anim_def_prop.type = type;
  9961. anim_def_prop.value_vec3 = anim_value->default_value;
  9962. anim_def_prop.value_int = ufbxi_f64_to_i64(anim_value->default_value.x);
  9963. anim_def_prop.value_real_arr[3] = 0.0f;
  9964. def_prop = &anim_def_prop;
  9965. } else {
  9966. flags |= UFBX_PROP_FLAG_NO_VALUE;
  9967. }
  9968. ufbx_prop *new_prop = ufbxi_push_zero(&uc->tmp_stack, ufbx_prop, 1);
  9969. ufbxi_check(new_prop);
  9970. if (def_prop) *new_prop = *def_prop;
  9971. flags |= (uint32_t)new_prop->flags;
  9972. new_prop->flags = (ufbx_prop_flags)(UFBX_PROP_FLAG_ANIMATABLE | UFBX_PROP_FLAG_SYNTHETIC | flags);
  9973. new_prop->name = name;
  9974. new_prop->_internal_key = key;
  9975. new_prop->value_str = ufbx_empty_string;
  9976. new_prop->value_blob = ufbx_empty_blob;
  9977. num_synthetic++;
  9978. }
  9979. }
  9980. // Copy the properties if necessary
  9981. if (needs_copy) {
  9982. size_t num_new_props = elem->props.props.count + num_synthetic;
  9983. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_prop, ufbxi_to_size(prop_end - copy_start), copy_start));
  9984. elem->props.props.data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_prop, num_new_props);
  9985. ufbxi_check(elem->props.props.data);
  9986. elem->props.props.count = num_new_props;
  9987. }
  9988. elem->props.num_animated = num_animated;
  9989. }
  9990. conn_src = src_end;
  9991. conn_dst = dst_end;
  9992. }
  9993. return 1;
  9994. }
  9995. ufbxi_nodiscard ufbxi_noinline static int ufbxi_linearize_nodes(ufbxi_context *uc)
  9996. {
  9997. size_t num_nodes = uc->tmp_node_ids.num_items;
  9998. uint32_t *node_ids = ufbxi_push_pop(&uc->tmp, &uc->tmp_node_ids, uint32_t, num_nodes);
  9999. ufbxi_buf_free(&uc->tmp_node_ids);
  10000. ufbxi_check(node_ids);
  10001. ufbx_node **node_ptrs = ufbxi_push(&uc->tmp_stack, ufbx_node*, num_nodes);
  10002. ufbxi_check(node_ptrs);
  10003. // Fetch the node pointers
  10004. for (size_t i = 0; i < num_nodes; i++) {
  10005. node_ptrs[i] = (ufbx_node*)uc->scene.elements.data[node_ids[i]];
  10006. ufbx_assert(node_ptrs[i]->element.type == UFBX_ELEMENT_NODE);
  10007. }
  10008. uc->scene.root_node = node_ptrs[0];
  10009. size_t *node_offsets = ufbxi_push_pop(&uc->tmp_stack, &uc->tmp_typed_element_offsets[UFBX_ELEMENT_NODE], size_t, num_nodes);
  10010. ufbxi_check(node_offsets);
  10011. // Hook up the parent nodes, we'll assume that there's no cycles at this point
  10012. ufbxi_for_ptr(ufbx_node, p_node, node_ptrs, num_nodes) {
  10013. ufbx_node *node = *p_node;
  10014. // Pre-6000 files don't have any explicit root connections so they must always
  10015. // be connected to ther root..
  10016. if (node->parent == NULL && !(uc->opts.allow_nodes_out_of_root && uc->version >= 6000)) {
  10017. if (node != uc->scene.root_node) {
  10018. node->parent = uc->scene.root_node;
  10019. }
  10020. }
  10021. ufbxi_for_list(ufbx_connection, conn, node->element.connections_dst) {
  10022. if (conn->src_prop.length > 0 || conn->dst_prop.length > 0) continue;
  10023. if (conn->src->type != UFBX_ELEMENT_NODE) continue;
  10024. ((ufbx_node*)conn->src)->parent = node;
  10025. }
  10026. }
  10027. // Count the parent depths and child amounts
  10028. ufbxi_for_ptr(ufbx_node, p_node, node_ptrs, num_nodes) {
  10029. ufbx_node *node = *p_node;
  10030. uint32_t depth = 0;
  10031. for (ufbx_node *p = node->parent; p; p = p->parent) {
  10032. depth += p->node_depth + 1;
  10033. if (p->node_depth > 0) break;
  10034. ufbxi_check_msg(depth <= num_nodes, "Cyclic node hierarchy");
  10035. }
  10036. node->node_depth = depth;
  10037. // Second pass to cache the depths to avoid O(n^2)
  10038. for (ufbx_node *p = node->parent; p; p = p->parent) {
  10039. if (--depth <= p->node_depth) break;
  10040. p->node_depth = depth;
  10041. }
  10042. }
  10043. ufbxi_check(ufbxi_sort_node_ptrs(uc, node_ptrs, num_nodes));
  10044. for (uint32_t i = 0; i < num_nodes; i++) {
  10045. size_t *p_offset = ufbxi_push(&uc->tmp_typed_element_offsets[UFBX_ELEMENT_NODE], size_t, 1);
  10046. ufbxi_check(p_offset);
  10047. ufbx_node *node = node_ptrs[i];
  10048. uint32_t original_id = node->element.typed_id;
  10049. node->element.typed_id = i;
  10050. *p_offset = node_offsets[original_id];
  10051. }
  10052. // Pop the temporary arrays
  10053. ufbxi_pop(&uc->tmp_stack, size_t, num_nodes, NULL);
  10054. ufbxi_pop(&uc->tmp_stack, ufbx_node*, num_nodes, NULL);
  10055. return 1;
  10056. }
  10057. ufbxi_nodiscard ufbxi_noinline static ufbx_connection_list ufbxi_find_dst_connections(ufbx_element *element, const char *prop)
  10058. {
  10059. if (!prop) prop = ufbxi_empty_char;
  10060. size_t begin = element->connections_dst.count, end = begin;
  10061. ufbxi_macro_lower_bound_eq(ufbx_connection, 32, &begin,
  10062. element->connections_dst.data, 0, element->connections_dst.count,
  10063. (strcmp(a->dst_prop.data, prop) < 0),
  10064. (a->dst_prop.data == prop && a->src_prop.length == 0));
  10065. ufbxi_macro_upper_bound_eq(ufbx_connection, 32, &end,
  10066. element->connections_dst.data, begin, element->connections_dst.count,
  10067. (a->dst_prop.data == prop && a->src_prop.length == 0));
  10068. ufbx_connection_list result = { element->connections_dst.data + begin, end - begin };
  10069. return result;
  10070. }
  10071. ufbxi_nodiscard ufbxi_noinline static ufbx_connection_list ufbxi_find_src_connections(ufbx_element *element, const char *prop)
  10072. {
  10073. if (!prop) prop = ufbxi_empty_char;
  10074. size_t begin = element->connections_src.count, end = begin;
  10075. ufbxi_macro_lower_bound_eq(ufbx_connection, 32, &begin,
  10076. element->connections_src.data, 0, element->connections_src.count,
  10077. (strcmp(a->src_prop.data, prop) < 0),
  10078. (a->src_prop.data == prop && a->dst_prop.length == 0));
  10079. ufbxi_macro_upper_bound_eq(ufbx_connection, 32, &end,
  10080. element->connections_src.data, begin, element->connections_src.count,
  10081. (a->src_prop.data == prop && a->dst_prop.length == 0));
  10082. ufbx_connection_list result = { element->connections_src.data + begin, end - begin };
  10083. return result;
  10084. }
  10085. ufbxi_nodiscard static ufbx_element *ufbxi_get_element_node(ufbx_element *element)
  10086. {
  10087. return element && element->instances.count > 0 ? &element->instances.data[0]->element : NULL;
  10088. }
  10089. ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_dst_elements(ufbxi_context *uc, void *p_dst_list, ufbx_element *element, bool search_node, const char *prop, ufbx_element_type src_type)
  10090. {
  10091. size_t num_elements = 0;
  10092. do {
  10093. ufbx_connection_list conns = ufbxi_find_dst_connections(element, prop);
  10094. ufbxi_for_list(ufbx_connection, conn, conns) {
  10095. if (conn->src->type == src_type) {
  10096. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_element*, 1, &conn->src));
  10097. num_elements++;
  10098. }
  10099. }
  10100. } while (search_node && (element = ufbxi_get_element_node(element)) != NULL);
  10101. ufbx_element_list *list = (ufbx_element_list*)p_dst_list;
  10102. list->data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_element*, num_elements);
  10103. list->count = num_elements;
  10104. ufbxi_check(list->data);
  10105. return 1;
  10106. }
  10107. ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_src_elements(ufbxi_context *uc, void *p_dst_list, ufbx_element *element, bool search_node, const char *prop, ufbx_element_type dst_type)
  10108. {
  10109. size_t num_elements = 0;
  10110. do {
  10111. ufbx_connection_list conns = ufbxi_find_src_connections(element, prop);
  10112. ufbxi_for_list(ufbx_connection, conn, conns) {
  10113. if (conn->dst->type == dst_type) {
  10114. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_element*, 1, &conn->dst));
  10115. num_elements++;
  10116. }
  10117. }
  10118. } while (search_node && (element = ufbxi_get_element_node(element)) != NULL);
  10119. ufbx_element_list *list = (ufbx_element_list*)p_dst_list;
  10120. list->data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_element*, num_elements);
  10121. list->count = num_elements;
  10122. ufbxi_check(list->data);
  10123. return 1;
  10124. }
  10125. ufbxi_nodiscard ufbxi_noinline static ufbx_element *ufbxi_fetch_dst_element(ufbx_element *element, bool search_node, const char *prop, ufbx_element_type src_type)
  10126. {
  10127. do {
  10128. ufbx_connection_list conns = ufbxi_find_dst_connections(element, prop);
  10129. ufbxi_for_list(ufbx_connection, conn, conns) {
  10130. if (conn->src->type == src_type) {
  10131. return conn->src;
  10132. }
  10133. }
  10134. } while (search_node && (element = ufbxi_get_element_node(element)) != NULL);
  10135. return NULL;
  10136. }
  10137. ufbxi_nodiscard ufbxi_noinline static ufbx_element *ufbxi_fetch_src_element(ufbx_element *element, bool search_node, const char *prop, ufbx_element_type dst_type)
  10138. {
  10139. do {
  10140. ufbx_connection_list conns = ufbxi_find_src_connections(element, prop);
  10141. ufbxi_for_list(ufbx_connection, conn, conns) {
  10142. if (conn->dst->type == dst_type) {
  10143. return conn->dst;
  10144. }
  10145. }
  10146. } while (search_node && (element = ufbxi_get_element_node(element)) != NULL);
  10147. return NULL;
  10148. }
  10149. ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_textures(ufbxi_context *uc, ufbx_material_texture_list *list, ufbx_element *element, bool search_node)
  10150. {
  10151. size_t num_textures = 0;
  10152. do {
  10153. ufbxi_for_list(ufbx_connection, conn, element->connections_dst) {
  10154. if (conn->src_prop.length > 0) continue;
  10155. if (conn->src->type == UFBX_ELEMENT_TEXTURE) {
  10156. ufbx_material_texture *tex = ufbxi_push(&uc->tmp_stack, ufbx_material_texture, 1);
  10157. ufbxi_check(tex);
  10158. tex->shader_prop = tex->material_prop = conn->dst_prop;
  10159. tex->texture = (ufbx_texture*)conn->src;
  10160. num_textures++;
  10161. }
  10162. }
  10163. } while (search_node && (element = ufbxi_get_element_node(element)) != NULL);
  10164. list->data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_material_texture, num_textures);
  10165. list->count = num_textures;
  10166. ufbxi_check(list->data);
  10167. return 1;
  10168. }
  10169. ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_mesh_materials(ufbxi_context *uc, ufbx_mesh_material_list *list, ufbx_element *element, bool search_node)
  10170. {
  10171. size_t num_materials = 0;
  10172. do {
  10173. ufbx_connection_list conns = ufbxi_find_dst_connections(element, NULL);
  10174. ufbxi_for_list(ufbx_connection, conn, conns) {
  10175. if (conn->src->type == UFBX_ELEMENT_MATERIAL) {
  10176. ufbx_mesh_material mesh_mat = { (ufbx_material*)conn->src };
  10177. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_mesh_material, 1, &mesh_mat));
  10178. num_materials++;
  10179. }
  10180. }
  10181. if (num_materials > 0) break;
  10182. } while (search_node && (element = ufbxi_get_element_node(element)) != NULL);
  10183. list->data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_mesh_material, num_materials);
  10184. list->count = num_materials;
  10185. ufbxi_check(list->data);
  10186. return 1;
  10187. }
  10188. ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_deformers(ufbxi_context *uc, ufbx_element_list *list, ufbx_element *element, bool search_node)
  10189. {
  10190. size_t num_deformers = 0;
  10191. do {
  10192. ufbxi_for_list(ufbx_connection, conn, element->connections_dst) {
  10193. if (conn->src_prop.length > 0) continue;
  10194. ufbx_element_type type = conn->src->type;
  10195. if (type == UFBX_ELEMENT_SKIN_DEFORMER || type == UFBX_ELEMENT_BLEND_DEFORMER || type == UFBX_ELEMENT_CACHE_DEFORMER) {
  10196. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_element*, 1, &conn->src));
  10197. num_deformers++;
  10198. }
  10199. }
  10200. } while (search_node && (element = ufbxi_get_element_node(element)) != NULL);
  10201. list->data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_element*, num_deformers);
  10202. list->count = num_deformers;
  10203. ufbxi_check(list->data);
  10204. return 1;
  10205. }
  10206. ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_blend_keyframes(ufbxi_context *uc, ufbx_blend_keyframe_list *list, ufbx_element *element)
  10207. {
  10208. size_t num_keyframes = 0;
  10209. ufbx_connection_list conns = ufbxi_find_dst_connections(element, NULL);
  10210. ufbxi_for_list(ufbx_connection, conn, conns) {
  10211. if (conn->src->type == UFBX_ELEMENT_BLEND_SHAPE) {
  10212. ufbx_blend_keyframe key = { (ufbx_blend_shape*)conn->src };
  10213. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_blend_keyframe, 1, &key));
  10214. num_keyframes++;
  10215. }
  10216. }
  10217. list->data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_blend_keyframe, num_keyframes);
  10218. list->count = num_keyframes;
  10219. ufbxi_check(list->data);
  10220. return 1;
  10221. }
  10222. ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_texture_layers(ufbxi_context *uc, ufbx_texture_layer_list *list, ufbx_element *element)
  10223. {
  10224. size_t num_layers = 0;
  10225. ufbx_connection_list conns = ufbxi_find_dst_connections(element, NULL);
  10226. ufbxi_for_list(ufbx_connection, conn, conns) {
  10227. if (conn->src->type == UFBX_ELEMENT_TEXTURE) {
  10228. ufbx_texture *texture = (ufbx_texture*)conn->src;
  10229. ufbx_texture_layer layer = { texture };
  10230. layer.alpha = ufbxi_find_real(&texture->props, ufbxi_Texture_alpha, 1.0f);
  10231. layer.blend_mode = (ufbx_blend_mode)ufbxi_find_enum(&texture->props, ufbxi_BlendMode, UFBX_BLEND_REPLACE, UFBX_BLEND_OVERLAY);
  10232. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_texture_layer, 1, &layer));
  10233. num_layers++;
  10234. }
  10235. }
  10236. list->data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_texture_layer, num_layers);
  10237. list->count = num_layers;
  10238. ufbxi_check(list->data);
  10239. return 1;
  10240. }
  10241. static ufbxi_forceinline bool ufbxi_prop_connection_less(const ufbx_connection *a, const char *prop)
  10242. {
  10243. int cmp = strcmp(a->dst_prop.data, prop);
  10244. if (cmp != 0) return cmp < 0;
  10245. return a->src_prop.length == 0;
  10246. }
  10247. ufbxi_nodiscard ufbxi_noinline static ufbx_connection *ufbxi_find_prop_connection(const ufbx_element *element, const char *prop)
  10248. {
  10249. if (!prop) prop = ufbxi_empty_char;
  10250. size_t index = SIZE_MAX;
  10251. ufbxi_macro_lower_bound_eq(ufbx_connection, 32, &index,
  10252. element->connections_dst.data, 0, element->connections_dst.count,
  10253. (ufbxi_prop_connection_less(a, prop)),
  10254. (a->dst_prop.data == prop && a->src_prop.length > 0));
  10255. return index < SIZE_MAX ? &element->connections_dst.data[index] : NULL;
  10256. }
  10257. ufbxi_forceinline static void ufbxi_patch_index_pointer(ufbxi_context *uc, uint32_t **p_index)
  10258. {
  10259. if (*p_index == ufbxi_sentinel_index_zero) {
  10260. *p_index = uc->zero_indices;
  10261. } else if (*p_index == ufbxi_sentinel_index_consecutive) {
  10262. *p_index = uc->consecutive_indices;
  10263. }
  10264. }
  10265. ufbxi_nodiscard static bool ufbxi_cmp_anim_prop_less(const ufbx_anim_prop *a, const ufbx_anim_prop *b)
  10266. {
  10267. if (a->element != b->element) return a->element < b->element;
  10268. if (a->_internal_key != b->_internal_key) return a->_internal_key < b->_internal_key;
  10269. return ufbxi_str_less(a->prop_name, b->prop_name);
  10270. }
  10271. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_anim_props(ufbxi_context *uc, ufbx_anim_prop *aprops, size_t count)
  10272. {
  10273. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_anim_prop)));
  10274. ufbxi_macro_stable_sort(ufbx_anim_prop, 32, aprops, uc->tmp_arr, count, ( ufbxi_cmp_anim_prop_less(a, b) ));
  10275. return 1;
  10276. }
  10277. ufbxi_noinline static bool ufbxi_material_texture_less(void *user, const void *va, const void *vb)
  10278. {
  10279. (void)user;
  10280. const ufbx_material_texture *a = (const ufbx_material_texture*)va, *b = (const ufbx_material_texture*)vb;
  10281. return ufbxi_str_less(a->material_prop, b->material_prop);
  10282. }
  10283. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_material_textures(ufbxi_context *uc, ufbx_material_texture *textures, size_t count)
  10284. {
  10285. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_material_texture)));
  10286. ufbxi_stable_sort(sizeof(ufbx_material_texture), 32, textures, uc->tmp_arr, count, &ufbxi_material_texture_less, NULL);
  10287. return 1;
  10288. }
  10289. ufbxi_noinline static bool ufbxi_video_ptr_less(void *user, const void *va, const void *vb)
  10290. {
  10291. (void)user;
  10292. const ufbx_video *a = *(const ufbx_video**)va, *b = *(const ufbx_video**)vb;
  10293. return ufbxi_str_less(a->absolute_filename, b->absolute_filename);
  10294. }
  10295. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_videos_by_filename(ufbxi_context *uc, ufbx_video **videos, size_t count)
  10296. {
  10297. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_video*)));
  10298. ufbxi_stable_sort(sizeof(ufbx_video*), 32, videos, uc->tmp_arr, count, &ufbxi_video_ptr_less, NULL);
  10299. return 1;
  10300. }
  10301. ufbxi_nodiscard ufbxi_noinline static ufbx_anim_prop *ufbxi_find_anim_prop_start(ufbx_anim_layer *layer, const ufbx_element *element)
  10302. {
  10303. size_t index = SIZE_MAX;
  10304. ufbxi_macro_lower_bound_eq(ufbx_anim_prop, 16, &index, layer->anim_props.data, 0, layer->anim_props.count,
  10305. (a->element < element), (a->element == element));
  10306. return index != SIZE_MAX ? &layer->anim_props.data[index] : NULL;
  10307. }
  10308. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_skin_weights(ufbxi_context *uc, ufbx_skin_deformer *skin)
  10309. {
  10310. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, skin->max_weights_per_vertex * sizeof(ufbx_skin_weight)));
  10311. for (size_t i = 0; i < skin->vertices.count; i++) {
  10312. ufbx_skin_vertex v = skin->vertices.data[i];
  10313. ufbxi_macro_stable_sort(ufbx_skin_weight, 32, skin->weights.data + v.weight_begin, uc->tmp_arr, v.num_weights,
  10314. ( a->weight > b->weight ));
  10315. }
  10316. return 1;
  10317. }
  10318. ufbxi_noinline static bool ufbxi_blend_keyframe_less(void *user, const void *va, const void *vb)
  10319. {
  10320. (void)user;
  10321. const ufbx_blend_keyframe *a = (const ufbx_blend_keyframe*)va, *b = (const ufbx_blend_keyframe*)vb;
  10322. return a->target_weight < b->target_weight;
  10323. }
  10324. ufbxi_nodiscard ufbxi_noinline static int ufbxi_sort_blend_keyframes(ufbxi_context *uc, ufbx_blend_keyframe *keyframes, size_t count)
  10325. {
  10326. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbx_blend_keyframe)));
  10327. ufbxi_stable_sort(sizeof(ufbx_blend_keyframe), 32, keyframes, uc->tmp_arr, count, &ufbxi_blend_keyframe_less, NULL);
  10328. return 1;
  10329. }
  10330. ufbxi_noinline static bool ufbxi_matrix_all_zero(const ufbx_matrix *matrix)
  10331. {
  10332. for (size_t i = 0; i < 12; i++) {
  10333. if (matrix->v[i] != 0.0f) return false;
  10334. }
  10335. return true;
  10336. }
  10337. static ufbxi_forceinline bool ufbxi_is_vec3_zero(ufbx_vec3 v)
  10338. {
  10339. return (v.x == 0.0) & (v.y == 0.0) & (v.z == 0.0);
  10340. }
  10341. static ufbxi_forceinline bool ufbxi_is_vec4_zero(ufbx_vec4 v)
  10342. {
  10343. return (v.x == 0.0) & (v.y == 0.0) & (v.z == 0.0);
  10344. }
  10345. static ufbxi_forceinline bool ufbxi_is_vec3_one(ufbx_vec3 v)
  10346. {
  10347. return (v.x == 1.0) & (v.y == 1.0) & (v.z == 1.0);
  10348. }
  10349. static ufbxi_forceinline bool ufbxi_is_quat_identity(ufbx_quat v)
  10350. {
  10351. return (v.x == 0.0) & (v.y == 0.0) & (v.z == 0.0) & (v.w == 1.0);
  10352. }
  10353. static ufbxi_forceinline bool ufbxi_is_transform_identity(ufbx_transform t)
  10354. {
  10355. return (bool)((int)ufbxi_is_vec3_zero(t.translation) & (int)ufbxi_is_quat_identity(t.rotation) & (int)ufbxi_is_vec3_one(t.scale));
  10356. }
  10357. // Material tables
  10358. typedef void (*ufbxi_mat_transform_fn)(ufbx_vec4 *a);
  10359. static void ufbxi_mat_transform_unknown_shininess(ufbx_vec4 *v) { if (v->x >= 0.0f) v->x = (ufbx_real)(1.0f - ufbx_sqrt(v->x) * (ufbx_real)0.1); if (!(v->x >= 0.0f)) v->x = 0.0f; }
  10360. static void ufbxi_mat_transform_blender_opacity(ufbx_vec4 *v) { v->x = 1.0f - v->x; }
  10361. static void ufbxi_mat_transform_blender_shininess(ufbx_vec4 *v) { if (v->x >= 0.0f) v->x = (ufbx_real)(1.0f - ufbx_sqrt(v->x) * (ufbx_real)0.1); if (!(v->x >= 0.0f)) v->x = 0.0f; }
  10362. static void ufbxi_mat_transform_max_pbr_use_glossiness(ufbx_vec4 *v) { v->x = v->x >= 0.5f && v->x <= 1.5f ? 1.0f : 0.0f; }
  10363. typedef enum {
  10364. UFBXI_MAT_TRANSFORM_IDENTITY,
  10365. UFBXI_MAT_TRANSFORM_UNKNOWN_SHININESS,
  10366. UFBXI_MAT_TRANSFORM_BLENDER_OPACITY,
  10367. UFBXI_MAT_TRANSFORM_BLENDER_SHININESS,
  10368. UFBXI_MAT_TRANSFORM_MAX_PBR_USE_GLOSSINESS,
  10369. UFBXI_MAT_TRANSFORM_COUNT,
  10370. } ufbxi_mat_transform;
  10371. typedef enum {
  10372. // Invert texture
  10373. UFBXI_SHADER_MAPPING_INVERT_TEXTURE = 0x1,
  10374. // Property toggles inversion of a value
  10375. // NOTE: These need to be the last entries in mappings
  10376. UFBXI_SHADER_MAPPING_TOGGLE_INVERT = 0x2,
  10377. } ufbxi_shader_mapping_flag;
  10378. typedef enum {
  10379. // Invert the feature flag
  10380. UFBXI_SHADER_FEATURE_INVERTED = 0x1,
  10381. } ufbxi_shader_feature_flag;
  10382. static const ufbxi_mat_transform_fn ufbxi_mat_transform_fns[] = {
  10383. NULL,
  10384. &ufbxi_mat_transform_unknown_shininess,
  10385. &ufbxi_mat_transform_blender_opacity,
  10386. &ufbxi_mat_transform_blender_shininess,
  10387. &ufbxi_mat_transform_max_pbr_use_glossiness,
  10388. };
  10389. typedef struct {
  10390. uint8_t index; // < `ufbx_material_(fbx|pbr)_map`
  10391. uint8_t flags; // < Combination of `ufbxi_shader_mapping_flag`
  10392. uint8_t transform; // < `ufbxi_mat_transform`
  10393. uint8_t prop_len; // < Length of `prop` not including NULL terminator
  10394. const char *prop; // < Name of FBX material property or shader mapping
  10395. } ufbxi_shader_mapping;
  10396. typedef struct {
  10397. const ufbxi_shader_mapping *data;
  10398. size_t count;
  10399. const ufbxi_shader_mapping *features;
  10400. size_t feature_count;
  10401. uint32_t default_features;
  10402. ufbx_string texture_prefix;
  10403. ufbx_string texture_suffix;
  10404. ufbx_string texture_enabled_prefix;
  10405. ufbx_string texture_enabled_suffix;
  10406. } ufbxi_shader_mapping_list;
  10407. ufbx_static_assert(transform_count, ufbxi_arraycount(ufbxi_mat_transform_fns) == UFBXI_MAT_TRANSFORM_COUNT);
  10408. #define ufbxi_mat_string(str) sizeof(str) - 1, str
  10409. static const ufbxi_shader_mapping ufbxi_base_fbx_mapping[] = {
  10410. { UFBX_MATERIAL_FBX_DIFFUSE_COLOR, 0, 0, ufbxi_mat_string("Diffuse") },
  10411. { UFBX_MATERIAL_FBX_DIFFUSE_COLOR, 0, 0, ufbxi_mat_string("DiffuseColor") },
  10412. { UFBX_MATERIAL_FBX_DIFFUSE_FACTOR, 0, 0, ufbxi_mat_string("DiffuseFactor") },
  10413. { UFBX_MATERIAL_FBX_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("Specular") },
  10414. { UFBX_MATERIAL_FBX_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("SpecularColor") },
  10415. { UFBX_MATERIAL_FBX_SPECULAR_FACTOR, 0, 0, ufbxi_mat_string("SpecularFactor") },
  10416. { UFBX_MATERIAL_FBX_SPECULAR_EXPONENT, 0, 0, ufbxi_mat_string("Shininess") },
  10417. { UFBX_MATERIAL_FBX_SPECULAR_EXPONENT, 0, 0, ufbxi_mat_string("ShininessExponent") },
  10418. { UFBX_MATERIAL_FBX_REFLECTION_COLOR, 0, 0, ufbxi_mat_string("Reflection") },
  10419. { UFBX_MATERIAL_FBX_REFLECTION_COLOR, 0, 0, ufbxi_mat_string("ReflectionColor") },
  10420. { UFBX_MATERIAL_FBX_REFLECTION_FACTOR, 0, 0, ufbxi_mat_string("ReflectionFactor") },
  10421. { UFBX_MATERIAL_FBX_TRANSPARENCY_COLOR, 0, 0, ufbxi_mat_string("Transparent") },
  10422. { UFBX_MATERIAL_FBX_TRANSPARENCY_COLOR, 0, 0, ufbxi_mat_string("TransparentColor") },
  10423. { UFBX_MATERIAL_FBX_TRANSPARENCY_FACTOR, 0, 0, ufbxi_mat_string("TransparentFactor") },
  10424. { UFBX_MATERIAL_FBX_TRANSPARENCY_FACTOR, 0, 0, ufbxi_mat_string("TransparencyFactor") },
  10425. { UFBX_MATERIAL_FBX_EMISSION_COLOR, 0, 0, ufbxi_mat_string("Emissive") },
  10426. { UFBX_MATERIAL_FBX_EMISSION_COLOR, 0, 0, ufbxi_mat_string("EmissiveColor") },
  10427. { UFBX_MATERIAL_FBX_EMISSION_FACTOR, 0, 0, ufbxi_mat_string("EmissiveFactor") },
  10428. { UFBX_MATERIAL_FBX_AMBIENT_COLOR, 0, 0, ufbxi_mat_string("Ambient") },
  10429. { UFBX_MATERIAL_FBX_AMBIENT_COLOR, 0, 0, ufbxi_mat_string("AmbientColor") },
  10430. { UFBX_MATERIAL_FBX_AMBIENT_FACTOR, 0, 0, ufbxi_mat_string("AmbientFactor") },
  10431. { UFBX_MATERIAL_FBX_NORMAL_MAP, 0, 0, ufbxi_mat_string("NormalMap") },
  10432. { UFBX_MATERIAL_FBX_BUMP, 0, 0, ufbxi_mat_string("Bump") },
  10433. { UFBX_MATERIAL_FBX_BUMP_FACTOR, 0, 0, ufbxi_mat_string("BumpFactor") },
  10434. { UFBX_MATERIAL_FBX_DISPLACEMENT, 0, 0, ufbxi_mat_string("Displacement") },
  10435. { UFBX_MATERIAL_FBX_DISPLACEMENT_FACTOR, 0, 0, ufbxi_mat_string("DisplacementFactor") },
  10436. { UFBX_MATERIAL_FBX_VECTOR_DISPLACEMENT, 0, 0, ufbxi_mat_string("VectorDisplacement") },
  10437. { UFBX_MATERIAL_FBX_VECTOR_DISPLACEMENT_FACTOR, 0, 0, ufbxi_mat_string("VectorDisplacementFactor") },
  10438. };
  10439. static const ufbxi_shader_mapping ufbxi_fbx_lambert_shader_pbr_mapping[] = {
  10440. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("Diffuse") },
  10441. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("DiffuseColor") },
  10442. { UFBX_MATERIAL_PBR_BASE_FACTOR, 0, 0, ufbxi_mat_string("DiffuseFactor") },
  10443. { UFBX_MATERIAL_PBR_TRANSMISSION_COLOR, 0, 0, ufbxi_mat_string("Transparent") },
  10444. { UFBX_MATERIAL_PBR_TRANSMISSION_COLOR, 0, 0, ufbxi_mat_string("TransparentColor") },
  10445. { UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, 0, 0, ufbxi_mat_string("TransparentFactor") },
  10446. { UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, 0, 0, ufbxi_mat_string("TransparencyFactor") },
  10447. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("Emissive") },
  10448. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("EmissiveColor") },
  10449. { UFBX_MATERIAL_PBR_EMISSION_FACTOR, 0, 0, ufbxi_mat_string("EmissiveFactor") },
  10450. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("NormalMap") },
  10451. };
  10452. static const ufbxi_shader_mapping ufbxi_fbx_phong_shader_pbr_mapping[] = {
  10453. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("Diffuse") },
  10454. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("DiffuseColor") },
  10455. { UFBX_MATERIAL_PBR_BASE_FACTOR, 0, 0, ufbxi_mat_string("DiffuseFactor") },
  10456. { UFBX_MATERIAL_PBR_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("Specular") },
  10457. { UFBX_MATERIAL_PBR_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("SpecularColor") },
  10458. { UFBX_MATERIAL_PBR_SPECULAR_FACTOR, 0, 0, ufbxi_mat_string("SpecularFactor") },
  10459. { UFBX_MATERIAL_PBR_ROUGHNESS, UFBXI_SHADER_MAPPING_INVERT_TEXTURE, UFBXI_MAT_TRANSFORM_UNKNOWN_SHININESS, ufbxi_mat_string("Shininess") },
  10460. { UFBX_MATERIAL_PBR_ROUGHNESS, UFBXI_SHADER_MAPPING_INVERT_TEXTURE, UFBXI_MAT_TRANSFORM_UNKNOWN_SHININESS, ufbxi_mat_string("ShininessExponent") },
  10461. { UFBX_MATERIAL_PBR_TRANSMISSION_COLOR, 0, 0, ufbxi_mat_string("Transparent") },
  10462. { UFBX_MATERIAL_PBR_TRANSMISSION_COLOR, 0, 0, ufbxi_mat_string("TransparentColor") },
  10463. { UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, 0, 0, ufbxi_mat_string("TransparentFactor") },
  10464. { UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, 0, 0, ufbxi_mat_string("TransparencyFactor") },
  10465. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("Emissive") },
  10466. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("EmissiveColor") },
  10467. { UFBX_MATERIAL_PBR_EMISSION_FACTOR, 0, 0, ufbxi_mat_string("EmissiveFactor") },
  10468. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("NormalMap") },
  10469. };
  10470. static const ufbxi_shader_mapping ufbxi_osl_standard_shader_pbr_mapping[] = {
  10471. { UFBX_MATERIAL_PBR_BASE_FACTOR, 0, 0, ufbxi_mat_string("base") },
  10472. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("base_color") },
  10473. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, 0, ufbxi_mat_string("specular_roughness") },
  10474. { UFBX_MATERIAL_PBR_DIFFUSE_ROUGHNESS, 0, 0, ufbxi_mat_string("diffuse_roughness") },
  10475. { UFBX_MATERIAL_PBR_METALNESS, 0, 0, ufbxi_mat_string("metalness") },
  10476. { UFBX_MATERIAL_PBR_SPECULAR_FACTOR, 0, 0, ufbxi_mat_string("specular") },
  10477. { UFBX_MATERIAL_PBR_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("specular_color") },
  10478. { UFBX_MATERIAL_PBR_SPECULAR_IOR, 0, 0, ufbxi_mat_string("specular_IOR") },
  10479. { UFBX_MATERIAL_PBR_SPECULAR_ANISOTROPY, 0, 0, ufbxi_mat_string("specular_anisotropy") },
  10480. { UFBX_MATERIAL_PBR_SPECULAR_ROTATION, 0, 0, ufbxi_mat_string("specular_rotation") },
  10481. { UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, 0, 0, ufbxi_mat_string("transmission") },
  10482. { UFBX_MATERIAL_PBR_TRANSMISSION_COLOR, 0, 0, ufbxi_mat_string("transmission_color") },
  10483. { UFBX_MATERIAL_PBR_TRANSMISSION_DEPTH, 0, 0, ufbxi_mat_string("transmission_depth") },
  10484. { UFBX_MATERIAL_PBR_TRANSMISSION_SCATTER, 0, 0, ufbxi_mat_string("transmission_scatter") },
  10485. { UFBX_MATERIAL_PBR_TRANSMISSION_SCATTER_ANISOTROPY, 0, 0, ufbxi_mat_string("transmission_scatter_anisotropy") },
  10486. { UFBX_MATERIAL_PBR_TRANSMISSION_DISPERSION, 0, 0, ufbxi_mat_string("transmission_dispersion") },
  10487. { UFBX_MATERIAL_PBR_TRANSMISSION_EXTRA_ROUGHNESS, 0, 0, ufbxi_mat_string("transmission_extra_roughness") },
  10488. { UFBX_MATERIAL_PBR_SUBSURFACE_FACTOR, 0, 0, ufbxi_mat_string("subsurface") },
  10489. { UFBX_MATERIAL_PBR_SUBSURFACE_COLOR, 0, 0, ufbxi_mat_string("subsurface_color") },
  10490. { UFBX_MATERIAL_PBR_SUBSURFACE_RADIUS, 0, 0, ufbxi_mat_string("subsurface_radius") },
  10491. { UFBX_MATERIAL_PBR_SUBSURFACE_SCALE, 0, 0, ufbxi_mat_string("subsurface_scale") },
  10492. { UFBX_MATERIAL_PBR_SUBSURFACE_ANISOTROPY, 0, 0, ufbxi_mat_string("subsurface_anisotropy") },
  10493. { UFBX_MATERIAL_PBR_SHEEN_FACTOR, 0, 0, ufbxi_mat_string("sheen") },
  10494. { UFBX_MATERIAL_PBR_SHEEN_COLOR, 0, 0, ufbxi_mat_string("sheen_color") },
  10495. { UFBX_MATERIAL_PBR_SHEEN_ROUGHNESS, 0, 0, ufbxi_mat_string("sheen_roughness") },
  10496. { UFBX_MATERIAL_PBR_COAT_FACTOR, 0, 0, ufbxi_mat_string("coat") },
  10497. { UFBX_MATERIAL_PBR_COAT_COLOR, 0, 0, ufbxi_mat_string("coat_color") },
  10498. { UFBX_MATERIAL_PBR_COAT_ROUGHNESS, 0, 0, ufbxi_mat_string("coat_roughness") },
  10499. { UFBX_MATERIAL_PBR_COAT_IOR, 0, 0, ufbxi_mat_string("coat_IOR") },
  10500. { UFBX_MATERIAL_PBR_COAT_ANISOTROPY, 0, 0, ufbxi_mat_string("coat_anisotropy") },
  10501. { UFBX_MATERIAL_PBR_COAT_ROTATION, 0, 0, ufbxi_mat_string("coat_rotation") },
  10502. { UFBX_MATERIAL_PBR_COAT_NORMAL, 0, 0, ufbxi_mat_string("coat_normal") },
  10503. { UFBX_MATERIAL_PBR_THIN_FILM_THICKNESS, 0, 0, ufbxi_mat_string("thin_film_thickness") },
  10504. { UFBX_MATERIAL_PBR_THIN_FILM_IOR, 0, 0, ufbxi_mat_string("thin_film_IOR") },
  10505. { UFBX_MATERIAL_PBR_EMISSION_FACTOR, 0, 0, ufbxi_mat_string("emission") },
  10506. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("emission_color") },
  10507. { UFBX_MATERIAL_PBR_OPACITY, 0, 0, ufbxi_mat_string("opacity") },
  10508. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("NormalMap") },
  10509. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("normalCamera") },
  10510. { UFBX_MATERIAL_PBR_TANGENT_MAP, 0, 0, ufbxi_mat_string("tangent") },
  10511. };
  10512. static const ufbxi_shader_mapping ufbxi_osl_standard_shader_features[] = {
  10513. { UFBX_MATERIAL_FEATURE_THIN_WALLED, 0, 0, ufbxi_mat_string("thin_walled") },
  10514. };
  10515. static const ufbxi_shader_mapping ufbxi_arnold_shader_pbr_mapping[] = {
  10516. { UFBX_MATERIAL_PBR_BASE_FACTOR, 0, 0, ufbxi_mat_string("base") },
  10517. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("baseColor") },
  10518. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, 0, ufbxi_mat_string("specularRoughness") },
  10519. { UFBX_MATERIAL_PBR_DIFFUSE_ROUGHNESS, 0, 0, ufbxi_mat_string("diffuseRoughness") },
  10520. { UFBX_MATERIAL_PBR_METALNESS, 0, 0, ufbxi_mat_string("metalness") },
  10521. { UFBX_MATERIAL_PBR_SPECULAR_FACTOR, 0, 0, ufbxi_mat_string("specular") },
  10522. { UFBX_MATERIAL_PBR_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("specularColor") },
  10523. { UFBX_MATERIAL_PBR_SPECULAR_IOR, 0, 0, ufbxi_mat_string("specularIOR") },
  10524. { UFBX_MATERIAL_PBR_SPECULAR_ANISOTROPY, 0, 0, ufbxi_mat_string("specularAnisotropy") },
  10525. { UFBX_MATERIAL_PBR_SPECULAR_ROTATION, 0, 0, ufbxi_mat_string("specularRotation") },
  10526. { UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, 0, 0, ufbxi_mat_string("transmission") },
  10527. { UFBX_MATERIAL_PBR_TRANSMISSION_COLOR, 0, 0, ufbxi_mat_string("transmissionColor") },
  10528. { UFBX_MATERIAL_PBR_TRANSMISSION_DEPTH, 0, 0, ufbxi_mat_string("transmissionDepth") },
  10529. { UFBX_MATERIAL_PBR_TRANSMISSION_SCATTER, 0, 0, ufbxi_mat_string("transmissionScatter") },
  10530. { UFBX_MATERIAL_PBR_TRANSMISSION_SCATTER_ANISOTROPY, 0, 0, ufbxi_mat_string("transmissionScatterAnisotropy") },
  10531. { UFBX_MATERIAL_PBR_TRANSMISSION_DISPERSION, 0, 0, ufbxi_mat_string("transmissionDispersion") },
  10532. { UFBX_MATERIAL_PBR_TRANSMISSION_EXTRA_ROUGHNESS, 0, 0, ufbxi_mat_string("transmissionExtraRoughness") },
  10533. { UFBX_MATERIAL_PBR_SUBSURFACE_FACTOR, 0, 0, ufbxi_mat_string("subsurface") },
  10534. { UFBX_MATERIAL_PBR_SUBSURFACE_COLOR, 0, 0, ufbxi_mat_string("subsurfaceColor") },
  10535. { UFBX_MATERIAL_PBR_SUBSURFACE_RADIUS, 0, 0, ufbxi_mat_string("subsurfaceRadius") },
  10536. { UFBX_MATERIAL_PBR_SUBSURFACE_SCALE, 0, 0, ufbxi_mat_string("subsurfaceScale") },
  10537. { UFBX_MATERIAL_PBR_SUBSURFACE_ANISOTROPY, 0, 0, ufbxi_mat_string("subsurfaceAnisotropy") },
  10538. { UFBX_MATERIAL_PBR_SHEEN_FACTOR, 0, 0, ufbxi_mat_string("sheen") },
  10539. { UFBX_MATERIAL_PBR_SHEEN_COLOR, 0, 0, ufbxi_mat_string("sheenColor") },
  10540. { UFBX_MATERIAL_PBR_SHEEN_ROUGHNESS, 0, 0, ufbxi_mat_string("sheenRoughness") },
  10541. { UFBX_MATERIAL_PBR_COAT_FACTOR, 0, 0, ufbxi_mat_string("coat") },
  10542. { UFBX_MATERIAL_PBR_COAT_COLOR, 0, 0, ufbxi_mat_string("coatColor") },
  10543. { UFBX_MATERIAL_PBR_COAT_ROUGHNESS, 0, 0, ufbxi_mat_string("coatRoughness") },
  10544. { UFBX_MATERIAL_PBR_COAT_IOR, 0, 0, ufbxi_mat_string("coatIOR") },
  10545. { UFBX_MATERIAL_PBR_COAT_ANISOTROPY, 0, 0, ufbxi_mat_string("coatAnisotropy") },
  10546. { UFBX_MATERIAL_PBR_COAT_ROTATION, 0, 0, ufbxi_mat_string("coatRotation") },
  10547. { UFBX_MATERIAL_PBR_COAT_NORMAL, 0, 0, ufbxi_mat_string("coatNormal") },
  10548. { UFBX_MATERIAL_PBR_THIN_FILM_THICKNESS, 0, 0, ufbxi_mat_string("thinFilmThickness") },
  10549. { UFBX_MATERIAL_PBR_THIN_FILM_IOR, 0, 0, ufbxi_mat_string("thinFilmIOR") },
  10550. { UFBX_MATERIAL_PBR_EMISSION_FACTOR, 0, 0, ufbxi_mat_string("emission") },
  10551. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("emissionColor") },
  10552. { UFBX_MATERIAL_PBR_OPACITY, 0, 0, ufbxi_mat_string("opacity") },
  10553. { UFBX_MATERIAL_PBR_INDIRECT_DIFFUSE, 0, 0, ufbxi_mat_string("indirectDiffuse") },
  10554. { UFBX_MATERIAL_PBR_INDIRECT_SPECULAR, 0, 0, ufbxi_mat_string("indirectSpecular") },
  10555. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("NormalMap") },
  10556. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("normalCamera") },
  10557. { UFBX_MATERIAL_PBR_TANGENT_MAP, 0, 0, ufbxi_mat_string("tangent") },
  10558. { UFBX_MATERIAL_PBR_MATTE_COLOR, 0, 0, ufbxi_mat_string("aiMatteColor") },
  10559. { UFBX_MATERIAL_PBR_MATTE_FACTOR, 0, 0, ufbxi_mat_string("aiMatteColorA") },
  10560. { UFBX_MATERIAL_PBR_SUBSURFACE_TYPE, 0, 0, ufbxi_mat_string("subsurfaceType") },
  10561. { UFBX_MATERIAL_PBR_TRANSMISSION_PRIORITY, 0, 0, ufbxi_mat_string("dielectricPriority") },
  10562. { UFBX_MATERIAL_PBR_TRANSMISSION_ENABLE_IN_AOV, 0, 0, ufbxi_mat_string("transmitAovs") },
  10563. };
  10564. static const ufbxi_shader_mapping ufbxi_arnold_shader_features[] = {
  10565. { UFBX_MATERIAL_FEATURE_MATTE, 0, 0, ufbxi_mat_string("aiEnableMatte") },
  10566. { UFBX_MATERIAL_FEATURE_THIN_WALLED, 0, 0, ufbxi_mat_string("thinWalled") },
  10567. { UFBX_MATERIAL_FEATURE_CAUSTICS, 0, 0, ufbxi_mat_string("caustics") },
  10568. { UFBX_MATERIAL_FEATURE_INTERNAL_REFLECTIONS, 0, 0, ufbxi_mat_string("internalReflections") },
  10569. { UFBX_MATERIAL_FEATURE_EXIT_TO_BACKGROUND, 0, 0, ufbxi_mat_string("exitToBackground") },
  10570. };
  10571. static const ufbxi_shader_mapping ufbxi_3ds_max_physical_material_pbr_mapping[] = {
  10572. { UFBX_MATERIAL_PBR_BASE_FACTOR, 0, 0, ufbxi_mat_string("base_weight") },
  10573. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("base_color") },
  10574. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, 0, ufbxi_mat_string("roughness") },
  10575. { UFBX_MATERIAL_PBR_DIFFUSE_ROUGHNESS, 0, 0, ufbxi_mat_string("diff_rough") },
  10576. { UFBX_MATERIAL_PBR_DIFFUSE_ROUGHNESS, 0, 0, ufbxi_mat_string("diff_roughness") },
  10577. { UFBX_MATERIAL_PBR_METALNESS, 0, 0, ufbxi_mat_string("metalness") },
  10578. { UFBX_MATERIAL_PBR_SPECULAR_FACTOR, 0, 0, ufbxi_mat_string("reflectivity") },
  10579. { UFBX_MATERIAL_PBR_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("refl_color") },
  10580. { UFBX_MATERIAL_PBR_SPECULAR_ANISOTROPY, 0, 0, ufbxi_mat_string("anisotropy") },
  10581. { UFBX_MATERIAL_PBR_SPECULAR_ROTATION, 0, 0, ufbxi_mat_string("aniso_angle") },
  10582. { UFBX_MATERIAL_PBR_SPECULAR_ROTATION, 0, 0, ufbxi_mat_string("anisoangle") },
  10583. { UFBX_MATERIAL_PBR_SPECULAR_IOR, 0, 0, ufbxi_mat_string("trans_ior") }, // NOTE: Not a typo, IOR is same for transparency/specular
  10584. { UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, 0, 0, ufbxi_mat_string("transparency") },
  10585. { UFBX_MATERIAL_PBR_TRANSMISSION_COLOR, 0, 0, ufbxi_mat_string("trans_color") },
  10586. { UFBX_MATERIAL_PBR_TRANSMISSION_DEPTH, 0, 0, ufbxi_mat_string("trans_depth") },
  10587. { UFBX_MATERIAL_PBR_TRANSMISSION_ROUGHNESS, 0, 0, ufbxi_mat_string("trans_rough") },
  10588. { UFBX_MATERIAL_PBR_TRANSMISSION_ROUGHNESS, 0, 0, ufbxi_mat_string("trans_roughness") },
  10589. { UFBX_MATERIAL_PBR_SUBSURFACE_FACTOR, 0, 0, ufbxi_mat_string("scattering") },
  10590. { UFBX_MATERIAL_PBR_SUBSURFACE_TINT_COLOR, 0, 0, ufbxi_mat_string("sss_color") },
  10591. { UFBX_MATERIAL_PBR_SUBSURFACE_COLOR, 0, 0, ufbxi_mat_string("sss_scatter_color") },
  10592. { UFBX_MATERIAL_PBR_SUBSURFACE_RADIUS, 0, 0, ufbxi_mat_string("sss_depth") },
  10593. { UFBX_MATERIAL_PBR_SUBSURFACE_SCALE, 0, 0, ufbxi_mat_string("sss_scale") },
  10594. { UFBX_MATERIAL_PBR_COAT_FACTOR, 0, 0, ufbxi_mat_string("coat") },
  10595. { UFBX_MATERIAL_PBR_COAT_FACTOR, 0, 0, ufbxi_mat_string("coating") },
  10596. { UFBX_MATERIAL_PBR_COAT_COLOR, 0, 0, ufbxi_mat_string("coat_color") },
  10597. { UFBX_MATERIAL_PBR_COAT_ROUGHNESS, 0, 0, ufbxi_mat_string("coat_rough") },
  10598. { UFBX_MATERIAL_PBR_COAT_ROUGHNESS, 0, 0, ufbxi_mat_string("coat_roughness") },
  10599. { UFBX_MATERIAL_PBR_COAT_IOR, 0, 0, ufbxi_mat_string("coat_ior") },
  10600. { UFBX_MATERIAL_PBR_COAT_NORMAL, 0, 0, ufbxi_mat_string("coat_bump") },
  10601. { UFBX_MATERIAL_PBR_COAT_NORMAL, 0, 0, ufbxi_mat_string("clearcoat_bump_map_amt") },
  10602. { UFBX_MATERIAL_PBR_COAT_AFFECT_BASE_COLOR, 0, 0, ufbxi_mat_string("coat_affect_color") },
  10603. { UFBX_MATERIAL_PBR_COAT_AFFECT_BASE_ROUGHNESS, 0, 0, ufbxi_mat_string("coat_affect_roughness") },
  10604. { UFBX_MATERIAL_PBR_EMISSION_FACTOR, 0, 0, ufbxi_mat_string("emission") },
  10605. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("emit_color") },
  10606. { UFBX_MATERIAL_PBR_OPACITY, 0, 0, ufbxi_mat_string("cutout") },
  10607. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("bump") },
  10608. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("bump_map_amt") },
  10609. { UFBX_MATERIAL_PBR_DISPLACEMENT_MAP, 0, 0, ufbxi_mat_string("displacement") },
  10610. { UFBX_MATERIAL_PBR_DISPLACEMENT_MAP, 0, 0, ufbxi_mat_string("displacement_map_amt") },
  10611. { UFBX_MATERIAL_PBR_SUBSURFACE_TYPE, 0, 0, ufbxi_mat_string("subsurfaceType") },
  10612. { UFBX_MATERIAL_PBR_ROUGHNESS, UFBXI_SHADER_MAPPING_TOGGLE_INVERT, 0, ufbxi_mat_string("roughness_inv") },
  10613. { UFBX_MATERIAL_PBR_TRANSMISSION_ROUGHNESS, UFBXI_SHADER_MAPPING_TOGGLE_INVERT, 0, ufbxi_mat_string("trans_roughness_inv") },
  10614. { UFBX_MATERIAL_PBR_COAT_ROUGHNESS, UFBXI_SHADER_MAPPING_TOGGLE_INVERT, 0, ufbxi_mat_string("coat_roughness_inv") },
  10615. };
  10616. static const ufbxi_shader_mapping ufbxi_3ds_max_physical_material_features[] = {
  10617. { UFBX_MATERIAL_FEATURE_THIN_WALLED, 0, 0, ufbxi_mat_string("thin_walled") },
  10618. { UFBX_MATERIAL_FEATURE_SPECULAR, 0, 0, ufbxi_mat_string("material_mode") },
  10619. { UFBX_MATERIAL_FEATURE_DIFFUSE_ROUGHNESS, 0, 0, ufbxi_mat_string("material_mode") },
  10620. { UFBX_MATERIAL_FEATURE_TRANSMISSION_ROUGHNESS, UFBXI_SHADER_FEATURE_INVERTED, 0, ufbxi_mat_string("trans_roughness_lock") },
  10621. };
  10622. static const ufbxi_shader_mapping ufbxi_gltf_material_pbr_mapping[] = {
  10623. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("main|baseColor") },
  10624. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, 0, ufbxi_mat_string("main|roughness") },
  10625. { UFBX_MATERIAL_PBR_METALNESS, 0, 0, ufbxi_mat_string("main|metalness") },
  10626. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("main|normal") },
  10627. { UFBX_MATERIAL_PBR_AMBIENT_OCCLUSION, 0, 0, ufbxi_mat_string("main|ambientOcclusion") },
  10628. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("main|emission") },
  10629. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("main|emissionColor") },
  10630. { UFBX_MATERIAL_PBR_OPACITY, 0, 0, ufbxi_mat_string("main|Alpha") },
  10631. { UFBX_MATERIAL_PBR_COAT_FACTOR, 0, 0, ufbxi_mat_string("extension|clearcoat") },
  10632. { UFBX_MATERIAL_PBR_COAT_ROUGHNESS, 0, 0, ufbxi_mat_string("extension|clearcoatRoughness") },
  10633. { UFBX_MATERIAL_PBR_COAT_NORMAL, 0, 0, ufbxi_mat_string("extension|clearcoatNormal") },
  10634. { UFBX_MATERIAL_PBR_SHEEN_COLOR, 0, 0, ufbxi_mat_string("extension|sheenColor") },
  10635. { UFBX_MATERIAL_PBR_SHEEN_ROUGHNESS, 0, 0, ufbxi_mat_string("extension|sheenRoughness") },
  10636. { UFBX_MATERIAL_PBR_SPECULAR_FACTOR, 0, 0, ufbxi_mat_string("extension|specular") },
  10637. { UFBX_MATERIAL_PBR_SPECULAR_FACTOR, 0, 0, ufbxi_mat_string("extension|Specular") },
  10638. { UFBX_MATERIAL_PBR_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("extension|specularcolor") },
  10639. { UFBX_MATERIAL_PBR_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("extension|specularColor") },
  10640. { UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, 0, 0, ufbxi_mat_string("extension|transmission") },
  10641. { UFBX_MATERIAL_PBR_SPECULAR_IOR, 0, 0, ufbxi_mat_string("extension|indexOfRefraction") },
  10642. };
  10643. static const ufbxi_shader_mapping ufbxi_3ds_max_pbr_metal_rough_pbr_mapping[] = {
  10644. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("base_color") },
  10645. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("baseColor") },
  10646. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, 0, ufbxi_mat_string("roughness") },
  10647. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, 0, ufbxi_mat_string("Roughness_Map") },
  10648. { UFBX_MATERIAL_PBR_METALNESS, 0, 0, ufbxi_mat_string("metalness") },
  10649. { UFBX_MATERIAL_PBR_AMBIENT_OCCLUSION, 0, 0, ufbxi_mat_string("ao") },
  10650. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("norm") },
  10651. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("emit_color") },
  10652. { UFBX_MATERIAL_PBR_DISPLACEMENT_MAP, 0, 0, ufbxi_mat_string("displacement") },
  10653. { UFBX_MATERIAL_PBR_DISPLACEMENT_MAP, 0, 0, ufbxi_mat_string("displacement_amt") },
  10654. { UFBX_MATERIAL_PBR_OPACITY, 0, 0, ufbxi_mat_string("opacity") },
  10655. { UFBX_MATERIAL_PBR_ROUGHNESS, UFBXI_SHADER_MAPPING_TOGGLE_INVERT, UFBXI_MAT_TRANSFORM_MAX_PBR_USE_GLOSSINESS, ufbxi_mat_string("useGlossiness") },
  10656. };
  10657. static const ufbxi_shader_mapping ufbxi_3ds_max_pbr_spec_gloss_pbr_mapping[] = {
  10658. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("base_color") },
  10659. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("baseColor") },
  10660. { UFBX_MATERIAL_PBR_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("Specular") },
  10661. { UFBX_MATERIAL_PBR_SPECULAR_COLOR, 0, 0, ufbxi_mat_string("specular") },
  10662. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, 0, ufbxi_mat_string("glossiness") },
  10663. { UFBX_MATERIAL_PBR_AMBIENT_OCCLUSION, 0, 0, ufbxi_mat_string("ao") },
  10664. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("norm") },
  10665. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("emit_color") },
  10666. { UFBX_MATERIAL_PBR_DISPLACEMENT_MAP, 0, 0, ufbxi_mat_string("displacement") },
  10667. { UFBX_MATERIAL_PBR_DISPLACEMENT_MAP, 0, 0, ufbxi_mat_string("displacement_amt") },
  10668. { UFBX_MATERIAL_PBR_OPACITY, 0, 0, ufbxi_mat_string("opacity") },
  10669. { UFBX_MATERIAL_PBR_ROUGHNESS, UFBXI_SHADER_MAPPING_TOGGLE_INVERT, UFBXI_MAT_TRANSFORM_MAX_PBR_USE_GLOSSINESS, ufbxi_mat_string("useGlossiness") },
  10670. };
  10671. static const ufbxi_shader_mapping ufbxi_gltf_material_features[] = {
  10672. { UFBX_MATERIAL_FEATURE_DOUBLE_SIDED, 0, 0, ufbxi_mat_string("main|DoubleSided") },
  10673. { UFBX_MATERIAL_FEATURE_SHEEN, 0, 0, ufbxi_mat_string("extension|enableSheen") },
  10674. { UFBX_MATERIAL_FEATURE_COAT, 0, 0, ufbxi_mat_string("extension|enableClearCoat") },
  10675. { UFBX_MATERIAL_FEATURE_TRANSMISSION, 0, 0, ufbxi_mat_string("extension|enableTransmission") },
  10676. { UFBX_MATERIAL_FEATURE_IOR, 0, 0, ufbxi_mat_string("extension|enableIndexOfRefraction") },
  10677. { UFBX_MATERIAL_FEATURE_SPECULAR, 0, 0, ufbxi_mat_string("extension|enableSpecular") },
  10678. { UFBX_MATERIAL_FEATURE_UNLIT, 0, 0, ufbxi_mat_string("extension|unlit") },
  10679. };
  10680. // NOTE: These are just the names used by the standard PBS "preset".
  10681. // In _theory_ we could walk ShaderGraph but that's a bit out of scope for ufbx.
  10682. static const ufbxi_shader_mapping ufbxi_shaderfx_graph_pbr_mapping[] = {
  10683. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("color") },
  10684. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("base_color") },
  10685. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, 0, ufbxi_mat_string("roughness") },
  10686. { UFBX_MATERIAL_PBR_METALNESS, 0, 0, ufbxi_mat_string("metallic") },
  10687. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("normal") },
  10688. { UFBX_MATERIAL_PBR_EMISSION_FACTOR, 0, 0, ufbxi_mat_string("emissive_intensity") },
  10689. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("emissive") },
  10690. { UFBX_MATERIAL_PBR_AMBIENT_OCCLUSION, 0, 0, ufbxi_mat_string("ao") },
  10691. };
  10692. static const ufbxi_shader_mapping ufbxi_blender_phong_shader_pbr_mapping[] = {
  10693. { UFBX_MATERIAL_PBR_BASE_COLOR, 0, 0, ufbxi_mat_string("DiffuseColor") },
  10694. { UFBX_MATERIAL_PBR_OPACITY, 0, UFBXI_MAT_TRANSFORM_BLENDER_OPACITY, ufbxi_mat_string("TransparencyFactor") },
  10695. { UFBX_MATERIAL_PBR_EMISSION_FACTOR, 0, 0, ufbxi_mat_string("EmissiveFactor") },
  10696. { UFBX_MATERIAL_PBR_EMISSION_COLOR, 0, 0, ufbxi_mat_string("EmissiveColor") },
  10697. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, UFBXI_MAT_TRANSFORM_BLENDER_SHININESS, ufbxi_mat_string("Shininess") },
  10698. { UFBX_MATERIAL_PBR_ROUGHNESS, 0, UFBXI_MAT_TRANSFORM_BLENDER_SHININESS, ufbxi_mat_string("ShininessExponent") },
  10699. { UFBX_MATERIAL_PBR_METALNESS, 0, 0, ufbxi_mat_string("ReflectionFactor") },
  10700. { UFBX_MATERIAL_PBR_NORMAL_MAP, 0, 0, ufbxi_mat_string("NormalMap") },
  10701. };
  10702. enum {
  10703. UFBXI_MAT_METALNESS = 1 << UFBX_MATERIAL_FEATURE_METALNESS,
  10704. UFBXI_MAT_DIFFUSE = 1 << UFBX_MATERIAL_FEATURE_DIFFUSE,
  10705. UFBXI_MAT_SPECULAR = 1 << UFBX_MATERIAL_FEATURE_SPECULAR,
  10706. UFBXI_MAT_EMISSION = 1 << UFBX_MATERIAL_FEATURE_EMISSION,
  10707. UFBXI_MAT_COAT = 1 << UFBX_MATERIAL_FEATURE_COAT,
  10708. UFBXI_MAT_SHEEN = 1 << UFBX_MATERIAL_FEATURE_SHEEN,
  10709. UFBXI_MAT_TRANSMISSION = 1 << UFBX_MATERIAL_FEATURE_TRANSMISSION,
  10710. UFBXI_MAT_OPACITY = 1 << UFBX_MATERIAL_FEATURE_OPACITY,
  10711. UFBXI_MAT_AMBIENT_OCCLUSION = 1 << UFBX_MATERIAL_FEATURE_AMBIENT_OCCLUSION,
  10712. UFBXI_MAT_MATTE = 1 << UFBX_MATERIAL_FEATURE_MATTE,
  10713. UFBXI_MAT_UNLIT = 1 << UFBX_MATERIAL_FEATURE_UNLIT,
  10714. UFBXI_MAT_IOR = 1 << UFBX_MATERIAL_FEATURE_IOR,
  10715. UFBXI_MAT_DIFFUSE_ROUGHNESS = 1 << UFBX_MATERIAL_FEATURE_DIFFUSE_ROUGHNESS,
  10716. UFBXI_MAT_TRANSMISSION_ROUGHNESS = 1 << UFBX_MATERIAL_FEATURE_TRANSMISSION_ROUGHNESS,
  10717. UFBXI_MAT_THIN_WALLED = 1 << UFBX_MATERIAL_FEATURE_THIN_WALLED,
  10718. UFBXI_MAT_CAUSTICS = 1 << UFBX_MATERIAL_FEATURE_CAUSTICS,
  10719. UFBXI_MAT_EXIT_TO_BACKGROUND = 1 << UFBX_MATERIAL_FEATURE_EXIT_TO_BACKGROUND,
  10720. UFBXI_MAT_INTERNAL_REFLECTIONS = 1 << UFBX_MATERIAL_FEATURE_INTERNAL_REFLECTIONS,
  10721. UFBXI_MAT_DOUBLE_SIDED = 1 << UFBX_MATERIAL_FEATURE_DOUBLE_SIDED,
  10722. };
  10723. static const ufbxi_shader_mapping_list ufbxi_shader_pbr_mappings[] = {
  10724. { // UFBX_SHADER_UNKNOWN
  10725. ufbxi_fbx_phong_shader_pbr_mapping, ufbxi_arraycount(ufbxi_fbx_phong_shader_pbr_mapping),
  10726. NULL, 0,
  10727. (uint32_t)(UFBXI_MAT_DIFFUSE | UFBXI_MAT_SPECULAR | UFBXI_MAT_EMISSION | UFBXI_MAT_TRANSMISSION),
  10728. },
  10729. { // UFBX_SHADER_FBX_LAMBERT
  10730. ufbxi_fbx_lambert_shader_pbr_mapping, ufbxi_arraycount(ufbxi_fbx_lambert_shader_pbr_mapping),
  10731. NULL, 0,
  10732. (uint32_t)(UFBXI_MAT_DIFFUSE | UFBXI_MAT_EMISSION | UFBXI_MAT_TRANSMISSION),
  10733. },
  10734. { // UFBX_SHADER_FBX_PHONG
  10735. ufbxi_fbx_phong_shader_pbr_mapping, ufbxi_arraycount(ufbxi_fbx_phong_shader_pbr_mapping),
  10736. NULL, 0,
  10737. (uint32_t)(UFBXI_MAT_DIFFUSE | UFBXI_MAT_SPECULAR | UFBXI_MAT_EMISSION | UFBXI_MAT_TRANSMISSION),
  10738. },
  10739. { // UFBX_SHADER_OSL_STANDARD_SURFACE
  10740. ufbxi_osl_standard_shader_pbr_mapping, ufbxi_arraycount(ufbxi_osl_standard_shader_pbr_mapping),
  10741. ufbxi_osl_standard_shader_features, ufbxi_arraycount(ufbxi_osl_standard_shader_features),
  10742. (uint32_t)(UFBXI_MAT_METALNESS | UFBXI_MAT_DIFFUSE | UFBXI_MAT_SPECULAR | UFBXI_MAT_COAT
  10743. | UFBXI_MAT_SHEEN | UFBXI_MAT_TRANSMISSION | UFBXI_MAT_OPACITY | UFBXI_MAT_IOR | UFBXI_MAT_DIFFUSE_ROUGHNESS),
  10744. },
  10745. { // UFBX_SHADER_ARNOLD_STANDARD_SURFACE
  10746. ufbxi_arnold_shader_pbr_mapping, ufbxi_arraycount(ufbxi_arnold_shader_pbr_mapping),
  10747. ufbxi_arnold_shader_features, ufbxi_arraycount(ufbxi_arnold_shader_features),
  10748. (uint32_t)(UFBXI_MAT_METALNESS | UFBXI_MAT_DIFFUSE | UFBXI_MAT_SPECULAR | UFBXI_MAT_COAT
  10749. | UFBXI_MAT_SHEEN | UFBXI_MAT_TRANSMISSION | UFBXI_MAT_OPACITY | UFBXI_MAT_IOR | UFBXI_MAT_DIFFUSE_ROUGHNESS),
  10750. },
  10751. { // UFBX_SHADER_3DS_MAX_PHYSICAL_MATERIAL
  10752. ufbxi_3ds_max_physical_material_pbr_mapping, ufbxi_arraycount(ufbxi_3ds_max_physical_material_pbr_mapping),
  10753. ufbxi_3ds_max_physical_material_features, ufbxi_arraycount(ufbxi_3ds_max_physical_material_features),
  10754. (uint32_t)(UFBXI_MAT_METALNESS | UFBXI_MAT_DIFFUSE | UFBXI_MAT_COAT
  10755. | UFBXI_MAT_SHEEN | UFBXI_MAT_TRANSMISSION | UFBXI_MAT_OPACITY | UFBXI_MAT_IOR),
  10756. { NULL, 0 }, ufbxi_string_literal("_map"), // texture_prefix/suffix
  10757. { NULL, 0 }, ufbxi_string_literal("_map_on"), // texture_enabled_prefix/suffix
  10758. },
  10759. { // UFBX_SHADER_3DS_MAX_PBR_METAL_ROUGH
  10760. ufbxi_3ds_max_pbr_metal_rough_pbr_mapping, ufbxi_arraycount(ufbxi_3ds_max_pbr_metal_rough_pbr_mapping),
  10761. NULL, 0,
  10762. (uint32_t)(UFBXI_MAT_METALNESS | UFBXI_MAT_DIFFUSE | UFBXI_MAT_OPACITY),
  10763. { NULL, 0 }, ufbxi_string_literal("_map"), // texture_prefix/suffix
  10764. { NULL, 0 }, { NULL, 0 }, // texture_enabled_prefix/suffix
  10765. },
  10766. { // UFBX_SHADER_3DS_MAX_PBR_SPEC_GLOSS
  10767. ufbxi_3ds_max_pbr_spec_gloss_pbr_mapping, ufbxi_arraycount(ufbxi_3ds_max_pbr_spec_gloss_pbr_mapping),
  10768. NULL, 0,
  10769. (uint32_t)(UFBXI_MAT_SPECULAR | UFBXI_MAT_DIFFUSE | UFBXI_MAT_OPACITY),
  10770. { NULL, 0 }, ufbxi_string_literal("_map"), // texture_prefix/suffix
  10771. { NULL, 0 }, { NULL, 0 }, // texture_enabled_prefix/suffix
  10772. },
  10773. { // UFBX_SHADER_GLTF_MATERIAL
  10774. ufbxi_gltf_material_pbr_mapping, ufbxi_arraycount(ufbxi_gltf_material_pbr_mapping),
  10775. ufbxi_gltf_material_features, ufbxi_arraycount(ufbxi_gltf_material_features),
  10776. (uint32_t)(UFBXI_MAT_METALNESS | UFBXI_MAT_DIFFUSE | UFBXI_MAT_EMISSION | UFBXI_MAT_OPACITY | UFBXI_MAT_AMBIENT_OCCLUSION),
  10777. { NULL, 0 }, ufbxi_string_literal("Map"), // texture_prefix/suffix
  10778. { NULL, 0 }, { NULL, 0 }, // texture_enabled_prefix/suffix
  10779. },
  10780. { // UFBX_SHADER_SHADERFX_GRAPH
  10781. ufbxi_shaderfx_graph_pbr_mapping, ufbxi_arraycount(ufbxi_shaderfx_graph_pbr_mapping),
  10782. NULL, 0,
  10783. (uint32_t)(UFBXI_MAT_METALNESS | UFBXI_MAT_DIFFUSE | UFBXI_MAT_EMISSION | UFBXI_MAT_AMBIENT_OCCLUSION),
  10784. ufbxi_string_literal("TEX_"), ufbxi_string_literal("_map"), // texture_prefix/suffix
  10785. ufbxi_string_literal("use_"), ufbxi_string_literal("_map"), // texture_enabled_prefix/suffix
  10786. },
  10787. { // UFBX_SHADER_BLENDER_PHONG
  10788. ufbxi_blender_phong_shader_pbr_mapping, ufbxi_arraycount(ufbxi_blender_phong_shader_pbr_mapping),
  10789. NULL, 0,
  10790. (uint32_t)(UFBXI_MAT_METALNESS | UFBXI_MAT_DIFFUSE | UFBXI_MAT_EMISSION),
  10791. },
  10792. };
  10793. ufbx_static_assert(shader_pbr_mapping_list, ufbxi_arraycount(ufbxi_shader_pbr_mappings) == UFBX_SHADER_TYPE_COUNT);
  10794. enum {
  10795. UFBXI_MAPPING_FETCH_VALUE = 0x1,
  10796. UFBXI_MAPPING_FETCH_TEXTURE = 0x2,
  10797. UFBXI_MAPPING_FETCH_TEXTURE_ENABLED = 0x4,
  10798. UFBXI_MAPPING_FETCH_INVERT = 0x8,
  10799. UFBXI_MAPPING_FETCH_FEATURE = 0x10,
  10800. };
  10801. ufbxi_noinline static void ufbxi_fetch_mapping_maps(ufbx_material *material, ufbx_material_map *maps, ufbx_material_feature_info *features,
  10802. ufbx_shader *shader, const ufbxi_shader_mapping *mappings, size_t count, ufbx_string prefix, ufbx_string prefix2, ufbx_string suffix, uint32_t flags)
  10803. {
  10804. char combined_name[512];
  10805. ufbx_shader_prop_binding identity_binding;
  10806. ufbxi_for(const ufbxi_shader_mapping, mapping, mappings, count) {
  10807. ufbx_string prop_name = { mapping->prop, mapping->prop_len };
  10808. if (prefix.length > 0 || prefix2.length > 0 || suffix.length > 0) {
  10809. if (prop_name.length + prefix.length + prefix2.length + suffix.length <= sizeof(combined_name)) {
  10810. char *dst = combined_name;
  10811. if (prefix.length > 0) {
  10812. memcpy(dst, prefix.data, prefix.length);
  10813. dst += prefix.length;
  10814. }
  10815. if (prefix2.length > 0) {
  10816. memcpy(dst, prefix2.data, prefix2.length);
  10817. dst += prefix2.length;
  10818. }
  10819. if (prop_name.length > 0) {
  10820. memcpy(dst, prop_name.data, prop_name.length);
  10821. dst += prop_name.length;
  10822. }
  10823. if (suffix.length > 0) {
  10824. memcpy(dst, suffix.data, suffix.length);
  10825. dst += suffix.length;
  10826. }
  10827. prop_name.data = combined_name;
  10828. prop_name.length = ufbxi_to_size(dst - combined_name);
  10829. }
  10830. }
  10831. ufbx_shader_prop_binding_list bindings = ufbx_find_shader_prop_bindings_len(shader, prop_name.data, prop_name.length);
  10832. if (bindings.count == 0) {
  10833. identity_binding.material_prop = prop_name;
  10834. identity_binding.shader_prop = ufbx_empty_string;
  10835. bindings.data = &identity_binding;
  10836. bindings.count = 1;
  10837. }
  10838. uint32_t mapping_flags = mapping->flags;
  10839. ufbxi_for_list(ufbx_shader_prop_binding, binding, bindings) {
  10840. ufbx_string name = binding->material_prop;
  10841. ufbx_prop *prop = ufbx_find_prop_len(&material->props, name.data, name.length);
  10842. if (flags & UFBXI_MAPPING_FETCH_FEATURE) {
  10843. ufbx_material_feature_info *feature = &features[mapping->index];
  10844. if (prop && prop->type != UFBX_PROP_REFERENCE) {
  10845. feature->enabled = prop->value_int != 0;
  10846. feature->is_explicit = true;
  10847. if (mapping_flags & UFBXI_SHADER_FEATURE_INVERTED) {
  10848. feature->enabled = !feature->enabled;
  10849. }
  10850. }
  10851. continue;
  10852. }
  10853. ufbx_material_map *map = &maps[mapping->index];
  10854. if (mapping_flags & UFBXI_SHADER_MAPPING_TOGGLE_INVERT) {
  10855. if ((flags & UFBXI_MAPPING_FETCH_INVERT) != 0 && prop) {
  10856. bool do_toggle = prop->value_int != 0;
  10857. if (mapping->transform) {
  10858. ufbxi_mat_transform_fn transform_fn = ufbxi_mat_transform_fns[mapping->transform];
  10859. ufbx_vec4 value = prop->value_vec4;
  10860. transform_fn(&value);
  10861. do_toggle = value.x > 0.5f;
  10862. }
  10863. if (do_toggle) {
  10864. if (map->has_value) {
  10865. map->value_real = 1.0f - map->value_real;
  10866. }
  10867. map->texture_inverted = !map->texture_inverted;
  10868. }
  10869. }
  10870. continue;
  10871. }
  10872. if (flags & UFBXI_MAPPING_FETCH_VALUE) {
  10873. if (prop && prop->type != UFBX_PROP_REFERENCE) {
  10874. map->value_vec4 = prop->value_vec4;
  10875. map->value_int = prop->value_int;
  10876. map->has_value = true;
  10877. if (mapping->transform) {
  10878. ufbxi_mat_transform_fn transform_fn = ufbxi_mat_transform_fns[mapping->transform];
  10879. transform_fn(&map->value_vec4);
  10880. }
  10881. }
  10882. }
  10883. if (flags & UFBXI_MAPPING_FETCH_TEXTURE) {
  10884. ufbx_texture *texture = ufbx_find_prop_texture_len(material, name.data, name.length);
  10885. if (!map->texture || texture) {
  10886. map->texture_inverted = (mapping_flags & UFBXI_SHADER_MAPPING_INVERT_TEXTURE) != 0;
  10887. }
  10888. if (texture) {
  10889. map->texture = texture;
  10890. map->texture_enabled = true;
  10891. }
  10892. }
  10893. if (flags & UFBXI_MAPPING_FETCH_TEXTURE_ENABLED) {
  10894. if (prop) {
  10895. map->texture_enabled = prop->value_int != 0;
  10896. }
  10897. }
  10898. }
  10899. }
  10900. }
  10901. ufbxi_noinline static void ufbxi_update_factor(ufbx_material_map *factor_map, ufbx_material_map *color_map)
  10902. {
  10903. if (!factor_map->has_value) {
  10904. if (color_map->has_value && !ufbxi_is_vec4_zero(color_map->value_vec4)) {
  10905. factor_map->value_real = 1.0f;
  10906. factor_map->value_int = 1;
  10907. } else {
  10908. factor_map->value_real = 0.0f;
  10909. factor_map->value_int = 0;
  10910. }
  10911. }
  10912. }
  10913. ufbxi_noinline static void ufbxi_fetch_maps(ufbx_scene *scene, ufbx_material *material)
  10914. {
  10915. (void)scene;
  10916. ufbx_shader *shader = material->shader;
  10917. ufbx_assert(material->shader_type < UFBX_SHADER_TYPE_COUNT);
  10918. memset(&material->fbx, 0, sizeof(material->fbx));
  10919. memset(&material->pbr, 0, sizeof(material->pbr));
  10920. memset(&material->features, 0, sizeof(material->features));
  10921. ufbxi_fetch_mapping_maps(material, material->fbx.maps, NULL, NULL,
  10922. ufbxi_base_fbx_mapping, ufbxi_arraycount(ufbxi_base_fbx_mapping),
  10923. ufbx_empty_string, ufbx_empty_string, ufbx_empty_string,
  10924. UFBXI_MAPPING_FETCH_VALUE | UFBXI_MAPPING_FETCH_TEXTURE);
  10925. ufbxi_shader_mapping_list list = ufbxi_shader_pbr_mappings[material->shader_type];
  10926. for (uint32_t i = 0; i < UFBX_MATERIAL_FEATURE_COUNT; i++) {
  10927. if ((list.default_features & (1u << i)) != 0) {
  10928. material->features.features[i].enabled = true;
  10929. }
  10930. }
  10931. ufbx_string prefix = ufbx_empty_string;
  10932. if (!shader) {
  10933. prefix = material->shader_prop_prefix;
  10934. }
  10935. if (list.texture_prefix.length > 0 || list.texture_suffix.length > 0) {
  10936. ufbxi_fetch_mapping_maps(material, material->pbr.maps, NULL, shader,
  10937. list.data, list.count, prefix, list.texture_prefix, list.texture_suffix,
  10938. UFBXI_MAPPING_FETCH_TEXTURE);
  10939. }
  10940. ufbxi_fetch_mapping_maps(material, material->pbr.maps, NULL, shader,
  10941. list.data, list.count, prefix, ufbx_empty_string, ufbx_empty_string,
  10942. UFBXI_MAPPING_FETCH_VALUE | UFBXI_MAPPING_FETCH_TEXTURE | UFBXI_MAPPING_FETCH_INVERT);
  10943. if (list.texture_enabled_prefix.length > 0 || list.texture_enabled_suffix.length > 0) {
  10944. ufbxi_fetch_mapping_maps(material, material->pbr.maps, NULL, shader,
  10945. list.data, list.count, prefix, list.texture_enabled_prefix, list.texture_enabled_suffix,
  10946. UFBXI_MAPPING_FETCH_TEXTURE_ENABLED);
  10947. }
  10948. ufbxi_fetch_mapping_maps(material, NULL, material->features.features, shader,
  10949. list.features, list.feature_count, prefix, ufbx_empty_string, ufbx_empty_string,
  10950. UFBXI_MAPPING_FETCH_FEATURE);
  10951. ufbxi_update_factor(&material->fbx.diffuse_factor, &material->fbx.diffuse_color);
  10952. ufbxi_update_factor(&material->fbx.specular_factor, &material->fbx.specular_color);
  10953. ufbxi_update_factor(&material->fbx.reflection_factor, &material->fbx.reflection_color);
  10954. ufbxi_update_factor(&material->fbx.transparency_factor, &material->fbx.transparency_color);
  10955. ufbxi_update_factor(&material->fbx.emission_factor, &material->fbx.emission_color);
  10956. ufbxi_update_factor(&material->fbx.ambient_factor, &material->fbx.ambient_color);
  10957. ufbxi_update_factor(&material->pbr.base_factor, &material->pbr.base_color);
  10958. ufbxi_update_factor(&material->pbr.specular_factor, &material->pbr.specular_color);
  10959. ufbxi_update_factor(&material->pbr.emission_factor, &material->pbr.emission_color);
  10960. // Patch transmission roughness if only extra roughness is defined
  10961. if (!material->pbr.transmission_roughness.has_value && material->pbr.roughness.has_value && material->pbr.transmission_extra_roughness.has_value) {
  10962. material->pbr.transmission_roughness.value_real = material->pbr.roughness.value_real + material->pbr.transmission_extra_roughness.value_real;
  10963. }
  10964. }
  10965. typedef enum {
  10966. UFBXI_CONSTRAINT_PROP_NODE,
  10967. UFBXI_CONSTRAINT_PROP_IK_EFFECTOR,
  10968. UFBXI_CONSTRAINT_PROP_IK_END_NODE,
  10969. UFBXI_CONSTRAINT_PROP_AIM_UP,
  10970. UFBXI_CONSTRAINT_PROP_TARGET,
  10971. } ufbxi_constraint_prop_type;
  10972. typedef struct {
  10973. ufbxi_constraint_prop_type type;
  10974. const char *name;
  10975. } ufbxi_constraint_prop;
  10976. static const ufbxi_constraint_prop ufbxi_constraint_props[] = {
  10977. { UFBXI_CONSTRAINT_PROP_NODE, "Constrained Object" },
  10978. { UFBXI_CONSTRAINT_PROP_NODE, "Constrained object (Child)" },
  10979. { UFBXI_CONSTRAINT_PROP_NODE, "First Joint" },
  10980. { UFBXI_CONSTRAINT_PROP_TARGET, "Source" },
  10981. { UFBXI_CONSTRAINT_PROP_TARGET, "Source (Parent)" },
  10982. { UFBXI_CONSTRAINT_PROP_TARGET, "Aim At Object" },
  10983. { UFBXI_CONSTRAINT_PROP_TARGET, "Pole Vector Object" },
  10984. { UFBXI_CONSTRAINT_PROP_IK_EFFECTOR, "Effector" },
  10985. { UFBXI_CONSTRAINT_PROP_IK_END_NODE, "End Joint" },
  10986. { UFBXI_CONSTRAINT_PROP_AIM_UP, "World Up Object" },
  10987. };
  10988. ufbxi_nodiscard ufbxi_noinline static int ufbxi_add_constraint_prop(ufbxi_context *uc, ufbx_constraint *constraint, ufbx_node *node, const char *prop)
  10989. {
  10990. ufbxi_for(const ufbxi_constraint_prop, cprop, ufbxi_constraint_props, ufbxi_arraycount(ufbxi_constraint_props)) {
  10991. if (strcmp(cprop->name, prop) != 0) continue;
  10992. switch (cprop->type) {
  10993. case UFBXI_CONSTRAINT_PROP_NODE: constraint->node = node; break;
  10994. case UFBXI_CONSTRAINT_PROP_IK_EFFECTOR: constraint->ik_effector = node; break;
  10995. case UFBXI_CONSTRAINT_PROP_IK_END_NODE: constraint->ik_end_node = node; break;
  10996. case UFBXI_CONSTRAINT_PROP_AIM_UP: constraint->aim_up_node = node; break;
  10997. case UFBXI_CONSTRAINT_PROP_TARGET: {
  10998. ufbx_constraint_target *target = ufbxi_push_zero(&uc->tmp_stack, ufbx_constraint_target, 1);
  10999. ufbxi_check(target);
  11000. target->node = node;
  11001. target->weight = 1.0f;
  11002. target->transform = ufbx_identity_transform;
  11003. } break;
  11004. }
  11005. }
  11006. return 1;
  11007. }
  11008. ufbxi_nodiscard ufbxi_noinline static size_t ufbxi_trim_delimiters(ufbxi_context *uc, const char *data, size_t length)
  11009. {
  11010. for (; length > 0; length--) {
  11011. char c = data[length - 1];
  11012. bool is_separator = c == '/' || c == uc->opts.path_separator;
  11013. if (is_separator) {
  11014. length--;
  11015. break;
  11016. }
  11017. }
  11018. return length;
  11019. }
  11020. ufbxi_nodiscard ufbxi_noinline static int ufbxi_init_file_paths(ufbxi_context *uc)
  11021. {
  11022. if (uc->opts.filename.length > 0) {
  11023. uc->scene.metadata.filename = uc->opts.filename;
  11024. } else if (uc->opts.raw_filename.size > 0) {
  11025. uc->scene.metadata.filename.data = (const char*)uc->opts.raw_filename.data;
  11026. uc->scene.metadata.filename.length = uc->opts.raw_filename.size;
  11027. }
  11028. if (uc->opts.raw_filename.size > 0) {
  11029. uc->scene.metadata.raw_filename = uc->opts.raw_filename;
  11030. } else if (uc->opts.filename.length > 0) {
  11031. uc->scene.metadata.raw_filename.data = uc->opts.filename.data;
  11032. uc->scene.metadata.raw_filename.size = uc->opts.filename.length;
  11033. }
  11034. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &uc->scene.metadata.filename, false));
  11035. ufbxi_check(ufbxi_push_string_place_blob(&uc->string_pool, &uc->scene.metadata.raw_filename, true));
  11036. uc->scene.metadata.relative_root.data = uc->opts.filename.data;
  11037. uc->scene.metadata.relative_root.length = ufbxi_trim_delimiters(uc, uc->opts.filename.data, uc->opts.filename.length);
  11038. uc->scene.metadata.raw_relative_root.data = uc->opts.raw_filename.data;
  11039. uc->scene.metadata.raw_relative_root.size = ufbxi_trim_delimiters(uc, (const char*)uc->opts.raw_filename.data, uc->opts.raw_filename.size);
  11040. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &uc->scene.metadata.relative_root, false));
  11041. ufbxi_check(ufbxi_push_string_place_blob(&uc->string_pool, &uc->scene.metadata.raw_relative_root, true));
  11042. return 1;
  11043. }
  11044. typedef union {
  11045. ufbx_string str;
  11046. ufbx_blob blob;
  11047. } ufbxi_strblob;
  11048. static ufbxi_noinline void ufbxi_strblob_set(ufbxi_strblob *dst, const char *data, size_t length, bool raw)
  11049. {
  11050. if (raw) {
  11051. dst->blob.data = data;
  11052. dst->blob.size = length;
  11053. } else {
  11054. dst->str.data = length == 0 ? ufbxi_empty_char : data;
  11055. dst->str.length = length;
  11056. }
  11057. }
  11058. static ufbxi_forceinline const char *ufbxi_strblob_data(const ufbxi_strblob *strblob, bool raw)
  11059. {
  11060. return raw ? (const char*)strblob->blob.data : strblob->str.data;
  11061. }
  11062. static ufbxi_forceinline size_t ufbxi_strblob_length(const ufbxi_strblob *strblob, bool raw)
  11063. {
  11064. return raw ? strblob->blob.size : strblob->str.length;
  11065. }
  11066. ufbxi_nodiscard ufbxi_noinline static int ufbxi_resolve_relative_filename(ufbxi_context *uc, ufbxi_strblob *p_dst, const ufbxi_strblob *p_src, bool raw)
  11067. {
  11068. const char *src = ufbxi_strblob_data(p_src, raw);
  11069. size_t src_length = ufbxi_strblob_length(p_src, raw);
  11070. // Skip leading directory separators and early return if the relative path is empty
  11071. while (src_length > 0 && (src[0] == '/' || src[0] == '\\')) {
  11072. src++;
  11073. src_length--;
  11074. }
  11075. if (src_length == 0) {
  11076. ufbxi_strblob_set(p_dst, NULL, 0, raw);
  11077. return 1;
  11078. }
  11079. const char *prefix_data;
  11080. size_t prefix_length;
  11081. if (raw) {
  11082. prefix_data = (const char*)uc->scene.metadata.raw_relative_root.data;
  11083. prefix_length = uc->scene.metadata.raw_relative_root.size;
  11084. } else {
  11085. prefix_data = (const char*)uc->scene.metadata.relative_root.data;
  11086. prefix_length = uc->scene.metadata.relative_root.length;
  11087. }
  11088. // Undo directories from `prefix` for every `..`
  11089. while (prefix_length > 0 && src_length >= 3 && src[0] == '.' && src[1] == '.' && (src[2] == '/' || src[2] == '\\')) {
  11090. size_t part_start = prefix_length;
  11091. while (part_start > 0 && !(prefix_data[part_start - 1] == '/' || prefix_data[part_start - 1] == '\\')) {
  11092. part_start--;
  11093. }
  11094. size_t part_len = prefix_length - part_start;
  11095. if (part_len == 2 && prefix_data[part_start] == '.' && prefix_data[part_start + 1] == '.') {
  11096. // Prefix itself ends in `..`, cannot cancel out a leading `../`
  11097. break;
  11098. }
  11099. // Eat the leading '/' before the part segment
  11100. prefix_length = part_start > 0 ? part_start - 1 : 0;
  11101. if (part_len == 1 && prefix_data[part_start] == '.') {
  11102. // Single '.' -> remove and continue without cancelling out a leading `../`
  11103. continue;
  11104. }
  11105. src += 3;
  11106. src_length -= 3;
  11107. }
  11108. size_t result_cap = prefix_length + src_length + 1;
  11109. char *result = ufbxi_push(&uc->tmp_stack, char, result_cap);
  11110. ufbxi_check(result);
  11111. char *ptr = result;
  11112. // Copy prefix and suffix converting separators in the process
  11113. if (prefix_length > 0) {
  11114. memcpy(ptr, prefix_data, prefix_length);
  11115. ptr[prefix_length] = uc->opts.path_separator;
  11116. ptr += prefix_length + 1;
  11117. }
  11118. for (size_t i = 0; i < src_length; i++) {
  11119. char c = src[i];
  11120. if (c == '/' || c == '\\') {
  11121. c = uc->opts.path_separator;
  11122. }
  11123. *ptr++ = c;
  11124. }
  11125. // Intern the string and pop the temporary buffer
  11126. ufbx_string dst = { result, ufbxi_to_size(ptr - result) };
  11127. ufbx_assert(dst.length <= result_cap);
  11128. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &dst, raw));
  11129. ufbxi_pop(&uc->tmp_stack, char, result_cap, NULL);
  11130. ufbxi_strblob_set(p_dst, dst.data, dst.length, raw);
  11131. return 1;
  11132. }
  11133. ufbxi_nodiscard ufbxi_noinline static int ufbxi_finalize_nurbs_basis(ufbxi_context *uc, ufbx_nurbs_basis *basis)
  11134. {
  11135. if (basis->topology == UFBX_NURBS_TOPOLOGY_CLOSED) {
  11136. basis->num_wrap_control_points = 1;
  11137. } else if (basis->topology == UFBX_NURBS_TOPOLOGY_PERIODIC) {
  11138. basis->num_wrap_control_points = basis->order - 1;
  11139. } else {
  11140. basis->num_wrap_control_points = 0;
  11141. }
  11142. if (basis->order > 1) {
  11143. size_t degree = basis->order - 1;
  11144. ufbx_real_list knots = basis->knot_vector;
  11145. if (knots.count >= 2*degree + 1) {
  11146. basis->t_min = knots.data[degree];
  11147. basis->t_max = knots.data[knots.count - degree - 1];
  11148. size_t max_spans = knots.count - 2*degree;
  11149. ufbx_real *spans = ufbxi_push(&uc->result, ufbx_real, max_spans);
  11150. ufbxi_check(spans);
  11151. ufbx_real prev = -UFBX_INFINITY;
  11152. size_t num_spans = 0;
  11153. for (size_t i = 0; i < max_spans; i++) {
  11154. ufbx_real t = knots.data[degree + i];
  11155. if (t != prev) {
  11156. spans[num_spans++] = t;
  11157. prev = t;
  11158. }
  11159. }
  11160. basis->spans.data = spans;
  11161. basis->spans.count = num_spans;
  11162. basis->valid = true;
  11163. for (size_t i = 1; i < knots.count; i++) {
  11164. if (knots.data[i - 1] > knots.data[i]) {
  11165. basis->valid = false;
  11166. break;
  11167. }
  11168. }
  11169. }
  11170. }
  11171. return 1;
  11172. }
  11173. ufbxi_nodiscard ufbxi_noinline static int ufbxi_finalize_lod_group(ufbxi_context *uc, ufbx_lod_group *lod)
  11174. {
  11175. size_t num_levels = 0;
  11176. for (size_t i = 0; i < lod->instances.count; i++) {
  11177. num_levels = ufbxi_max_sz(num_levels, lod->instances.data[0]->children.count);
  11178. }
  11179. char prop_name[64];
  11180. for (size_t i = 0; ; i++) {
  11181. int len = snprintf(prop_name, sizeof(prop_name), "Thresholds|Level%zu", i);
  11182. ufbx_prop *prop = ufbx_find_prop_len(&lod->props, prop_name, (size_t)len);
  11183. if (!prop) break;
  11184. num_levels = ufbxi_max_sz(num_levels, i + 1);
  11185. }
  11186. ufbx_lod_level *levels = ufbxi_push_zero(&uc->result, ufbx_lod_level, num_levels);
  11187. ufbxi_check(levels);
  11188. lod->relative_distances = ufbx_find_bool(&lod->props, "ThresholdsUsedAsPercentage", false);
  11189. lod->ignore_parent_transform = !ufbx_find_bool(&lod->props, "WorldSpace", true);
  11190. lod->use_distance_limit = ufbx_find_bool(&lod->props, "MinMaxDistance", false);
  11191. lod->distance_limit_min = ufbx_find_real(&lod->props, "MinDistance", (ufbx_real)-100.0);
  11192. lod->distance_limit_max = ufbx_find_real(&lod->props, "MaxDistance", (ufbx_real)100.0);
  11193. lod->lod_levels.data = levels;
  11194. lod->lod_levels.count = num_levels;
  11195. for (size_t i = 0; i < num_levels; i++) {
  11196. ufbx_lod_level *level = &levels[i];
  11197. if (i > 0) {
  11198. int len = snprintf(prop_name, sizeof(prop_name), "Thresholds|Level%zu", i - 1);
  11199. level->distance = ufbx_find_real_len(&lod->props, prop_name, (size_t)len, 0.0f);
  11200. } else if (lod->relative_distances) {
  11201. level->distance = (ufbx_real)100.0;
  11202. }
  11203. {
  11204. int len = snprintf(prop_name, sizeof(prop_name), "DisplayLevels|Level%zu", i);
  11205. int64_t display = ufbx_find_int_len(&lod->props, prop_name, (size_t)len, 0);
  11206. if (display >= 0 && display <= 2) {
  11207. level->display = (ufbx_lod_display)display;
  11208. }
  11209. }
  11210. }
  11211. return 1;
  11212. }
  11213. ufbxi_nodiscard ufbxi_noinline static int ufbxi_generate_normals(ufbxi_context *uc, ufbx_mesh *mesh)
  11214. {
  11215. size_t num_indices = mesh->num_indices;
  11216. ufbx_topo_edge *topo = ufbxi_push(&uc->tmp_stack, ufbx_topo_edge, num_indices);
  11217. ufbxi_check(topo);
  11218. uint32_t *normal_indices = ufbxi_push(&uc->result, uint32_t, num_indices);
  11219. ufbxi_check(normal_indices);
  11220. ufbx_compute_topology(mesh, topo, num_indices);
  11221. size_t num_normals = ufbx_generate_normal_mapping(mesh, topo, num_indices, normal_indices, num_indices, false);
  11222. if (num_normals == mesh->num_vertices) {
  11223. mesh->vertex_normal.unique_per_vertex = true;
  11224. }
  11225. ufbx_vec3 *normal_data = ufbxi_push(&uc->result, ufbx_vec3, num_normals + 1);
  11226. ufbxi_check(normal_data);
  11227. normal_data[0] = ufbx_zero_vec3;
  11228. normal_data++;
  11229. ufbx_compute_normals(mesh, &mesh->vertex_position, normal_indices, num_indices, normal_data, num_normals);
  11230. mesh->vertex_normal.exists = true;
  11231. mesh->vertex_normal.values.data = normal_data;
  11232. mesh->vertex_normal.values.count = num_normals;
  11233. mesh->vertex_normal.indices.data = normal_indices;
  11234. mesh->vertex_normal.indices.count = num_indices;
  11235. mesh->vertex_normal.value_reals = 3;
  11236. mesh->skinned_normal = mesh->vertex_normal;
  11237. ufbxi_pop(&uc->tmp_stack, ufbx_topo_edge, num_indices, NULL);
  11238. return 1;
  11239. }
  11240. ufbxi_nodiscard ufbxi_noinline static int ufbxi_push_prop_prefix(ufbxi_context *uc, ufbx_string *dst, ufbx_string prefix)
  11241. {
  11242. size_t stack_size = 0;
  11243. if (prefix.length > 0 && prefix.data[prefix.length - 1] != '|') {
  11244. stack_size = prefix.length + 1;
  11245. char *copy = ufbxi_push(&uc->tmp_stack, char, stack_size);
  11246. ufbxi_check(copy);
  11247. memcpy(copy, prefix.data, prefix.length);
  11248. copy[prefix.length] = '|';
  11249. prefix.data = copy;
  11250. prefix.length += 1;
  11251. }
  11252. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &prefix, false));
  11253. *dst = prefix;
  11254. if (stack_size > 0) {
  11255. ufbxi_pop(&uc->tmp_stack, char, stack_size, NULL);
  11256. }
  11257. return 1;
  11258. }
  11259. ufbxi_nodiscard ufbxi_noinline static int ufbxi_shader_texture_find_prefix(ufbxi_context *uc, ufbx_texture *texture, ufbx_shader_texture *shader)
  11260. {
  11261. ufbx_string suffixes[3];
  11262. size_t num_suffixes = 0;
  11263. suffixes[num_suffixes++] = ufbxi_str_c(" Parameters/Connections");
  11264. if (shader->shader_name.length > 0) {
  11265. suffixes[num_suffixes++] = shader->shader_name;
  11266. }
  11267. suffixes[num_suffixes++] = ufbxi_str_c("3dsMax|parameters");
  11268. ufbx_assert(num_suffixes <= ufbxi_arraycount(suffixes));
  11269. ufbxi_for(ufbx_string, p_suffix, suffixes, num_suffixes) {
  11270. ufbx_string suffix = *p_suffix;
  11271. ufbxi_for_list(ufbx_prop, prop, texture->props.props) {
  11272. if (prop->type != UFBX_PROP_COMPOUND) continue;
  11273. if (ufbxi_ends_with(prop->name, suffix)) {
  11274. ufbxi_check(ufbxi_push_prop_prefix(uc, &shader->prop_prefix, prop->name));
  11275. return 1;
  11276. }
  11277. }
  11278. }
  11279. // Pre-7000 files don't have explicit Compound properties, so let's look for
  11280. // any property that has the suffix before the last `|` ...
  11281. ufbxi_for(ufbx_string, p_suffix, suffixes, num_suffixes) {
  11282. ufbx_string suffix = *p_suffix;
  11283. ufbxi_for_list(ufbx_prop, prop, texture->props.props) {
  11284. ufbx_string name = prop->name;
  11285. while (name.length > 0) {
  11286. if (name.data[name.length - 1] == '|') {
  11287. break;
  11288. }
  11289. name.length--;
  11290. }
  11291. if (name.length <= 1) continue;
  11292. name.length--;
  11293. if (ufbxi_ends_with(name, suffix)) {
  11294. ufbxi_check(ufbxi_push_prop_prefix(uc, &shader->prop_prefix, name));
  11295. return 1;
  11296. }
  11297. }
  11298. }
  11299. return 1;
  11300. }
  11301. typedef struct {
  11302. uint64_t shader_id;
  11303. const char *shader_name;
  11304. const char *input_name;
  11305. } ufbxi_file_shader;
  11306. // Known shaders that represent sampled images.
  11307. static const ufbxi_file_shader ufbxi_file_shaders[] = {
  11308. { UINT64_C(0x7e73161fad53b12a), "ai_image", "filename" },
  11309. { 0, "OSLBitmap", ufbxi_Filename },
  11310. { 0, "OSLBitmap2", ufbxi_Filename },
  11311. { 0, "UberBitmap", ufbxi_Filename },
  11312. { 0, "UberBitmap2", ufbxi_Filename },
  11313. };
  11314. ufbxi_noinline static void ufbxi_update_shader_texture(ufbx_texture *texture, ufbx_shader_texture *shader)
  11315. {
  11316. ufbxi_for_list(ufbx_shader_texture_input, input, shader->inputs) {
  11317. ufbx_prop *prop = input->prop;
  11318. if (prop) {
  11319. input->prop = prop = ufbx_find_prop_len(&texture->props, prop->name.data, prop->name.length);
  11320. input->value_vec4 = prop->value_vec4;
  11321. input->value_int = prop->value_int;
  11322. input->value_str = prop->value_str;
  11323. input->value_blob = prop->value_blob;
  11324. input->texture = (ufbx_texture*)ufbx_get_prop_element(&texture->element, input->prop, UFBX_ELEMENT_TEXTURE);
  11325. }
  11326. prop = input->texture_prop;
  11327. if (prop) {
  11328. input->texture_prop = prop = ufbx_find_prop_len(&texture->props, prop->name.data, prop->name.length);
  11329. ufbx_texture *tex = (ufbx_texture*)ufbx_get_prop_element(&texture->element, prop, UFBX_ELEMENT_TEXTURE);
  11330. if (tex) input->texture = tex;
  11331. }
  11332. input->texture_enabled = input->texture != NULL;
  11333. prop = input->texture_enabled_prop;
  11334. if (prop) {
  11335. input->texture_enabled_prop = prop = ufbx_find_prop_len(&texture->props, prop->name.data, prop->name.length);
  11336. input->texture_enabled = prop->value_int != 0;
  11337. }
  11338. }
  11339. if (shader->type == UFBX_SHADER_TEXTURE_SELECT_OUTPUT) {
  11340. ufbx_shader_texture_input *map = ufbx_find_shader_texture_input(shader, "sourceMap");
  11341. ufbx_shader_texture_input *index = ufbx_find_shader_texture_input(shader, "outputChannelIndex");
  11342. if (index) {
  11343. shader->main_texture_output_index = index->value_int;
  11344. }
  11345. if (map) {
  11346. shader->main_texture = map->texture;
  11347. map->texture_output_index = shader->main_texture_output_index;
  11348. }
  11349. }
  11350. }
  11351. ufbxi_nodiscard ufbxi_noinline static int ufbxi_finalize_shader_texture(ufbxi_context *uc, ufbx_texture *texture)
  11352. {
  11353. uint32_t classid_a = (uint32_t)(uint64_t)ufbx_find_int(&texture->props, "3dsMax|ClassIDa", 0);
  11354. uint32_t classid_b = (uint32_t)(uint64_t)ufbx_find_int(&texture->props, "3dsMax|ClassIDb", 0);
  11355. uint64_t classid = (uint64_t)classid_a << 32u | classid_b;
  11356. ufbx_string max_texture = ufbx_find_string(&texture->props, "3dsMax|MaxTexture", ufbx_empty_string);
  11357. // Check first if the texture looks like it could be a shader.
  11358. ufbx_shader_texture_type type = UFBX_SHADER_TEXTURE_TYPE_COUNT;
  11359. if (!strcmp(max_texture.data, "MULTIOUTPUT_TO_OSLMap") || classid == UINT64_C(0x896ef2fc44bd743f)) {
  11360. type = UFBX_SHADER_TEXTURE_SELECT_OUTPUT;
  11361. } else if (!strcmp(max_texture.data, "OSLMap") || classid == UINT64_C(0x7f9a7b9d6fcdf00d)) {
  11362. type = UFBX_SHADER_TEXTURE_OSL;
  11363. } else if (texture->type == UFBX_TEXTURE_FILE && texture->relative_filename.length == 0 && texture->absolute_filename.length == 0 && !texture->video) {
  11364. type = UFBX_SHADER_TEXTURE_UNKNOWN;
  11365. }
  11366. if (type == UFBX_SHADER_TEXTURE_TYPE_COUNT) return 1;
  11367. ufbx_shader_texture *shader = ufbxi_push_zero(&uc->result, ufbx_shader_texture, 1);
  11368. ufbxi_check(shader);
  11369. shader->type = type;
  11370. static const char *name_props[] = {
  11371. "3dsMax|params|OSLShaderName",
  11372. };
  11373. static const char *source_props[] = {
  11374. "3dsMax|params|OSLCode",
  11375. };
  11376. shader->shader_source.data = ufbxi_empty_char;
  11377. shader->shader_name.data = ufbxi_empty_char;
  11378. ufbxi_nounroll for (size_t i = 0; i < ufbxi_arraycount(name_props); i++) {
  11379. ufbx_prop *prop = ufbx_find_prop(&texture->props, name_props[i]);
  11380. if (prop) {
  11381. shader->shader_name = prop->value_str;
  11382. break;
  11383. }
  11384. }
  11385. ufbxi_nounroll for (size_t i = 0; i < ufbxi_arraycount(source_props); i++) {
  11386. ufbx_prop *prop = ufbx_find_prop(&texture->props, source_props[i]);
  11387. if (prop) {
  11388. shader->shader_source = prop->value_str;
  11389. shader->raw_shader_source = prop->value_blob;
  11390. break;
  11391. }
  11392. }
  11393. ufbxi_check(ufbxi_shader_texture_find_prefix(uc, texture, shader));
  11394. if (shader->shader_name.length == 0) {
  11395. ufbx_string name = shader->prop_prefix;
  11396. if (ufbxi_remove_suffix_c(&name, " Parameters/Connections|")) {
  11397. size_t begin = name.length;
  11398. while (begin > 0 && name.data[begin - 1] != '|') {
  11399. begin--;
  11400. }
  11401. shader->shader_name.data = name.data + begin;
  11402. shader->shader_name.length = name.length - begin;
  11403. ufbxi_check(ufbxi_push_string_place_str(&uc->string_pool, &shader->shader_name, false));
  11404. }
  11405. }
  11406. if (shader->shader_name.length == 0) {
  11407. if (max_texture.length > 0) {
  11408. shader->shader_name = max_texture;
  11409. }
  11410. }
  11411. if (classid != 0) {
  11412. shader->shader_type_id = classid;
  11413. }
  11414. if (shader->prop_prefix.length == 0) {
  11415. // If we not find any shader properties so we might have guessed wrong.
  11416. // We "leak" (freed with scene) the shader in this case but it's negligible.
  11417. return 1;
  11418. }
  11419. ufbxi_for_list(ufbx_prop, prop, texture->props.props) {
  11420. ufbx_string name = prop->name;
  11421. if (!ufbxi_remove_prefix_str(&name, shader->prop_prefix)) continue;
  11422. // Check if this property is a modifier to an existing input.
  11423. ufbx_string base_name = name;
  11424. if (ufbxi_remove_suffix_c(&base_name, "_map") || ufbxi_remove_suffix_c(&base_name, ".shader")) {
  11425. ufbx_shader_texture_input *base = ufbx_find_shader_texture_input_len(shader, base_name.data, base_name.length);
  11426. if (base) {
  11427. base->texture_prop = prop;
  11428. continue;
  11429. }
  11430. } else if (ufbxi_remove_suffix_c(&base_name, ".connected") || ufbxi_remove_suffix_c(&base_name, "Enabled")) {
  11431. ufbx_shader_texture_input *base = ufbx_find_shader_texture_input_len(shader, base_name.data, base_name.length);
  11432. if (base) {
  11433. base->texture_enabled_prop = prop;
  11434. continue;
  11435. }
  11436. }
  11437. // Use `uc->tmp_arr` to store the texture inputs so we can search them while we insert new ones.
  11438. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size,
  11439. (shader->inputs.count + 1) * sizeof(ufbx_shader_texture_input)));
  11440. shader->inputs.data = (ufbx_shader_texture_input*)uc->tmp_arr;
  11441. // Add a new property
  11442. ufbx_shader_texture_input *input = &shader->inputs.data[shader->inputs.count++];
  11443. memset(input, 0, sizeof(ufbx_shader_texture_input));
  11444. // NOTE: This is a bit hackish, we are using a suffix of an interned string. It won't compare
  11445. // pointer equal to the same string but that shouldn't matter..
  11446. input->name = name;
  11447. // Connect the property only, values and textures etc are fetched in `ufbxi_update_shader_texture()`.
  11448. input->prop = prop;
  11449. }
  11450. // Retain the shader inputs
  11451. shader->inputs.data = ufbxi_push_copy(&uc->result, ufbx_shader_texture_input, shader->inputs.count, shader->inputs.data);
  11452. ufbxi_check(shader->inputs.data);
  11453. texture->shader = shader;
  11454. texture->type = UFBX_TEXTURE_SHADER;
  11455. uc->scene.metadata.num_shader_textures++;
  11456. if (!uc->opts.disable_quirks) {
  11457. ufbxi_nounroll for (size_t i = 0; i < ufbxi_arraycount(ufbxi_file_shaders); i++) {
  11458. const ufbxi_file_shader *fs = &ufbxi_file_shaders[i];
  11459. if ((fs->shader_id && shader->shader_type_id == fs->shader_id) || !strcmp(shader->shader_name.data, fs->shader_name)) {
  11460. ufbx_shader_texture_input *input = ufbx_find_shader_texture_input(shader, fs->input_name);
  11461. if (input) {
  11462. // TODO: Support for specifying relative filename here if ever needed
  11463. ufbx_prop *prop = input->prop;
  11464. texture->absolute_filename = prop->value_str;
  11465. texture->raw_absolute_filename = prop->value_blob;
  11466. texture->type = UFBX_TEXTURE_FILE;
  11467. break;
  11468. }
  11469. }
  11470. }
  11471. }
  11472. ufbxi_update_shader_texture(texture, shader);
  11473. return 1;
  11474. }
  11475. ufbxi_noinline static void ufbxi_propagate_main_textures(ufbx_scene *scene)
  11476. {
  11477. // We need to do at least 2^(N-1) passes for N shader textures
  11478. size_t mask = scene->metadata.num_shader_textures;
  11479. while (mask) {
  11480. mask >>= 1;
  11481. ufbxi_for_ptr_list(ufbx_texture, p_texture, scene->textures) {
  11482. ufbx_texture *texture = *p_texture;
  11483. ufbx_shader_texture *shader = texture->shader;
  11484. if (!shader) continue;
  11485. ufbx_texture *main = shader->main_texture;
  11486. if (!main || shader->main_texture_output_index != 0) continue;
  11487. ufbx_shader_texture *main_shader = main->shader;
  11488. if (!main_shader || !main_shader->main_texture) continue;
  11489. shader->main_texture = main_shader->main_texture;
  11490. shader->main_texture_output_index = main_shader->main_texture_output_index;
  11491. }
  11492. }
  11493. // Remove cyclic main textures
  11494. ufbxi_for_ptr_list(ufbx_texture, p_texture, scene->textures) {
  11495. ufbx_texture *texture = *p_texture;
  11496. ufbx_shader_texture *shader = texture->shader;
  11497. if (!shader || !shader->main_texture || shader->main_texture_output_index != 0) continue;
  11498. ufbx_texture *main = shader->main_texture;
  11499. if (main && main->shader && main->shader->main_texture) {
  11500. // Should have been propagated to `texture`
  11501. shader->main_texture = NULL;
  11502. }
  11503. }
  11504. ufbxi_for_ptr_list(ufbx_texture, p_texture, scene->textures) {
  11505. ufbx_texture *texture = *p_texture;
  11506. ufbx_shader_texture *shader = texture->shader;
  11507. if (!shader) continue;
  11508. ufbxi_for_list(ufbx_shader_texture_input, input, shader->inputs) {
  11509. if (!input->texture || !input->texture->shader) continue;
  11510. ufbx_shader_texture *input_shader = input->texture->shader;
  11511. if (input_shader->main_texture) {
  11512. input->texture = input_shader->main_texture;
  11513. input->texture_output_index = input_shader->main_texture_output_index;
  11514. }
  11515. }
  11516. }
  11517. ufbxi_for_ptr_list(ufbx_material, p_material, scene->materials) {
  11518. ufbx_material *material = *p_material;
  11519. ufbxi_for_list(ufbx_material_texture, tex, material->textures) {
  11520. ufbx_shader_texture *shader = tex->texture->shader;
  11521. if (shader && shader->main_texture && shader->main_texture_output_index == 0) {
  11522. tex->texture = shader->main_texture;
  11523. }
  11524. }
  11525. }
  11526. }
  11527. typedef struct {
  11528. ufbx_texture *texture;
  11529. size_t order;
  11530. } ufbxi_ordered_texture;
  11531. ufbxi_noinline static bool ufbxi_ordered_texture_less_texture(void *user, const void *va, const void *vb)
  11532. {
  11533. (void)user;
  11534. const ufbxi_ordered_texture *a = (const ufbxi_ordered_texture*)va, *b = (const ufbxi_ordered_texture*)vb;
  11535. return a->texture < b->texture;
  11536. }
  11537. ufbxi_noinline static bool ufbxi_ordered_texture_less_order(void *user, const void *va, const void *vb)
  11538. {
  11539. (void)user;
  11540. const ufbxi_ordered_texture *a = (const ufbxi_ordered_texture*)va, *b = (const ufbxi_ordered_texture*)vb;
  11541. return a->order < b->order;
  11542. }
  11543. ufbxi_nodiscard ufbxi_noinline static int ufbxi_deduplicate_textures(ufbxi_context *uc, ufbxi_buf *dst_buf, ufbxi_ordered_texture **p_dst, size_t *p_dst_count, size_t count)
  11544. {
  11545. ufbxi_ordered_texture *textures = ufbxi_push_pop(dst_buf, &uc->tmp_stack, ufbxi_ordered_texture, count);
  11546. ufbxi_check(textures);
  11547. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, count * sizeof(ufbxi_ordered_texture)));
  11548. ufbxi_stable_sort(sizeof(ufbxi_ordered_texture), 16, textures, uc->tmp_arr, count, &ufbxi_ordered_texture_less_texture, NULL);
  11549. // Remove adjacent duplicates
  11550. size_t dst_ix = 0;
  11551. for (size_t src_ix = 0; src_ix < count; src_ix++) {
  11552. if (src_ix > 0 && textures[src_ix - 1].texture == textures[src_ix].texture) {
  11553. continue;
  11554. } else {
  11555. if (src_ix != dst_ix) {
  11556. textures[dst_ix] = textures[src_ix];
  11557. }
  11558. dst_ix++;
  11559. }
  11560. }
  11561. size_t new_count = dst_ix;
  11562. ufbxi_stable_sort(sizeof(ufbxi_ordered_texture), 16, textures, uc->tmp_arr, new_count, &ufbxi_ordered_texture_less_order, NULL);
  11563. *p_dst_count = new_count;
  11564. *p_dst = textures;
  11565. return 1;
  11566. }
  11567. typedef enum {
  11568. UFBXI_FILE_TEXTURE_FETCH_INITIAL,
  11569. UFBXI_FILE_TEXTURE_FETCH_STARTED,
  11570. UFBXI_FILE_TEXTURE_FETCH_FINISHED,
  11571. } ufbxi_file_texture_fetch_state;
  11572. // Populate `ufbx_texture.file_textures[]` arrays.
  11573. ufbxi_nodiscard ufbxi_noinline static int ufbxi_fetch_file_textures(ufbxi_context *uc)
  11574. {
  11575. // We keep pointers to `ufbx_texture` in `tmp_stack` as a working set, since we don't know
  11576. // how deep the shader graphs might be.
  11577. // Start by pushing all the textures into the stack
  11578. size_t num_stack_textures = uc->scene.textures.count;
  11579. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_texture*, num_stack_textures, uc->scene.textures.data));
  11580. // Compressed `ufbxi_file_texture_fetch_state`
  11581. uint8_t *states = ufbxi_push_zero(&uc->tmp, uint8_t, uc->scene.textures.count);
  11582. ufbxi_check(states);
  11583. while (num_stack_textures-- > 0) {
  11584. ufbx_texture *texture = NULL;
  11585. ufbxi_pop(&uc->tmp_stack, ufbx_texture*, 1, &texture);
  11586. ufbxi_file_texture_fetch_state state = (ufbxi_file_texture_fetch_state)states[texture->typed_id];
  11587. if (state == UFBXI_FILE_TEXTURE_FETCH_FINISHED) continue;
  11588. ufbx_shader_texture *shader = texture->shader;
  11589. if (state == UFBXI_FILE_TEXTURE_FETCH_STARTED) {
  11590. states[texture->typed_id] = UFBXI_FILE_TEXTURE_FETCH_FINISHED;
  11591. // HACK: Reuse `tmp_parse` for storing intermediate information as we can clear it.
  11592. ufbxi_buf_clear(&uc->tmp_parse);
  11593. // Now all non-cyclical dependents should be processed.
  11594. size_t num_deps = 0;
  11595. if (texture->type == UFBX_TEXTURE_FILE) {
  11596. ufbxi_ordered_texture *dst = ufbxi_push(&uc->tmp_stack, ufbxi_ordered_texture, 1);
  11597. ufbxi_check(dst);
  11598. dst->texture = texture;
  11599. dst->order = num_deps++;
  11600. }
  11601. ufbxi_for_list(ufbx_texture_layer, layer, texture->layers) {
  11602. ufbx_texture *dep_tex = layer->texture;
  11603. if (dep_tex->file_textures.count > 0) {
  11604. ufbxi_ordered_texture *dst = ufbxi_push(&uc->tmp_stack, ufbxi_ordered_texture, 1);
  11605. ufbxi_check(dst);
  11606. dst->texture = dep_tex;
  11607. dst->order = num_deps++;
  11608. }
  11609. }
  11610. if (shader) {
  11611. ufbxi_for_list(ufbx_shader_texture_input, input, shader->inputs) {
  11612. ufbx_texture *dep_tex = input->texture;
  11613. if (dep_tex && dep_tex->file_textures.count > 0) {
  11614. ufbxi_ordered_texture *dst = ufbxi_push(&uc->tmp_stack, ufbxi_ordered_texture, 1);
  11615. ufbxi_check(dst);
  11616. dst->texture = dep_tex;
  11617. dst->order = num_deps++;
  11618. }
  11619. }
  11620. }
  11621. // Deduplicate the direct dependencies first
  11622. ufbxi_ordered_texture *deps;
  11623. ufbxi_check(ufbxi_deduplicate_textures(uc, &uc->tmp_parse, &deps, &num_deps, num_deps));
  11624. if (num_deps == 1) {
  11625. // If we have only a single dependency (that is not the same one) we can just copy the pointer
  11626. texture->file_textures = deps[0].texture->file_textures;
  11627. } else {
  11628. // Now collect all the file textures and deduplicate them
  11629. size_t num_files = 0;
  11630. ufbxi_for(ufbxi_ordered_texture, dep, deps, num_deps) {
  11631. ufbxi_for_ptr_list(ufbx_texture, p_tex, dep->texture->file_textures) {
  11632. ufbxi_ordered_texture *dst = ufbxi_push(&uc->tmp_stack, ufbxi_ordered_texture, 1);
  11633. ufbxi_check(dst);
  11634. dst->texture = *p_tex;
  11635. dst->order = num_files++;
  11636. }
  11637. }
  11638. // Deduplicate the file textures
  11639. ufbxi_ordered_texture *files;
  11640. ufbxi_check(ufbxi_deduplicate_textures(uc, &uc->tmp_parse, &files, &num_files, num_files));
  11641. texture->file_textures.count = num_files;
  11642. texture->file_textures.data = ufbxi_push(&uc->result, ufbx_texture*, num_files);
  11643. ufbxi_check(texture->file_textures.data);
  11644. for (size_t i = 0; i < num_files; i++) {
  11645. texture->file_textures.data[i] = files[i].texture;
  11646. }
  11647. }
  11648. } else {
  11649. if (texture->type == UFBX_TEXTURE_FILE) {
  11650. // Simple case: Just point to self
  11651. texture->file_textures.count = 1;
  11652. texture->file_textures.data = ufbxi_push(&uc->result, ufbx_texture*, 1);
  11653. ufbxi_check(texture->file_textures.data);
  11654. texture->file_textures.data[0] = texture;
  11655. // In simple cases we can quit here, for more complex file textures queue
  11656. // the texture in case there are other file textures as inputs.
  11657. if (!texture->shader) {
  11658. states[texture->typed_id] = UFBXI_FILE_TEXTURE_FETCH_FINISHED;
  11659. continue;
  11660. }
  11661. }
  11662. // Complex: Process all dependencies first
  11663. states[texture->typed_id] = UFBXI_FILE_TEXTURE_FETCH_STARTED;
  11664. // Push self first so we can return after processing depenencies
  11665. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_texture*, 1, &texture));
  11666. num_stack_textures++;
  11667. ufbxi_for_list(ufbx_texture_layer, layer, texture->layers) {
  11668. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_texture*, 1, &layer->texture));
  11669. num_stack_textures++;
  11670. }
  11671. if (shader) {
  11672. ufbxi_for_list(ufbx_shader_texture_input, input, shader->inputs) {
  11673. if (input->texture) {
  11674. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_texture*, 1, &input->texture));
  11675. num_stack_textures++;
  11676. }
  11677. }
  11678. }
  11679. }
  11680. }
  11681. return 1;
  11682. }
  11683. ufbxi_noinline static size_t ufbxi_next_path_segment(const char *data, size_t begin, size_t length)
  11684. {
  11685. for (size_t i = begin; i < length; i++) {
  11686. if (data[i] == '/' || data[i] == '\\') {
  11687. return i;
  11688. }
  11689. }
  11690. return length;
  11691. }
  11692. ufbxi_nodiscard ufbxi_noinline static int ufbxi_absolute_to_relative_path(ufbxi_context *uc, ufbxi_strblob *p_dst, const ufbxi_strblob *p_rel, const ufbxi_strblob *p_src, bool raw)
  11693. {
  11694. const char *rel = ufbxi_strblob_data(p_rel, raw);
  11695. const char *src = ufbxi_strblob_data(p_src, raw);
  11696. size_t rel_length = ufbxi_strblob_length(p_rel, raw);
  11697. size_t src_length = ufbxi_strblob_length(p_src, raw);
  11698. if (rel_length == 0 || src_length == 0) return 1;
  11699. // Absolute paths must start with the same character (either drive or '/')
  11700. if (rel[0] != src[0]) return 1;
  11701. // Find the last directory of the path we want to be relative to
  11702. while (rel_length > 0 && (rel[rel_length - 1] != '/' && rel[rel_length - 1] != '\\')) {
  11703. rel_length--;
  11704. }
  11705. if (rel_length == 0) return 1;
  11706. char separator = rel[rel_length - 1];
  11707. size_t max_length = rel_length * 2 + src_length;
  11708. ufbxi_check(ufbxi_grow_array(&uc->ator_tmp, &uc->tmp_arr, &uc->tmp_arr_size, max_length));
  11709. char *tmp = uc->tmp_arr;
  11710. size_t tmp_length = 0;
  11711. size_t rel_begin = 0;
  11712. size_t src_begin = 0;
  11713. while (rel_begin < rel_length && src_begin < src_length) {
  11714. size_t rel_end = ufbxi_next_path_segment(rel, rel_begin, rel_length);
  11715. size_t src_end = ufbxi_next_path_segment(src, src_begin, src_length);
  11716. if (rel_end != src_end && memcmp(rel + rel_begin, src + src_begin, src_end - src_begin) != 0) break;
  11717. rel_begin = rel_end + 1;
  11718. src_begin = src_end + 1;
  11719. }
  11720. while (rel_begin < rel_length) {
  11721. size_t rel_end = ufbxi_next_path_segment(rel, rel_begin, rel_length);
  11722. tmp[tmp_length++] = '.';
  11723. tmp[tmp_length++] = '.';
  11724. tmp[tmp_length++] = separator;
  11725. rel_begin = rel_end + 1;
  11726. }
  11727. while (src_begin < src_length) {
  11728. size_t src_end = ufbxi_next_path_segment(src, src_begin, src_length);
  11729. size_t len = src_end - src_begin;
  11730. memcpy(tmp + tmp_length, src + src_begin, len);
  11731. tmp_length += len;
  11732. if (src_end < src_length) {
  11733. tmp[tmp_length++] = separator;
  11734. }
  11735. src_begin = src_end + 1;
  11736. }
  11737. ufbx_assert(tmp_length <= max_length);
  11738. const char *dst = ufbxi_push_string(&uc->string_pool, tmp, tmp_length, NULL, true);
  11739. ufbxi_check(dst);
  11740. ufbxi_strblob_set(p_dst, dst, tmp_length, raw);
  11741. return 1;
  11742. }
  11743. ufbxi_nodiscard ufbxi_noinline static int ufbxi_resolve_filenames(ufbxi_context *uc, ufbxi_strblob *filename, ufbxi_strblob *absolute_filename, ufbxi_strblob *relative_filename, bool raw)
  11744. {
  11745. if (ufbxi_strblob_length(relative_filename, raw) == 0) {
  11746. const ufbxi_strblob *original_file_path = raw
  11747. ? (const ufbxi_strblob*)&uc->scene.metadata.raw_original_file_path
  11748. : (const ufbxi_strblob*)&uc->scene.metadata.original_file_path;
  11749. ufbxi_check(ufbxi_absolute_to_relative_path(uc, relative_filename, original_file_path, absolute_filename, raw));
  11750. }
  11751. ufbxi_check(ufbxi_resolve_relative_filename(uc, filename, relative_filename, raw));
  11752. return 1;
  11753. }
  11754. ufbxi_nodiscard ufbxi_noinline static int ufbxi_validate_indices(ufbxi_context *uc, ufbx_uint32_list *indices, size_t max_index)
  11755. {
  11756. if (max_index == 0 && uc->opts.index_error_handling == UFBX_INDEX_ERROR_HANDLING_CLAMP) {
  11757. indices->data = NULL;
  11758. indices->count = 0;
  11759. return 1;
  11760. }
  11761. ufbxi_nounroll ufbxi_for_list(uint32_t, p_ix, *indices) {
  11762. uint32_t ix = *p_ix;
  11763. if (ix >= max_index) {
  11764. ufbxi_check(ufbxi_fix_index(uc, p_ix, ix, (uint32_t)max_index - 1));
  11765. }
  11766. }
  11767. return 1;
  11768. }
  11769. ufbxi_nodiscard ufbxi_noinline static int ufbxi_finalize_scene(ufbxi_context *uc)
  11770. {
  11771. size_t num_elements = uc->num_elements;
  11772. uc->scene.elements.count = num_elements;
  11773. uc->scene.elements.data = ufbxi_push(&uc->result, ufbx_element*, num_elements);
  11774. ufbxi_check(uc->scene.elements.data);
  11775. uc->scene.metadata.element_buffer_size = uc->tmp_element_byte_offset;
  11776. char *element_data = (char*)ufbxi_push_pop(&uc->result, &uc->tmp_elements, uint64_t, uc->tmp_element_byte_offset/8);
  11777. ufbxi_buf_free(&uc->tmp_elements);
  11778. ufbxi_check(element_data);
  11779. size_t *element_offsets = ufbxi_push_pop(&uc->tmp, &uc->tmp_element_offsets, size_t, uc->tmp_element_offsets.num_items);
  11780. ufbxi_buf_free(&uc->tmp_element_offsets);
  11781. ufbxi_check(element_offsets);
  11782. for (size_t i = 0; i < num_elements; i++) {
  11783. uc->scene.elements.data[i] = (ufbx_element*)(element_data + element_offsets[i]);
  11784. }
  11785. uc->scene.elements.count = num_elements;
  11786. ufbxi_buf_free(&uc->tmp_element_offsets);
  11787. uc->scene.metadata.original_file_path = ufbx_find_string(&uc->scene.metadata.scene_props, "DocumentUrl", ufbx_empty_string);
  11788. uc->scene.metadata.raw_original_file_path = ufbx_find_blob(&uc->scene.metadata.scene_props, "DocumentUrl", ufbx_empty_blob);
  11789. // Resolve and add the connections to elements
  11790. ufbxi_check(ufbxi_resolve_connections(uc));
  11791. ufbxi_check(ufbxi_add_connections_to_elements(uc));
  11792. ufbxi_check(ufbxi_linearize_nodes(uc));
  11793. for (size_t type = 0; type < UFBX_ELEMENT_TYPE_COUNT; type++) {
  11794. size_t num_typed = uc->tmp_typed_element_offsets[type].num_items;
  11795. size_t *typed_offsets = ufbxi_push_pop(&uc->tmp, &uc->tmp_typed_element_offsets[type], size_t, num_typed);
  11796. ufbxi_buf_free(&uc->tmp_typed_element_offsets[type]);
  11797. ufbxi_check(typed_offsets);
  11798. ufbx_element_list *typed_elems = &uc->scene.elements_by_type[type];
  11799. typed_elems->count = num_typed;
  11800. typed_elems->data = ufbxi_push(&uc->result, ufbx_element*, num_typed);
  11801. ufbxi_check(typed_elems->data);
  11802. for (size_t i = 0; i < num_typed; i++) {
  11803. typed_elems->data[i] = (ufbx_element*)(element_data + typed_offsets[i]);
  11804. }
  11805. ufbxi_buf_free(&uc->tmp_typed_element_offsets[type]);
  11806. }
  11807. // Create named elements
  11808. uc->scene.elements_by_name.count = num_elements;
  11809. uc->scene.elements_by_name.data = ufbxi_push(&uc->result, ufbx_name_element, num_elements);
  11810. ufbxi_check(uc->scene.elements_by_name.data);
  11811. for (size_t i = 0; i < num_elements; i++) {
  11812. ufbx_element *elem = uc->scene.elements.data[i];
  11813. ufbx_name_element *name_elem = &uc->scene.elements_by_name.data[i];
  11814. name_elem->name = elem->name;
  11815. name_elem->type = elem->type;
  11816. name_elem->_internal_key = ufbxi_get_name_key(elem->name.data, elem->name.length);
  11817. name_elem->element = elem;
  11818. }
  11819. ufbxi_check(ufbxi_sort_name_elements(uc, uc->scene.elements_by_name.data, num_elements));
  11820. // Setup node children arrays and attribute pointers/lists
  11821. ufbxi_for_ptr_list(ufbx_node, p_node, uc->scene.nodes) {
  11822. ufbx_node *node = *p_node, *parent = node->parent;
  11823. if (parent) {
  11824. parent->children.count++;
  11825. if (parent->children.data == NULL) {
  11826. parent->children.data = p_node;
  11827. }
  11828. }
  11829. ufbx_connection_list conns = ufbxi_find_dst_connections(&node->element, NULL);
  11830. ufbxi_for_list(ufbx_connection, conn, conns) {
  11831. ufbx_element *elem = conn->src;
  11832. ufbx_element_type type = elem->type;
  11833. if (!(type >= UFBX_ELEMENT_TYPE_FIRST_ATTRIB && type <= UFBX_ELEMENT_TYPE_LAST_ATTRIB)) continue;
  11834. size_t index = node->all_attribs.count++;
  11835. if (index == 0) {
  11836. node->attrib = elem;
  11837. node->attrib_type = type;
  11838. } else {
  11839. if (index == 1) {
  11840. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_element*, 1, &node->attrib));
  11841. }
  11842. ufbxi_check(ufbxi_push_copy(&uc->tmp_stack, ufbx_element*, 1, &elem));
  11843. }
  11844. switch (elem->type) {
  11845. case UFBX_ELEMENT_MESH: node->mesh = (ufbx_mesh*)elem; break;
  11846. case UFBX_ELEMENT_LIGHT: node->light = (ufbx_light*)elem; break;
  11847. case UFBX_ELEMENT_CAMERA: node->camera = (ufbx_camera*)elem; break;
  11848. case UFBX_ELEMENT_BONE: node->bone = (ufbx_bone*)elem; break;
  11849. default: /* No shorthand */ break;
  11850. }
  11851. }
  11852. if (node->all_attribs.count > 1) {
  11853. node->all_attribs.data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_element*, node->all_attribs.count);
  11854. ufbxi_check(node->all_attribs.data);
  11855. } else if (node->all_attribs.count == 1) {
  11856. node->all_attribs.data = &node->attrib;
  11857. }
  11858. ufbxi_check(ufbxi_fetch_dst_elements(uc, &node->materials, &node->element, false, NULL, UFBX_ELEMENT_MATERIAL));
  11859. }
  11860. // Resolve bind pose bones that don't use the normal connection system
  11861. ufbxi_for_ptr_list(ufbx_pose, p_pose, uc->scene.poses) {
  11862. ufbx_pose *pose = *p_pose;
  11863. // HACK: Transport `ufbxi_tmp_bone_pose` array through the `ufbx_bone_pose` pointer
  11864. size_t num_bones = pose->bone_poses.count;
  11865. ufbxi_tmp_bone_pose *tmp_poses = (ufbxi_tmp_bone_pose*)pose->bone_poses.data;
  11866. pose->bone_poses.data = ufbxi_push(&uc->result, ufbx_bone_pose, num_bones);
  11867. ufbxi_check(pose->bone_poses.data);
  11868. // Filter only found bones
  11869. pose->bone_poses.count = 0;
  11870. for (size_t i = 0; i < num_bones; i++) {
  11871. ufbx_element *elem = ufbxi_find_element_by_fbx_id(uc, tmp_poses[i].bone_fbx_id);
  11872. if (!elem || elem->type != UFBX_ELEMENT_NODE) continue;
  11873. ufbx_bone_pose *bone = &pose->bone_poses.data[pose->bone_poses.count++];
  11874. bone->bone_node = (ufbx_node*)elem;
  11875. bone->bone_to_world = tmp_poses[i].bone_to_world;
  11876. if (pose->bind_pose) {
  11877. ufbx_connection_list node_conns = ufbxi_find_src_connections(elem, NULL);
  11878. ufbxi_for_list(ufbx_connection, conn, node_conns) {
  11879. if (conn->dst->type != UFBX_ELEMENT_SKIN_CLUSTER) continue;
  11880. ufbx_skin_cluster *cluster = (ufbx_skin_cluster*)conn->dst;
  11881. if (ufbxi_matrix_all_zero(&cluster->bind_to_world)) {
  11882. cluster->bind_to_world = bone->bone_to_world;
  11883. }
  11884. }
  11885. }
  11886. }
  11887. }
  11888. // Fetch pointers that may break elements
  11889. // Setup node attribute instances
  11890. for (int type = UFBX_ELEMENT_TYPE_FIRST_ATTRIB; type <= UFBX_ELEMENT_TYPE_LAST_ATTRIB; type++) {
  11891. ufbxi_for_ptr_list(ufbx_element, p_elem, uc->scene.elements_by_type[type]) {
  11892. ufbx_element *elem = *p_elem;
  11893. ufbxi_check(ufbxi_fetch_src_elements(uc, &elem->instances, elem, false, NULL, UFBX_ELEMENT_NODE));
  11894. }
  11895. }
  11896. bool search_node = uc->version < 7000;
  11897. ufbxi_for_ptr_list(ufbx_skin_cluster, p_cluster, uc->scene.skin_clusters) {
  11898. ufbx_skin_cluster *cluster = *p_cluster;
  11899. cluster->bone_node = (ufbx_node*)ufbxi_fetch_dst_element(&cluster->element, false, NULL, UFBX_ELEMENT_NODE);
  11900. }
  11901. ufbxi_for_ptr_list(ufbx_skin_deformer, p_skin, uc->scene.skin_deformers) {
  11902. ufbx_skin_deformer *skin = *p_skin;
  11903. ufbxi_check(ufbxi_fetch_dst_elements(uc, &skin->clusters, &skin->element, false, NULL, UFBX_ELEMENT_SKIN_CLUSTER));
  11904. // Remove clusters without a valid `bone`
  11905. if (!uc->opts.connect_broken_elements) {
  11906. size_t num_broken = 0;
  11907. for (size_t i = 0; i < skin->clusters.count; i++) {
  11908. if (!skin->clusters.data[i]->bone_node) {
  11909. num_broken++;
  11910. } else if (num_broken > 0) {
  11911. skin->clusters.data[i - num_broken] = skin->clusters.data[i];
  11912. }
  11913. }
  11914. skin->clusters.count -= num_broken;
  11915. }
  11916. size_t total_weights = 0;
  11917. ufbxi_for_ptr_list(ufbx_skin_cluster, p_cluster, skin->clusters) {
  11918. ufbx_skin_cluster *cluster = *p_cluster;
  11919. ufbxi_check(SIZE_MAX - total_weights > cluster->num_weights);
  11920. total_weights += cluster->num_weights;
  11921. }
  11922. size_t num_vertices = 0;
  11923. // Iterate through meshes so we can pad the vertices to the largest one
  11924. {
  11925. ufbx_connection_list conns = ufbxi_find_src_connections(&skin->element, NULL);
  11926. ufbxi_for_list(ufbx_connection, conn, conns) {
  11927. ufbx_mesh *mesh = NULL;
  11928. if (conn->dst_prop.length > 0) continue;
  11929. if (conn->dst->type == UFBX_ELEMENT_MESH) {
  11930. mesh = (ufbx_mesh*)conn->dst;
  11931. } else if (conn->dst->type == UFBX_ELEMENT_NODE) {
  11932. mesh = ((ufbx_node*)conn->dst)->mesh;
  11933. }
  11934. if (!mesh) continue;
  11935. num_vertices = ufbxi_max_sz(num_vertices, mesh->num_vertices);
  11936. }
  11937. }
  11938. if (!uc->opts.skip_skin_vertices) {
  11939. skin->vertices.count = num_vertices;
  11940. skin->vertices.data = ufbxi_push_zero(&uc->result, ufbx_skin_vertex, num_vertices);
  11941. ufbxi_check(skin->vertices.data);
  11942. skin->weights.count = total_weights;
  11943. skin->weights.data = ufbxi_push_zero(&uc->result, ufbx_skin_weight, total_weights);
  11944. ufbxi_check(skin->weights.data);
  11945. // Count the number of weights per vertex
  11946. ufbxi_for_ptr_list(ufbx_skin_cluster, p_cluster, skin->clusters) {
  11947. ufbx_skin_cluster *cluster = *p_cluster;
  11948. for (size_t i = 0; i < cluster->num_weights; i++) {
  11949. uint32_t vertex = cluster->vertices.data[i];
  11950. if (vertex < num_vertices) {
  11951. skin->vertices.data[vertex].num_weights++;
  11952. }
  11953. }
  11954. }
  11955. ufbx_real default_dq = skin->skinning_method == UFBX_SKINNING_METHOD_DUAL_QUATERNION ? 1.0f : 0.0f;
  11956. // Prefix sum to assign the vertex weight offsets and set up default DQ values
  11957. uint32_t offset = 0;
  11958. uint32_t max_weights = 0;
  11959. for (size_t i = 0; i < num_vertices; i++) {
  11960. skin->vertices.data[i].weight_begin = offset;
  11961. skin->vertices.data[i].dq_weight = default_dq;
  11962. uint32_t num_weights = skin->vertices.data[i].num_weights;
  11963. offset += num_weights;
  11964. skin->vertices.data[i].num_weights = 0;
  11965. if (num_weights > max_weights) max_weights = num_weights;
  11966. }
  11967. ufbx_assert(offset <= total_weights);
  11968. skin->max_weights_per_vertex = max_weights;
  11969. // Copy the DQ weights to vertices
  11970. for (size_t i = 0; i < skin->num_dq_weights; i++) {
  11971. uint32_t vertex = skin->dq_vertices.data[i];
  11972. if (vertex < num_vertices) {
  11973. skin->vertices.data[vertex].dq_weight = skin->dq_weights.data[i];
  11974. }
  11975. }
  11976. // Copy the weights to vertices
  11977. uint32_t cluster_index = 0;
  11978. ufbxi_for_ptr_list(ufbx_skin_cluster, p_cluster, skin->clusters) {
  11979. ufbx_skin_cluster *cluster = *p_cluster;
  11980. for (size_t i = 0; i < cluster->num_weights; i++) {
  11981. uint32_t vertex = cluster->vertices.data[i];
  11982. if (vertex < num_vertices) {
  11983. uint32_t local_index = skin->vertices.data[vertex].num_weights++;
  11984. uint32_t index = skin->vertices.data[vertex].weight_begin + local_index;
  11985. skin->weights.data[index].cluster_index = cluster_index;
  11986. skin->weights.data[index].weight = cluster->weights.data[i];
  11987. }
  11988. }
  11989. cluster_index++;
  11990. }
  11991. // Sort the vertex weights by descending weight value
  11992. ufbxi_check(ufbxi_sort_skin_weights(uc, skin));
  11993. }
  11994. }
  11995. ufbxi_for_ptr_list(ufbx_blend_deformer, p_blend, uc->scene.blend_deformers) {
  11996. ufbx_blend_deformer *blend = *p_blend;
  11997. ufbxi_check(ufbxi_fetch_dst_elements(uc, &blend->channels, &blend->element, false, NULL, UFBX_ELEMENT_BLEND_CHANNEL));
  11998. }
  11999. ufbxi_for_ptr_list(ufbx_cache_deformer, p_deformer, uc->scene.cache_deformers) {
  12000. ufbx_cache_deformer *deformer = *p_deformer;
  12001. deformer->channel = ufbx_find_string(&deformer->props, "ChannelName", ufbx_empty_string);
  12002. deformer->file = (ufbx_cache_file*)ufbxi_fetch_dst_element(&deformer->element, false, NULL, UFBX_ELEMENT_CACHE_FILE);
  12003. }
  12004. ufbxi_for_ptr_list(ufbx_cache_file, p_cache, uc->scene.cache_files) {
  12005. ufbx_cache_file *cache = *p_cache;
  12006. cache->absolute_filename = ufbx_find_string(&cache->props, "CacheAbsoluteFileName", ufbx_empty_string);
  12007. cache->relative_filename = ufbx_find_string(&cache->props, "CacheFileName", ufbx_empty_string);
  12008. cache->raw_absolute_filename = ufbx_find_blob(&cache->props, "CacheAbsoluteFileName", ufbx_empty_blob);
  12009. cache->raw_relative_filename = ufbx_find_blob(&cache->props, "CacheFileName", ufbx_empty_blob);
  12010. int64_t type = ufbx_find_int(&cache->props, "CacheFileType", 0);
  12011. if (type >= 0 && type <= UFBX_CACHE_FILE_FORMAT_MC) {
  12012. cache->format = (ufbx_cache_file_format)type;
  12013. }
  12014. ufbxi_check(ufbxi_resolve_filenames(uc, (ufbxi_strblob*)&cache->filename, (ufbxi_strblob*)&cache->absolute_filename, (ufbxi_strblob*)&cache->relative_filename, false));
  12015. ufbxi_check(ufbxi_resolve_filenames(uc, (ufbxi_strblob*)&cache->raw_filename, (ufbxi_strblob*)&cache->raw_absolute_filename, (ufbxi_strblob*)&cache->raw_relative_filename, true));
  12016. }
  12017. ufbx_assert(uc->tmp_full_weights.num_items == uc->scene.blend_channels.count);
  12018. ufbx_real_list *full_weights = ufbxi_push_pop(&uc->tmp, &uc->tmp_full_weights, ufbx_real_list, uc->tmp_full_weights.num_items);
  12019. ufbxi_buf_free(&uc->tmp_full_weights);
  12020. ufbxi_check(full_weights);
  12021. ufbxi_for_ptr_list(ufbx_blend_channel, p_channel, uc->scene.blend_channels) {
  12022. ufbx_blend_channel *channel = *p_channel;
  12023. ufbxi_check(ufbxi_fetch_blend_keyframes(uc, &channel->keyframes, &channel->element));
  12024. for (size_t i = 0; i < channel->keyframes.count; i++) {
  12025. ufbx_blend_keyframe *key = &channel->keyframes.data[i];
  12026. if (i < full_weights->count) {
  12027. key->target_weight = full_weights->data[i] / (ufbx_real)100.0;
  12028. } else {
  12029. key->target_weight = 1.0f;
  12030. }
  12031. }
  12032. ufbxi_check(ufbxi_sort_blend_keyframes(uc, channel->keyframes.data, channel->keyframes.count));
  12033. full_weights++;
  12034. }
  12035. ufbxi_buf_free(&uc->tmp_full_weights);
  12036. {
  12037. // Generate and patch procedural index buffers
  12038. uint32_t *zero_indices = ufbxi_push(&uc->result, uint32_t, uc->max_zero_indices);
  12039. uint32_t *consecutive_indices = ufbxi_push(&uc->result, uint32_t, uc->max_consecutive_indices);
  12040. ufbxi_check(zero_indices && consecutive_indices);
  12041. memset(zero_indices, 0, sizeof(uint32_t) * uc->max_zero_indices);
  12042. for (size_t i = 0; i < uc->max_consecutive_indices; i++) {
  12043. consecutive_indices[i] = (uint32_t)i;
  12044. }
  12045. uc->zero_indices = zero_indices;
  12046. uc->consecutive_indices = consecutive_indices;
  12047. ufbxi_for_ptr_list(ufbx_mesh, p_mesh, uc->scene.meshes) {
  12048. ufbx_mesh *mesh = *p_mesh;
  12049. ufbxi_patch_index_pointer(uc, &mesh->vertex_position.indices.data);
  12050. ufbxi_patch_index_pointer(uc, &mesh->vertex_normal.indices.data);
  12051. ufbxi_patch_index_pointer(uc, &mesh->vertex_bitangent.indices.data);
  12052. ufbxi_patch_index_pointer(uc, &mesh->vertex_tangent.indices.data);
  12053. ufbxi_patch_index_pointer(uc, &mesh->face_material.data);
  12054. ufbxi_patch_index_pointer(uc, &mesh->skinned_position.indices.data);
  12055. ufbxi_patch_index_pointer(uc, &mesh->skinned_normal.indices.data);
  12056. ufbxi_for_list(ufbx_uv_set, set, mesh->uv_sets) {
  12057. ufbxi_patch_index_pointer(uc, &set->vertex_uv.indices.data);
  12058. ufbxi_patch_index_pointer(uc, &set->vertex_bitangent.indices.data);
  12059. ufbxi_patch_index_pointer(uc, &set->vertex_tangent.indices.data);
  12060. }
  12061. ufbxi_for_list(ufbx_color_set, set, mesh->color_sets) {
  12062. ufbxi_patch_index_pointer(uc, &set->vertex_color.indices.data);
  12063. }
  12064. // Generate normals if necessary
  12065. if (!mesh->vertex_normal.exists && uc->opts.generate_missing_normals) {
  12066. ufbxi_check(ufbxi_generate_normals(uc, mesh));
  12067. }
  12068. // Assign first UV and color sets as the "canonical" ones
  12069. if (mesh->uv_sets.count > 0) {
  12070. mesh->vertex_uv = mesh->uv_sets.data[0].vertex_uv;
  12071. mesh->vertex_bitangent = mesh->uv_sets.data[0].vertex_bitangent;
  12072. mesh->vertex_tangent = mesh->uv_sets.data[0].vertex_tangent;
  12073. }
  12074. if (mesh->color_sets.count > 0) {
  12075. mesh->vertex_color = mesh->color_sets.data[0].vertex_color;
  12076. }
  12077. ufbxi_check(ufbxi_fetch_mesh_materials(uc, &mesh->materials, &mesh->element, true));
  12078. // Patch materials to instances if necessary
  12079. if (mesh->materials.count > 0) {
  12080. ufbxi_for_ptr_list(ufbx_node, p_node, mesh->instances) {
  12081. ufbx_node *node = *p_node;
  12082. if (node->materials.count < mesh->materials.count) {
  12083. ufbx_material **materials = ufbxi_push(&uc->result, ufbx_material*, mesh->materials.count);
  12084. ufbxi_check(materials);
  12085. ufbxi_nounroll for (size_t i = 0; i < node->materials.count; i++) {
  12086. materials[i] = node->materials.data[i];
  12087. }
  12088. ufbxi_nounroll for (size_t i = node->materials.count; i < mesh->materials.count; i++) {
  12089. materials[i] = mesh->materials.data[i].material;
  12090. }
  12091. node->materials.data = materials;
  12092. node->materials.count = mesh->materials.count;
  12093. }
  12094. }
  12095. }
  12096. // Search for a non-standard `ufbx:UVBoundary` property in both the mesh and node
  12097. ufbx_prop *uv_prop = ufbx_find_prop(&mesh->props, "ufbx:UVBoundary");
  12098. if (!uv_prop) {
  12099. ufbxi_for_ptr_list(ufbx_node, p_node, mesh->instances) {
  12100. uv_prop = ufbx_find_prop(&(*p_node)->props, "ufbx:UVBoundary");
  12101. if (uv_prop) break;
  12102. }
  12103. }
  12104. if (uv_prop && uv_prop->value_int >= 0 && uv_prop->value_int <= UFBX_SUBDIVISION_BOUNDARY_SHARP_INTERIOR) {
  12105. mesh->subdivision_uv_boundary = (ufbx_subdivision_boundary)uv_prop->value_int;
  12106. } else {
  12107. mesh->subdivision_uv_boundary = UFBX_SUBDIVISION_BOUNDARY_SHARP_BOUNDARY;
  12108. }
  12109. // Push a NULL material if necessary if requested
  12110. if (mesh->materials.count == 0 && uc->opts.allow_null_material) {
  12111. mesh->materials.data = ufbxi_push_zero(&uc->result, ufbx_mesh_material, 1);
  12112. ufbxi_check(mesh->materials.data);
  12113. mesh->materials.count = 1;
  12114. }
  12115. if (mesh->materials.count == 1) {
  12116. // Use the shared consecutive index buffer for mesh faces if there's only one material
  12117. // See HACK(consecutive-faces) in `ufbxi_read_mesh()`.
  12118. ufbx_mesh_material *mat = &mesh->materials.data[0];
  12119. mat->num_faces = mesh->num_faces;
  12120. mat->num_triangles = mesh->num_triangles;
  12121. mat->face_indices.data = uc->consecutive_indices;
  12122. mat->face_indices.count = mat->num_faces;
  12123. mesh->face_material.data = uc->zero_indices;
  12124. mesh->face_material.count = mesh->num_faces;
  12125. } else if (mesh->materials.count > 0 && mesh->face_material.count) {
  12126. size_t num_materials = mesh->materials.count;
  12127. // Count the number of faces and triangles per material
  12128. for (size_t i = 0; i < mesh->num_faces; i++) {
  12129. ufbx_face face = mesh->faces.data[i];
  12130. uint32_t mat_ix = mesh->face_material.data[i];
  12131. if (mat_ix >= num_materials) {
  12132. mesh->face_material.data[i] = 0;
  12133. mat_ix = 0;
  12134. }
  12135. mesh->materials.data[mat_ix].num_faces++;
  12136. if (face.num_indices >= 3) {
  12137. mesh->materials.data[mat_ix].num_triangles += face.num_indices - 2;
  12138. }
  12139. }
  12140. // Allocate per-material buffers (clear `num_faces` to 0 to re-use it as
  12141. // an index when fetching the face indices).
  12142. ufbxi_for_list(ufbx_mesh_material, mat, mesh->materials) {
  12143. mat->face_indices.count = mat->num_faces;
  12144. mat->face_indices.data = ufbxi_push(&uc->result, uint32_t, mat->num_faces);
  12145. ufbxi_check(mat->face_indices.data);
  12146. mat->num_faces = 0;
  12147. }
  12148. // Fetch the per-material face indices
  12149. for (size_t i = 0; i < mesh->num_faces; i++) {
  12150. uint32_t mat_ix = mesh->face_material.data[i];
  12151. if (mat_ix < num_materials) {
  12152. ufbx_mesh_material *mat = &mesh->materials.data[mat_ix];
  12153. mat->face_indices.data[mat->num_faces++] = (uint32_t)i;
  12154. }
  12155. }
  12156. } else {
  12157. mesh->face_material.data = NULL;
  12158. mesh->face_material.count = 0;
  12159. }
  12160. // Blender writes materials attached to models even in 7x00
  12161. // TODO: Should per-instance materials be supported?
  12162. // Fetch deformers
  12163. ufbxi_check(ufbxi_fetch_dst_elements(uc, &mesh->skin_deformers, &mesh->element, search_node, NULL, UFBX_ELEMENT_SKIN_DEFORMER));
  12164. ufbxi_check(ufbxi_fetch_dst_elements(uc, &mesh->blend_deformers, &mesh->element, search_node, NULL, UFBX_ELEMENT_BLEND_DEFORMER));
  12165. ufbxi_check(ufbxi_fetch_dst_elements(uc, &mesh->cache_deformers, &mesh->element, search_node, NULL, UFBX_ELEMENT_CACHE_DEFORMER));
  12166. ufbxi_check(ufbxi_fetch_deformers(uc, &mesh->all_deformers, &mesh->element, search_node));
  12167. // Update metadata
  12168. if (mesh->max_face_triangles > uc->scene.metadata.max_face_triangles) {
  12169. uc->scene.metadata.max_face_triangles = mesh->max_face_triangles;
  12170. }
  12171. }
  12172. }
  12173. ufbxi_for_ptr_list(ufbx_stereo_camera, p_stereo, uc->scene.stereo_cameras) {
  12174. ufbx_stereo_camera *stereo = *p_stereo;
  12175. stereo->left = (ufbx_camera*)ufbxi_fetch_dst_element(&stereo->element, search_node, ufbxi_LeftCamera, UFBX_ELEMENT_CAMERA);
  12176. stereo->right = (ufbx_camera*)ufbxi_fetch_dst_element(&stereo->element, search_node, ufbxi_RightCamera, UFBX_ELEMENT_CAMERA);
  12177. }
  12178. ufbxi_for_ptr_list(ufbx_nurbs_curve, p_curve, uc->scene.nurbs_curves) {
  12179. ufbx_nurbs_curve *curve = *p_curve;
  12180. ufbxi_check(ufbxi_finalize_nurbs_basis(uc, &curve->basis));
  12181. }
  12182. ufbxi_for_ptr_list(ufbx_nurbs_surface, p_surface, uc->scene.nurbs_surfaces) {
  12183. ufbx_nurbs_surface *surface = *p_surface;
  12184. ufbxi_check(ufbxi_finalize_nurbs_basis(uc, &surface->basis_u));
  12185. ufbxi_check(ufbxi_finalize_nurbs_basis(uc, &surface->basis_v));
  12186. surface->material = (ufbx_material*)ufbxi_fetch_dst_element(&surface->element, true, NULL, UFBX_ELEMENT_MATERIAL);
  12187. }
  12188. ufbxi_for_ptr_list(ufbx_anim_stack, p_stack, uc->scene.anim_stacks) {
  12189. ufbx_anim_stack *stack = *p_stack;
  12190. ufbxi_check(ufbxi_fetch_dst_elements(uc, &stack->layers, &stack->element, false, NULL, UFBX_ELEMENT_ANIM_LAYER));
  12191. stack->anim.layers.count = stack->layers.count;
  12192. stack->anim.layers.data = ufbxi_push_zero(&uc->result, ufbx_anim_layer_desc, stack->layers.count);
  12193. ufbxi_check(stack->anim.layers.data);
  12194. for (size_t i = 0; i < stack->layers.count; i++) {
  12195. ufbx_anim_layer_desc *desc = (ufbx_anim_layer_desc*)&stack->anim.layers.data[i];
  12196. desc->layer = stack->layers.data[i];
  12197. desc->weight = 1.0f;
  12198. }
  12199. }
  12200. ufbxi_for_ptr_list(ufbx_anim_layer, p_layer, uc->scene.anim_layers) {
  12201. ufbx_anim_layer *layer = *p_layer;
  12202. ufbxi_check(ufbxi_fetch_dst_elements(uc, &layer->anim_values, &layer->element, false, NULL, UFBX_ELEMENT_ANIM_VALUE));
  12203. ufbx_anim_layer_desc *layer_desc = ufbxi_push_zero(&uc->result, ufbx_anim_layer_desc, 1);
  12204. ufbxi_check(layer_desc);
  12205. layer_desc->layer = layer;
  12206. layer_desc->weight = 1.0f;
  12207. layer->anim.layers.data = layer_desc;
  12208. layer->anim.layers.count = 1;
  12209. uint32_t min_id = UINT32_MAX, max_id = 0;
  12210. // Combine the animated properties with elements (potentially duplicates!)
  12211. size_t num_anim_props = 0;
  12212. ufbxi_for_ptr_list(ufbx_anim_value, p_value, layer->anim_values) {
  12213. ufbx_anim_value *value = *p_value;
  12214. ufbxi_for_list(ufbx_connection, ac, value->element.connections_src) {
  12215. if (ac->src_prop.length == 0 && ac->dst_prop.length > 0) {
  12216. ufbx_anim_prop *aprop = ufbxi_push(&uc->tmp_stack, ufbx_anim_prop, 1);
  12217. uint32_t id = ac->dst->element_id;
  12218. min_id = ufbxi_min32(min_id, id);
  12219. max_id = ufbxi_max32(max_id, id);
  12220. uint32_t id_mask = ufbxi_arraycount(layer->_element_id_bitmask) - 1;
  12221. layer->_element_id_bitmask[(id >> 5) & id_mask] |= 1u << (id & 31);
  12222. ufbxi_check(aprop);
  12223. aprop->anim_value = value;
  12224. aprop->element = ac->dst;
  12225. aprop->_internal_key = ufbxi_get_name_key(ac->dst_prop.data, ac->dst_prop.length);
  12226. aprop->prop_name = ac->dst_prop;
  12227. num_anim_props++;
  12228. }
  12229. }
  12230. }
  12231. if (min_id != UINT32_MAX) {
  12232. layer->_min_element_id = min_id;
  12233. layer->_max_element_id = max_id;
  12234. }
  12235. switch (ufbxi_find_int(&layer->props, ufbxi_BlendMode, 0)) {
  12236. case 0: // Additive
  12237. layer->blended = true;
  12238. layer->additive = true;
  12239. break;
  12240. case 1: // Override
  12241. layer->blended = false;
  12242. layer->additive = false;
  12243. break;
  12244. case 2: // Override Passthrough
  12245. layer->blended = true;
  12246. layer->additive = false;
  12247. break;
  12248. default: // Unknown
  12249. layer->blended = false;
  12250. layer->additive = false;
  12251. break;
  12252. }
  12253. ufbx_prop *weight_prop = ufbxi_find_prop(&layer->props, ufbxi_Weight);
  12254. if (weight_prop) {
  12255. layer->weight = weight_prop->value_real / (ufbx_real)100.0;
  12256. if (layer->weight < 0.0f) layer->weight = 0.0f;
  12257. if (layer->weight > 0.99999f) layer->weight = 1.0f;
  12258. layer->weight_is_animated = (weight_prop->flags & UFBX_PROP_FLAG_ANIMATED) != 0;
  12259. } else {
  12260. layer->weight = 1.0f;
  12261. layer->weight_is_animated = false;
  12262. }
  12263. layer->compose_rotation = ufbxi_find_int(&layer->props, ufbxi_RotationAccumulationMode, 0) == 0;
  12264. layer->compose_scale = ufbxi_find_int(&layer->props, ufbxi_ScaleAccumulationMode, 0) == 0;
  12265. // Add a dummy NULL element animated prop at the end so we can iterate
  12266. // animated props without worrying about boundary conditions..
  12267. {
  12268. ufbx_anim_prop *aprop = ufbxi_push_zero(&uc->tmp_stack, ufbx_anim_prop, 1);
  12269. ufbxi_check(aprop);
  12270. }
  12271. layer->anim_props.data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_anim_prop, num_anim_props + 1);
  12272. ufbxi_check(layer->anim_props.data);
  12273. layer->anim_props.count = num_anim_props;
  12274. ufbxi_check(ufbxi_sort_anim_props(uc, layer->anim_props.data, layer->anim_props.count));
  12275. }
  12276. ufbxi_for_ptr_list(ufbx_anim_value, p_value, uc->scene.anim_values) {
  12277. ufbx_anim_value *value = *p_value;
  12278. // TODO: Search for things like d|Visibility with a constructed name
  12279. value->default_value.x = ufbxi_find_real(&value->props, ufbxi_X, value->default_value.x);
  12280. value->default_value.x = ufbxi_find_real(&value->props, ufbxi_d_X, value->default_value.x);
  12281. value->default_value.y = ufbxi_find_real(&value->props, ufbxi_Y, value->default_value.y);
  12282. value->default_value.y = ufbxi_find_real(&value->props, ufbxi_d_Y, value->default_value.y);
  12283. value->default_value.z = ufbxi_find_real(&value->props, ufbxi_Z, value->default_value.z);
  12284. value->default_value.z = ufbxi_find_real(&value->props, ufbxi_d_Z, value->default_value.z);
  12285. ufbxi_for_list(ufbx_connection, conn, value->element.connections_dst) {
  12286. if (conn->src->type == UFBX_ELEMENT_ANIM_CURVE && conn->src_prop.length == 0) {
  12287. ufbx_anim_curve *curve = (ufbx_anim_curve*)conn->src;
  12288. uint32_t index = 0;
  12289. const char *name = conn->dst_prop.data;
  12290. if (name == ufbxi_Y || name == ufbxi_d_Y) index = 1;
  12291. if (name == ufbxi_Z || name == ufbxi_d_Z) index = 2;
  12292. ufbx_prop *prop = ufbx_find_prop_len(&value->props, conn->dst_prop.data, conn->dst_prop.length);
  12293. if (prop) {
  12294. value->default_value.v[index] = prop->value_real;
  12295. }
  12296. value->curves[index] = curve;
  12297. }
  12298. }
  12299. }
  12300. ufbxi_for_ptr_list(ufbx_shader, p_shader, uc->scene.shaders) {
  12301. ufbx_shader *shader = *p_shader;
  12302. ufbxi_check(ufbxi_fetch_dst_elements(uc, &shader->bindings, &shader->element, false, NULL, UFBX_ELEMENT_SHADER_BINDING));
  12303. ufbx_prop *api = ufbx_find_prop(&shader->props, "RenderAPI");
  12304. if (api) {
  12305. if (!strcmp(api->value_str.data, "ARNOLD_SHADER_ID")) {
  12306. shader->type = UFBX_SHADER_ARNOLD_STANDARD_SURFACE;
  12307. } else if (!strcmp(api->value_str.data, "OSL")) {
  12308. shader->type = UFBX_SHADER_OSL_STANDARD_SURFACE;
  12309. } else if (!strcmp(api->value_str.data, "SFX_PBS_SHADER")) {
  12310. shader->type = UFBX_SHADER_SHADERFX_GRAPH;
  12311. }
  12312. }
  12313. }
  12314. ufbxi_for_ptr_list(ufbx_material, p_material, uc->scene.materials) {
  12315. ufbx_material *material = *p_material;
  12316. material->shader = (ufbx_shader*)ufbxi_fetch_src_element(&material->element, false, NULL, UFBX_ELEMENT_SHADER);
  12317. if (!strcmp(material->shading_model_name.data, "lambert") || !strcmp(material->shading_model_name.data, "Lambert")) {
  12318. material->shader_type = UFBX_SHADER_FBX_LAMBERT;
  12319. } else if (!strcmp(material->shading_model_name.data, "phong") || !strcmp(material->shading_model_name.data, "Phong")) {
  12320. material->shader_type = UFBX_SHADER_FBX_PHONG;
  12321. }
  12322. if (material->shader) {
  12323. material->shader_type = material->shader->type;
  12324. } else {
  12325. if (uc->exporter == UFBX_EXPORTER_BLENDER_BINARY && uc->exporter_version >= ufbx_pack_version(4,12,0)) {
  12326. material->shader_type = UFBX_SHADER_BLENDER_PHONG;
  12327. }
  12328. // TODO: Is this too strict?
  12329. if (material->shader_type == UFBX_SHADER_UNKNOWN) {
  12330. uint32_t classid_a = (uint32_t)(uint64_t)ufbx_find_int(&material->props, "3dsMax|ClassIDa", 0);
  12331. uint32_t classid_b = (uint32_t)(uint64_t)ufbx_find_int(&material->props, "3dsMax|ClassIDb", 0);
  12332. if (classid_a == 0x3d6b1cecu && classid_b == 0xdeadc001u) {
  12333. material->shader_type = UFBX_SHADER_3DS_MAX_PHYSICAL_MATERIAL;
  12334. material->shader_prop_prefix.data = "3dsMax|Parameters|";
  12335. material->shader_prop_prefix.length = strlen("3dsMax|Parameters|");
  12336. } else if (classid_a == 0x38420192u && classid_b == 0x45fe4e1bu) {
  12337. material->shader_type = UFBX_SHADER_GLTF_MATERIAL;
  12338. material->shader_prop_prefix.data = "3dsMax|";
  12339. material->shader_prop_prefix.length = strlen("3dsMax|");
  12340. } else if (classid_a == 0xd00f1e00u && classid_b == 0xbe77e500u) {
  12341. material->shader_type = UFBX_SHADER_3DS_MAX_PBR_METAL_ROUGH;
  12342. material->shader_prop_prefix.data = "3dsMax|main|";
  12343. material->shader_prop_prefix.length = strlen("3dsMax|main|");
  12344. } else if (classid_a == 0xd00f1e00u && classid_b == 0x01dbad33u) {
  12345. material->shader_type = UFBX_SHADER_3DS_MAX_PBR_SPEC_GLOSS;
  12346. material->shader_prop_prefix.data = "3dsMax|main|";
  12347. material->shader_prop_prefix.length = strlen("3dsMax|main|");
  12348. }
  12349. }
  12350. }
  12351. ufbxi_check(ufbxi_fetch_textures(uc, &material->textures, &material->element, false));
  12352. }
  12353. // Ugh.. Patch the textures from meshes for legacy LayerElement-style textures
  12354. {
  12355. ufbxi_for_ptr_list(ufbx_mesh, p_mesh, uc->scene.meshes) {
  12356. ufbx_mesh *mesh = *p_mesh;
  12357. size_t num_materials = mesh->materials.count;
  12358. ufbxi_mesh_extra *extra = (ufbxi_mesh_extra*)ufbxi_get_element_extra(uc, mesh->element.element_id);
  12359. if (!extra) continue;
  12360. if (num_materials == 0) continue;
  12361. // TODO: This leaks currently to result, probably doesn't matter..
  12362. ufbx_texture_list textures;
  12363. ufbxi_check(ufbxi_fetch_dst_elements(uc, &textures, &mesh->element, true, NULL, UFBX_ELEMENT_TEXTURE));
  12364. size_t num_material_textures = 0;
  12365. ufbxi_for(ufbxi_tmp_mesh_texture, tex, extra->texture_arr, extra->texture_count) {
  12366. if (tex->all_same) {
  12367. int32_t texture_id = tex->num_faces > 0 ? (int32_t)tex->face_texture[0] : 0;
  12368. if (texture_id >= 0 && (size_t)texture_id < textures.count) {
  12369. ufbxi_tmp_material_texture *mat_texs = ufbxi_push(&uc->tmp_stack, ufbxi_tmp_material_texture, num_materials);
  12370. ufbxi_check(mat_texs);
  12371. num_material_textures += num_materials;
  12372. for (size_t i = 0; i < num_materials; i++) {
  12373. mat_texs[i].material_id = (int32_t)i;
  12374. mat_texs[i].texture_id = texture_id;
  12375. mat_texs[i].prop_name = tex->prop_name;
  12376. }
  12377. }
  12378. } else if (mesh->face_material.count) {
  12379. size_t num_faces = ufbxi_min_sz(tex->num_faces, mesh->num_faces);
  12380. int32_t prev_material = -1;
  12381. int32_t prev_texture = -1;
  12382. for (size_t i = 0; i < num_faces; i++) {
  12383. int32_t texture_id = (int32_t)tex->face_texture[i];
  12384. int32_t material_id = (int32_t)mesh->face_material.data[i];
  12385. if (texture_id < 0 || (size_t)texture_id >= textures.count) continue;
  12386. if (material_id < 0 || (size_t)material_id >= num_materials) continue;
  12387. if (material_id == prev_material && texture_id == prev_texture) continue;
  12388. prev_material = material_id;
  12389. prev_texture = texture_id;
  12390. ufbxi_tmp_material_texture *mat_tex = ufbxi_push(&uc->tmp_stack, ufbxi_tmp_material_texture, 1);
  12391. ufbxi_check(mat_tex);
  12392. mat_tex->material_id = material_id;
  12393. mat_tex->texture_id = texture_id;
  12394. mat_tex->prop_name = tex->prop_name;
  12395. num_material_textures++;
  12396. }
  12397. }
  12398. }
  12399. // Push a sentinel material texture to the end so we don't need to
  12400. // duplicate the material texture flushing code twice.
  12401. {
  12402. ufbxi_tmp_material_texture *mat_tex = ufbxi_push(&uc->tmp_stack, ufbxi_tmp_material_texture, 1);
  12403. ufbxi_check(mat_tex);
  12404. mat_tex->material_id = -1;
  12405. mat_tex->texture_id = -1;
  12406. mat_tex->prop_name = ufbx_empty_string;
  12407. }
  12408. ufbxi_tmp_material_texture *mat_texs = ufbxi_push_pop(&uc->tmp, &uc->tmp_stack, ufbxi_tmp_material_texture, num_material_textures + 1);
  12409. ufbxi_check(mat_texs);
  12410. ufbxi_check(ufbxi_sort_tmp_material_textures(uc, mat_texs, num_material_textures));
  12411. int32_t prev_material = -2;
  12412. int32_t prev_texture = -2;
  12413. const char *prev_prop = NULL;
  12414. size_t num_textures_in_material = 0;
  12415. for (size_t i = 0; i < num_material_textures + 1; i++) {
  12416. ufbxi_tmp_material_texture mat_tex = mat_texs[i];
  12417. if (mat_tex.material_id != prev_material) {
  12418. if (prev_material >= 0 && num_textures_in_material > 0) {
  12419. ufbx_material *mat = mesh->materials.data[prev_material].material;
  12420. if (mat->textures.count == 0) {
  12421. ufbx_material_texture *texs = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_material_texture, num_textures_in_material);
  12422. ufbxi_check(texs);
  12423. mat->textures.data = texs;
  12424. mat->textures.count = num_textures_in_material;
  12425. } else {
  12426. ufbxi_pop(&uc->tmp_stack, ufbx_material_texture, num_textures_in_material, NULL);
  12427. }
  12428. }
  12429. if (mat_tex.material_id < 0) break;
  12430. prev_material = mat_tex.material_id;
  12431. prev_texture = -1;
  12432. prev_prop = NULL;
  12433. num_textures_in_material = 0;
  12434. }
  12435. if (mat_tex.texture_id == prev_texture && mat_tex.prop_name.data == prev_prop) continue;
  12436. prev_texture = mat_tex.texture_id;
  12437. prev_prop = mat_tex.prop_name.data;
  12438. ufbx_material_texture *tex = ufbxi_push(&uc->tmp_stack, ufbx_material_texture, 1);
  12439. ufbxi_check(tex);
  12440. ufbx_assert(prev_texture >= 0 && (size_t)prev_texture < textures.count);
  12441. tex->texture = textures.data[prev_texture];
  12442. tex->shader_prop = tex->material_prop = mat_tex.prop_name;
  12443. num_textures_in_material++;
  12444. }
  12445. }
  12446. }
  12447. // HACK: If there are multiple textures in an FBX file that use the same embedded
  12448. // texture they get duplicated Video elements instead of a shared one _and only one
  12449. // of them has the content?!_ So let's gather all Video instances with content and
  12450. // sort them by filename so we can patch the other ones..
  12451. ufbx_video **content_videos = ufbxi_push(&uc->tmp, ufbx_video*, uc->scene.videos.count);
  12452. ufbxi_check(content_videos);
  12453. size_t num_content_videos = 0;
  12454. ufbxi_for_ptr_list(ufbx_video, p_video, uc->scene.videos) {
  12455. ufbx_video *video = *p_video;
  12456. ufbxi_check(ufbxi_resolve_filenames(uc, (ufbxi_strblob*)&video->filename, (ufbxi_strblob*)&video->absolute_filename, (ufbxi_strblob*)&video->relative_filename, false));
  12457. ufbxi_check(ufbxi_resolve_filenames(uc, (ufbxi_strblob*)&video->raw_filename, (ufbxi_strblob*)&video->raw_absolute_filename, (ufbxi_strblob*)&video->raw_relative_filename, true));
  12458. if (video->content.size > 0) {
  12459. content_videos[num_content_videos++] = video;
  12460. }
  12461. }
  12462. if (num_content_videos > 0) {
  12463. ufbxi_check(ufbxi_sort_videos_by_filename(uc, content_videos, num_content_videos));
  12464. ufbxi_for_ptr_list(ufbx_video, p_video, uc->scene.videos) {
  12465. ufbx_video *video = *p_video;
  12466. if (video->content.size > 0) continue;
  12467. size_t index = SIZE_MAX;
  12468. ufbxi_macro_lower_bound_eq(ufbx_video*, 16, &index, content_videos, 0, num_content_videos,
  12469. ( ufbxi_str_less((*a)->absolute_filename, video->absolute_filename) ),
  12470. ( (*a)->absolute_filename.data == video->absolute_filename.data ));
  12471. if (index != SIZE_MAX) {
  12472. video->content = content_videos[index]->content;
  12473. }
  12474. }
  12475. }
  12476. ufbxi_for_ptr_list(ufbx_texture, p_texture, uc->scene.textures) {
  12477. ufbx_texture *texture = *p_texture;
  12478. ufbxi_texture_extra *extra = (ufbxi_texture_extra*)ufbxi_get_element_extra(uc, texture->element.element_id);
  12479. ufbx_prop *uv_set = ufbxi_find_prop(&texture->props, ufbxi_UVSet);
  12480. if (uv_set) {
  12481. texture->uv_set = uv_set->value_str;
  12482. } else {
  12483. texture->uv_set = ufbx_empty_string;
  12484. }
  12485. texture->video = (ufbx_video*)ufbxi_fetch_dst_element(&texture->element, false, NULL, UFBX_ELEMENT_VIDEO);
  12486. if (texture->video) {
  12487. texture->content = texture->video->content;
  12488. }
  12489. ufbxi_check(ufbxi_finalize_shader_texture(uc, texture));
  12490. ufbxi_check(ufbxi_resolve_filenames(uc, (ufbxi_strblob*)&texture->filename, (ufbxi_strblob*)&texture->absolute_filename, (ufbxi_strblob*)&texture->relative_filename, false));
  12491. ufbxi_check(ufbxi_resolve_filenames(uc, (ufbxi_strblob*)&texture->raw_filename, (ufbxi_strblob*)&texture->raw_absolute_filename, (ufbxi_strblob*)&texture->raw_relative_filename, true));
  12492. // Fetch layered texture layers and patch alphas/blend modes
  12493. if (texture->type == UFBX_TEXTURE_LAYERED) {
  12494. ufbxi_check(ufbxi_fetch_texture_layers(uc, &texture->layers, &texture->element));
  12495. if (extra) {
  12496. for (size_t i = 0, num = ufbxi_min_sz(extra->num_alphas, texture->layers.count); i < num; i++) {
  12497. texture->layers.data[i].alpha = extra->alphas[i];
  12498. }
  12499. for (size_t i = 0, num = ufbxi_min_sz(extra->num_blend_modes, texture->layers.count); i < num; i++) {
  12500. int32_t mode = extra->blend_modes[i];
  12501. if (mode >= 0 && mode < UFBX_BLEND_OVERLAY) {
  12502. texture->layers.data[i].blend_mode = (ufbx_blend_mode)mode;
  12503. }
  12504. }
  12505. }
  12506. }
  12507. }
  12508. ufbxi_propagate_main_textures(&uc->scene);
  12509. // Second pass to fetch material maps
  12510. ufbxi_for_ptr_list(ufbx_material, p_material, uc->scene.materials) {
  12511. ufbx_material *material = *p_material;
  12512. ufbxi_check(ufbxi_sort_material_textures(uc, material->textures.data, material->textures.count));
  12513. ufbxi_fetch_maps(&uc->scene, material);
  12514. // Fetch `ufbx_material_texture.shader_prop` names
  12515. if (material->shader) {
  12516. ufbxi_for_ptr_list(ufbx_shader_binding, p_binding, material->shader->bindings) {
  12517. ufbx_shader_binding *binding = *p_binding;
  12518. ufbxi_for_list(ufbx_shader_prop_binding, prop, binding->prop_bindings) {
  12519. ufbx_string name = prop->material_prop;
  12520. size_t index = SIZE_MAX;
  12521. ufbxi_macro_lower_bound_eq(ufbx_material_texture, 4, &index, material->textures.data, 0, material->textures.count,
  12522. ( ufbxi_str_less(a->material_prop, name) ), ( a->material_prop.data == name.data ));
  12523. for (; index < material->textures.count && material->textures.data[index].shader_prop.data == name.data; index++) {
  12524. material->textures.data[index].shader_prop = prop->shader_prop;
  12525. }
  12526. }
  12527. }
  12528. }
  12529. }
  12530. ufbxi_for_ptr_list(ufbx_display_layer, p_layer, uc->scene.display_layers) {
  12531. ufbx_display_layer *layer = *p_layer;
  12532. ufbxi_check(ufbxi_fetch_dst_elements(uc, &layer->nodes, &layer->element, false, NULL, UFBX_ELEMENT_NODE));
  12533. }
  12534. ufbxi_for_ptr_list(ufbx_selection_set, p_set, uc->scene.selection_sets) {
  12535. ufbx_selection_set *set = *p_set;
  12536. ufbxi_check(ufbxi_fetch_dst_elements(uc, &set->nodes, &set->element, false, NULL, UFBX_ELEMENT_SELECTION_NODE));
  12537. }
  12538. ufbxi_for_ptr_list(ufbx_selection_node, p_node, uc->scene.selection_nodes) {
  12539. ufbx_selection_node *node = *p_node;
  12540. node->target_node = (ufbx_node*)ufbxi_fetch_dst_element(&node->element, false, NULL, UFBX_ELEMENT_NODE);
  12541. node->target_mesh = (ufbx_mesh*)ufbxi_fetch_dst_element(&node->element, false, NULL, UFBX_ELEMENT_MESH);
  12542. if (!node->target_mesh && node->target_node) {
  12543. node->target_mesh = node->target_node->mesh;
  12544. } else if (!node->target_node && node->target_mesh && node->target_mesh->instances.count > 0) {
  12545. node->target_node = node->target_mesh->instances.data[0];
  12546. }
  12547. ufbx_mesh *mesh = node->target_mesh;
  12548. if (mesh) {
  12549. ufbxi_check(ufbxi_validate_indices(uc, &node->vertices, mesh->num_vertices));
  12550. ufbxi_check(ufbxi_validate_indices(uc, &node->edges, mesh->num_edges));
  12551. ufbxi_check(ufbxi_validate_indices(uc, &node->faces, mesh->num_faces));
  12552. }
  12553. }
  12554. ufbxi_for_ptr_list(ufbx_constraint, p_constraint, uc->scene.constraints) {
  12555. ufbx_constraint *constraint = *p_constraint;
  12556. size_t tmp_base = uc->tmp_stack.num_items;
  12557. // Find property connections in _both_ src and dst connections as they are inconsistent
  12558. // in pre-7000 files. For example "Constrained Object" is a "PO" connection in 6100.
  12559. ufbxi_for_list(ufbx_connection, conn, constraint->element.connections_src) {
  12560. if (conn->src_prop.length == 0 || conn->dst->type != UFBX_ELEMENT_NODE) continue;
  12561. ufbxi_check(ufbxi_add_constraint_prop(uc, constraint, (ufbx_node*)conn->dst, conn->src_prop.data));
  12562. }
  12563. ufbxi_for_list(ufbx_connection, conn, constraint->element.connections_dst) {
  12564. if (conn->dst_prop.length == 0 || conn->src->type != UFBX_ELEMENT_NODE) continue;
  12565. ufbxi_check(ufbxi_add_constraint_prop(uc, constraint, (ufbx_node*)conn->src, conn->dst_prop.data));
  12566. }
  12567. size_t num_targets = uc->tmp_stack.num_items - tmp_base;
  12568. constraint->targets.count = num_targets;
  12569. constraint->targets.data = ufbxi_push_pop(&uc->result, &uc->tmp_stack, ufbx_constraint_target, num_targets);
  12570. ufbxi_check(constraint->targets.data);
  12571. }
  12572. if (uc->scene.anim_stacks.count > 0) {
  12573. // Combine all animation stacks into one
  12574. size_t num_layers = 0;
  12575. ufbxi_for_ptr_list(ufbx_anim_stack, p_stack, uc->scene.anim_stacks) {
  12576. num_layers += (*p_stack)->layers.count;
  12577. }
  12578. ufbx_anim_layer_desc *descs = ufbxi_push_zero(&uc->result, ufbx_anim_layer_desc, num_layers);
  12579. ufbxi_check(descs);
  12580. uc->scene.combined_anim.layers.data = descs;
  12581. uc->scene.combined_anim.layers.count = num_layers;
  12582. ufbx_anim_layer_desc *desc = descs;
  12583. ufbxi_for_ptr_list(ufbx_anim_stack, p_stack, uc->scene.anim_stacks) {
  12584. ufbx_anim_stack *stack = *p_stack;
  12585. ufbxi_for_ptr_list(ufbx_anim_layer, p_layer, stack->layers) {
  12586. desc->layer = *p_layer;
  12587. desc->weight = 1.0f;
  12588. desc++;
  12589. }
  12590. }
  12591. }
  12592. ufbxi_for_ptr_list(ufbx_lod_group, p_lod, uc->scene.lod_groups) {
  12593. ufbxi_check(ufbxi_finalize_lod_group(uc, *p_lod));
  12594. }
  12595. ufbxi_check(ufbxi_fetch_file_textures(uc));
  12596. uc->scene.metadata.ktime_to_sec = uc->ktime_to_sec;
  12597. // Maya seems to use scale of 100/3, Blender binary uses exactly 33, ASCII has always value of 1.0
  12598. if (uc->version < 6000) {
  12599. uc->scene.metadata.bone_prop_size_unit = 1.0f;
  12600. } else if (uc->exporter == UFBX_EXPORTER_BLENDER_BINARY) {
  12601. uc->scene.metadata.bone_prop_size_unit = 33.0f;
  12602. } else if (uc->exporter == UFBX_EXPORTER_BLENDER_ASCII) {
  12603. uc->scene.metadata.bone_prop_size_unit = 1.0f;
  12604. } else {
  12605. uc->scene.metadata.bone_prop_size_unit = (ufbx_real)(100.0/3.0);
  12606. }
  12607. if (uc->exporter == UFBX_EXPORTER_BLENDER_ASCII) {
  12608. uc->scene.metadata.bone_prop_limb_length_relative = false;
  12609. } else {
  12610. uc->scene.metadata.bone_prop_limb_length_relative = true;
  12611. }
  12612. return 1;
  12613. }
  12614. // -- Interpret the read scene
  12615. static ufbxi_forceinline void ufbxi_add_translate(ufbx_transform *t, ufbx_vec3 v)
  12616. {
  12617. t->translation.x += v.x;
  12618. t->translation.y += v.y;
  12619. t->translation.z += v.z;
  12620. }
  12621. static ufbxi_forceinline void ufbxi_sub_translate(ufbx_transform *t, ufbx_vec3 v)
  12622. {
  12623. t->translation.x -= v.x;
  12624. t->translation.y -= v.y;
  12625. t->translation.z -= v.z;
  12626. }
  12627. static ufbxi_forceinline void ufbxi_mul_scale(ufbx_transform *t, ufbx_vec3 v)
  12628. {
  12629. t->translation.x *= v.x;
  12630. t->translation.y *= v.y;
  12631. t->translation.z *= v.z;
  12632. t->scale.x *= v.x;
  12633. t->scale.y *= v.y;
  12634. t->scale.z *= v.z;
  12635. }
  12636. static const ufbx_vec3 ufbxi_one_vec3 = { 1.0f, 1.0f, 1.0f };
  12637. #define UFBXI_PI ((ufbx_real)3.14159265358979323846)
  12638. #define UFBXI_DPI (3.14159265358979323846)
  12639. #define UFBXI_DEG_TO_RAD ((ufbx_real)(UFBXI_PI / 180.0))
  12640. #define UFBXI_RAD_TO_DEG ((ufbx_real)(180.0 / UFBXI_PI))
  12641. #define UFBXI_MM_TO_INCH ((ufbx_real)0.0393700787)
  12642. static ufbxi_forceinline ufbx_quat ufbxi_mul_quat(ufbx_quat a, ufbx_quat b)
  12643. {
  12644. ufbx_quat r;
  12645. r.x = a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y;
  12646. r.y = a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x;
  12647. r.z = a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w;
  12648. r.w = a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z;
  12649. return r;
  12650. }
  12651. static ufbxi_forceinline void ufbxi_add_weighted_vec3(ufbx_vec3 *r, ufbx_vec3 b, ufbx_real w)
  12652. {
  12653. r->x += b.x * w;
  12654. r->y += b.y * w;
  12655. r->z += b.z * w;
  12656. }
  12657. static ufbxi_forceinline void ufbxi_add_weighted_quat(ufbx_quat *r, ufbx_quat b, ufbx_real w)
  12658. {
  12659. r->x += b.x * w;
  12660. r->y += b.y * w;
  12661. r->z += b.z * w;
  12662. r->w += b.w * w;
  12663. }
  12664. static ufbxi_forceinline void ufbxi_add_weighted_mat(ufbx_matrix *r, const ufbx_matrix *b, ufbx_real w)
  12665. {
  12666. ufbxi_add_weighted_vec3(&r->cols[0], b->cols[0], w);
  12667. ufbxi_add_weighted_vec3(&r->cols[1], b->cols[1], w);
  12668. ufbxi_add_weighted_vec3(&r->cols[2], b->cols[2], w);
  12669. ufbxi_add_weighted_vec3(&r->cols[3], b->cols[3], w);
  12670. }
  12671. static void ufbxi_mul_rotate(ufbx_transform *t, ufbx_vec3 v, ufbx_rotation_order order)
  12672. {
  12673. if (ufbxi_is_vec3_zero(v)) return;
  12674. ufbx_quat q = ufbx_euler_to_quat(v, order);
  12675. if (t->rotation.w != 1.0) {
  12676. t->rotation = ufbxi_mul_quat(q, t->rotation);
  12677. } else {
  12678. t->rotation = q;
  12679. }
  12680. if (!ufbxi_is_vec3_zero(t->translation)) {
  12681. t->translation = ufbx_quat_rotate_vec3(q, t->translation);
  12682. }
  12683. }
  12684. static void ufbxi_mul_inv_rotate(ufbx_transform *t, ufbx_vec3 v, ufbx_rotation_order order)
  12685. {
  12686. if (ufbxi_is_vec3_zero(v)) return;
  12687. ufbx_quat q = ufbx_euler_to_quat(v, order);
  12688. q.x = -q.x; q.y = -q.y; q.z = -q.z;
  12689. if (t->rotation.w != 1.0) {
  12690. t->rotation = ufbxi_mul_quat(q, t->rotation);
  12691. } else {
  12692. t->rotation = q;
  12693. }
  12694. if (!ufbxi_is_vec3_zero(t->translation)) {
  12695. t->translation = ufbx_quat_rotate_vec3(q, t->translation);
  12696. }
  12697. }
  12698. // -- Updating state from properties
  12699. ufbxi_noinline static ufbx_transform ufbxi_get_transform(const ufbx_props *props, ufbx_rotation_order order)
  12700. {
  12701. ufbx_vec3 scale_pivot = ufbxi_find_vec3(props, ufbxi_ScalingPivot, 0.0f, 0.0f, 0.0f);
  12702. ufbx_vec3 rot_pivot = ufbxi_find_vec3(props, ufbxi_RotationPivot, 0.0f, 0.0f, 0.0f);
  12703. ufbx_vec3 scale_offset = ufbxi_find_vec3(props, ufbxi_ScalingOffset, 0.0f, 0.0f, 0.0f);
  12704. ufbx_vec3 rot_offset = ufbxi_find_vec3(props, ufbxi_RotationOffset, 0.0f, 0.0f, 0.0f);
  12705. ufbx_vec3 translation = ufbxi_find_vec3(props, ufbxi_Lcl_Translation, 0.0f, 0.0f, 0.0f);
  12706. ufbx_vec3 rotation = ufbxi_find_vec3(props, ufbxi_Lcl_Rotation, 0.0f, 0.0f, 0.0f);
  12707. ufbx_vec3 scaling = ufbxi_find_vec3(props, ufbxi_Lcl_Scaling, 1.0f, 1.0f, 1.0f);
  12708. ufbx_vec3 pre_rotation = ufbxi_find_vec3(props, ufbxi_PreRotation, 0.0f, 0.0f, 0.0f);
  12709. ufbx_vec3 post_rotation = ufbxi_find_vec3(props, ufbxi_PostRotation, 0.0f, 0.0f, 0.0f);
  12710. ufbx_transform t = { { 0,0,0 }, { 0,0,0,1 }, { 1,1,1 }};
  12711. // WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
  12712. // NOTE: Rpost is inverted (!) after converting from PostRotation Euler angles
  12713. ufbxi_sub_translate(&t, scale_pivot);
  12714. ufbxi_mul_scale(&t, scaling);
  12715. ufbxi_add_translate(&t, scale_pivot);
  12716. ufbxi_add_translate(&t, scale_offset);
  12717. ufbxi_sub_translate(&t, rot_pivot);
  12718. ufbxi_mul_inv_rotate(&t, post_rotation, UFBX_ROTATION_XYZ);
  12719. ufbxi_mul_rotate(&t, rotation, order);
  12720. ufbxi_mul_rotate(&t, pre_rotation, UFBX_ROTATION_XYZ);
  12721. ufbxi_add_translate(&t, rot_pivot);
  12722. ufbxi_add_translate(&t, rot_offset);
  12723. ufbxi_add_translate(&t, translation);
  12724. return t;
  12725. }
  12726. ufbxi_noinline static ufbx_transform ufbxi_get_geometry_transform(const ufbx_props *props)
  12727. {
  12728. ufbx_vec3 translation = ufbxi_find_vec3(props, ufbxi_GeometricTranslation, 0.0f, 0.0f, 0.0f);
  12729. ufbx_vec3 rotation = ufbxi_find_vec3(props, ufbxi_GeometricRotation, 0.0f, 0.0f, 0.0f);
  12730. ufbx_vec3 scaling = ufbxi_find_vec3(props, ufbxi_GeometricScaling, 1.0f, 1.0f, 1.0f);
  12731. ufbx_transform t = { { 0,0,0 }, { 0,0,0,1 }, { 1,1,1 }};
  12732. // WorldTransform = ParentWorldTransform * T * R * S * (OT * OR * OS)
  12733. ufbxi_mul_scale(&t, scaling);
  12734. ufbxi_mul_rotate(&t, rotation, UFBX_ROTATION_XYZ);
  12735. ufbxi_add_translate(&t, translation);
  12736. return t;
  12737. }
  12738. ufbxi_noinline static ufbx_transform ufbxi_get_texture_transform(const ufbx_props *props)
  12739. {
  12740. ufbx_vec3 scale_pivot = ufbxi_find_vec3(props, ufbxi_TextureScalingPivot, 0.0f, 0.0f, 0.0f);
  12741. ufbx_vec3 rot_pivot = ufbxi_find_vec3(props, ufbxi_TextureRotationPivot, 0.0f, 0.0f, 0.0f);
  12742. ufbx_vec3 translation = ufbxi_find_vec3(props, ufbxi_Translation, 0.0f, 0.0f, 0.0f);
  12743. ufbx_vec3 rotation = ufbxi_find_vec3(props, ufbxi_Rotation, 0.0f, 0.0f, 0.0f);
  12744. ufbx_vec3 scaling = ufbxi_find_vec3(props, ufbxi_Scaling, 1.0f, 1.0f, 1.0f);
  12745. ufbx_transform t = { { 0,0,0 }, { 0,0,0,1 }, { 1,1,1 }};
  12746. ufbxi_sub_translate(&t, scale_pivot);
  12747. ufbxi_mul_scale(&t, scaling);
  12748. ufbxi_add_translate(&t, scale_pivot);
  12749. ufbxi_sub_translate(&t, rot_pivot);
  12750. ufbxi_mul_rotate(&t, rotation, UFBX_ROTATION_XYZ);
  12751. ufbxi_add_translate(&t, rot_pivot);
  12752. ufbxi_add_translate(&t, translation);
  12753. if (ufbxi_find_int(props, ufbxi_UVSwap, 0) != 0) {
  12754. const ufbx_vec3 swap_scale = { -1.0f, 0.0f, 0.0f };
  12755. const ufbx_vec3 swap_rotate = { 0.0f, 0.0f, -90.0f };
  12756. ufbxi_mul_scale(&t, swap_scale);
  12757. ufbxi_mul_rotate(&t, swap_rotate, UFBX_ROTATION_XYZ);
  12758. }
  12759. return t;
  12760. }
  12761. ufbxi_noinline static ufbx_transform ufbxi_get_constraint_transform(const ufbx_props *props)
  12762. {
  12763. ufbx_vec3 translation = ufbxi_find_vec3(props, ufbxi_Translation, 0.0f, 0.0f, 0.0f);
  12764. ufbx_vec3 rotation = ufbxi_find_vec3(props, ufbxi_Rotation, 0.0f, 0.0f, 0.0f);
  12765. ufbx_vec3 rotation_offset = ufbxi_find_vec3(props, ufbxi_RotationOffset, 0.0f, 0.0f, 0.0f);
  12766. ufbx_vec3 scaling = ufbxi_find_vec3(props, ufbxi_Scaling, 1.0f, 1.0f, 1.0f);
  12767. ufbx_transform t = { { 0,0,0 }, { 0,0,0,1 }, { 1,1,1 }};
  12768. ufbxi_mul_scale(&t, scaling);
  12769. ufbxi_mul_rotate(&t, rotation, UFBX_ROTATION_XYZ);
  12770. ufbxi_mul_rotate(&t, rotation_offset, UFBX_ROTATION_XYZ);
  12771. ufbxi_add_translate(&t, translation);
  12772. return t;
  12773. }
  12774. ufbxi_noinline static void ufbxi_update_node(ufbx_node *node)
  12775. {
  12776. node->rotation_order = (ufbx_rotation_order)ufbxi_find_enum(&node->props, ufbxi_RotationOrder, UFBX_ROTATION_XYZ, UFBX_ROTATION_SPHERIC);
  12777. node->euler_rotation = ufbxi_find_vec3(&node->props, ufbxi_Lcl_Rotation, 0.0f, 0.0f, 0.0f);
  12778. node->inherit_type = (ufbx_inherit_type)ufbxi_find_enum(&node->props, ufbxi_InheritType, UFBX_INHERIT_NORMAL, UFBX_INHERIT_NO_SCALE);
  12779. if (!node->is_root) {
  12780. node->local_transform = ufbxi_get_transform(&node->props, node->rotation_order);
  12781. node->geometry_transform = ufbxi_get_geometry_transform(&node->props);
  12782. node->node_to_parent = ufbx_transform_to_matrix(&node->local_transform);
  12783. }
  12784. ufbx_node *parent = node->parent;
  12785. if (parent) {
  12786. node->world_transform.rotation = ufbxi_mul_quat(parent->world_transform.rotation, node->local_transform.rotation);
  12787. node->world_transform.translation = ufbx_transform_position(&parent->node_to_world, node->local_transform.translation);
  12788. if (node->inherit_type != UFBX_INHERIT_NO_SCALE) {
  12789. node->world_transform.scale.x = parent->world_transform.scale.x * node->local_transform.scale.x;
  12790. node->world_transform.scale.y = parent->world_transform.scale.y * node->local_transform.scale.y;
  12791. node->world_transform.scale.z = parent->world_transform.scale.z * node->local_transform.scale.z;
  12792. } else {
  12793. node->world_transform.scale = node->local_transform.scale;
  12794. }
  12795. if (node->inherit_type == UFBX_INHERIT_NORMAL) {
  12796. node->node_to_world = ufbx_matrix_mul(&parent->node_to_world, &node->node_to_parent);
  12797. } else {
  12798. node->node_to_world = ufbx_transform_to_matrix(&node->world_transform);
  12799. }
  12800. } else {
  12801. node->world_transform = node->local_transform;
  12802. node->node_to_world = node->node_to_parent;
  12803. }
  12804. if (!ufbxi_is_transform_identity(node->geometry_transform)) {
  12805. node->geometry_to_node = ufbx_transform_to_matrix(&node->geometry_transform);
  12806. node->geometry_to_world = ufbx_matrix_mul(&node->node_to_world, &node->geometry_to_node);
  12807. } else {
  12808. node->geometry_to_node = ufbx_identity_matrix;
  12809. node->geometry_to_world = node->node_to_world;
  12810. }
  12811. node->visible = ufbxi_find_int(&node->props, ufbxi_Visibility, 1) != 0;
  12812. }
  12813. ufbxi_noinline static void ufbxi_update_light(ufbx_light *light)
  12814. {
  12815. // NOTE: FBX seems to store intensities 100x of what's specified in at least
  12816. // Maya and Blender, should there be a quirks mode to not do this for specific
  12817. // exporters. Does the FBX SDK do this transparently as well?
  12818. light->intensity = ufbxi_find_real(&light->props, ufbxi_Intensity, (ufbx_real)100.0) / (ufbx_real)100.0;
  12819. light->color = ufbxi_find_vec3(&light->props, ufbxi_Color, 1.0f, 1.0f, 1.0f);
  12820. light->type = (ufbx_light_type)ufbxi_find_enum(&light->props, ufbxi_LightType, 0, UFBX_LIGHT_VOLUME);
  12821. int64_t default_decay = light->type == UFBX_LIGHT_DIRECTIONAL ? UFBX_LIGHT_DECAY_NONE : UFBX_LIGHT_DECAY_QUADRATIC;
  12822. light->decay = (ufbx_light_decay)ufbxi_find_enum(&light->props, ufbxi_DecayType, default_decay, UFBX_LIGHT_DECAY_CUBIC);
  12823. light->area_shape = (ufbx_light_area_shape)ufbxi_find_enum(&light->props, ufbxi_AreaLightShape, 0, UFBX_LIGHT_AREA_SHAPE_SPHERE);
  12824. light->inner_angle = ufbxi_find_real(&light->props, ufbxi_HotSpot, 0.0f);
  12825. light->inner_angle = ufbxi_find_real(&light->props, ufbxi_InnerAngle, light->inner_angle);
  12826. light->outer_angle = ufbxi_find_real(&light->props, ufbxi_Cone_angle, 0.0f);
  12827. light->outer_angle = ufbxi_find_real(&light->props, ufbxi_ConeAngle, light->outer_angle);
  12828. light->outer_angle = ufbxi_find_real(&light->props, ufbxi_OuterAngle, light->outer_angle);
  12829. light->cast_light = ufbxi_find_int(&light->props, ufbxi_CastLight, 1) != 0;
  12830. light->cast_shadows = ufbxi_find_int(&light->props, ufbxi_CastShadows, 0) != 0;
  12831. // TODO: Can this vary
  12832. light->local_direction.x = 0.0f;
  12833. light->local_direction.y = -1.0f;
  12834. light->local_direction.z = 0.0f;
  12835. }
  12836. typedef struct {
  12837. // 1/1000 decimal fixed point for size
  12838. uint16_t film_size_x, film_size_y;
  12839. } ufbxi_aperture_format;
  12840. static const ufbxi_aperture_format ufbxi_aperture_formats[] = {
  12841. { 1000, 1000, }, // UFBX_APERTURE_FORMAT_CUSTOM
  12842. { 404, 295, }, // UFBX_APERTURE_FORMAT_16MM_THEATRICAL
  12843. { 493, 292, }, // UFBX_APERTURE_FORMAT_SUPER_16MM
  12844. { 864, 630, }, // UFBX_APERTURE_FORMAT_35MM_ACADEMY
  12845. { 816, 612, }, // UFBX_APERTURE_FORMAT_35MM_TV_PROJECTION
  12846. { 980, 735, }, // UFBX_APERTURE_FORMAT_35MM_FULL_APERTURE
  12847. { 825, 446, }, // UFBX_APERTURE_FORMAT_35MM_185_PROJECTION
  12848. { 864, 732, }, // UFBX_APERTURE_FORMAT_35MM_ANAMORPHIC
  12849. { 2066, 906, }, // UFBX_APERTURE_FORMAT_70MM_PROJECTION
  12850. { 1485, 991, }, // UFBX_APERTURE_FORMAT_VISTAVISION
  12851. { 2080, 1480, }, // UFBX_APERTURE_FORMAT_DYNAVISION
  12852. { 2772, 2072, }, // UFBX_APERTURE_FORMAT_IMAX
  12853. };
  12854. ufbxi_noinline static void ufbxi_update_camera(ufbx_camera *camera)
  12855. {
  12856. camera->aspect_mode = (ufbx_aspect_mode) ufbxi_find_enum(&camera->props, ufbxi_AspectRatioMode, 0, UFBX_ASPECT_MODE_FIXED_HEIGHT);
  12857. camera->aperture_mode = (ufbx_aperture_mode)ufbxi_find_enum(&camera->props, ufbxi_ApertureMode, UFBX_APERTURE_MODE_VERTICAL, UFBX_APERTURE_MODE_FOCAL_LENGTH);
  12858. camera->aperture_format = (ufbx_aperture_format)ufbxi_find_enum(&camera->props, ufbxi_ApertureFormat, UFBX_APERTURE_FORMAT_CUSTOM, UFBX_APERTURE_FORMAT_IMAX);
  12859. camera->gate_fit = (ufbx_gate_fit)ufbxi_find_enum(&camera->props, ufbxi_GateFit, 0, UFBX_GATE_FIT_STRETCH);
  12860. // Search both W/H and Width/Height but prefer the latter
  12861. ufbx_real aspect_x = ufbxi_find_real(&camera->props, ufbxi_AspectW, 0.0f);
  12862. ufbx_real aspect_y = ufbxi_find_real(&camera->props, ufbxi_AspectH, 0.0f);
  12863. aspect_x = ufbxi_find_real(&camera->props, ufbxi_AspectWidth, aspect_x);
  12864. aspect_y = ufbxi_find_real(&camera->props, ufbxi_AspectHeight, aspect_y);
  12865. ufbx_real fov = ufbxi_find_real(&camera->props, ufbxi_FieldOfView, 0.0f);
  12866. ufbx_real fov_x = ufbxi_find_real(&camera->props, ufbxi_FieldOfViewX, 0.0f);
  12867. ufbx_real fov_y = ufbxi_find_real(&camera->props, ufbxi_FieldOfViewY, 0.0f);
  12868. ufbx_real focal_length = ufbxi_find_real(&camera->props, ufbxi_FocalLength, 0.0f);
  12869. ufbxi_aperture_format format = ufbxi_aperture_formats[camera->aperture_format];
  12870. ufbx_vec2 film_size = { (ufbx_real)format.film_size_x * (ufbx_real)0.001, (ufbx_real)format.film_size_y * (ufbx_real)0.001 };
  12871. ufbx_real squeeze_ratio = camera->aperture_format == UFBX_APERTURE_FORMAT_35MM_ANAMORPHIC ? 2.0f : 1.0f;
  12872. film_size.x = ufbxi_find_real(&camera->props, ufbxi_FilmWidth, film_size.x);
  12873. film_size.y = ufbxi_find_real(&camera->props, ufbxi_FilmHeight, film_size.y);
  12874. squeeze_ratio = ufbxi_find_real(&camera->props, ufbxi_FilmSqueezeRatio, squeeze_ratio);
  12875. if (aspect_x <= 0.0f && aspect_y <= 0.0f) {
  12876. aspect_x = film_size.x > 0.0f ? film_size.x : 1.0f;
  12877. aspect_y = film_size.y > 0.0f ? film_size.y : 1.0f;
  12878. } else if (aspect_x <= 0.0f) {
  12879. if (film_size.x > 0.0f && film_size.y > 0.0f) {
  12880. aspect_x = aspect_y / film_size.y * film_size.x;
  12881. } else {
  12882. aspect_x = aspect_y;
  12883. }
  12884. } else if (aspect_y <= 0.0f) {
  12885. if (film_size.x > 0.0f && film_size.y > 0.0f) {
  12886. aspect_y = aspect_x / film_size.x * film_size.y;
  12887. } else {
  12888. aspect_y = aspect_x;
  12889. }
  12890. }
  12891. film_size.y *= squeeze_ratio;
  12892. camera->focal_length_mm = focal_length;
  12893. camera->film_size_inch = film_size;
  12894. camera->squeeze_ratio = squeeze_ratio;
  12895. switch (camera->aspect_mode) {
  12896. case UFBX_ASPECT_MODE_WINDOW_SIZE:
  12897. case UFBX_ASPECT_MODE_FIXED_RATIO:
  12898. camera->resolution_is_pixels = false;
  12899. camera->resolution.x = aspect_x;
  12900. camera->resolution.y = aspect_y;
  12901. break;
  12902. case UFBX_ASPECT_MODE_FIXED_RESOLUTION:
  12903. camera->resolution_is_pixels = true;
  12904. camera->resolution.x = aspect_x;
  12905. camera->resolution.y = aspect_y;
  12906. break;
  12907. case UFBX_ASPECT_MODE_FIXED_WIDTH:
  12908. camera->resolution_is_pixels = true;
  12909. camera->resolution.x = aspect_x;
  12910. camera->resolution.y = aspect_x * aspect_y;
  12911. break;
  12912. case UFBX_ASPECT_MODE_FIXED_HEIGHT:
  12913. camera->resolution_is_pixels = true;
  12914. camera->resolution.x = aspect_y * aspect_x;
  12915. camera->resolution.y = aspect_y;
  12916. break;
  12917. default:
  12918. ufbx_assert(0 && "Unexpected aspect mode");
  12919. break;
  12920. }
  12921. ufbx_real aspect_ratio = camera->resolution.x / camera->resolution.y;
  12922. ufbx_real film_ratio = film_size.x / film_size.y;
  12923. ufbx_gate_fit effective_fit = camera->gate_fit;
  12924. if (effective_fit == UFBX_GATE_FIT_FILL) {
  12925. effective_fit = aspect_ratio > film_ratio ? UFBX_GATE_FIT_HORIZONTAL : UFBX_GATE_FIT_VERTICAL;
  12926. } else if (effective_fit == UFBX_GATE_FIT_OVERSCAN) {
  12927. effective_fit = aspect_ratio < film_ratio ? UFBX_GATE_FIT_HORIZONTAL : UFBX_GATE_FIT_VERTICAL;
  12928. }
  12929. switch (effective_fit) {
  12930. case UFBX_GATE_FIT_NONE:
  12931. camera->aperture_size_inch = camera->film_size_inch;
  12932. break;
  12933. case UFBX_GATE_FIT_VERTICAL:
  12934. camera->aperture_size_inch.x = camera->film_size_inch.y * aspect_ratio;
  12935. camera->aperture_size_inch.y = camera->film_size_inch.y;
  12936. break;
  12937. case UFBX_GATE_FIT_HORIZONTAL:
  12938. camera->aperture_size_inch.x = camera->film_size_inch.x;
  12939. camera->aperture_size_inch.y = camera->film_size_inch.x / aspect_ratio;
  12940. break;
  12941. case UFBX_GATE_FIT_FILL:
  12942. case UFBX_GATE_FIT_OVERSCAN:
  12943. camera->aperture_size_inch = camera->film_size_inch;
  12944. ufbx_assert(0 && "Unreachable, set to vertical/horizontal above");
  12945. break;
  12946. case UFBX_GATE_FIT_STRETCH:
  12947. camera->aperture_size_inch = camera->film_size_inch;
  12948. // TODO: Not sure what to do here...
  12949. break;
  12950. default:
  12951. ufbx_assert(0 && "Unexpected gate fit");
  12952. break;
  12953. }
  12954. switch (camera->aperture_mode) {
  12955. case UFBX_APERTURE_MODE_HORIZONTAL_AND_VERTICAL:
  12956. camera->field_of_view_deg.x = fov_x;
  12957. camera->field_of_view_deg.y = fov_y;
  12958. camera->field_of_view_tan.x = (ufbx_real)ufbx_tan((double)(fov_x * (UFBXI_DEG_TO_RAD * 0.5f)));
  12959. camera->field_of_view_tan.y = (ufbx_real)ufbx_tan((double)(fov_y * (UFBXI_DEG_TO_RAD * 0.5f)));
  12960. break;
  12961. case UFBX_APERTURE_MODE_HORIZONTAL:
  12962. camera->field_of_view_deg.x = fov;
  12963. camera->field_of_view_tan.x = (ufbx_real)ufbx_tan((double)(fov * (UFBXI_DEG_TO_RAD * 0.5f)));
  12964. camera->field_of_view_tan.y = camera->field_of_view_tan.x / aspect_ratio;
  12965. camera->field_of_view_deg.y = (ufbx_real)ufbx_atan((double)camera->field_of_view_tan.y) * UFBXI_RAD_TO_DEG * 2.0f;
  12966. break;
  12967. case UFBX_APERTURE_MODE_VERTICAL:
  12968. camera->field_of_view_deg.y = fov;
  12969. camera->field_of_view_tan.y = (ufbx_real)ufbx_tan((double)(fov * (UFBXI_DEG_TO_RAD * 0.5f)));
  12970. camera->field_of_view_tan.x = camera->field_of_view_tan.y * aspect_ratio;
  12971. camera->field_of_view_deg.x = (ufbx_real)ufbx_atan((double)camera->field_of_view_tan.x) * UFBXI_RAD_TO_DEG * 2.0f;
  12972. break;
  12973. case UFBX_APERTURE_MODE_FOCAL_LENGTH:
  12974. camera->field_of_view_tan.x = camera->aperture_size_inch.x / (camera->focal_length_mm * UFBXI_MM_TO_INCH) * 0.5f;
  12975. camera->field_of_view_tan.y = camera->aperture_size_inch.y / (camera->focal_length_mm * UFBXI_MM_TO_INCH) * 0.5f;
  12976. camera->field_of_view_deg.x = (ufbx_real)ufbx_atan((double)camera->field_of_view_tan.x) * UFBXI_RAD_TO_DEG * 2.0f;
  12977. camera->field_of_view_deg.y = (ufbx_real)ufbx_atan((double)camera->field_of_view_tan.y) * UFBXI_RAD_TO_DEG * 2.0f;
  12978. break;
  12979. default:
  12980. ufbx_assert(0 && "Unexpected aperture mode");
  12981. break;
  12982. }
  12983. }
  12984. ufbxi_noinline static void ufbxi_update_bone(ufbx_scene *scene, ufbx_bone *bone)
  12985. {
  12986. ufbx_real unit = scene->metadata.bone_prop_size_unit;
  12987. bone->radius = ufbxi_find_real(&bone->props, ufbxi_Size, unit) / unit;
  12988. if (scene->metadata.bone_prop_limb_length_relative) {
  12989. bone->relative_length = ufbxi_find_real(&bone->props, ufbxi_LimbLength, 1.0f);
  12990. } else {
  12991. bone->relative_length = 1.0f;
  12992. }
  12993. }
  12994. ufbxi_noinline static void ufbxi_update_line_curve(ufbx_line_curve *line)
  12995. {
  12996. line->color = ufbxi_find_vec3(&line->props, ufbxi_Color, 1.0f, 1.0f, 1.0f);
  12997. }
  12998. ufbxi_noinline static void ufbxi_update_skin_cluster(ufbx_skin_cluster *cluster)
  12999. {
  13000. if (cluster->bone_node) {
  13001. cluster->geometry_to_world = ufbx_matrix_mul(&cluster->bone_node->node_to_world, &cluster->geometry_to_bone);
  13002. } else {
  13003. cluster->geometry_to_world = ufbx_matrix_mul(&cluster->bind_to_world, &cluster->geometry_to_bone);
  13004. }
  13005. cluster->geometry_to_world_transform = ufbx_matrix_to_transform(&cluster->geometry_to_world);
  13006. }
  13007. ufbxi_noinline static void ufbxi_update_blend_channel(ufbx_blend_channel *channel)
  13008. {
  13009. ufbx_real weight = ufbxi_find_real(&channel->props, ufbxi_DeformPercent, 0.0f) * (ufbx_real)0.01;
  13010. channel->weight = weight;
  13011. ptrdiff_t num_keys = (ptrdiff_t)channel->keyframes.count;
  13012. if (num_keys > 0) {
  13013. ufbx_blend_keyframe *keys = channel->keyframes.data;
  13014. // Reset the effective weights to zero and find the split around zero
  13015. ptrdiff_t last_negative = -1;
  13016. for (ptrdiff_t i = 0; i < num_keys; i++) {
  13017. keys[i].effective_weight = (ufbx_real)0.0;
  13018. if (keys[i].target_weight < 0.0) last_negative = i;
  13019. }
  13020. // Find either the next or last keyframe away from zero
  13021. ufbx_blend_keyframe zero_key = { NULL };
  13022. ufbx_blend_keyframe *prev = &zero_key, *next = &zero_key;
  13023. if (weight > 0.0) {
  13024. if (last_negative >= 0) prev = &keys[last_negative];
  13025. for (ptrdiff_t i = last_negative + 1; i < num_keys; i++) {
  13026. prev = next;
  13027. next = &keys[i];
  13028. if (next->target_weight > weight) break;
  13029. }
  13030. } else {
  13031. if (last_negative + 1 < num_keys) prev = &keys[last_negative + 1];
  13032. for (ptrdiff_t i = last_negative; i >= 0; i--) {
  13033. prev = next;
  13034. next = &keys[i];
  13035. if (next->target_weight < weight) break;
  13036. }
  13037. }
  13038. // Linearly interpolate between the endpoints with the weight
  13039. ufbx_real delta = next->target_weight - prev->target_weight;
  13040. if (delta != 0.0) {
  13041. ufbx_real t = (weight - prev->target_weight) / delta;
  13042. prev->effective_weight = 1.0f - t;
  13043. next->effective_weight = t;
  13044. }
  13045. }
  13046. }
  13047. ufbxi_noinline static void ufbxi_update_material(ufbx_scene *scene, ufbx_material *material)
  13048. {
  13049. if (material->props.num_animated > 0) {
  13050. ufbxi_fetch_maps(scene, material);
  13051. }
  13052. }
  13053. ufbxi_noinline static void ufbxi_update_texture(ufbx_texture *texture)
  13054. {
  13055. texture->transform = ufbxi_get_texture_transform(&texture->props);
  13056. if (!ufbxi_is_transform_identity(texture->transform)) {
  13057. texture->texture_to_uv = ufbx_transform_to_matrix(&texture->transform);
  13058. texture->uv_to_texture = ufbx_matrix_invert(&texture->texture_to_uv);
  13059. } else {
  13060. texture->texture_to_uv = ufbx_identity_matrix;
  13061. texture->uv_to_texture = ufbx_identity_matrix;
  13062. }
  13063. texture->wrap_u = (ufbx_wrap_mode)ufbxi_find_enum(&texture->props, ufbxi_WrapModeU, 0, UFBX_WRAP_CLAMP);
  13064. texture->wrap_v = (ufbx_wrap_mode)ufbxi_find_enum(&texture->props, ufbxi_WrapModeV, 0, UFBX_WRAP_CLAMP);
  13065. if (texture->shader) {
  13066. ufbxi_update_shader_texture(texture, texture->shader);
  13067. }
  13068. }
  13069. ufbxi_noinline static void ufbxi_update_anim_stack(ufbx_scene *scene, ufbx_anim_stack *stack)
  13070. {
  13071. ufbx_prop *begin, *end;
  13072. begin = ufbxi_find_prop(&stack->props, ufbxi_LocalStart);
  13073. end = ufbxi_find_prop(&stack->props, ufbxi_LocalStop);
  13074. if (begin && end) {
  13075. stack->time_begin = (double)begin->value_int * scene->metadata.ktime_to_sec;
  13076. stack->time_end = (double)end->value_int * scene->metadata.ktime_to_sec;
  13077. } else {
  13078. begin = ufbxi_find_prop(&stack->props, ufbxi_ReferenceStart);
  13079. end = ufbxi_find_prop(&stack->props, ufbxi_ReferenceStop);
  13080. if (begin && end) {
  13081. stack->time_begin = (double)begin->value_int * scene->metadata.ktime_to_sec;
  13082. stack->time_end = (double)end->value_int * scene->metadata.ktime_to_sec;
  13083. }
  13084. }
  13085. stack->anim.time_begin = stack->time_begin;
  13086. stack->anim.time_end = stack->time_end;
  13087. }
  13088. ufbxi_noinline static void ufbxi_update_display_layer(ufbx_display_layer *layer)
  13089. {
  13090. layer->visible = ufbxi_find_int(&layer->props, ufbxi_Show, 1) != 0;
  13091. layer->frozen = ufbxi_find_int(&layer->props, ufbxi_Freeze, 1) != 0;
  13092. layer->ui_color = ufbxi_find_vec3(&layer->props, ufbxi_Color, 0.8f, 0.8f, 0.8f);
  13093. }
  13094. ufbxi_noinline static void ufbxi_find_bool3(bool *dst, ufbx_props *props, const char *name, bool default_value)
  13095. {
  13096. size_t name_len = strlen(name);
  13097. char local[64];
  13098. ufbx_assert(name_len < sizeof(local) - 2);
  13099. memcpy(local, name, name_len);
  13100. size_t local_len = name_len + 1;
  13101. local[local_len] = '\0';
  13102. int64_t def = default_value ? 1 : 0;
  13103. local[name_len] = 'X';
  13104. dst[0] = ufbx_find_int_len(props, local, local_len, def) != 0;
  13105. local[name_len] = 'Y';
  13106. dst[1] = ufbx_find_int_len(props, local, local_len, def) != 0;
  13107. local[name_len] = 'Z';
  13108. dst[2] = ufbx_find_int_len(props, local, local_len, def) != 0;
  13109. }
  13110. ufbxi_noinline static void ufbxi_update_constraint(ufbx_constraint *constraint)
  13111. {
  13112. ufbx_props *props = &constraint->props;
  13113. ufbx_constraint_type constraint_type = constraint->type;
  13114. constraint->transform_offset = ufbxi_get_constraint_transform(props);
  13115. constraint->weight = ufbxi_find_real(props, ufbxi_Weight, (ufbx_real)100.0) / (ufbx_real)100.0;
  13116. ufbxi_for_list(ufbx_constraint_target, target, constraint->targets) {
  13117. ufbx_node *node = target->node;
  13118. // Node names are at most 255 bytes so the suffixed names are bounded
  13119. char name_buf[256 + 8];
  13120. size_t name_len = node->name.length;
  13121. ufbx_assert(name_len < 256);
  13122. memcpy(name_buf, node->name.data, name_len);
  13123. ufbx_real weight_scale = (ufbx_real)100.0;
  13124. if (constraint_type == UFBX_CONSTRAINT_SINGLE_CHAIN_IK) {
  13125. // IK weights seem to be not scaled 100x?
  13126. weight_scale = (ufbx_real)1.0;
  13127. }
  13128. memcpy(name_buf + name_len, ".Weight", 7 + 1);
  13129. target->weight = ufbx_find_real_len(props, name_buf, name_len + 7, weight_scale) / weight_scale;
  13130. if (constraint_type == UFBX_CONSTRAINT_PARENT) {
  13131. memcpy(name_buf + name_len, ".Offset T", 9 + 1);
  13132. ufbx_vec3 t = ufbx_find_vec3_len(props, name_buf, name_len + 9, ufbx_zero_vec3);
  13133. name_buf[name_len + 8] = 'R';
  13134. ufbx_vec3 r = ufbx_find_vec3_len(props, name_buf, name_len + 9, ufbx_zero_vec3);
  13135. name_buf[name_len + 8] = 'S';
  13136. ufbx_vec3 s = ufbx_find_vec3_len(props, name_buf, name_len + 9, ufbxi_one_vec3);
  13137. target->transform.translation = t;
  13138. target->transform.rotation = ufbx_euler_to_quat(r, UFBX_ROTATION_XYZ);
  13139. target->transform.scale = s;
  13140. }
  13141. }
  13142. constraint->active = ufbx_find_int(props, "Active", 1) != 0;
  13143. if (constraint_type == UFBX_CONSTRAINT_AIM) {
  13144. ufbxi_find_bool3(constraint->constrain_rotation, props, "Affect", 1);
  13145. const ufbx_vec3 default_aim = { 1.0f, 0.0f, 0.0f };
  13146. const ufbx_vec3 default_up = { 0.0f, 1.0f, 0.0f };
  13147. int64_t up_type = ufbx_find_int(props, "WorldUpType", 0);
  13148. if (up_type >= 0 && up_type < UFBX_CONSTRAINT_AIM_UP_NONE) {
  13149. constraint->aim_up_type = (ufbx_constraint_aim_up_type)up_type;
  13150. }
  13151. constraint->aim_vector = ufbx_find_vec3(props, "AimVector", default_aim);
  13152. constraint->aim_up_vector = ufbx_find_vec3(props, "UpVector", default_up);
  13153. } else if (constraint_type == UFBX_CONSTRAINT_PARENT) {
  13154. ufbxi_find_bool3(constraint->constrain_translation, props, "AffectTranslation", 1);
  13155. ufbxi_find_bool3(constraint->constrain_rotation, props, "AffectRotation", 1);
  13156. ufbxi_find_bool3(constraint->constrain_scale, props, "AffectScale", 0);
  13157. } else if (constraint_type == UFBX_CONSTRAINT_POSITION) {
  13158. ufbxi_find_bool3(constraint->constrain_translation, props, "Affect", 1);
  13159. } else if (constraint_type == UFBX_CONSTRAINT_ROTATION) {
  13160. ufbxi_find_bool3(constraint->constrain_rotation, props, "Affect", 1);
  13161. } else if (constraint_type == UFBX_CONSTRAINT_SCALE) {
  13162. ufbxi_find_bool3(constraint->constrain_scale, props, "Affect", 1);
  13163. } else if (constraint_type == UFBX_CONSTRAINT_SINGLE_CHAIN_IK) {
  13164. constraint->constrain_rotation[0] = true;
  13165. constraint->constrain_rotation[1] = true;
  13166. constraint->constrain_rotation[2] = true;
  13167. constraint->ik_pole_vector = ufbx_find_vec3(props, "PoleVectorType", ufbx_zero_vec3);
  13168. }
  13169. }
  13170. ufbxi_noinline static void ufbxi_update_anim(ufbx_scene *scene)
  13171. {
  13172. if (scene->anim_stacks.count > 0) {
  13173. scene->anim = scene->anim_stacks.data[0]->anim;
  13174. scene->combined_anim.time_begin = scene->anim.time_begin;
  13175. scene->combined_anim.time_end = scene->anim.time_end;
  13176. ufbxi_for_ptr_list(ufbx_anim_stack, p_stack, scene->anim_stacks) {
  13177. ufbx_anim_stack *stack = *p_stack;
  13178. if (stack->time_begin < scene->combined_anim.time_begin) scene->combined_anim.time_begin = stack->time_begin;
  13179. if (stack->time_end > scene->combined_anim.time_end) scene->combined_anim.time_end = stack->time_end;
  13180. }
  13181. }
  13182. }
  13183. ufbxi_noinline static void ufbxi_update_initial_clusters(ufbx_scene *scene)
  13184. {
  13185. ufbxi_for_ptr_list(ufbx_skin_cluster, p_cluster, scene->skin_clusters) {
  13186. ufbx_skin_cluster *cluster = *p_cluster;
  13187. cluster->geometry_to_bone = cluster->mesh_node_to_bone;
  13188. }
  13189. // Patch initial `mesh_node_to_bone`
  13190. ufbxi_for_ptr_list(ufbx_skin_cluster, p_cluster, scene->skin_clusters) {
  13191. ufbx_skin_cluster *cluster = *p_cluster;
  13192. ufbx_skin_deformer *skin = (ufbx_skin_deformer*)ufbxi_fetch_src_element(&cluster->element, false, NULL, UFBX_ELEMENT_SKIN_DEFORMER);
  13193. if (!skin) continue;
  13194. ufbx_node *node = (ufbx_node*)ufbxi_fetch_src_element(&skin->element, false, NULL, UFBX_ELEMENT_NODE);
  13195. if (!node) {
  13196. ufbx_mesh *mesh = (ufbx_mesh*)ufbxi_fetch_src_element(&skin->element, false, NULL, UFBX_ELEMENT_MESH);
  13197. if (mesh && mesh->instances.count > 0) {
  13198. node = mesh->instances.data[0];
  13199. }
  13200. }
  13201. if (!node) continue;
  13202. if (ufbxi_matrix_all_zero(&cluster->mesh_node_to_bone)) {
  13203. ufbx_matrix world_to_bind = ufbx_matrix_invert(&cluster->bind_to_world);
  13204. cluster->mesh_node_to_bone = ufbx_matrix_mul(&world_to_bind, &node->node_to_world);
  13205. }
  13206. cluster->geometry_to_bone = ufbx_matrix_mul(&cluster->mesh_node_to_bone, &node->geometry_to_node);
  13207. }
  13208. }
  13209. ufbxi_noinline static ufbx_coordinate_axis ufbxi_find_axis(const ufbx_props *props, const char *axis_name, const char *sign_name)
  13210. {
  13211. int64_t axis = ufbxi_find_int(props, axis_name, 3);
  13212. int64_t sign = ufbxi_find_int(props, sign_name, 2);
  13213. switch (axis) {
  13214. case 0: return sign > 0 ? UFBX_COORDINATE_AXIS_POSITIVE_X : UFBX_COORDINATE_AXIS_NEGATIVE_X;
  13215. case 1: return sign > 0 ? UFBX_COORDINATE_AXIS_POSITIVE_Y : UFBX_COORDINATE_AXIS_NEGATIVE_Y;
  13216. case 2: return sign > 0 ? UFBX_COORDINATE_AXIS_POSITIVE_Z : UFBX_COORDINATE_AXIS_NEGATIVE_Z;
  13217. default: return UFBX_COORDINATE_AXIS_UNKNOWN;
  13218. }
  13219. }
  13220. static const ufbx_real ufbxi_time_mode_fps[] = {
  13221. 24.0f, // UFBX_TIME_MODE_DEFAULT
  13222. 120.0f, // UFBX_TIME_MODE_120_FPS
  13223. 100.0f, // UFBX_TIME_MODE_100_FPS
  13224. 60.0f, // UFBX_TIME_MODE_60_FPS
  13225. 50.0f, // UFBX_TIME_MODE_50_FPS
  13226. 48.0f, // UFBX_TIME_MODE_48_FPS
  13227. 30.0f, // UFBX_TIME_MODE_30_FPS
  13228. 30.0f, // UFBX_TIME_MODE_30_FPS_DROP
  13229. 29.97f, // UFBX_TIME_MODE_NTSC_DROP_FRAME
  13230. 29.97f, // UFBX_TIME_MODE_NTSC_FULL_FRAME
  13231. 25.0f, // UFBX_TIME_MODE_PAL
  13232. 24.0f, // UFBX_TIME_MODE_24_FPS
  13233. 1000.0f, // UFBX_TIME_MODE_1000_FPS
  13234. 23.976f, // UFBX_TIME_MODE_FILM_FULL_FRAME
  13235. 24.0f, // UFBX_TIME_MODE_CUSTOM
  13236. 96.0f, // UFBX_TIME_MODE_96_FPS
  13237. 72.0f, // UFBX_TIME_MODE_72_FPS
  13238. 59.94f, // UFBX_TIME_MODE_59_94_FPS
  13239. };
  13240. ufbxi_noinline static void ufbxi_update_scene(ufbx_scene *scene, bool initial)
  13241. {
  13242. ufbxi_for_ptr_list(ufbx_node, p_node, scene->nodes) {
  13243. ufbxi_update_node(*p_node);
  13244. }
  13245. ufbxi_for_ptr_list(ufbx_light, p_light, scene->lights) {
  13246. ufbxi_update_light(*p_light);
  13247. }
  13248. ufbxi_for_ptr_list(ufbx_camera, p_camera, scene->cameras) {
  13249. ufbxi_update_camera(*p_camera);
  13250. }
  13251. ufbxi_for_ptr_list(ufbx_bone, p_bone, scene->bones) {
  13252. ufbxi_update_bone(scene, *p_bone);
  13253. }
  13254. ufbxi_for_ptr_list(ufbx_line_curve, p_line, scene->line_curves) {
  13255. ufbxi_update_line_curve(*p_line);
  13256. }
  13257. if (initial) {
  13258. ufbxi_update_initial_clusters(scene);
  13259. }
  13260. ufbxi_for_ptr_list(ufbx_skin_cluster, p_cluster, scene->skin_clusters) {
  13261. ufbxi_update_skin_cluster(*p_cluster);
  13262. }
  13263. ufbxi_for_ptr_list(ufbx_blend_channel, p_channel, scene->blend_channels) {
  13264. ufbxi_update_blend_channel(*p_channel);
  13265. }
  13266. ufbxi_for_ptr_list(ufbx_texture, p_texture, scene->textures) {
  13267. ufbxi_update_texture(*p_texture);
  13268. }
  13269. ufbxi_propagate_main_textures(scene);
  13270. ufbxi_for_ptr_list(ufbx_material, p_material, scene->materials) {
  13271. ufbxi_update_material(scene, *p_material);
  13272. }
  13273. ufbxi_for_ptr_list(ufbx_anim_stack, p_stack, scene->anim_stacks) {
  13274. ufbxi_update_anim_stack(scene, *p_stack);
  13275. }
  13276. ufbxi_for_ptr_list(ufbx_display_layer, p_layer, scene->display_layers) {
  13277. ufbxi_update_display_layer(*p_layer);
  13278. }
  13279. ufbxi_for_ptr_list(ufbx_constraint, p_constraint, scene->constraints) {
  13280. ufbxi_update_constraint(*p_constraint);
  13281. }
  13282. ufbxi_update_anim(scene);
  13283. }
  13284. static ufbxi_noinline void ufbxi_update_scene_metadata(ufbx_metadata *metadata)
  13285. {
  13286. ufbx_props *props = &metadata->scene_props;
  13287. metadata->original_application.vendor = ufbx_find_string(props, "Original|ApplicationVendor", ufbx_empty_string);
  13288. metadata->original_application.name = ufbx_find_string(props, "Original|ApplicationName", ufbx_empty_string);
  13289. metadata->original_application.version = ufbx_find_string(props, "Original|ApplicationVersion", ufbx_empty_string);
  13290. metadata->latest_application.vendor = ufbx_find_string(props, "LastSaved|ApplicationVendor", ufbx_empty_string);
  13291. metadata->latest_application.name = ufbx_find_string(props, "LastSaved|ApplicationName", ufbx_empty_string);
  13292. metadata->latest_application.version = ufbx_find_string(props, "LastSaved|ApplicationVersion", ufbx_empty_string);
  13293. }
  13294. static const ufbx_real ufbxi_pow10_targets[] = {
  13295. 0.0f,
  13296. (ufbx_real)1e-8, (ufbx_real)1e-7, (ufbx_real)1e-6, (ufbx_real)1e-5,
  13297. (ufbx_real)1e-4, (ufbx_real)1e-3, (ufbx_real)1e-2, (ufbx_real)1e-1,
  13298. (ufbx_real)1e+0, (ufbx_real)1e+1, (ufbx_real)1e+2, (ufbx_real)1e+3,
  13299. (ufbx_real)1e+4, (ufbx_real)1e+5, (ufbx_real)1e+6, (ufbx_real)1e+7,
  13300. (ufbx_real)1e+8, (ufbx_real)1e+9,
  13301. };
  13302. static ufbxi_noinline ufbx_real ufbxi_round_if_near(const ufbx_real *targets, size_t num_targets, ufbx_real value)
  13303. {
  13304. for (size_t i = 0; i < num_targets; i++) {
  13305. double target = targets[i];
  13306. double error = target * 9.5367431640625e-7;
  13307. if (error < 0.0) error = -error;
  13308. if (error < 7.52316384526264005e-37) error = 7.52316384526264005e-37;
  13309. if (value >= target - error && value <= target + error) {
  13310. return (ufbx_real)target;
  13311. }
  13312. }
  13313. return value;
  13314. }
  13315. static ufbxi_noinline void ufbxi_update_scene_settings(ufbx_scene_settings *settings)
  13316. {
  13317. ufbx_real unit_scale_factor = ufbxi_find_real(&settings->props, ufbxi_UnitScaleFactor, 1.0f);
  13318. ufbx_real original_unit_scale_factor = ufbxi_find_real(&settings->props, ufbxi_OriginalUnitScaleFactor, unit_scale_factor);
  13319. settings->axes.up = ufbxi_find_axis(&settings->props, ufbxi_UpAxis, ufbxi_UpAxisSign);
  13320. settings->axes.front = ufbxi_find_axis(&settings->props, ufbxi_FrontAxis, ufbxi_FrontAxisSign);
  13321. settings->axes.right = ufbxi_find_axis(&settings->props, ufbxi_CoordAxis, ufbxi_CoordAxisSign);
  13322. settings->unit_meters = ufbxi_round_if_near(ufbxi_pow10_targets, ufbxi_arraycount(ufbxi_pow10_targets), unit_scale_factor * (ufbx_real)0.01);
  13323. settings->original_unit_meters = ufbxi_round_if_near(ufbxi_pow10_targets, ufbxi_arraycount(ufbxi_pow10_targets), original_unit_scale_factor * (ufbx_real)0.01);
  13324. settings->frames_per_second = ufbxi_find_real(&settings->props, ufbxi_CustomFrameRate, 24.0f);
  13325. settings->ambient_color = ufbxi_find_vec3(&settings->props, ufbxi_AmbientColor, 0.0f, 0.0f, 0.0f);
  13326. settings->original_axis_up = ufbxi_find_axis(&settings->props, ufbxi_OriginalUpAxis, ufbxi_OriginalUpAxisSign);
  13327. ufbx_prop *default_camera = ufbxi_find_prop(&settings->props, ufbxi_DefaultCamera);
  13328. if (default_camera) {
  13329. settings->default_camera = default_camera->value_str;
  13330. } else {
  13331. settings->default_camera = ufbx_empty_string;
  13332. }
  13333. settings->time_mode = (ufbx_time_mode)ufbxi_find_enum(&settings->props, ufbxi_TimeMode, UFBX_TIME_MODE_24_FPS, UFBX_TIME_MODE_59_94_FPS);
  13334. settings->time_protocol = (ufbx_time_protocol)ufbxi_find_enum(&settings->props, ufbxi_TimeProtocol, UFBX_TIME_PROTOCOL_DEFAULT, UFBX_TIME_PROTOCOL_DEFAULT);
  13335. settings->snap_mode = (ufbx_snap_mode)ufbxi_find_enum(&settings->props, ufbxi_SnapOnFrameMode, UFBX_SNAP_MODE_NONE, UFBX_SNAP_MODE_SNAP_AND_PLAY);
  13336. if (settings->time_mode != UFBX_TIME_MODE_CUSTOM) {
  13337. settings->frames_per_second = ufbxi_time_mode_fps[settings->time_mode];
  13338. }
  13339. }
  13340. // -- Geometry caches
  13341. #if UFBXI_FEATURE_GEOMETRY_CACHE
  13342. typedef struct {
  13343. ufbxi_refcount refcount;
  13344. ufbx_geometry_cache cache;
  13345. uint32_t magic;
  13346. bool owned_by_scene;
  13347. ufbxi_allocator ator;
  13348. ufbxi_buf result_buf;
  13349. ufbxi_buf string_buf;
  13350. } ufbxi_geometry_cache_imp;
  13351. ufbx_static_assert(geometry_cache_imp_offset, offsetof(ufbxi_geometry_cache_imp, cache) == sizeof(ufbxi_refcount));
  13352. typedef struct {
  13353. ufbx_string name;
  13354. ufbx_string interpretation;
  13355. uint32_t sample_rate;
  13356. uint32_t start_time;
  13357. uint32_t end_time;
  13358. uint32_t current_time;
  13359. uint32_t conescutive_fails;
  13360. bool try_load;
  13361. } ufbxi_cache_tmp_channel;
  13362. typedef enum {
  13363. UFBXI_CACHE_XML_TYPE_NONE,
  13364. UFBXI_CACHE_XML_TYPE_FILE_PER_FRAME,
  13365. UFBXI_CACHE_XML_TYPE_SINGLE_FILE,
  13366. } ufbxi_cache_xml_type;
  13367. typedef enum {
  13368. UFBXI_CACHE_XML_FORMAT_NONE,
  13369. UFBXI_CACHE_XML_FORMAT_MCC,
  13370. UFBXI_CACHE_XML_FORMAT_MCX,
  13371. } ufbxi_cache_xml_format;
  13372. typedef struct {
  13373. ufbx_error error;
  13374. ufbx_string filename;
  13375. bool owned_by_scene;
  13376. ufbx_geometry_cache_opts opts;
  13377. ufbxi_allocator *ator_tmp;
  13378. ufbxi_allocator ator_result;
  13379. ufbxi_buf result;
  13380. ufbxi_buf tmp;
  13381. ufbxi_buf tmp_stack;
  13382. ufbxi_cache_tmp_channel *channels;
  13383. size_t num_channels;
  13384. // Temporary array
  13385. char *tmp_arr;
  13386. size_t tmp_arr_size;
  13387. ufbxi_string_pool string_pool;
  13388. ufbx_open_file_cb open_file_cb;
  13389. double frames_per_second;
  13390. ufbx_string stream_filename;
  13391. ufbx_stream stream;
  13392. bool mc_for8;
  13393. ufbx_string xml_filename;
  13394. uint32_t xml_ticks_per_frame;
  13395. ufbxi_cache_xml_type xml_type;
  13396. ufbxi_cache_xml_format xml_format;
  13397. ufbx_string channel_name;
  13398. char *name_buf;
  13399. size_t name_cap;
  13400. uint64_t file_offset;
  13401. const char *pos, *pos_end;
  13402. ufbx_geometry_cache cache;
  13403. ufbxi_geometry_cache_imp *imp;
  13404. char buffer[128];
  13405. } ufbxi_cache_context;
  13406. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_read(ufbxi_cache_context *cc, void *dst, size_t size, bool allow_eof)
  13407. {
  13408. size_t buffered = ufbxi_min_sz(ufbxi_to_size(cc->pos_end - cc->pos), size);
  13409. memcpy(dst, cc->pos, buffered);
  13410. cc->pos += buffered;
  13411. size -= buffered;
  13412. cc->file_offset += buffered;
  13413. if (size == 0) return 1;
  13414. dst = (char*)dst + buffered;
  13415. if (size >= sizeof(cc->buffer)) {
  13416. size_t num_read = cc->stream.read_fn(cc->stream.user, dst, size);
  13417. ufbxi_check_err_msg(&cc->error, num_read <= size, "IO error");
  13418. if (!allow_eof) {
  13419. ufbxi_check_err_msg(&cc->error, num_read == size, "Truncated file");
  13420. }
  13421. cc->file_offset += num_read;
  13422. size -= num_read;
  13423. dst = (char*)dst + num_read;
  13424. } else {
  13425. size_t num_read = cc->stream.read_fn(cc->stream.user, cc->buffer, sizeof(cc->buffer));
  13426. ufbxi_check_err_msg(&cc->error, num_read <= sizeof(cc->buffer), "IO error");
  13427. if (!allow_eof) {
  13428. ufbxi_check_err_msg(&cc->error, num_read >= size, "Truncated file");
  13429. }
  13430. cc->pos = cc->buffer;
  13431. cc->pos_end = cc->buffer + sizeof(cc->buffer);
  13432. memcpy(dst, cc->pos, size);
  13433. cc->pos += size;
  13434. cc->file_offset += size;
  13435. size_t num_written = ufbxi_min_sz(size, num_read);
  13436. size -= num_written;
  13437. dst = (char*)dst + num_written;
  13438. }
  13439. if (size > 0) {
  13440. memset(dst, 0, size);
  13441. }
  13442. return 1;
  13443. }
  13444. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_skip(ufbxi_cache_context *cc, uint64_t size)
  13445. {
  13446. cc->file_offset += size;
  13447. uint64_t buffered = ufbxi_min64((uint64_t)(cc->pos_end - cc->pos), size);
  13448. cc->pos += buffered;
  13449. size -= buffered;
  13450. if (cc->stream.skip_fn) {
  13451. while (size >= UFBXI_MAX_SKIP_SIZE) {
  13452. size -= UFBXI_MAX_SKIP_SIZE;
  13453. ufbxi_check_err_msg(&cc->error, cc->stream.skip_fn(cc->stream.user, UFBXI_MAX_SKIP_SIZE - 1), "Truncated file");
  13454. // Check that we can read at least one byte in case the file is broken
  13455. // and causes us to seek indefinitely forwards as `fseek()` does not
  13456. // report if we hit EOF...
  13457. char single_byte[1];
  13458. size_t num_read = cc->stream.read_fn(cc->stream.user, single_byte, 1);
  13459. ufbxi_check_err_msg(&cc->error, num_read <= 1, "IO error");
  13460. ufbxi_check_err_msg(&cc->error, num_read == 1, "Truncated file");
  13461. }
  13462. if (size > 0) {
  13463. ufbxi_check_err_msg(&cc->error, cc->stream.skip_fn(cc->stream.user, (size_t)size), "Truncated file");
  13464. }
  13465. } else {
  13466. char skip_buf[2048];
  13467. while (size > 0) {
  13468. size_t to_skip = (size_t)ufbxi_min64(size, sizeof(skip_buf));
  13469. size -= to_skip;
  13470. ufbxi_check_err_msg(&cc->error, cc->stream.read_fn(cc->stream.user, skip_buf, to_skip), "Truncated file");
  13471. }
  13472. }
  13473. return 1;
  13474. }
  13475. #define ufbxi_cache_mc_tag(a,b,c,d) ((uint32_t)(a)<<24u | (uint32_t)(b)<<16 | (uint32_t)(c)<<8u | (uint32_t)(d))
  13476. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_mc_read_tag(ufbxi_cache_context *cc, uint32_t *p_tag)
  13477. {
  13478. char buf[4];
  13479. ufbxi_check_err(&cc->error, ufbxi_cache_read(cc, buf, 4, true));
  13480. *p_tag = (uint32_t)(uint8_t)buf[0]<<24u | (uint32_t)(uint8_t)buf[1]<<16 | (uint32_t)(uint8_t)buf[2]<<8u | (uint32_t)(uint8_t)buf[3];
  13481. if (*p_tag == ufbxi_cache_mc_tag('F','O','R','8')) {
  13482. cc->mc_for8 = true;
  13483. }
  13484. return 1;
  13485. }
  13486. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_mc_read_u32(ufbxi_cache_context *cc, uint32_t *p_value)
  13487. {
  13488. char buf[4];
  13489. ufbxi_check_err(&cc->error, ufbxi_cache_read(cc, buf, 4, false));
  13490. *p_value = (uint32_t)(uint8_t)buf[0]<<24u | (uint32_t)(uint8_t)buf[1]<<16 | (uint32_t)(uint8_t)buf[2]<<8u | (uint32_t)(uint8_t)buf[3];
  13491. if (cc->mc_for8) {
  13492. ufbxi_check_err(&cc->error, ufbxi_cache_read(cc, buf, 4, false));
  13493. }
  13494. return 1;
  13495. }
  13496. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_mc_read_u64(ufbxi_cache_context *cc, uint64_t *p_value)
  13497. {
  13498. if (!cc->mc_for8) {
  13499. uint32_t v32;
  13500. ufbxi_check_err(&cc->error, ufbxi_cache_mc_read_u32(cc, &v32));
  13501. *p_value = v32;
  13502. } else {
  13503. char buf[8];
  13504. ufbxi_check_err(&cc->error, ufbxi_cache_read(cc, buf, 8, false));
  13505. uint32_t hi = (uint32_t)(uint8_t)buf[0]<<24u | (uint32_t)(uint8_t)buf[1]<<16 | (uint32_t)(uint8_t)buf[2]<<8u | (uint32_t)(uint8_t)buf[3];
  13506. uint32_t lo = (uint32_t)(uint8_t)buf[4]<<24u | (uint32_t)(uint8_t)buf[5]<<16 | (uint32_t)(uint8_t)buf[6]<<8u | (uint32_t)(uint8_t)buf[7];
  13507. *p_value = (uint64_t)hi << 32u | (uint64_t)lo;
  13508. }
  13509. return 1;
  13510. }
  13511. static const uint8_t ufbxi_cache_data_format_size[] = {
  13512. 0, 4, 12, 8, 24,
  13513. };
  13514. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_load_mc(ufbxi_cache_context *cc)
  13515. {
  13516. uint32_t version = 0, time_start = 0, time_end = 0;
  13517. uint32_t count = 0, time = 0;
  13518. char skip_buf[8];
  13519. for (;;) {
  13520. uint32_t tag;
  13521. uint64_t size;
  13522. ufbxi_check_err(&cc->error, ufbxi_cache_mc_read_tag(cc, &tag));
  13523. if (tag == 0) break;
  13524. if (tag == ufbxi_cache_mc_tag('C','A','C','H') || tag == ufbxi_cache_mc_tag('M','Y','C','H')) {
  13525. continue;
  13526. }
  13527. if (cc->mc_for8) {
  13528. ufbxi_check_err(&cc->error, ufbxi_cache_read(cc, skip_buf, 4, false));
  13529. }
  13530. ufbxi_check_err(&cc->error, ufbxi_cache_mc_read_u64(cc, &size));
  13531. uint64_t begin = cc->file_offset;
  13532. size_t alignment = cc->mc_for8 ? 8 : 4;
  13533. ufbx_cache_data_format format = UFBX_CACHE_DATA_FORMAT_UNKNOWN;
  13534. switch (tag) {
  13535. case ufbxi_cache_mc_tag('F','O','R','4'): cc->mc_for8 = false; break;
  13536. case ufbxi_cache_mc_tag('F','O','R','8'): cc->mc_for8 = true; break;
  13537. case ufbxi_cache_mc_tag('V','R','S','N'): ufbxi_check_err(&cc->error, ufbxi_cache_mc_read_u32(cc, &version)); break;
  13538. case ufbxi_cache_mc_tag('S','T','I','M'):
  13539. ufbxi_check_err(&cc->error, ufbxi_cache_mc_read_u32(cc, &time_start));
  13540. time = time_start;
  13541. break;
  13542. case ufbxi_cache_mc_tag('E','T','I','M'): ufbxi_check_err(&cc->error, ufbxi_cache_mc_read_u32(cc, &time_end)); break;
  13543. case ufbxi_cache_mc_tag('T','I','M','E'): ufbxi_check_err(&cc->error, ufbxi_cache_mc_read_u32(cc, &time)); break;
  13544. case ufbxi_cache_mc_tag('C','H','N','M'): {
  13545. ufbxi_check_err(&cc->error, size > 0 && size < SIZE_MAX);
  13546. size_t length = (size_t)size - 1;
  13547. size_t padded_length = ((size_t)size + alignment - 1) & ~(alignment - 1);
  13548. ufbxi_check_err(&cc->error, ufbxi_grow_array(cc->ator_tmp, &cc->name_buf, &cc->name_cap, padded_length));
  13549. ufbxi_check_err(&cc->error, ufbxi_cache_read(cc, cc->name_buf, padded_length, false));
  13550. cc->channel_name.data = cc->name_buf;
  13551. cc->channel_name.length = length;
  13552. ufbxi_check_err(&cc->error, ufbxi_push_string_place_str(&cc->string_pool, &cc->channel_name, false));
  13553. } break;
  13554. case ufbxi_cache_mc_tag('S','I','Z','E'): ufbxi_check_err(&cc->error, ufbxi_cache_mc_read_u32(cc, &count)); break;
  13555. case ufbxi_cache_mc_tag('F','V','C','A'): format = UFBX_CACHE_DATA_FORMAT_VEC3_FLOAT; break;
  13556. case ufbxi_cache_mc_tag('D','V','C','A'): format = UFBX_CACHE_DATA_FORMAT_VEC3_DOUBLE; break;
  13557. case ufbxi_cache_mc_tag('F','B','C','A'): format = UFBX_CACHE_DATA_FORMAT_REAL_FLOAT; break;
  13558. case ufbxi_cache_mc_tag('D','B','C','A'): format = UFBX_CACHE_DATA_FORMAT_REAL_DOUBLE; break;
  13559. case ufbxi_cache_mc_tag('D','B','L','A'): format = UFBX_CACHE_DATA_FORMAT_REAL_DOUBLE; break;
  13560. default: ufbxi_fail_err(&cc->error, "Unknown tag");
  13561. }
  13562. if (format != UFBX_CACHE_DATA_FORMAT_UNKNOWN) {
  13563. ufbx_cache_frame *frame = ufbxi_push_zero(&cc->tmp_stack, ufbx_cache_frame, 1);
  13564. ufbxi_check_err(&cc->error, frame);
  13565. uint32_t elem_size = ufbxi_cache_data_format_size[format];
  13566. uint64_t total_size = (uint64_t)elem_size * (uint64_t)count;
  13567. ufbxi_check_err(&cc->error, size >= elem_size * count);
  13568. frame->channel = cc->channel_name;
  13569. frame->time = (double)time * (1.0/6000.0);
  13570. frame->filename = cc->stream_filename;
  13571. frame->data_format = format;
  13572. frame->data_encoding = UFBX_CACHE_DATA_ENCODING_BIG_ENDIAN;
  13573. frame->data_offset = cc->file_offset;
  13574. frame->data_count = count;
  13575. frame->data_element_bytes = elem_size;
  13576. frame->data_total_bytes = total_size;
  13577. frame->file_format = UFBX_CACHE_FILE_FORMAT_MC;
  13578. uint64_t end = begin + ((size + alignment - 1) & ~(uint64_t)(alignment - 1));
  13579. ufbxi_check_err(&cc->error, end >= cc->file_offset);
  13580. uint64_t left = end - cc->file_offset;
  13581. ufbxi_check_err(&cc->error, ufbxi_cache_skip(cc, left));
  13582. }
  13583. }
  13584. return 1;
  13585. }
  13586. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_load_pc2(ufbxi_cache_context *cc)
  13587. {
  13588. char header[32];
  13589. ufbxi_check_err(&cc->error, ufbxi_cache_read(cc, header, sizeof(header), false));
  13590. uint32_t version = ufbxi_read_u32(header + 12);
  13591. uint32_t num_points = ufbxi_read_u32(header + 16);
  13592. double start_frame = ufbxi_read_f32(header + 20);
  13593. double frames_per_sample = ufbxi_read_f32(header + 24);
  13594. uint32_t num_samples = ufbxi_read_u32(header + 28);
  13595. (void)version;
  13596. ufbx_cache_frame *frames = ufbxi_push_zero(&cc->tmp_stack, ufbx_cache_frame, num_samples);
  13597. ufbxi_check_err(&cc->error, frames);
  13598. uint64_t total_points = (uint64_t)num_points * (uint64_t)num_samples;
  13599. ufbxi_check_err(&cc->error, total_points < UINT64_MAX / 12);
  13600. uint64_t offset = cc->file_offset;
  13601. // Skip almost to the end of the data and try to read one byte as there's
  13602. // nothing after the data so we can't detect EOF..
  13603. if (total_points > 0) {
  13604. char last_byte[1];
  13605. ufbxi_check_err(&cc->error, ufbxi_cache_skip(cc, total_points * 12 - 1));
  13606. ufbxi_check_err(&cc->error, ufbxi_cache_read(cc, last_byte, 1, false));
  13607. }
  13608. for (uint32_t i = 0; i < num_samples; i++) {
  13609. ufbx_cache_frame *frame = &frames[i];
  13610. double sample_frame = start_frame + (double)i * frames_per_sample;
  13611. frame->channel = cc->channel_name;
  13612. frame->time = sample_frame / cc->frames_per_second;
  13613. frame->filename = cc->stream_filename;
  13614. frame->data_format = UFBX_CACHE_DATA_FORMAT_VEC3_FLOAT;
  13615. frame->data_encoding = UFBX_CACHE_DATA_ENCODING_LITTLE_ENDIAN;
  13616. frame->data_offset = offset;
  13617. frame->data_count = num_points;
  13618. frame->data_element_bytes = 12;
  13619. frame->data_total_bytes = num_points * 12;
  13620. frame->file_format = UFBX_CACHE_FILE_FORMAT_PC2;
  13621. offset += num_points * 12;
  13622. }
  13623. return 1;
  13624. }
  13625. static ufbxi_noinline bool ufbxi_tmp_channel_less(void *user, const void *va, const void *vb)
  13626. {
  13627. (void)user;
  13628. const ufbxi_cache_tmp_channel *a = (const ufbxi_cache_tmp_channel *)va, *b = (const ufbxi_cache_tmp_channel *)vb;
  13629. return ufbxi_str_less(a->name, b->name);
  13630. }
  13631. static ufbxi_noinline int ufbxi_cache_sort_tmp_channels(ufbxi_cache_context *cc, ufbxi_cache_tmp_channel *channels, size_t count)
  13632. {
  13633. ufbxi_check_err(&cc->error, ufbxi_grow_array(cc->ator_tmp, &cc->tmp_arr, &cc->tmp_arr_size, count * sizeof(ufbxi_cache_tmp_channel)));
  13634. ufbxi_stable_sort(sizeof(ufbxi_cache_tmp_channel), 16, channels, cc->tmp_arr, count, &ufbxi_tmp_channel_less, NULL);
  13635. return 1;
  13636. }
  13637. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_load_xml_imp(ufbxi_cache_context *cc, ufbxi_xml_document *doc)
  13638. {
  13639. cc->xml_ticks_per_frame = 250;
  13640. cc->xml_filename = cc->stream_filename;
  13641. ufbxi_xml_tag *tag_root = ufbxi_xml_find_child(doc->root, "Autodesk_Cache_File");
  13642. if (tag_root) {
  13643. ufbxi_xml_tag *tag_type = ufbxi_xml_find_child(tag_root, "cacheType");
  13644. ufbxi_xml_tag *tag_fps = ufbxi_xml_find_child(tag_root, "cacheTimePerFrame");
  13645. ufbxi_xml_tag *tag_channels = ufbxi_xml_find_child(tag_root, "Channels");
  13646. size_t num_extra = 0;
  13647. ufbxi_for(ufbxi_xml_tag, tag, tag_root->children, tag_root->num_children) {
  13648. if (tag->num_children != 1) continue;
  13649. if (strcmp(tag->name.data, "extra") != 0) continue;
  13650. ufbx_string *extra = ufbxi_push(&cc->tmp_stack, ufbx_string, 1);
  13651. ufbxi_check_err(&cc->error, extra);
  13652. *extra = tag->children[0].text;
  13653. ufbxi_check_err(&cc->error, ufbxi_push_string_place_str(&cc->string_pool, extra, false));
  13654. num_extra++;
  13655. }
  13656. cc->cache.extra_info.count = num_extra;
  13657. cc->cache.extra_info.data = ufbxi_push_pop(&cc->result, &cc->tmp_stack, ufbx_string, num_extra);
  13658. ufbxi_check_err(&cc->error, cc->cache.extra_info.data);
  13659. if (tag_type) {
  13660. ufbxi_xml_attrib *type = ufbxi_xml_find_attrib(tag_type, "Type");
  13661. ufbxi_xml_attrib *format = ufbxi_xml_find_attrib(tag_type, "Format");
  13662. if (type) {
  13663. if (!strcmp(type->value.data, "OneFilePerFrame")) {
  13664. cc->xml_type = UFBXI_CACHE_XML_TYPE_FILE_PER_FRAME;
  13665. } else if (!strcmp(type->value.data, "OneFile")) {
  13666. cc->xml_type = UFBXI_CACHE_XML_TYPE_SINGLE_FILE;
  13667. }
  13668. }
  13669. if (format) {
  13670. if (!strcmp(format->value.data, "mcc")) {
  13671. cc->xml_format = UFBXI_CACHE_XML_FORMAT_MCC;
  13672. } else if (!strcmp(format->value.data, "mcx")) {
  13673. cc->xml_format = UFBXI_CACHE_XML_FORMAT_MCX;
  13674. }
  13675. }
  13676. }
  13677. if (tag_fps) {
  13678. ufbxi_xml_attrib *fps = ufbxi_xml_find_attrib(tag_fps, "TimePerFrame");
  13679. if (fps) {
  13680. int value = atoi(fps->value.data);
  13681. if (value > 0) {
  13682. cc->xml_ticks_per_frame = (uint32_t)value;
  13683. }
  13684. }
  13685. }
  13686. if (tag_channels) {
  13687. cc->channels = ufbxi_push_zero(&cc->tmp, ufbxi_cache_tmp_channel, tag_channels->num_children);
  13688. ufbxi_check_err(&cc->error, cc->channels);
  13689. ufbxi_for(ufbxi_xml_tag, tag, tag_channels->children, tag_channels->num_children) {
  13690. ufbxi_xml_attrib *name = ufbxi_xml_find_attrib(tag, "ChannelName");
  13691. ufbxi_xml_attrib *type = ufbxi_xml_find_attrib(tag, "ChannelType");
  13692. ufbxi_xml_attrib *interpretation = ufbxi_xml_find_attrib(tag, "ChannelInterpretation");
  13693. if (!(name && type && interpretation)) continue;
  13694. ufbxi_cache_tmp_channel *channel = &cc->channels[cc->num_channels++];
  13695. channel->name = name->value;
  13696. channel->interpretation = interpretation->value;
  13697. ufbxi_check_err(&cc->error, ufbxi_push_string_place_str(&cc->string_pool, &channel->name, false));
  13698. ufbxi_check_err(&cc->error, ufbxi_push_string_place_str(&cc->string_pool, &channel->interpretation, false));
  13699. ufbxi_xml_attrib *sampling_rate = ufbxi_xml_find_attrib(tag, "SamplingRate");
  13700. ufbxi_xml_attrib *start_time = ufbxi_xml_find_attrib(tag, "StartTime");
  13701. ufbxi_xml_attrib *end_time = ufbxi_xml_find_attrib(tag, "EndTime");
  13702. if (sampling_rate && start_time && end_time) {
  13703. channel->sample_rate = (uint32_t)atoi(sampling_rate->value.data);
  13704. channel->start_time = (uint32_t)atoi(start_time->value.data);
  13705. channel->end_time = (uint32_t)atoi(end_time->value.data);
  13706. channel->current_time = channel->start_time;
  13707. channel->try_load = true;
  13708. }
  13709. }
  13710. }
  13711. }
  13712. ufbxi_check_err(&cc->error, ufbxi_cache_sort_tmp_channels(cc, cc->channels, cc->num_channels));
  13713. return 1;
  13714. }
  13715. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_load_xml(ufbxi_cache_context *cc)
  13716. {
  13717. ufbxi_xml_load_opts opts = { 0 };
  13718. opts.ator = cc->ator_tmp;
  13719. opts.read_fn = cc->stream.read_fn;
  13720. opts.read_user = cc->stream.user;
  13721. opts.prefix = cc->pos;
  13722. opts.prefix_length = ufbxi_to_size(cc->pos_end - cc->pos);
  13723. ufbxi_xml_document *doc = ufbxi_load_xml(&opts, &cc->error);
  13724. ufbxi_check_err(&cc->error, doc);
  13725. int xml_ok = ufbxi_cache_load_xml_imp(cc, doc);
  13726. ufbxi_free_xml(doc);
  13727. ufbxi_check_err(&cc->error, xml_ok);
  13728. return 1;
  13729. }
  13730. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_load_file(ufbxi_cache_context *cc, ufbx_string filename)
  13731. {
  13732. cc->stream_filename = filename;
  13733. ufbxi_check_err(&cc->error, ufbxi_push_string_place_str(&cc->string_pool, &cc->stream_filename, false));
  13734. // Assume all files have at least 16 bytes of header
  13735. size_t magic_len = cc->stream.read_fn(cc->stream.user, cc->buffer, 16);
  13736. ufbxi_check_err_msg(&cc->error, magic_len <= 16, "IO error");
  13737. ufbxi_check_err_msg(&cc->error, magic_len == 16, "Truncated file");
  13738. cc->pos = cc->buffer;
  13739. cc->pos_end = cc->buffer + 16;
  13740. cc->file_offset = 0;
  13741. if (!memcmp(cc->buffer, "POINTCACHE2", 11)) {
  13742. ufbxi_check_err(&cc->error, ufbxi_cache_load_pc2(cc));
  13743. } else if (!memcmp(cc->buffer, "FOR4", 4) || !memcmp(cc->buffer, "FOR8", 4)) {
  13744. ufbxi_check_err(&cc->error, ufbxi_cache_load_mc(cc));
  13745. } else {
  13746. ufbxi_check_err(&cc->error, ufbxi_cache_load_xml(cc));
  13747. }
  13748. return 1;
  13749. }
  13750. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_try_open_file(ufbxi_cache_context *cc, ufbx_string filename, bool *p_found)
  13751. {
  13752. memset(&cc->stream, 0, sizeof(cc->stream));
  13753. ufbxi_regression_assert(strlen(filename.data) == filename.length);
  13754. if (!cc->open_file_cb.fn(cc->open_file_cb.user, &cc->stream, filename.data, filename.length)) {
  13755. return 1;
  13756. }
  13757. int ok = ufbxi_cache_load_file(cc, filename);
  13758. *p_found = true;
  13759. if (cc->stream.close_fn) {
  13760. cc->stream.close_fn(cc->stream.user);
  13761. }
  13762. return ok;
  13763. }
  13764. ufbxi_nodiscard static ufbxi_noinline int ufbxi_cache_load_frame_files(ufbxi_cache_context *cc)
  13765. {
  13766. if (cc->xml_filename.length == 0) return 1;
  13767. const char *extension = NULL;
  13768. switch (cc->xml_format) {
  13769. case UFBXI_CACHE_XML_FORMAT_MCC: extension = "mc"; break;
  13770. case UFBXI_CACHE_XML_FORMAT_MCX: extension = "mcx"; break;
  13771. default: return 1;
  13772. }
  13773. // Ensure worst case space for `path/filenameFrame123Tick456.mcx`
  13774. size_t name_buf_len = cc->xml_filename.length + 64;
  13775. char *name_buf = ufbxi_push(&cc->tmp, char, name_buf_len);
  13776. ufbxi_check_err(&cc->error, name_buf);
  13777. // Find the prefix before `.xml`
  13778. size_t prefix_len = cc->xml_filename.length;
  13779. for (size_t i = prefix_len; i > 0; --i) {
  13780. if (cc->xml_filename.data[i - 1] == '.') {
  13781. prefix_len = i - 1;
  13782. break;
  13783. }
  13784. }
  13785. memcpy(name_buf, cc->xml_filename.data, prefix_len);
  13786. char *suffix_data = name_buf + prefix_len;
  13787. size_t suffix_len = name_buf_len - prefix_len;
  13788. ufbx_string filename;
  13789. filename.data = name_buf;
  13790. if (cc->xml_type == UFBXI_CACHE_XML_TYPE_SINGLE_FILE) {
  13791. filename.length = prefix_len + (size_t)snprintf(suffix_data, suffix_len, ".%s", extension);
  13792. bool found = false;
  13793. ufbxi_check_err(&cc->error, ufbxi_cache_try_open_file(cc, filename, &found));
  13794. } else if (cc->xml_type == UFBXI_CACHE_XML_TYPE_FILE_PER_FRAME) {
  13795. uint32_t lowest_time = 0;
  13796. for (;;) {
  13797. // Find the first `time >= lowest_time` value that has data in some channel
  13798. uint32_t time = UINT32_MAX;
  13799. ufbxi_for(ufbxi_cache_tmp_channel, chan, cc->channels, cc->num_channels) {
  13800. if (!chan->try_load || chan->conescutive_fails > 10) continue;
  13801. uint32_t sample_rate = chan->sample_rate ? chan->sample_rate : cc->xml_ticks_per_frame;
  13802. if (chan->current_time < lowest_time) {
  13803. uint32_t delta = (lowest_time - chan->current_time - 1) / sample_rate;
  13804. chan->current_time += delta * sample_rate;
  13805. if (UINT32_MAX - chan->current_time >= sample_rate) {
  13806. chan->current_time += sample_rate;
  13807. } else {
  13808. chan->try_load = false;
  13809. continue;
  13810. }
  13811. }
  13812. if (chan->current_time <= chan->end_time) {
  13813. time = ufbxi_min32(time, chan->current_time);
  13814. }
  13815. }
  13816. if (time == UINT32_MAX) break;
  13817. // Try to load a file at the specified frame/tick
  13818. uint32_t frame = time / cc->xml_ticks_per_frame;
  13819. uint32_t tick = time % cc->xml_ticks_per_frame;
  13820. if (tick == 0) {
  13821. filename.length = prefix_len + (size_t)snprintf(suffix_data, suffix_len, "Frame%u.%s", frame, extension);
  13822. } else {
  13823. filename.length = prefix_len + (size_t)snprintf(suffix_data, suffix_len, "Frame%uTick%u.%s", frame, tick, extension);
  13824. }
  13825. bool found = false;
  13826. ufbxi_check_err(&cc->error, ufbxi_cache_try_open_file(cc, filename, &found));
  13827. // Update channel status
  13828. ufbxi_for(ufbxi_cache_tmp_channel, chan, cc->channels, cc->num_channels) {
  13829. if (chan->current_time == time) {
  13830. chan->conescutive_fails = found ? 0 : chan->conescutive_fails + 1;
  13831. }
  13832. }
  13833. lowest_time = time + 1;
  13834. }
  13835. }
  13836. return 1;
  13837. }
  13838. static ufbxi_noinline bool ufbxi_cmp_cache_frame_less(void *user, const void *va, const void *vb)
  13839. {
  13840. (void)user;
  13841. const ufbx_cache_frame *a = (const ufbx_cache_frame *)va, *b = (const ufbx_cache_frame *)vb;
  13842. if (a->channel.data != b->channel.data) {
  13843. // Channel names should be interned
  13844. ufbxi_regression_assert(!ufbxi_str_equal(a->channel, b->channel));
  13845. return ufbxi_str_less(a->channel, b->channel);
  13846. }
  13847. return a->time < b->time;
  13848. }
  13849. static ufbxi_noinline int ufbxi_cache_sort_frames(ufbxi_cache_context *cc, ufbx_cache_frame *frames, size_t count)
  13850. {
  13851. ufbxi_check_err(&cc->error, ufbxi_grow_array(cc->ator_tmp, &cc->tmp_arr, &cc->tmp_arr_size, count * sizeof(ufbx_cache_frame)));
  13852. ufbxi_stable_sort(sizeof(ufbx_cache_frame), 16, frames, cc->tmp_arr, count, &ufbxi_cmp_cache_frame_less, NULL);
  13853. return 1;
  13854. }
  13855. typedef struct {
  13856. ufbx_cache_interpretation interpretation;
  13857. const char *name;
  13858. } ufbxi_cache_interpretation_name;
  13859. static const ufbxi_cache_interpretation_name ufbxi_cache_interpretation_names[] = {
  13860. { UFBX_CACHE_INTERPRETATION_POINTS, "points" },
  13861. { UFBX_CACHE_INTERPRETATION_VERTEX_POSITION, "positions" },
  13862. { UFBX_CACHE_INTERPRETATION_VERTEX_NORMAL, "normals" },
  13863. };
  13864. static ufbxi_noinline int ufbxi_cache_setup_channels(ufbxi_cache_context *cc)
  13865. {
  13866. ufbxi_cache_tmp_channel *tmp_chan = cc->channels, *tmp_end = ufbxi_add_ptr(tmp_chan, cc->num_channels);
  13867. size_t begin = 0, num_channels = 0;
  13868. while (begin < cc->cache.frames.count) {
  13869. ufbx_cache_frame *frame = &cc->cache.frames.data[begin];
  13870. size_t end = begin + 1;
  13871. while (end < cc->cache.frames.count && cc->cache.frames.data[end].channel.data == frame->channel.data) {
  13872. end++;
  13873. }
  13874. ufbx_cache_channel *chan = ufbxi_push_zero(&cc->tmp_stack, ufbx_cache_channel, 1);
  13875. ufbxi_check_err(&cc->error, chan);
  13876. chan->name = frame->channel;
  13877. chan->interpretation_name = ufbx_empty_string;
  13878. chan->frames.data = frame;
  13879. chan->frames.count = end - begin;
  13880. while (tmp_chan < tmp_end && ufbxi_str_less(tmp_chan->name, chan->name)) {
  13881. tmp_chan++;
  13882. }
  13883. if (tmp_chan < tmp_end && ufbxi_str_equal(tmp_chan->name, chan->name)) {
  13884. chan->interpretation_name = tmp_chan->interpretation;
  13885. }
  13886. if (frame->file_format == UFBX_CACHE_FILE_FORMAT_PC2) {
  13887. chan->interpretation = UFBX_CACHE_INTERPRETATION_VERTEX_POSITION;
  13888. } else {
  13889. ufbx_string interp = chan->interpretation_name;
  13890. char *interp_lowercase = ufbxi_push(&cc->tmp_stack, char, interp.length + 1);
  13891. ufbxi_check_err(&cc->error, interp_lowercase);
  13892. for (size_t i = 0; i < interp.length + 1; i++) {
  13893. char c = interp.data[i];
  13894. if (c >= 'A' && c <= 'Z') {
  13895. c = (char)((int)c + ((int)'a' - (int)'A'));
  13896. }
  13897. interp_lowercase[i] = c;
  13898. }
  13899. ufbxi_for(const ufbxi_cache_interpretation_name, name, ufbxi_cache_interpretation_names, ufbxi_arraycount(ufbxi_cache_interpretation_names)) {
  13900. if (!strcmp(interp_lowercase, name->name)) {
  13901. chan->interpretation = name->interpretation;
  13902. break;
  13903. }
  13904. }
  13905. ufbxi_pop(&cc->tmp_stack, char, interp.length + 1, NULL);
  13906. }
  13907. num_channels++;
  13908. begin = end;
  13909. }
  13910. cc->cache.channels.data = ufbxi_push_pop(&cc->result, &cc->tmp_stack, ufbx_cache_channel, num_channels);
  13911. ufbxi_check_err(&cc->error, cc->cache.channels.data);
  13912. cc->cache.channels.count = num_channels;
  13913. return 1;
  13914. }
  13915. static ufbxi_noinline int ufbxi_cache_load_imp(ufbxi_cache_context *cc, ufbx_string filename)
  13916. {
  13917. // `ufbx_geometry_cache_opts` must be cleared to zero first!
  13918. ufbx_assert(cc->opts._begin_zero == 0 && cc->opts._end_zero == 0);
  13919. ufbxi_check_err_msg(&cc->error, cc->opts._begin_zero == 0 && cc->opts._end_zero == 0, "Uninitialized options");
  13920. cc->tmp.ator = cc->ator_tmp;
  13921. cc->tmp_stack.ator = cc->ator_tmp;
  13922. cc->channel_name.data = ufbxi_empty_char;
  13923. if (!cc->open_file_cb.fn) {
  13924. cc->open_file_cb.fn = ufbx_open_file;
  13925. }
  13926. // Make sure the filename we pass to `open_file_fn()` is NULL-terminated
  13927. char *filename_data = ufbxi_push(&cc->tmp, char, filename.length + 1);
  13928. ufbxi_check_err(&cc->error, filename_data);
  13929. memcpy(filename_data, filename.data, filename.length);
  13930. filename_data[filename.length] = '\0';
  13931. ufbx_string filename_copy = { filename_data, filename.length };
  13932. // TODO: NULL termination!
  13933. bool found = false;
  13934. ufbxi_check_err(&cc->error, ufbxi_cache_try_open_file(cc, filename_copy, &found));
  13935. if (!found) {
  13936. ufbxi_fail_err_msg(&cc->error, "open_file_fn()", "File not found");
  13937. }
  13938. cc->cache.root_filename = cc->stream_filename;
  13939. ufbxi_check_err(&cc->error, ufbxi_cache_load_frame_files(cc));
  13940. size_t num_frames = cc->tmp_stack.num_items;
  13941. cc->cache.frames.count = num_frames;
  13942. cc->cache.frames.data = ufbxi_push_pop(&cc->result, &cc->tmp_stack, ufbx_cache_frame, num_frames);
  13943. ufbxi_check_err(&cc->error, cc->cache.frames.data);
  13944. ufbxi_check_err(&cc->error, ufbxi_cache_sort_frames(cc, cc->cache.frames.data, cc->cache.frames.count));
  13945. ufbxi_check_err(&cc->error, ufbxi_cache_setup_channels(cc));
  13946. // Must be last allocation!
  13947. cc->imp = ufbxi_push(&cc->result, ufbxi_geometry_cache_imp, 1);
  13948. ufbxi_check_err(&cc->error, cc->imp);
  13949. ufbxi_init_ref(&cc->imp->refcount, UFBXI_CACHE_IMP_MAGIC, NULL);
  13950. cc->imp->cache = cc->cache;
  13951. cc->imp->magic = UFBXI_CACHE_IMP_MAGIC;
  13952. cc->imp->owned_by_scene = cc->owned_by_scene;
  13953. cc->imp->ator = cc->ator_result;
  13954. cc->imp->result_buf = cc->result;
  13955. cc->imp->result_buf.ator = &cc->imp->ator;
  13956. cc->imp->string_buf = cc->string_pool.buf;
  13957. cc->imp->string_buf.ator = &cc->imp->ator;
  13958. return 1;
  13959. }
  13960. ufbxi_noinline static ufbx_geometry_cache *ufbxi_cache_load(ufbxi_cache_context *cc, ufbx_string filename)
  13961. {
  13962. int ok = ufbxi_cache_load_imp(cc, filename);
  13963. ufbxi_buf_free(&cc->tmp);
  13964. ufbxi_buf_free(&cc->tmp_stack);
  13965. ufbxi_free(cc->ator_tmp, char, cc->name_buf, cc->name_cap);
  13966. ufbxi_free(cc->ator_tmp, char, cc->tmp_arr, cc->tmp_arr_size);
  13967. if (!cc->owned_by_scene) {
  13968. ufbxi_string_pool_temp_free(&cc->string_pool);
  13969. ufbxi_free_ator(cc->ator_tmp);
  13970. }
  13971. if (ok) {
  13972. return &cc->imp->cache;
  13973. } else {
  13974. ufbxi_fix_error_type(&cc->error, "Failed to load geometry cache");
  13975. if (!cc->owned_by_scene) {
  13976. ufbxi_buf_free(&cc->string_pool.buf);
  13977. ufbxi_free_ator(&cc->ator_result);
  13978. }
  13979. return NULL;
  13980. }
  13981. }
  13982. ufbxi_noinline static ufbx_geometry_cache *ufbxi_load_geometry_cache(ufbx_string filename, const ufbx_geometry_cache_opts *user_opts, ufbx_error *p_error)
  13983. {
  13984. ufbx_geometry_cache_opts opts;
  13985. if (user_opts) {
  13986. opts = *user_opts;
  13987. } else {
  13988. memset(&opts, 0, sizeof(opts));
  13989. }
  13990. ufbxi_cache_context cc = { UFBX_ERROR_NONE };
  13991. ufbxi_allocator ator_tmp = { 0 };
  13992. ufbxi_init_ator(&cc.error, &ator_tmp, &opts.temp_allocator);
  13993. ufbxi_init_ator(&cc.error, &cc.ator_result, &opts.result_allocator);
  13994. cc.ator_tmp = &ator_tmp;
  13995. cc.opts = opts;
  13996. cc.open_file_cb = opts.open_file_cb;
  13997. cc.string_pool.error = &cc.error;
  13998. ufbxi_map_init(&cc.string_pool.map, cc.ator_tmp, &ufbxi_map_cmp_string, NULL);
  13999. cc.string_pool.buf.ator = &cc.ator_result;
  14000. cc.string_pool.buf.unordered = true;
  14001. cc.string_pool.initial_size = 64;
  14002. cc.result.ator = &cc.ator_result;
  14003. cc.frames_per_second = opts.frames_per_second > 0.0 ? opts.frames_per_second : 30.0;
  14004. ufbx_geometry_cache *cache = ufbxi_cache_load(&cc, filename);
  14005. if (p_error) {
  14006. if (cache) {
  14007. p_error->type = UFBX_ERROR_NONE;
  14008. p_error->description.data = ufbxi_empty_char;
  14009. p_error->description.length = 0;
  14010. p_error->stack_size = 0;
  14011. } else {
  14012. *p_error = cc.error;
  14013. }
  14014. }
  14015. return cache;
  14016. }
  14017. static ufbxi_noinline void ufbxi_free_geometry_cache_imp(ufbxi_geometry_cache_imp *imp)
  14018. {
  14019. ufbx_assert(imp->magic == UFBXI_CACHE_IMP_MAGIC);
  14020. if (imp->magic != UFBXI_CACHE_IMP_MAGIC) return;
  14021. if (imp->owned_by_scene) return;
  14022. imp->magic = 0;
  14023. ufbxi_buf_free(&imp->string_buf);
  14024. // We need to free `result_buf` last and be careful to copy it to
  14025. // the stack since the `ufbxi_scene_imp` that contains it is allocated
  14026. // from the same result buffer!
  14027. ufbxi_allocator ator = imp->ator;
  14028. ufbxi_buf result = imp->result_buf;
  14029. result.ator = &ator;
  14030. ufbxi_buf_free(&result);
  14031. ufbxi_free_ator(&ator);
  14032. }
  14033. #else
  14034. typedef struct {
  14035. ufbxi_refcount refcount;
  14036. uint32_t magic;
  14037. bool owned_by_scene;
  14038. } ufbxi_geometry_cache_imp;
  14039. static ufbxi_noinline ufbx_geometry_cache *ufbxi_load_geometry_cache(ufbx_string filename, const ufbx_geometry_cache_opts *user_opts, ufbx_error *p_error)
  14040. {
  14041. if (p_error) {
  14042. memset(p_error, 0, sizeof(ufbx_error));
  14043. ufbxi_report_err_msg(p_error, "UFBXI_FEATURE_GEOMETRY_CACHE", "Feature disabled");
  14044. }
  14045. return NULL;
  14046. }
  14047. static ufbxi_forceinline void ufbxi_free_geometry_cache_imp(ufbxi_geometry_cache_imp *imp)
  14048. {
  14049. }
  14050. #endif
  14051. // -- External files
  14052. typedef enum {
  14053. UFBXI_EXTERNAL_FILE_GEOMETRY_CACHE,
  14054. } ufbxi_external_file_type;
  14055. typedef struct {
  14056. ufbxi_external_file_type type;
  14057. ufbx_string filename;
  14058. ufbx_string absolute_filename;
  14059. size_t index;
  14060. void *data;
  14061. size_t data_size;
  14062. } ufbxi_external_file;
  14063. static int ufbxi_cmp_external_file(const void *va, const void *vb)
  14064. {
  14065. const ufbxi_external_file *a = (const ufbxi_external_file*)va, *b = (const ufbxi_external_file*)vb;
  14066. if (a->type != b->type) return a->type < b->type ? -1 : 1;
  14067. int cmp = ufbxi_str_cmp(a->filename, b->filename);
  14068. if (cmp != 0) return cmp;
  14069. if (a->index != b->index) return a->index < b->index ? -1 : 1;
  14070. return 0;
  14071. }
  14072. ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_external_cache(ufbxi_context *uc, ufbxi_external_file *file)
  14073. {
  14074. #if UFBXI_FEATURE_GEOMETRY_CACHE
  14075. ufbxi_cache_context cc = { UFBX_ERROR_NONE };
  14076. cc.owned_by_scene = true;
  14077. cc.open_file_cb = uc->opts.open_file_cb;
  14078. cc.frames_per_second = uc->scene.settings.frames_per_second;
  14079. // Temporarily "borrow" allocators for the geometry cache
  14080. cc.ator_tmp = &uc->ator_tmp;
  14081. cc.string_pool = uc->string_pool;
  14082. cc.result = uc->result;
  14083. ufbx_geometry_cache *cache = ufbxi_cache_load(&cc, file->filename);
  14084. if (!cache) {
  14085. if (cc.error.type == UFBX_ERROR_FILE_NOT_FOUND) {
  14086. memset(&cc.error, 0, sizeof(cc.error));
  14087. cache = ufbxi_cache_load(&cc, file->absolute_filename);
  14088. }
  14089. }
  14090. // Return the "borrowed" allocators
  14091. uc->string_pool = cc.string_pool;
  14092. uc->result = cc.result;
  14093. if (!cache) {
  14094. uc->error = cc.error;
  14095. return 0;
  14096. }
  14097. file->data = cache;
  14098. return 1;
  14099. #else
  14100. ufbxi_fail_msg("UFBXI_FEATURE_GEOMETRY_CACHE", "Feature disabled");
  14101. #endif
  14102. }
  14103. static ufbxi_noinline ufbxi_external_file *ufbxi_find_external_file(ufbxi_external_file *files, size_t num_files, ufbxi_external_file_type type, const char *name)
  14104. {
  14105. size_t ix = SIZE_MAX;
  14106. ufbxi_macro_lower_bound_eq(ufbxi_external_file, 32, &ix, files, 0, num_files,
  14107. ( type != a->type ? type < a->type : strcmp(a->filename.data, name) < 0 ),
  14108. ( a->type == type && a->filename.data == name ));
  14109. return ix != SIZE_MAX ? &files[ix] : NULL;
  14110. }
  14111. ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_external_files(ufbxi_context *uc)
  14112. {
  14113. size_t num_files = 0;
  14114. // Gather external files to deduplicate them
  14115. ufbxi_for_ptr_list(ufbx_cache_file, p_cache, uc->scene.cache_files) {
  14116. ufbx_cache_file *cache = *p_cache;
  14117. if (cache->filename.length > 0) {
  14118. ufbxi_external_file *file = ufbxi_push_zero(&uc->tmp_stack, ufbxi_external_file, 1);
  14119. ufbxi_check(file);
  14120. file->index = num_files++;
  14121. file->type = UFBXI_EXTERNAL_FILE_GEOMETRY_CACHE;
  14122. file->filename = cache->filename;
  14123. file->absolute_filename = cache->absolute_filename;
  14124. }
  14125. }
  14126. // Sort and load the external files
  14127. ufbxi_external_file *files = ufbxi_push_pop(&uc->tmp, &uc->tmp_stack, ufbxi_external_file, num_files);
  14128. ufbxi_check(files);
  14129. qsort(files, num_files, sizeof(ufbxi_external_file), &ufbxi_cmp_external_file);
  14130. ufbxi_external_file_type prev_type = UFBXI_EXTERNAL_FILE_GEOMETRY_CACHE;
  14131. const char *prev_name = NULL;
  14132. ufbxi_for(ufbxi_external_file, file, files, num_files) {
  14133. if (file->filename.data == prev_name && file->type == prev_type) continue;
  14134. if (file->type == UFBXI_EXTERNAL_FILE_GEOMETRY_CACHE) {
  14135. ufbxi_check(ufbxi_load_external_cache(uc, file));
  14136. }
  14137. prev_name = file->filename.data;
  14138. prev_type = file->type;
  14139. }
  14140. // Patch the loaded files
  14141. ufbxi_for_ptr_list(ufbx_cache_file, p_cache, uc->scene.cache_files) {
  14142. ufbx_cache_file *cache = *p_cache;
  14143. ufbxi_external_file *file = ufbxi_find_external_file(files, num_files,
  14144. UFBXI_EXTERNAL_FILE_GEOMETRY_CACHE, cache->filename.data);
  14145. if (file && file->data) {
  14146. cache->external_cache = (ufbx_geometry_cache*)file->data;
  14147. }
  14148. }
  14149. // Patch the geometry deformers
  14150. ufbxi_for_ptr_list(ufbx_cache_deformer, p_deformer, uc->scene.cache_deformers) {
  14151. ufbx_cache_deformer *deformer = *p_deformer;
  14152. if (!deformer->file || !deformer->file->external_cache) continue;
  14153. ufbx_geometry_cache *cache = deformer->file->external_cache;
  14154. deformer->external_cache = cache;
  14155. // HACK: It seems like channels may be connected even if the name is wrong
  14156. // and they work when exporting from Marvelous to Maya...
  14157. if (cache->channels.count == 1) {
  14158. deformer->external_channel = &cache->channels.data[0];
  14159. } else {
  14160. ufbx_string channel = deformer->channel;
  14161. size_t ix = SIZE_MAX;
  14162. ufbxi_macro_lower_bound_eq(ufbx_cache_channel, 16, &ix, cache->channels.data, 0, cache->channels.count,
  14163. ( ufbxi_str_less(a->name, channel) ), ( a->name.data == channel.data ));
  14164. if (ix != SIZE_MAX) {
  14165. deformer->external_channel = &cache->channels.data[ix];
  14166. }
  14167. }
  14168. }
  14169. return 1;
  14170. }
  14171. static ufbxi_noinline void ufbxi_transform_to_axes(ufbxi_context *uc, ufbx_coordinate_axes dst_axes)
  14172. {
  14173. if (!ufbx_coordinate_axes_valid(uc->scene.settings.axes)) return;
  14174. ufbx_coordinate_axes src_axes = uc->scene.settings.axes;
  14175. uint32_t src_x = (uint32_t)src_axes.right;
  14176. uint32_t dst_x = (uint32_t)dst_axes.right;
  14177. uint32_t src_y = (uint32_t)src_axes.up;
  14178. uint32_t dst_y = (uint32_t)dst_axes.up;
  14179. uint32_t src_z = (uint32_t)src_axes.front;
  14180. uint32_t dst_z = (uint32_t)dst_axes.front;
  14181. if (src_x == dst_x && src_y == dst_y && src_z == dst_z) return;
  14182. ufbx_matrix axis_mat = { 0 };
  14183. // Remap axes (axis enum divided by 2) potentially flipping if the signs (enum parity) doesn't match
  14184. axis_mat.cols[src_x >> 1].v[dst_x >> 1] = ((src_x ^ dst_x) & 1) == 0 ? 1.0f : -1.0f;
  14185. axis_mat.cols[src_y >> 1].v[dst_y >> 1] = ((src_y ^ dst_y) & 1) == 0 ? 1.0f : -1.0f;
  14186. axis_mat.cols[src_z >> 1].v[dst_z >> 1] = ((src_z ^ dst_z) & 1) == 0 ? 1.0f : -1.0f;
  14187. if (!ufbxi_is_transform_identity(uc->scene.root_node->local_transform)) {
  14188. ufbx_matrix root_mat = ufbx_transform_to_matrix(&uc->scene.root_node->local_transform);
  14189. axis_mat = ufbx_matrix_mul(&root_mat, &axis_mat);
  14190. }
  14191. uc->scene.root_node->local_transform = ufbx_matrix_to_transform(&axis_mat);
  14192. uc->scene.root_node->node_to_parent = axis_mat;
  14193. }
  14194. static ufbxi_noinline void ufbxi_scale_anim_curve(ufbx_anim_curve *curve, ufbx_real scale)
  14195. {
  14196. if (!curve) return;
  14197. ufbxi_for_list(ufbx_keyframe, key, curve->keyframes) {
  14198. key->value *= scale;
  14199. }
  14200. }
  14201. static ufbxi_noinline void ufbxi_scale_anim_value(ufbx_anim_value *value, ufbx_real scale)
  14202. {
  14203. if (!value) return;
  14204. ufbxi_scale_anim_curve(value->curves[0], scale);
  14205. ufbxi_scale_anim_curve(value->curves[1], scale);
  14206. ufbxi_scale_anim_curve(value->curves[2], scale);
  14207. }
  14208. static ufbxi_noinline int ufbxi_scale_units(ufbxi_context *uc, ufbx_real target_meters)
  14209. {
  14210. if (uc->scene.settings.unit_meters <= 0.0f) return 1;
  14211. target_meters = ufbxi_round_if_near(ufbxi_pow10_targets, ufbxi_arraycount(ufbxi_pow10_targets), target_meters);
  14212. ufbx_real ratio = uc->scene.settings.unit_meters / target_meters;
  14213. ratio = ufbxi_round_if_near(ufbxi_pow10_targets, ufbxi_arraycount(ufbxi_pow10_targets), ratio);
  14214. if (ratio == 1.0f) return 1;
  14215. uc->scene.root_node->local_transform.scale.x *= ratio;
  14216. uc->scene.root_node->local_transform.scale.y *= ratio;
  14217. uc->scene.root_node->local_transform.scale.z *= ratio;
  14218. uc->scene.root_node->node_to_parent.m00 *= ratio;
  14219. uc->scene.root_node->node_to_parent.m01 *= ratio;
  14220. uc->scene.root_node->node_to_parent.m02 *= ratio;
  14221. uc->scene.root_node->node_to_parent.m10 *= ratio;
  14222. uc->scene.root_node->node_to_parent.m11 *= ratio;
  14223. uc->scene.root_node->node_to_parent.m12 *= ratio;
  14224. uc->scene.root_node->node_to_parent.m20 *= ratio;
  14225. uc->scene.root_node->node_to_parent.m21 *= ratio;
  14226. uc->scene.root_node->node_to_parent.m22 *= ratio;
  14227. // HACK: Pre-fetch `ufbx_node.inherit_type` as we need it multiple times below.
  14228. // This is a bit inconsistent but will get overwritten in `ufbxi_update_node()`.
  14229. if (!uc->opts.no_prop_unit_scaling || !uc->opts.no_anim_curve_unit_scaling) {
  14230. ufbxi_for_ptr_list(ufbx_node, p_node, uc->scene.nodes) {
  14231. ufbx_node *node = *p_node;
  14232. node->inherit_type = (ufbx_inherit_type)ufbxi_find_enum(&node->props, ufbxi_InheritType, UFBX_INHERIT_NORMAL, UFBX_INHERIT_NO_SCALE);
  14233. }
  14234. }
  14235. if (!uc->opts.no_prop_unit_scaling) {
  14236. ufbxi_for_ptr_list(ufbx_node, p_node, uc->scene.nodes) {
  14237. ufbx_node *node = *p_node;
  14238. if (node->inherit_type != UFBX_INHERIT_NO_SCALE) continue;
  14239. // Find only in own properties
  14240. ufbx_props own_props = node->props;
  14241. own_props.defaults = NULL;
  14242. ufbx_prop *prop = ufbxi_find_prop(&own_props, ufbxi_Lcl_Scaling);
  14243. if (prop) {
  14244. prop->value_vec3.x *= ratio;
  14245. prop->value_vec3.y *= ratio;
  14246. prop->value_vec3.z *= ratio;
  14247. prop->value_int = ufbxi_f64_to_i64(prop->value_vec3.x);
  14248. } else {
  14249. // We need to add a new Lcl Scaling property based on the defaults
  14250. ufbx_props *defaults = node->props.defaults;
  14251. ufbx_vec3 scale = { 1.0f, 1.0f, 1.0f };
  14252. if (defaults) {
  14253. prop = ufbxi_find_prop(defaults, ufbxi_Lcl_Scaling);
  14254. if (prop) {
  14255. scale = prop->value_vec3;
  14256. }
  14257. }
  14258. scale.x *= ratio;
  14259. scale.y *= ratio;
  14260. scale.z *= ratio;
  14261. ufbx_prop new_prop = { 0 };
  14262. new_prop.name.data = ufbxi_Lcl_Scaling;
  14263. new_prop.name.length = sizeof(ufbxi_Lcl_Scaling) - 1;
  14264. new_prop._internal_key = ufbxi_get_name_key(ufbxi_Lcl_Scaling, sizeof(ufbxi_Lcl_Scaling) - 1);
  14265. new_prop.type = UFBX_PROP_SCALING;
  14266. new_prop.flags = UFBX_PROP_FLAG_SYNTHETIC;
  14267. new_prop.value_str = ufbx_empty_string;
  14268. new_prop.value_blob = ufbx_empty_blob;
  14269. new_prop.value_vec3 = scale;
  14270. new_prop.value_int = ufbxi_f64_to_i64(new_prop.value_vec3.x);
  14271. size_t new_num_props = node->props.props.count + 1;
  14272. ufbx_prop *props_copy = ufbxi_push(&uc->result, ufbx_prop, new_num_props);
  14273. ufbxi_check(props_copy);
  14274. memcpy(props_copy, node->props.props.data, node->props.props.count * sizeof(ufbx_prop));
  14275. props_copy[node->props.props.count] = new_prop;
  14276. ufbxi_check(ufbxi_sort_properties(uc, props_copy, new_num_props));
  14277. node->props.props.data = props_copy;
  14278. node->props.props.count = new_num_props;
  14279. }
  14280. }
  14281. }
  14282. if (!uc->opts.no_anim_curve_unit_scaling) {
  14283. ufbxi_for_ptr_list(ufbx_anim_layer, p_layer, uc->scene.anim_layers) {
  14284. ufbx_anim_layer *layer = *p_layer;
  14285. ufbxi_for_list(ufbx_anim_prop, aprop, layer->anim_props) {
  14286. if (aprop->prop_name.data == ufbxi_Lcl_Scaling) {
  14287. ufbx_element *elem = aprop->element;
  14288. if (elem->type != UFBX_ELEMENT_NODE) continue;
  14289. ufbx_node *node = (ufbx_node*)elem;
  14290. if (node->inherit_type != UFBX_INHERIT_NO_SCALE) continue;
  14291. ufbxi_scale_anim_value(aprop->anim_value, ratio);
  14292. }
  14293. }
  14294. }
  14295. }
  14296. return 1;
  14297. }
  14298. // -- Curve evaluation
  14299. static ufbxi_forceinline double ufbxi_find_cubic_bezier_t(double p1, double p2, double x0)
  14300. {
  14301. double p1_3 = p1 * 3.0, p2_3 = p2 * 3.0;
  14302. double a = p1_3 - p2_3 + 1.0;
  14303. double b = p2_3 - p1_3 - p1_3;
  14304. double c = p1_3;
  14305. double a_3 = 3.0*a, b_2 = 2.0*b;
  14306. double t = x0;
  14307. double x1, t2, t3;
  14308. // Manually unroll three iterations of Newton-Rhapson, this is enough
  14309. // for most tangents
  14310. t2 = t*t; t3 = t2*t; x1 = a*t3 + b*t2 + c*t - x0;
  14311. t -= x1 / (a_3*t2 + b_2*t + c);
  14312. t2 = t*t; t3 = t2*t; x1 = a*t3 + b*t2 + c*t - x0;
  14313. t -= x1 / (a_3*t2 + b_2*t + c);
  14314. t2 = t*t; t3 = t2*t; x1 = a*t3 + b*t2 + c*t - x0;
  14315. t -= x1 / (a_3*t2 + b_2*t + c);
  14316. // 4 ULP from 1.0
  14317. const double eps = 8.881784197001252e-16;
  14318. if (ufbx_fabs(x1) <= eps) return t;
  14319. // Perform more iterations until we reach desired accuracy
  14320. for (size_t i = 0; i < 4; i++) {
  14321. t2 = t*t; t3 = t2*t; x1 = a*t3 + b*t2 + c*t - x0;
  14322. t -= x1 / (a_3*t2 + b_2*t + c);
  14323. t2 = t*t; t3 = t2*t; x1 = a*t3 + b*t2 + c*t - x0;
  14324. t -= x1 / (a_3*t2 + b_2*t + c);
  14325. if (ufbx_fabs(x1) <= eps) return t;
  14326. }
  14327. return t;
  14328. }
  14329. ufbxi_nodiscard static ufbxi_noinline int ufbxi_evaluate_skinning(ufbx_scene *scene, ufbx_error *error, ufbxi_buf *buf_result, ufbxi_buf *buf_tmp,
  14330. double time, bool load_caches, ufbx_geometry_cache_data_opts *cache_opts)
  14331. {
  14332. size_t max_skinned_indices = 0;
  14333. ufbxi_for_ptr_list(ufbx_mesh, p_mesh, scene->meshes) {
  14334. ufbx_mesh *mesh = *p_mesh;
  14335. if (mesh->blend_deformers.count == 0 && mesh->skin_deformers.count == 0 && (mesh->cache_deformers.count == 0 || !load_caches)) continue;
  14336. max_skinned_indices = ufbxi_max_sz(max_skinned_indices, mesh->num_indices);
  14337. }
  14338. ufbx_topo_edge *topo = ufbxi_push(buf_tmp, ufbx_topo_edge, max_skinned_indices);
  14339. ufbxi_check_err(error, topo);
  14340. ufbxi_for_ptr_list(ufbx_mesh, p_mesh, scene->meshes) {
  14341. ufbx_mesh *mesh = *p_mesh;
  14342. if (mesh->blend_deformers.count == 0 && mesh->skin_deformers.count == 0 && (mesh->cache_deformers.count == 0 || !load_caches)) continue;
  14343. if (mesh->num_vertices == 0) continue;
  14344. size_t num_vertices = mesh->num_vertices;
  14345. ufbx_vec3 *result_pos = ufbxi_push(buf_result, ufbx_vec3, num_vertices + 1);
  14346. ufbxi_check_err(error, result_pos);
  14347. result_pos[0] = ufbx_zero_vec3;
  14348. result_pos++;
  14349. bool cached_position = false, cached_normals = false;
  14350. if (load_caches && mesh->cache_deformers.count > 0) {
  14351. ufbxi_for_ptr_list(ufbx_cache_deformer, p_cache, mesh->cache_deformers) {
  14352. ufbx_cache_channel *channel = (*p_cache)->external_channel;
  14353. if (!channel) continue;
  14354. if ((channel->interpretation == UFBX_CACHE_INTERPRETATION_VERTEX_POSITION || channel->interpretation == UFBX_CACHE_INTERPRETATION_POINTS) && !cached_position) {
  14355. size_t num_read = ufbx_sample_geometry_cache_vec3(channel, time, result_pos, num_vertices, cache_opts);
  14356. if (num_read == num_vertices) {
  14357. mesh->skinned_is_local = true;
  14358. cached_position = true;
  14359. }
  14360. } else if (channel->interpretation == UFBX_CACHE_INTERPRETATION_VERTEX_NORMAL && !cached_normals) {
  14361. // TODO: Is this right at all?
  14362. size_t num_normals = mesh->skinned_normal.values.count;
  14363. ufbx_vec3 *normal_data = ufbxi_push(buf_result, ufbx_vec3, num_normals + 1);
  14364. ufbxi_check_err(error, normal_data);
  14365. normal_data[0] = ufbx_zero_vec3;
  14366. normal_data++;
  14367. size_t num_read = ufbx_sample_geometry_cache_vec3(channel, time, normal_data, num_normals, cache_opts);
  14368. if (num_read == num_normals) {
  14369. cached_normals = true;
  14370. mesh->skinned_normal.values.data = normal_data;
  14371. } else {
  14372. ufbxi_pop(buf_result, ufbx_vec3, num_normals + 1, NULL);
  14373. }
  14374. }
  14375. }
  14376. }
  14377. if (!cached_position) {
  14378. memcpy(result_pos, mesh->vertices.data, num_vertices * sizeof(ufbx_vec3));
  14379. ufbxi_for_ptr_list(ufbx_blend_deformer, p_blend, mesh->blend_deformers) {
  14380. ufbx_add_blend_vertex_offsets(*p_blend, result_pos, num_vertices, 1.0f);
  14381. }
  14382. // TODO: What should we do about multiple skins??
  14383. if (mesh->skin_deformers.count > 0) {
  14384. ufbx_matrix *fallback = mesh->instances.count > 0 ? &mesh->instances.data[0]->geometry_to_world : NULL;
  14385. ufbx_skin_deformer *skin = mesh->skin_deformers.data[0];
  14386. for (size_t i = 0; i < num_vertices; i++) {
  14387. ufbx_matrix mat = ufbx_get_skin_vertex_matrix(skin, i, fallback);
  14388. result_pos[i] = ufbx_transform_position(&mat, result_pos[i]);
  14389. }
  14390. mesh->skinned_is_local = false;
  14391. }
  14392. }
  14393. mesh->skinned_position.values.data = result_pos;
  14394. if (!cached_normals) {
  14395. size_t num_indices = mesh->num_indices;
  14396. uint32_t *normal_indices = ufbxi_push(buf_result, uint32_t, num_indices);
  14397. ufbxi_check_err(error, normal_indices);
  14398. ufbx_compute_topology(mesh, topo, num_indices);
  14399. size_t num_normals = ufbx_generate_normal_mapping(mesh, topo, num_indices, normal_indices, num_indices, false);
  14400. if (num_normals == mesh->num_vertices) {
  14401. mesh->skinned_normal.unique_per_vertex = true;
  14402. }
  14403. ufbx_vec3 *normal_data = ufbxi_push(buf_result, ufbx_vec3, num_normals + 1);
  14404. ufbxi_check_err(error, normal_data);
  14405. normal_data[0] = ufbx_zero_vec3;
  14406. normal_data++;
  14407. ufbx_compute_normals(mesh, &mesh->skinned_position, normal_indices, num_indices, normal_data, num_normals);
  14408. mesh->skinned_normal.exists = true;
  14409. mesh->skinned_normal.values.data = normal_data;
  14410. mesh->skinned_normal.values.count = num_normals;
  14411. mesh->skinned_normal.indices.data = normal_indices;
  14412. mesh->skinned_normal.indices.count = num_indices;
  14413. mesh->skinned_normal.value_reals = 3;
  14414. }
  14415. }
  14416. return 1;
  14417. }
  14418. ufbxi_nodiscard static ufbxi_noinline int ufbxi_load_imp(ufbxi_context *uc)
  14419. {
  14420. // `ufbx_load_opts` must be cleared to zero first!
  14421. ufbx_assert(uc->opts._begin_zero == 0 && uc->opts._end_zero == 0);
  14422. ufbxi_check_msg(uc->opts._begin_zero == 0 && uc->opts._end_zero == 0, "Uninitialized options");
  14423. ufbxi_check(uc->opts.path_separator >= 0x20 && uc->opts.path_separator <= 0x7e);
  14424. if (!uc->opts.allow_unsafe) {
  14425. ufbxi_check_msg(uc->opts.index_error_handling != UFBX_INDEX_ERROR_HANDLING_UNSAFE_IGNORE, "Unsafe options");
  14426. ufbxi_check_msg(uc->opts.unicode_error_handling != UFBX_UNICODE_ERROR_HANDLING_UNSAFE_IGNORE, "Unsafe options");
  14427. } else {
  14428. uc->scene.metadata.unsafe = true;
  14429. }
  14430. if (uc->opts.index_error_handling == UFBX_INDEX_ERROR_HANDLING_NO_INDEX) {
  14431. uc->scene.metadata.may_contain_no_index = true;
  14432. }
  14433. ufbxi_check(ufbxi_load_strings(uc));
  14434. ufbxi_check(ufbxi_load_maps(uc));
  14435. ufbxi_check(ufbxi_begin_parse(uc));
  14436. if (uc->version < 6000) {
  14437. ufbxi_check(ufbxi_read_legacy_root(uc));
  14438. } else {
  14439. ufbxi_check(ufbxi_read_root(uc));
  14440. }
  14441. // We can free `tmp_parse` already here as all parsing is done by now.
  14442. ufbxi_buf_free(&uc->tmp_parse);
  14443. ufbxi_update_scene_metadata(&uc->scene.metadata);
  14444. ufbxi_check(ufbxi_init_file_paths(uc));
  14445. ufbxi_check(ufbxi_finalize_scene(uc));
  14446. ufbxi_update_scene_settings(&uc->scene.settings);
  14447. // Axis conversion
  14448. if (ufbx_coordinate_axes_valid(uc->opts.target_axes)) {
  14449. ufbxi_transform_to_axes(uc, uc->opts.target_axes);
  14450. }
  14451. // Unit conversion
  14452. if (uc->opts.target_unit_meters > 0.0f) {
  14453. ufbxi_check(ufbxi_scale_units(uc, uc->opts.target_unit_meters));
  14454. }
  14455. ufbxi_update_scene(&uc->scene, true);
  14456. if (uc->opts.load_external_files) {
  14457. ufbxi_check(ufbxi_load_external_files(uc));
  14458. }
  14459. // Evaluate skinning if requested
  14460. if (uc->opts.evaluate_skinning) {
  14461. ufbx_geometry_cache_data_opts cache_opts = { 0 };
  14462. cache_opts.open_file_cb = uc->opts.open_file_cb;
  14463. ufbxi_check(ufbxi_evaluate_skinning(&uc->scene, &uc->error, &uc->result, &uc->tmp,
  14464. 0.0, uc->opts.load_external_files && uc->opts.evaluate_caches, &cache_opts));
  14465. }
  14466. // Copy local data to the scene
  14467. uc->scene.metadata.version = uc->version;
  14468. uc->scene.metadata.ascii = uc->from_ascii;
  14469. uc->scene.metadata.big_endian = uc->file_big_endian;
  14470. uc->scene.metadata.geometry_ignored = uc->opts.ignore_geometry;
  14471. uc->scene.metadata.animation_ignored = uc->opts.ignore_animation;
  14472. uc->scene.metadata.embedded_ignored = uc->opts.ignore_embedded;
  14473. // Retain the scene, this must be the final allocation as we copy
  14474. // `ator_result` to `ufbx_scene_imp`.
  14475. ufbxi_scene_imp *imp = ufbxi_push(&uc->result, ufbxi_scene_imp, 1);
  14476. ufbxi_check(imp);
  14477. ufbxi_init_ref(&imp->refcount, UFBXI_SCENE_IMP_MAGIC, NULL);
  14478. imp->magic = UFBXI_SCENE_IMP_MAGIC;
  14479. imp->scene = uc->scene;
  14480. imp->ator = uc->ator_result;
  14481. imp->ator.error = NULL;
  14482. // Copy retained buffers and translate the allocator struct to the one
  14483. // contained within `ufbxi_scene_imp`
  14484. imp->result_buf = uc->result;
  14485. imp->result_buf.ator = &imp->ator;
  14486. imp->string_buf = uc->string_pool.buf;
  14487. imp->string_buf.ator = &imp->ator;
  14488. imp->scene.metadata.result_memory_used = imp->ator.current_size;
  14489. imp->scene.metadata.temp_memory_used = uc->ator_tmp.current_size;
  14490. imp->scene.metadata.result_allocs = imp->ator.num_allocs;
  14491. imp->scene.metadata.temp_allocs = uc->ator_tmp.num_allocs;
  14492. ufbxi_for_ptr_list(ufbx_element, p_elem, imp->scene.elements) {
  14493. (*p_elem)->scene = &imp->scene;
  14494. }
  14495. uc->scene_imp = imp;
  14496. return 1;
  14497. }
  14498. static ufbxi_noinline void ufbxi_free_temp(ufbxi_context *uc)
  14499. {
  14500. ufbxi_string_pool_temp_free(&uc->string_pool);
  14501. ufbxi_map_free(&uc->prop_type_map);
  14502. ufbxi_map_free(&uc->fbx_id_map);
  14503. ufbxi_map_free(&uc->fbx_attr_map);
  14504. ufbxi_map_free(&uc->node_prop_set);
  14505. ufbxi_map_free(&uc->dom_node_map);
  14506. ufbxi_buf_free(&uc->tmp);
  14507. ufbxi_buf_free(&uc->tmp_parse);
  14508. ufbxi_buf_free(&uc->tmp_stack);
  14509. ufbxi_buf_free(&uc->tmp_connections);
  14510. ufbxi_buf_free(&uc->tmp_node_ids);
  14511. ufbxi_buf_free(&uc->tmp_elements);
  14512. ufbxi_buf_free(&uc->tmp_element_offsets);
  14513. for (size_t i = 0; i < UFBX_ELEMENT_TYPE_COUNT; i++) {
  14514. ufbxi_buf_free(&uc->tmp_typed_element_offsets[i]);
  14515. }
  14516. ufbxi_buf_free(&uc->tmp_mesh_textures);
  14517. ufbxi_buf_free(&uc->tmp_full_weights);
  14518. ufbxi_buf_free(&uc->tmp_dom_nodes);
  14519. ufbxi_free(&uc->ator_tmp, ufbxi_node, uc->top_nodes, uc->top_nodes_cap);
  14520. ufbxi_free(&uc->ator_tmp, void*, uc->element_extra_arr, uc->element_extra_cap);
  14521. ufbxi_free(&uc->ator_tmp, char, uc->ascii.token.str_data, uc->ascii.token.str_cap);
  14522. ufbxi_free(&uc->ator_tmp, char, uc->ascii.prev_token.str_data, uc->ascii.prev_token.str_cap);
  14523. ufbxi_free(&uc->ator_tmp, char, uc->read_buffer, uc->read_buffer_size);
  14524. ufbxi_free(&uc->ator_tmp, char, uc->tmp_arr, uc->tmp_arr_size);
  14525. ufbxi_free(&uc->ator_tmp, char, uc->swap_arr, uc->swap_arr_size);
  14526. ufbxi_free_ator(&uc->ator_tmp);
  14527. }
  14528. static ufbxi_noinline void ufbxi_free_result(ufbxi_context *uc)
  14529. {
  14530. ufbxi_buf_free(&uc->result);
  14531. ufbxi_buf_free(&uc->string_pool.buf);
  14532. ufbxi_free_ator(&uc->ator_result);
  14533. }
  14534. static ufbxi_noinline ufbx_scene *ufbxi_load(ufbxi_context *uc, const ufbx_load_opts *user_opts, ufbx_error *p_error)
  14535. {
  14536. // Test endianness
  14537. {
  14538. uint8_t buf[2];
  14539. uint16_t val = 0xbbaa;
  14540. memcpy(buf, &val, 2);
  14541. uc->local_big_endian = buf[0] == 0xbb;
  14542. }
  14543. if (user_opts) {
  14544. uc->opts = *user_opts;
  14545. } else {
  14546. memset(&uc->opts, 0, sizeof(uc->opts));
  14547. }
  14548. if (uc->opts.file_size_estimate) {
  14549. uc->progress_bytes_total = uc->opts.file_size_estimate;
  14550. }
  14551. if (uc->opts.filename.length == SIZE_MAX) {
  14552. uc->opts.filename.length = uc->opts.filename.data ? strlen(uc->opts.filename.data) : 0;
  14553. }
  14554. ufbx_inflate_retain inflate_retain;
  14555. inflate_retain.initialized = false;
  14556. ufbxi_init_ator(&uc->error, &uc->ator_tmp, &uc->opts.temp_allocator);
  14557. ufbxi_init_ator(&uc->error, &uc->ator_result, &uc->opts.result_allocator);
  14558. if (uc->opts.read_buffer_size == 0) {
  14559. uc->opts.read_buffer_size = 0x4000;
  14560. }
  14561. if (!uc->opts.path_separator) {
  14562. uc->opts.path_separator = UFBX_PATH_SEPARATOR;
  14563. }
  14564. if (!uc->opts.progress_cb.fn || uc->opts.progress_interval_hint >= SIZE_MAX) {
  14565. uc->progress_interval = SIZE_MAX;
  14566. } else if (uc->opts.progress_interval_hint > 0) {
  14567. uc->progress_interval = (size_t)uc->opts.progress_interval_hint;
  14568. } else {
  14569. uc->progress_interval = 0x4000;
  14570. }
  14571. if (!uc->opts.open_file_cb.fn) {
  14572. uc->opts.open_file_cb.fn = &ufbx_open_file;
  14573. }
  14574. uc->string_pool.error = &uc->error;
  14575. ufbxi_map_init(&uc->string_pool.map, &uc->ator_tmp, &ufbxi_map_cmp_string, NULL);
  14576. uc->string_pool.buf.ator = &uc->ator_result;
  14577. uc->string_pool.buf.unordered = true;
  14578. uc->string_pool.initial_size = 1024;
  14579. uc->string_pool.error_handling = uc->opts.unicode_error_handling;
  14580. ufbxi_map_init(&uc->prop_type_map, &uc->ator_tmp, &ufbxi_map_cmp_const_char_ptr, NULL);
  14581. ufbxi_map_init(&uc->fbx_id_map, &uc->ator_tmp, &ufbxi_map_cmp_uint64, NULL);
  14582. ufbxi_map_init(&uc->fbx_attr_map, &uc->ator_tmp, &ufbxi_map_cmp_uint64, NULL);
  14583. ufbxi_map_init(&uc->node_prop_set, &uc->ator_tmp, &ufbxi_map_cmp_const_char_ptr, NULL);
  14584. ufbxi_map_init(&uc->dom_node_map, &uc->ator_tmp, &ufbxi_map_cmp_uintptr, NULL);
  14585. uc->tmp.ator = &uc->ator_tmp;
  14586. uc->tmp_parse.ator = &uc->ator_tmp;
  14587. uc->tmp_stack.ator = &uc->ator_tmp;
  14588. uc->tmp_connections.ator = &uc->ator_tmp;
  14589. uc->tmp_node_ids.ator = &uc->ator_tmp;
  14590. uc->tmp_elements.ator = &uc->ator_tmp;
  14591. uc->tmp_element_offsets.ator = &uc->ator_tmp;
  14592. for (size_t i = 0; i < UFBX_ELEMENT_TYPE_COUNT; i++) {
  14593. uc->tmp_typed_element_offsets[i].ator = &uc->ator_tmp;
  14594. }
  14595. uc->tmp_mesh_textures.ator = &uc->ator_tmp;
  14596. uc->tmp_full_weights.ator = &uc->ator_tmp;
  14597. uc->tmp_dom_nodes.ator = &uc->ator_tmp;
  14598. uc->result.ator = &uc->ator_result;
  14599. uc->tmp.unordered = true;
  14600. uc->tmp_parse.unordered = true;
  14601. uc->tmp_parse.clearable = true;
  14602. uc->result.unordered = true;
  14603. // NOTE: Though `inflate_retain` leaks out of the scope we don't use it outside this function.
  14604. // cppcheck-suppress autoVariables
  14605. uc->inflate_retain = &inflate_retain;
  14606. int ok = ufbxi_load_imp(uc);
  14607. ufbxi_free_temp(uc);
  14608. if (uc->close_fn) {
  14609. uc->close_fn(uc->read_user);
  14610. }
  14611. if (ok) {
  14612. if (p_error) {
  14613. p_error->type = UFBX_ERROR_NONE;
  14614. p_error->description.data = ufbxi_empty_char;
  14615. p_error->description.length = 0;
  14616. p_error->stack_size = 0;
  14617. }
  14618. return &uc->scene_imp->scene;
  14619. } else {
  14620. ufbxi_fix_error_type(&uc->error, "Failed to load");
  14621. if (p_error) *p_error = uc->error;
  14622. ufbxi_free_result(uc);
  14623. return NULL;
  14624. }
  14625. }
  14626. // -- TODO: Find a place for these...
  14627. ufbx_inline ufbx_vec3 ufbxi_add3(ufbx_vec3 a, ufbx_vec3 b) {
  14628. ufbx_vec3 v = { a.x + b.x, a.y + b.y, a.z + b.z };
  14629. return v;
  14630. }
  14631. ufbx_inline ufbx_vec3 ufbxi_sub3(ufbx_vec3 a, ufbx_vec3 b) {
  14632. ufbx_vec3 v = { a.x - b.x, a.y - b.y, a.z - b.z };
  14633. return v;
  14634. }
  14635. ufbx_inline ufbx_vec3 ufbxi_mul3(ufbx_vec3 a, ufbx_real b) {
  14636. ufbx_vec3 v = { a.x * b, a.y * b, a.z * b };
  14637. return v;
  14638. }
  14639. ufbx_inline ufbx_real ufbxi_dot3(ufbx_vec3 a, ufbx_vec3 b) {
  14640. return a.x*b.x + a.y*b.y + a.z*b.z;
  14641. }
  14642. ufbx_inline ufbx_real ufbxi_length3(ufbx_vec3 v)
  14643. {
  14644. return (ufbx_real)ufbx_sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
  14645. }
  14646. ufbx_inline ufbx_vec3 ufbxi_cross3(ufbx_vec3 a, ufbx_vec3 b) {
  14647. ufbx_vec3 v = { a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x };
  14648. return v;
  14649. }
  14650. ufbx_inline ufbx_vec3 ufbxi_normalize3(ufbx_vec3 a) {
  14651. ufbx_real len = (ufbx_real)ufbx_sqrt(ufbxi_dot3(a, a));
  14652. if (len != 0.0) {
  14653. return ufbxi_mul3(a, (ufbx_real)1.0 / len);
  14654. } else {
  14655. ufbx_vec3 zero = { (ufbx_real)0 };
  14656. return zero;
  14657. }
  14658. }
  14659. static ufbxi_noinline ufbx_vec3 ufbxi_slow_normalize3(const ufbx_vec3 *a) {
  14660. return ufbxi_normalize3(*a);
  14661. }
  14662. static ufbxi_noinline ufbx_vec3 ufbxi_slow_normalized_cross3(const ufbx_vec3 *a, const ufbx_vec3 *b) {
  14663. return ufbxi_normalize3(ufbxi_cross3(*a, *b));
  14664. }
  14665. // -- Animation evaluation
  14666. static int ufbxi_cmp_prop_override(const void *va, const void *vb)
  14667. {
  14668. const ufbx_prop_override *a = (const ufbx_prop_override*)va, *b = (const ufbx_prop_override*)vb;
  14669. if (a->element_id != b->element_id) return a->element_id < b->element_id ? -1 : 1;
  14670. if (a->_internal_key != b->_internal_key) return a->_internal_key < b->_internal_key ? -1 : 1;
  14671. return strcmp(a->prop_name, b->prop_name);
  14672. }
  14673. static ufbxi_forceinline bool ufbxi_override_less_than_prop(const ufbx_prop_override *over, uint32_t element_id, const ufbx_prop *prop)
  14674. {
  14675. if (over->element_id != element_id) return over->element_id < element_id;
  14676. if (over->_internal_key != prop->_internal_key) return over->_internal_key < prop->_internal_key;
  14677. return strcmp(over->prop_name, prop->name.data);
  14678. }
  14679. static ufbxi_forceinline bool ufbxi_override_equals_to_prop(const ufbx_prop_override *over, uint32_t element_id, const ufbx_prop *prop)
  14680. {
  14681. if (over->element_id != element_id) return false;
  14682. if (over->_internal_key != prop->_internal_key) return false;
  14683. return strcmp(over->prop_name, prop->name.data) == 0;
  14684. }
  14685. static ufbxi_forceinline ufbxi_unused bool ufbxi_prop_override_is_prepared(const ufbx_prop_override *over)
  14686. {
  14687. if (over->_internal_key != ufbxi_get_name_key_c(over->prop_name)) return false;
  14688. if (over->value_str == NULL) return false;
  14689. return true;
  14690. }
  14691. static ufbxi_noinline bool ufbxi_find_prop_override(const ufbx_const_prop_override_list *overrides, uint32_t element_id, ufbx_prop *prop)
  14692. {
  14693. if (overrides->count > 0) {
  14694. // If this assert fails make sure to call `ufbx_prepare_prop_overrides()` first!
  14695. ufbx_assert(ufbxi_prop_override_is_prepared(&overrides->data[0]));
  14696. }
  14697. size_t ix = SIZE_MAX;
  14698. ufbxi_macro_lower_bound_eq(ufbx_prop_override, 16, &ix, overrides->data, 0, overrides->count,
  14699. ( ufbxi_override_less_than_prop(a, element_id, prop) ),
  14700. ( ufbxi_override_equals_to_prop(a, element_id, prop) ));
  14701. if (ix != SIZE_MAX) {
  14702. const ufbx_prop_override *over = &overrides->data[ix];
  14703. const uint32_t clear_flags = UFBX_PROP_FLAG_NO_VALUE | UFBX_PROP_FLAG_NOT_FOUND;
  14704. prop->flags = (ufbx_prop_flags)(((uint32_t)prop->flags & ~clear_flags) | UFBX_PROP_FLAG_OVERRIDDEN);
  14705. prop->value_vec3 = over->value;
  14706. prop->value_real_arr[3] = 0.0f;
  14707. prop->value_int = over->value_int;
  14708. prop->value_str = ufbxi_str_c(over->value_str);
  14709. prop->value_blob.data = prop->value_str.data;
  14710. prop->value_blob.size = prop->value_str.length;
  14711. return true;
  14712. } else {
  14713. return false;
  14714. }
  14715. }
  14716. static ufbxi_noinline ufbx_const_prop_override_list ufbxi_find_element_prop_overrides(const ufbx_const_prop_override_list *overrides, uint32_t element_id)
  14717. {
  14718. if (overrides->count > 0) {
  14719. // If this assert fails make sure to call `ufbx_prepare_prop_overrides()` first!
  14720. ufbx_assert(ufbxi_prop_override_is_prepared(&overrides->data[0]));
  14721. }
  14722. size_t begin = overrides->count, end = begin;
  14723. ufbxi_macro_lower_bound_eq(ufbx_prop_override, 32, &begin, overrides->data, 0, overrides->count,
  14724. (a->element_id < element_id),
  14725. (a->element_id == element_id));
  14726. ufbxi_macro_upper_bound_eq(ufbx_prop_override, 32, &end, overrides->data, begin, overrides->count,
  14727. (a->element_id == element_id));
  14728. ufbx_const_prop_override_list result = { overrides->data + begin, end - begin };
  14729. return result;
  14730. }
  14731. typedef struct ufbxi_anim_layer_combine_ctx {
  14732. ufbx_anim anim;
  14733. const ufbx_element *element;
  14734. double time;
  14735. ufbx_rotation_order rotation_order;
  14736. bool has_rotation_order;
  14737. } ufbxi_anim_layer_combine_ctx;
  14738. static double ufbxi_pow_abs(double v, double e)
  14739. {
  14740. if (e <= 0.0) return 1.0;
  14741. if (e >= 1.0) return v;
  14742. double sign = v < 0.0 ? -1.0 : 1.0;
  14743. return sign * ufbx_pow(v * sign, e);
  14744. }
  14745. static ufbxi_noinline void ufbxi_combine_anim_layer(ufbxi_anim_layer_combine_ctx *ctx, ufbx_anim_layer *layer, ufbx_real weight, const char *prop_name, ufbx_vec3 *result, const ufbx_vec3 *value)
  14746. {
  14747. if (layer->compose_rotation && layer->blended && prop_name == ufbxi_Lcl_Rotation && !ctx->has_rotation_order) {
  14748. ufbx_prop rp = ufbx_evaluate_prop_len(&ctx->anim, ctx->element, ufbxi_RotationOrder, sizeof(ufbxi_RotationOrder) - 1, ctx->time);
  14749. // NOTE: Defaults to 0 (UFBX_ROTATION_XYZ) gracefully if property is not found
  14750. if (rp.value_int >= 0 && rp.value_int <= UFBX_ROTATION_SPHERIC) {
  14751. ctx->rotation_order = (ufbx_rotation_order)rp.value_int;
  14752. } else {
  14753. ctx->rotation_order = UFBX_ROTATION_XYZ;
  14754. }
  14755. ctx->has_rotation_order = true;
  14756. }
  14757. if (layer->additive) {
  14758. if (layer->compose_scale && prop_name == ufbxi_Lcl_Scaling) {
  14759. result->x *= (ufbx_real)ufbxi_pow_abs(value->x, weight);
  14760. result->y *= (ufbx_real)ufbxi_pow_abs(value->y, weight);
  14761. result->z *= (ufbx_real)ufbxi_pow_abs(value->z, weight);
  14762. } else if (layer->compose_rotation && prop_name == ufbxi_Lcl_Rotation) {
  14763. ufbx_quat a = ufbx_euler_to_quat(*result, ctx->rotation_order);
  14764. ufbx_quat b = ufbx_euler_to_quat(*value, ctx->rotation_order);
  14765. b = ufbx_quat_slerp(ufbx_identity_quat, b, weight);
  14766. ufbx_quat res = ufbxi_mul_quat(a, b);
  14767. *result = ufbx_quat_to_euler(res, ctx->rotation_order);
  14768. } else {
  14769. result->x += value->x * weight;
  14770. result->y += value->y * weight;
  14771. result->z += value->z * weight;
  14772. }
  14773. } else if (layer->blended) {
  14774. ufbx_real res_weight = 1.0f - weight;
  14775. if (layer->compose_scale && prop_name == ufbxi_Lcl_Scaling) {
  14776. result->x = (ufbx_real)(ufbxi_pow_abs(result->x, res_weight) * ufbxi_pow_abs(value->x, weight));
  14777. result->y = (ufbx_real)(ufbxi_pow_abs(result->y, res_weight) * ufbxi_pow_abs(value->y, weight));
  14778. result->z = (ufbx_real)(ufbxi_pow_abs(result->z, res_weight) * ufbxi_pow_abs(value->z, weight));
  14779. } else if (layer->compose_rotation && prop_name == ufbxi_Lcl_Rotation) {
  14780. ufbx_quat a = ufbx_euler_to_quat(*result, ctx->rotation_order);
  14781. ufbx_quat b = ufbx_euler_to_quat(*value, ctx->rotation_order);
  14782. ufbx_quat res = ufbx_quat_slerp(a, b, weight);
  14783. *result = ufbx_quat_to_euler(res, ctx->rotation_order);
  14784. } else {
  14785. result->x = result->x * res_weight + value->x * weight;
  14786. result->y = result->y * res_weight + value->y * weight;
  14787. result->z = result->z * res_weight + value->z * weight;
  14788. }
  14789. } else {
  14790. *result = *value;
  14791. }
  14792. }
  14793. static ufbxi_forceinline bool ufbxi_anim_layer_might_contain_id(const ufbx_anim_layer *layer, uint32_t id)
  14794. {
  14795. uint32_t id_mask = ufbxi_arraycount(layer->_element_id_bitmask) - 1;
  14796. bool ok = id - layer->_min_element_id <= (layer->_max_element_id - layer->_min_element_id);
  14797. ok &= (layer->_element_id_bitmask[(id >> 5) & id_mask] & (1u << (id & 31))) != 0;
  14798. return ok;
  14799. }
  14800. static ufbxi_noinline void ufbxi_evaluate_props(const ufbx_anim *anim, const ufbx_element *element, double time, ufbx_prop *props, size_t num_props)
  14801. {
  14802. ufbxi_anim_layer_combine_ctx combine_ctx = { *anim, element, time };
  14803. uint32_t element_id = element->element_id;
  14804. ufbxi_for_list(const ufbx_anim_layer_desc, layer_desc, anim->layers) {
  14805. ufbx_anim_layer *layer = layer_desc->layer;
  14806. if (!ufbxi_anim_layer_might_contain_id(layer, element_id)) continue;
  14807. // Find the weight for the current layer
  14808. // TODO: Should this be searched from multipler layers?
  14809. // TODO: Use weight from layer_desc
  14810. ufbx_real weight = layer->weight;
  14811. if (layer->weight_is_animated && layer->blended) {
  14812. ufbx_anim_prop *weight_aprop = ufbxi_find_anim_prop_start(layer, &layer->element);
  14813. if (weight_aprop) {
  14814. weight = ufbx_evaluate_anim_value_real(weight_aprop->anim_value, time) / (ufbx_real)100.0;
  14815. if (weight < 0.0f) weight = 0.0f;
  14816. if (weight > 0.99999f) weight = 1.0f;
  14817. }
  14818. }
  14819. ufbx_anim_prop *aprop = ufbxi_find_anim_prop_start(layer, element);
  14820. if (!aprop) continue;
  14821. for (size_t i = 0; i < num_props; i++) {
  14822. ufbx_prop *prop = &props[i];
  14823. // Don't evaluate on top of overridden properties
  14824. if ((prop->flags & UFBX_PROP_FLAG_OVERRIDDEN) != 0) continue;
  14825. // Connections override animation by default
  14826. if ((prop->flags & UFBX_PROP_FLAG_CONNECTED) != 0 && !anim->ignore_connections) continue;
  14827. // Skip until we reach `aprop >= prop`
  14828. while (aprop->element == element && aprop->_internal_key < prop->_internal_key) aprop++;
  14829. if (aprop->prop_name.data != prop->name.data) {
  14830. while (aprop->element == element && strcmp(aprop->prop_name.data, prop->name.data) < 0) aprop++;
  14831. }
  14832. // TODO: Should we skip the blending for the first layer _per property_
  14833. // This could be done by having `UFBX_PROP_FLAG_ANIMATION_EVALUATED`
  14834. // that gets set for the first layer of animation that is applied.
  14835. if (aprop->prop_name.data == prop->name.data) {
  14836. ufbx_vec3 v = ufbx_evaluate_anim_value_vec3(aprop->anim_value, time);
  14837. if (layer_desc == anim->layers.data) {
  14838. prop->value_vec3 = v;
  14839. } else {
  14840. ufbxi_combine_anim_layer(&combine_ctx, layer, weight, prop->name.data, &prop->value_vec3, &v);
  14841. }
  14842. }
  14843. }
  14844. }
  14845. ufbxi_for(ufbx_prop, prop, props, num_props) {
  14846. prop->value_int = ufbxi_f64_to_i64(prop->value_real);
  14847. }
  14848. }
  14849. static ufbxi_noinline void ufbxi_evaluate_connected_prop(ufbx_prop *prop, const ufbx_anim *anim, const ufbx_element *element, const char *name, double time)
  14850. {
  14851. ufbx_connection *conn = ufbxi_find_prop_connection(element, name);
  14852. for (size_t i = 0; i < 1000 && conn; i++) {
  14853. ufbx_connection *next_conn = ufbxi_find_prop_connection(conn->src, conn->src_prop.data);
  14854. if (!next_conn) break;
  14855. conn = next_conn;
  14856. }
  14857. if (conn) {
  14858. ufbx_prop ep = ufbx_evaluate_prop_len(anim, conn->src, conn->src_prop.data, conn->src_prop.length, time);
  14859. prop->value_vec4 = ep.value_vec4;
  14860. prop->value_int = ep.value_int;
  14861. prop->value_str = ep.value_str;
  14862. prop->value_blob = ep.value_blob;
  14863. } else {
  14864. // Connection not found, maybe it's animated?
  14865. prop->flags = (ufbx_prop_flags)((uint32_t)prop->flags & ~(uint32_t)UFBX_PROP_FLAG_CONNECTED);
  14866. }
  14867. }
  14868. static ufbxi_noinline ufbx_props ufbxi_evaluate_selected_props(const ufbx_anim *anim, const ufbx_element *element, double time, ufbx_prop *props, const char **prop_names, size_t max_props)
  14869. {
  14870. const char *name = prop_names[0];
  14871. uint32_t key = ufbxi_get_name_key_c(name);
  14872. size_t num_props = 0;
  14873. const ufbx_prop_override *over = NULL, *over_end = NULL;
  14874. if (anim->prop_overrides.count > 0) {
  14875. ufbx_const_prop_override_list list = ufbxi_find_element_prop_overrides(&anim->prop_overrides, element->element_id);
  14876. over = list.data;
  14877. over_end = over + list.count;
  14878. }
  14879. #if defined(UFBX_REGRESSION)
  14880. for (size_t i = 1; i < max_props; i++) {
  14881. ufbx_assert(strcmp(prop_names[i - 1], prop_names[i]) < 0);
  14882. }
  14883. #endif
  14884. size_t name_ix = 0;
  14885. for (size_t i = 0; i < element->props.props.count; i++) {
  14886. ufbx_prop *prop = &element->props.props.data[i];
  14887. while (name_ix < max_props) {
  14888. if (key > prop->_internal_key) break;
  14889. if (over) {
  14890. bool found_override = false;
  14891. for (; over != over_end; over++) {
  14892. ufbx_prop *dst = &props[num_props];
  14893. if (over->_internal_key < key || strcmp(over->prop_name, name) < 0) {
  14894. continue;
  14895. } else if (over->_internal_key == key && strcmp(over->prop_name, name) == 0) {
  14896. dst->name = ufbxi_str_c(name);
  14897. dst->_internal_key = key;
  14898. dst->type = UFBX_PROP_UNKNOWN;
  14899. dst->flags = UFBX_PROP_FLAG_OVERRIDDEN;
  14900. } else {
  14901. break;
  14902. }
  14903. dst->value_str = ufbxi_str_c(over->value_str);
  14904. dst->value_blob.data = dst->value_str.data;
  14905. dst->value_blob.size = dst->value_str.length;
  14906. dst->value_int = over->value_int;
  14907. dst->value_vec3 = over->value;
  14908. dst->value_real_arr[3] = 0.0f;
  14909. num_props++;
  14910. found_override = true;
  14911. }
  14912. if (found_override) break;
  14913. }
  14914. if (name == prop->name.data) {
  14915. if ((prop->flags & UFBX_PROP_FLAG_CONNECTED) != 0 && !anim->ignore_connections) {
  14916. ufbx_prop *dst = &props[num_props++];
  14917. *dst = *prop;
  14918. ufbxi_evaluate_connected_prop(dst, anim, element, name, time);
  14919. } else if (prop->flags & UFBX_PROP_FLAG_ANIMATED) {
  14920. props[num_props++] = *prop;
  14921. }
  14922. break;
  14923. } else if (strcmp(name, prop->name.data) < 0) {
  14924. name_ix++;
  14925. if (name_ix < max_props) {
  14926. name = prop_names[name_ix];
  14927. key = ufbxi_get_name_key_c(name);
  14928. }
  14929. } else {
  14930. break;
  14931. }
  14932. }
  14933. }
  14934. if (over) {
  14935. for (; over != over_end && name_ix < max_props; over++) {
  14936. ufbx_prop *dst = &props[num_props];
  14937. if (over->_internal_key < key || strcmp(over->prop_name, name) < 0) {
  14938. continue;
  14939. } else if (over->_internal_key == key && strcmp(over->prop_name, name) == 0) {
  14940. dst->name = ufbxi_str_c(name);
  14941. dst->_internal_key = key;
  14942. dst->type = UFBX_PROP_UNKNOWN;
  14943. dst->flags = UFBX_PROP_FLAG_OVERRIDDEN;
  14944. } else {
  14945. name_ix++;
  14946. if (name_ix < max_props) {
  14947. name = prop_names[name_ix];
  14948. key = ufbxi_get_name_key_c(name);
  14949. }
  14950. }
  14951. dst->value_str = ufbxi_str_c(over->value_str);
  14952. dst->value_blob.data = dst->value_str.data;
  14953. dst->value_blob.size = dst->value_str.length;
  14954. dst->value_int = over->value_int;
  14955. dst->value_vec3 = over->value;
  14956. dst->value_real_arr[3] = 0.0f;
  14957. num_props++;
  14958. }
  14959. }
  14960. ufbxi_evaluate_props(anim, element, time, props, num_props);
  14961. ufbx_props prop_list;
  14962. prop_list.props.data = props;
  14963. prop_list.props.count = prop_list.num_animated = num_props;
  14964. prop_list.defaults = (ufbx_props*)&element->props;
  14965. return prop_list;
  14966. }
  14967. #if UFBXI_FEATURE_SCENE_EVALUATION
  14968. typedef struct {
  14969. char *src_element;
  14970. char *dst_element;
  14971. ufbxi_scene_imp *src_imp;
  14972. ufbx_scene src_scene;
  14973. ufbx_evaluate_opts opts;
  14974. ufbx_anim anim;
  14975. double time;
  14976. ufbx_error error;
  14977. // Allocators
  14978. ufbxi_allocator ator_result;
  14979. ufbxi_allocator ator_tmp;
  14980. ufbxi_buf result;
  14981. ufbxi_buf tmp;
  14982. ufbx_scene scene;
  14983. ufbxi_scene_imp *scene_imp;
  14984. } ufbxi_eval_context;
  14985. static ufbxi_forceinline ufbx_element *ufbxi_translate_element(ufbxi_eval_context *ec, void *elem)
  14986. {
  14987. return elem ? (ufbx_element*)(ec->dst_element + ((char*)elem - ec->src_element)) : NULL;
  14988. }
  14989. ufbxi_nodiscard static ufbxi_noinline int ufbxi_translate_element_list(ufbxi_eval_context *ec, void *p_list)
  14990. {
  14991. ufbx_element_list *list = (ufbx_element_list*)p_list;
  14992. size_t count = list->count;
  14993. ufbx_element **src = list->data;
  14994. ufbx_element **dst = ufbxi_push(&ec->result, ufbx_element*, count);
  14995. ufbxi_check_err(&ec->error, dst);
  14996. list->data = dst;
  14997. for (size_t i = 0; i < count; i++) {
  14998. dst[i] = ufbxi_translate_element(ec, src[i]);
  14999. }
  15000. return 1;
  15001. }
  15002. ufbxi_nodiscard static ufbxi_noinline int ufbxi_translate_anim(ufbxi_eval_context *ec, ufbx_anim *anim)
  15003. {
  15004. ufbx_anim_layer_desc *layers = ufbxi_push(&ec->result, ufbx_anim_layer_desc, anim->layers.count);
  15005. ufbxi_check_err(&ec->error, layers);
  15006. for (size_t i = 0; i < anim->layers.count; i++) {
  15007. layers[i] = anim->layers.data[i];
  15008. layers[i].layer = (ufbx_anim_layer*)ufbxi_translate_element(ec, layers[i].layer);
  15009. }
  15010. anim->layers.data = layers;
  15011. return 1;
  15012. }
  15013. ufbxi_nodiscard static ufbxi_noinline int ufbxi_evaluate_imp(ufbxi_eval_context *ec)
  15014. {
  15015. // `ufbx_evaluate_opts` must be cleared to zero first!
  15016. ufbx_assert(ec->opts._begin_zero == 0 && ec->opts._end_zero == 0);
  15017. ufbxi_check_err_msg(&ec->error, ec->opts._begin_zero == 0 && ec->opts._end_zero == 0, "Uninitialized options");
  15018. ec->scene = ec->src_scene;
  15019. size_t num_elements = ec->scene.elements.count;
  15020. char *element_data = (char*)ufbxi_push(&ec->result, uint64_t, ec->scene.metadata.element_buffer_size/8);
  15021. ufbxi_check_err(&ec->error, element_data);
  15022. ec->scene.elements.data = ufbxi_push(&ec->result, ufbx_element*, num_elements);
  15023. ufbxi_check_err(&ec->error, ec->scene.elements.data);
  15024. ec->src_element = (char*)ec->src_scene.elements.data[0];
  15025. ec->dst_element = element_data;
  15026. for (size_t i = 0; i < UFBX_ELEMENT_TYPE_COUNT; i++) {
  15027. ec->scene.elements_by_type[i].data = ufbxi_push(&ec->result, ufbx_element*, ec->scene.elements_by_type[i].count);
  15028. ufbxi_check_err(&ec->error, ec->scene.elements_by_type[i].data);
  15029. }
  15030. size_t num_connections = ec->scene.connections_dst.count;
  15031. ec->scene.connections_src.data = ufbxi_push(&ec->result, ufbx_connection, num_connections);
  15032. ec->scene.connections_dst.data = ufbxi_push(&ec->result, ufbx_connection, num_connections);
  15033. ufbxi_check_err(&ec->error, ec->scene.connections_src.data);
  15034. ufbxi_check_err(&ec->error, ec->scene.connections_dst.data);
  15035. for (size_t i = 0; i < num_connections; i++) {
  15036. ufbx_connection *src = &ec->scene.connections_src.data[i];
  15037. ufbx_connection *dst = &ec->scene.connections_dst.data[i];
  15038. *src = ec->src_scene.connections_src.data[i];
  15039. *dst = ec->src_scene.connections_dst.data[i];
  15040. src->src = ufbxi_translate_element(ec, src->src);
  15041. src->dst = ufbxi_translate_element(ec, src->dst);
  15042. dst->src = ufbxi_translate_element(ec, dst->src);
  15043. dst->dst = ufbxi_translate_element(ec, dst->dst);
  15044. }
  15045. ec->scene.elements_by_name.data = ufbxi_push(&ec->result, ufbx_name_element, num_elements);
  15046. ufbxi_check_err(&ec->error, ec->scene.elements_by_name.data);
  15047. ec->scene.root_node = (ufbx_node*)ufbxi_translate_element(ec, ec->scene.root_node);
  15048. ufbxi_check_err(&ec->error, ufbxi_translate_anim(ec, &ec->scene.anim));
  15049. ufbxi_check_err(&ec->error, ufbxi_translate_anim(ec, &ec->scene.combined_anim));
  15050. for (size_t i = 0; i < num_elements; i++) {
  15051. ufbx_element *src = ec->src_scene.elements.data[i];
  15052. ufbx_element *dst = ufbxi_translate_element(ec, src);
  15053. size_t size = ufbx_element_type_size[src->type];
  15054. ufbx_assert(size > 0);
  15055. memcpy(dst, src, size);
  15056. ec->scene.elements.data[i] = dst;
  15057. ec->scene.elements_by_type[src->type].data[src->typed_id] = dst;
  15058. dst->connections_src.data = ec->scene.connections_src.data + (dst->connections_src.data - ec->src_scene.connections_src.data);
  15059. dst->connections_dst.data = ec->scene.connections_dst.data + (dst->connections_dst.data - ec->src_scene.connections_dst.data);
  15060. if (dst->instances.count > 0) {
  15061. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &dst->instances));
  15062. }
  15063. ufbx_name_element named = ec->src_scene.elements_by_name.data[i];
  15064. named.element = ufbxi_translate_element(ec, named.element);
  15065. ec->scene.elements_by_name.data[i] = named;
  15066. }
  15067. ufbxi_for_ptr_list(ufbx_node, p_node, ec->scene.nodes) {
  15068. ufbx_node *node = *p_node;
  15069. node->parent = (ufbx_node*)ufbxi_translate_element(ec, node->parent);
  15070. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &node->children));
  15071. node->attrib = ufbxi_translate_element(ec, node->attrib);
  15072. node->mesh = (ufbx_mesh*)ufbxi_translate_element(ec, node->mesh);
  15073. node->light = (ufbx_light*)ufbxi_translate_element(ec, node->light);
  15074. node->camera = (ufbx_camera*)ufbxi_translate_element(ec, node->camera);
  15075. node->bone = (ufbx_bone*)ufbxi_translate_element(ec, node->bone);
  15076. if (node->all_attribs.count > 1) {
  15077. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &node->all_attribs));
  15078. } else if (node->all_attribs.count == 1) {
  15079. node->all_attribs.data = &node->attrib;
  15080. }
  15081. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &node->materials));
  15082. }
  15083. ufbxi_for_ptr_list(ufbx_mesh, p_mesh, ec->scene.meshes) {
  15084. ufbx_mesh *mesh = *p_mesh;
  15085. ufbx_mesh_material *materials = ufbxi_push(&ec->result, ufbx_mesh_material, mesh->materials.count);
  15086. ufbxi_check_err(&ec->error, materials);
  15087. for (size_t i = 0; i < mesh->materials.count; i++) {
  15088. materials[i] = mesh->materials.data[i];
  15089. materials[i].material = (ufbx_material*)ufbxi_translate_element(ec, materials[i].material);
  15090. }
  15091. mesh->materials.data = materials;
  15092. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &mesh->skin_deformers));
  15093. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &mesh->blend_deformers));
  15094. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &mesh->cache_deformers));
  15095. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &mesh->all_deformers));
  15096. }
  15097. ufbxi_for_ptr_list(ufbx_stereo_camera, p_stereo, ec->scene.stereo_cameras) {
  15098. ufbx_stereo_camera *stereo = *p_stereo;
  15099. stereo->left = (ufbx_camera*)ufbxi_translate_element(ec, stereo->left);
  15100. stereo->right = (ufbx_camera*)ufbxi_translate_element(ec, stereo->right);
  15101. }
  15102. ufbxi_for_ptr_list(ufbx_skin_deformer, p_skin, ec->scene.skin_deformers) {
  15103. ufbx_skin_deformer *skin = *p_skin;
  15104. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &skin->clusters));
  15105. }
  15106. ufbxi_for_ptr_list(ufbx_skin_cluster, p_cluster, ec->scene.skin_clusters) {
  15107. ufbx_skin_cluster *cluster = *p_cluster;
  15108. cluster->bone_node = (ufbx_node*)ufbxi_translate_element(ec, cluster->bone_node);
  15109. }
  15110. ufbxi_for_ptr_list(ufbx_blend_deformer, p_blend, ec->scene.blend_deformers) {
  15111. ufbx_blend_deformer *blend = *p_blend;
  15112. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &blend->channels));
  15113. }
  15114. ufbxi_for_ptr_list(ufbx_blend_channel, p_chan, ec->scene.blend_channels) {
  15115. ufbx_blend_channel *chan = *p_chan;
  15116. ufbx_blend_keyframe *keys = ufbxi_push(&ec->result, ufbx_blend_keyframe, chan->keyframes.count);
  15117. ufbxi_check_err(&ec->error, keys);
  15118. for (size_t i = 0; i < chan->keyframes.count; i++) {
  15119. keys[i] = chan->keyframes.data[i];
  15120. keys[i].shape = (ufbx_blend_shape*)ufbxi_translate_element(ec, keys[i].shape);
  15121. }
  15122. chan->keyframes.data = keys;
  15123. }
  15124. ufbxi_for_ptr_list(ufbx_cache_deformer, p_deformer, ec->scene.cache_deformers) {
  15125. ufbx_cache_deformer *deformer = *p_deformer;
  15126. deformer->file = (ufbx_cache_file*)ufbxi_translate_element(ec, deformer->file);
  15127. }
  15128. ufbxi_for_ptr_list(ufbx_material, p_material, ec->scene.materials) {
  15129. ufbx_material *material = *p_material;
  15130. material->shader = (ufbx_shader*)ufbxi_translate_element(ec, material->shader);
  15131. for (size_t i = 0; i < UFBX_MATERIAL_FBX_MAP_COUNT; i++) {
  15132. ufbx_material_map *map = &material->fbx.maps[i];
  15133. map->texture = (ufbx_texture*)ufbxi_translate_element(ec, map->texture);
  15134. }
  15135. for (size_t i = 0; i < UFBX_MATERIAL_PBR_MAP_COUNT; i++) {
  15136. ufbx_material_map *map = &material->pbr.maps[i];
  15137. map->texture = (ufbx_texture*)ufbxi_translate_element(ec, map->texture);
  15138. }
  15139. ufbx_material_texture *textures = ufbxi_push(&ec->result, ufbx_material_texture, material->textures.count);
  15140. ufbxi_check_err(&ec->error, textures);
  15141. for (size_t i = 0; i < material->textures.count; i++) {
  15142. textures[i] = material->textures.data[i];
  15143. textures[i].texture = (ufbx_texture*)ufbxi_translate_element(ec, textures[i].texture);
  15144. }
  15145. material->textures.data = textures;
  15146. }
  15147. ufbxi_for_ptr_list(ufbx_texture, p_texture, ec->scene.textures) {
  15148. ufbx_texture *texture = *p_texture;
  15149. texture->video = (ufbx_video*)ufbxi_translate_element(ec, texture->video);
  15150. ufbx_texture_layer *layers = ufbxi_push(&ec->result, ufbx_texture_layer, texture->layers.count);
  15151. ufbxi_check_err(&ec->error, layers);
  15152. for (size_t i = 0; i < texture->layers.count; i++) {
  15153. layers[i] = texture->layers.data[i];
  15154. layers[i].texture = (ufbx_texture*)ufbxi_translate_element(ec, layers[i].texture);
  15155. }
  15156. texture->layers.data = layers;
  15157. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &texture->file_textures));
  15158. if (texture->shader) {
  15159. ufbx_shader_texture *shader = texture->shader;
  15160. shader = ufbxi_push_copy(&ec->result, ufbx_shader_texture, 1, shader);
  15161. ufbxi_check_err(&ec->error, shader);
  15162. texture->shader = shader;
  15163. ufbx_shader_texture_input *inputs = ufbxi_push_copy(&ec->result, ufbx_shader_texture_input, shader->inputs.count, shader->inputs.data);
  15164. ufbxi_check_err(&ec->error, inputs);
  15165. shader->inputs.data = inputs;
  15166. }
  15167. }
  15168. ufbxi_for_ptr_list(ufbx_shader, p_shader, ec->scene.shaders) {
  15169. ufbx_shader *shader = *p_shader;
  15170. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &shader->bindings));
  15171. }
  15172. ufbxi_for_ptr_list(ufbx_display_layer, p_layer, ec->scene.display_layers) {
  15173. ufbx_display_layer *layer = *p_layer;
  15174. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &layer->nodes));
  15175. }
  15176. ufbxi_for_ptr_list(ufbx_selection_set, p_set, ec->scene.selection_sets) {
  15177. ufbx_selection_set *set = *p_set;
  15178. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &set->nodes));
  15179. }
  15180. ufbxi_for_ptr_list(ufbx_selection_node, p_node, ec->scene.selection_nodes) {
  15181. ufbx_selection_node *node = *p_node;
  15182. node->target_node = (ufbx_node*)ufbxi_translate_element(ec, node->target_node);
  15183. node->target_mesh = (ufbx_mesh*)ufbxi_translate_element(ec, node->target_mesh);
  15184. }
  15185. ufbxi_for_ptr_list(ufbx_constraint, p_constraint, ec->scene.constraints) {
  15186. ufbx_constraint *constraint = *p_constraint;
  15187. constraint->node = (ufbx_node*)ufbxi_translate_element(ec, constraint->node);
  15188. constraint->aim_up_node = (ufbx_node*)ufbxi_translate_element(ec, constraint->aim_up_node);
  15189. constraint->ik_effector = (ufbx_node*)ufbxi_translate_element(ec, constraint->ik_effector);
  15190. constraint->ik_end_node = (ufbx_node*)ufbxi_translate_element(ec, constraint->ik_end_node);
  15191. ufbx_constraint_target *targets = ufbxi_push(&ec->result, ufbx_constraint_target, constraint->targets.count);
  15192. ufbxi_check_err(&ec->error, targets);
  15193. for (size_t i = 0; i < constraint->targets.count; i++) {
  15194. targets[i] = constraint->targets.data[i];
  15195. targets[i].node = (ufbx_node*)ufbxi_translate_element(ec, targets[i].node);
  15196. }
  15197. constraint->targets.data = targets;
  15198. }
  15199. ufbxi_for_ptr_list(ufbx_anim_stack, p_stack, ec->scene.anim_stacks) {
  15200. ufbx_anim_stack *stack = *p_stack;
  15201. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &stack->layers));
  15202. ufbxi_check_err(&ec->error, ufbxi_translate_anim(ec, &stack->anim));
  15203. }
  15204. ufbxi_for_ptr_list(ufbx_anim_layer, p_layer, ec->scene.anim_layers) {
  15205. ufbx_anim_layer *layer = *p_layer;
  15206. ufbxi_check_err(&ec->error, ufbxi_translate_element_list(ec, &layer->anim_values));
  15207. ufbx_anim_prop *props = ufbxi_push(&ec->result, ufbx_anim_prop, layer->anim_props.count);
  15208. ufbxi_check_err(&ec->error, props);
  15209. for (size_t i = 0; i < layer->anim_props.count; i++) {
  15210. props[i] = layer->anim_props.data[i];
  15211. props[i].element = ufbxi_translate_element(ec, props[i].element);
  15212. props[i].anim_value = (ufbx_anim_value*)ufbxi_translate_element(ec, props[i].anim_value);
  15213. }
  15214. layer->anim_props.data = props;
  15215. }
  15216. ufbxi_for_ptr_list(ufbx_pose, p_pose, ec->scene.poses) {
  15217. ufbx_pose *pose = *p_pose;
  15218. ufbx_bone_pose *bones = ufbxi_push(&ec->result, ufbx_bone_pose, pose->bone_poses.count);
  15219. ufbxi_check_err(&ec->error, bones);
  15220. for (size_t i = 0; i < pose->bone_poses.count; i++) {
  15221. bones[i] = pose->bone_poses.data[i];
  15222. bones[i].bone_node = (ufbx_node*)ufbxi_translate_element(ec, bones[i].bone_node);
  15223. }
  15224. pose->bone_poses.data = bones;
  15225. }
  15226. ufbxi_check_err(&ec->error, ufbxi_translate_anim(ec, &ec->anim));
  15227. ufbxi_for_ptr_list(ufbx_anim_value, p_value, ec->scene.anim_values) {
  15228. ufbx_anim_value *value = *p_value;
  15229. value->curves[0] = (ufbx_anim_curve*)ufbxi_translate_element(ec, value->curves[0]);
  15230. value->curves[1] = (ufbx_anim_curve*)ufbxi_translate_element(ec, value->curves[1]);
  15231. value->curves[2] = (ufbx_anim_curve*)ufbxi_translate_element(ec, value->curves[2]);
  15232. }
  15233. ufbx_anim anim = ec->anim;
  15234. ufbx_const_prop_override_list overrides_left = ec->anim.prop_overrides;
  15235. // Evaluate the properties
  15236. ufbxi_for_ptr_list(ufbx_element, p_elem, ec->scene.elements) {
  15237. ufbx_element *elem = *p_elem;
  15238. size_t num_animated = elem->props.num_animated;
  15239. // Setup the overrides for this element if found
  15240. if (overrides_left.count > 0) {
  15241. if (overrides_left.data[0].element_id <= elem->element_id) {
  15242. anim.prop_overrides = ufbxi_find_element_prop_overrides(&overrides_left, elem->element_id);
  15243. overrides_left.data = anim.prop_overrides.data + anim.prop_overrides.count;
  15244. overrides_left.count = ufbxi_to_size((ec->anim.prop_overrides.data + ec->anim.prop_overrides.count) - overrides_left.data);
  15245. num_animated += anim.prop_overrides.count;
  15246. }
  15247. }
  15248. if (num_animated == 0) continue;
  15249. ufbx_prop *props = ufbxi_push(&ec->result, ufbx_prop, num_animated);
  15250. ufbxi_check_err(&ec->error, props);
  15251. elem->props = ufbx_evaluate_props(&anim, elem, ec->time, props, num_animated);
  15252. elem->props.defaults = &ec->src_scene.elements.data[elem->element_id]->props;
  15253. anim.prop_overrides.count = 0;
  15254. }
  15255. // Update all derived values
  15256. ufbxi_update_scene(&ec->scene, false);
  15257. // Evaluate skinning if requested
  15258. if (ec->opts.evaluate_skinning) {
  15259. ufbx_geometry_cache_data_opts cache_opts = { 0 };
  15260. cache_opts.open_file_cb = ec->opts.open_file_cb;
  15261. ufbxi_check_err(&ec->error, ufbxi_evaluate_skinning(&ec->scene, &ec->error, &ec->result, &ec->tmp,
  15262. ec->time, ec->opts.load_external_files && ec->opts.evaluate_caches, &cache_opts));
  15263. }
  15264. // Retain the scene, this must be the final allocation as we copy
  15265. // `ator_result` to `ufbx_scene_imp`.
  15266. ufbxi_scene_imp *imp = ufbxi_push_zero(&ec->result, ufbxi_scene_imp, 1);
  15267. ufbxi_check_err(&ec->error, imp);
  15268. ufbx_assert(ec->src_imp->magic == UFBXI_SCENE_IMP_MAGIC);
  15269. ufbxi_init_ref(&imp->refcount, UFBXI_SCENE_IMP_MAGIC, &ec->src_imp->refcount);
  15270. imp->magic = UFBXI_SCENE_IMP_MAGIC;
  15271. imp->scene = ec->scene;
  15272. imp->ator = ec->ator_result;
  15273. imp->ator.error = NULL;
  15274. // Copy retained buffers and translate the allocator struct to the one
  15275. // contained within `ufbxi_scene_imp`
  15276. imp->result_buf = ec->result;
  15277. imp->result_buf.ator = &imp->ator;
  15278. imp->scene.metadata.result_memory_used = imp->ator.current_size;
  15279. imp->scene.metadata.temp_memory_used = ec->ator_tmp.current_size;
  15280. imp->scene.metadata.result_allocs = imp->ator.num_allocs;
  15281. imp->scene.metadata.temp_allocs = ec->ator_tmp.num_allocs;
  15282. ufbxi_for_ptr_list(ufbx_element, p_elem, imp->scene.elements) {
  15283. (*p_elem)->scene = &imp->scene;
  15284. }
  15285. ec->scene_imp = imp;
  15286. ec->result.ator = &ec->ator_result;
  15287. return 1;
  15288. }
  15289. ufbxi_nodiscard static ufbxi_noinline ufbx_scene *ufbxi_evaluate_scene(ufbxi_eval_context *ec, ufbx_scene *scene, const ufbx_anim *anim, double time, const ufbx_evaluate_opts *user_opts, ufbx_error *p_error)
  15290. {
  15291. if (user_opts) {
  15292. ec->opts = *user_opts;
  15293. } else {
  15294. memset(&ec->opts, 0, sizeof(ec->opts));
  15295. }
  15296. ec->src_imp = ufbxi_get_imp(ufbxi_scene_imp, scene);
  15297. ec->src_scene = *scene;
  15298. ec->anim = anim ? *anim : scene->anim;
  15299. ec->time = time;
  15300. ufbxi_init_ator(&ec->error, &ec->ator_tmp, &ec->opts.temp_allocator);
  15301. ufbxi_init_ator(&ec->error, &ec->ator_result, &ec->opts.result_allocator);
  15302. ec->result.ator = &ec->ator_result;
  15303. ec->tmp.ator = &ec->ator_tmp;
  15304. ec->result.unordered = true;
  15305. ec->tmp.unordered = true;
  15306. if (ufbxi_evaluate_imp(ec)) {
  15307. ufbxi_buf_free(&ec->tmp);
  15308. ufbxi_free_ator(&ec->ator_tmp);
  15309. if (p_error) {
  15310. p_error->type = UFBX_ERROR_NONE;
  15311. p_error->description.data = ufbxi_empty_char;
  15312. p_error->description.length = 0;
  15313. p_error->stack_size = 0;
  15314. }
  15315. return &ec->scene_imp->scene;
  15316. } else {
  15317. ufbxi_fix_error_type(&ec->error, "Failed to evaluate");
  15318. if (p_error) *p_error = ec->error;
  15319. ufbxi_buf_free(&ec->tmp);
  15320. ufbxi_buf_free(&ec->result);
  15321. ufbxi_free_ator(&ec->ator_tmp);
  15322. ufbxi_free_ator(&ec->ator_result);
  15323. return NULL;
  15324. }
  15325. }
  15326. #endif
  15327. // -- Spatial
  15328. #if UFBXI_FEATURE_SPATIAL
  15329. typedef struct {
  15330. int32_t x, y, z;
  15331. } ufbxi_spatial_key;
  15332. typedef struct {
  15333. ufbxi_spatial_key key;
  15334. ufbx_vec3 position;
  15335. } ufbxi_spatial_bucket;
  15336. static ufbxi_forceinline uint32_t ufbxi_hash_spatial_key(ufbxi_spatial_key key)
  15337. {
  15338. uint32_t h = 0;
  15339. h = (h<<6) + (h>>2) + 0x9e3779b9 + ufbxi_hash32((uint32_t)key.x);
  15340. h = (h<<6) + (h>>2) + 0x9e3779b9 + ufbxi_hash32((uint32_t)key.y);
  15341. h = (h<<6) + (h>>2) + 0x9e3779b9 + ufbxi_hash32((uint32_t)key.z);
  15342. return h;
  15343. }
  15344. static int ufbxi_map_cmp_spatial_key(void *user, const void *va, const void *vb)
  15345. {
  15346. (void)user;
  15347. ufbxi_spatial_key a = *(const ufbxi_spatial_key*)va, b = *(const ufbxi_spatial_key*)vb;
  15348. if (a.x != b.x) return a.x < b.x ? -1 : +1;
  15349. if (a.y != b.y) return a.y < b.y ? -1 : +1;
  15350. if (a.z != b.z) return a.z < b.z ? -1 : +1;
  15351. return 0;
  15352. }
  15353. static int32_t ufbxi_noinline ufbxi_spatial_coord(ufbx_real v)
  15354. {
  15355. bool negative = false;
  15356. if (v < 0.0f) {
  15357. v = -v;
  15358. negative = true;
  15359. }
  15360. if (!(v < 1.27605887595e+38f)) {
  15361. return INT32_MIN;
  15362. }
  15363. const int32_t min_exponent = -20;
  15364. const int32_t mantissa_bits = 21;
  15365. const int32_t mantissa_max = 1 << mantissa_bits;
  15366. int exponent = 0;
  15367. double mantissa = ufbx_frexp(v, &exponent);
  15368. if (exponent < min_exponent) {
  15369. return 0;
  15370. } else {
  15371. int32_t biased = (int32_t)(exponent - min_exponent);
  15372. int32_t truncated_mantissa = (int32_t)(mantissa * (double)(mantissa_max*2)) - mantissa_max;
  15373. int32_t value = (biased << mantissa_bits) + truncated_mantissa;
  15374. return negative ? -value : value;
  15375. }
  15376. }
  15377. static uint32_t ufbxi_noinline ufbxi_insert_spatial_imp(ufbxi_map *map, int32_t kx, int32_t ky, int32_t kz)
  15378. {
  15379. ufbxi_spatial_key key = { kx, ky, kz };
  15380. uint32_t hash = ufbxi_hash_spatial_key(key);
  15381. ufbxi_spatial_bucket *bucket = ufbxi_map_find(map, ufbxi_spatial_bucket, hash, &key);
  15382. if (bucket) {
  15383. return (uint32_t)(bucket - (ufbxi_spatial_bucket*)map->items);
  15384. } else {
  15385. return UINT32_MAX;
  15386. }
  15387. }
  15388. static uint32_t ufbxi_noinline ufbxi_insert_spatial(ufbxi_map *map, const ufbx_vec3 *pos)
  15389. {
  15390. int32_t kx = ufbxi_spatial_coord(pos->x);
  15391. int32_t ky = ufbxi_spatial_coord(pos->y);
  15392. int32_t kz = ufbxi_spatial_coord(pos->z);
  15393. uint32_t ix = UINT32_MAX;
  15394. if (kx != INT32_MIN && ky != INT32_MIN && kz != INT32_MIN) {
  15395. const int32_t low_bits = 2, low_mask = (1 << low_bits) - 1;
  15396. kx += low_mask/2;
  15397. ky += low_mask/2;
  15398. kz += low_mask/2;
  15399. int32_t dx = (((kx+1) & low_mask) < 2) ? (((kx >> (low_bits-1)) & 1) ? +1 : -1) : 0;
  15400. int32_t dy = (((ky+1) & low_mask) < 2) ? (((ky >> (low_bits-1)) & 1) ? +1 : -1) : 0;
  15401. int32_t dz = (((kz+1) & low_mask) < 2) ? (((kz >> (low_bits-1)) & 1) ? +1 : -1) : 0;
  15402. int32_t dnum = (dx&1) + (dy&1) + (dz&1);
  15403. kx >>= low_bits;
  15404. ky >>= low_bits;
  15405. kz >>= low_bits;
  15406. ix = ufbxi_insert_spatial_imp(map, kx, ky, kz);
  15407. if (dnum >= 1 && ix == UINT32_MAX) {
  15408. if (dx) ix = ufbxi_insert_spatial_imp(map, kx+dx, ky, kz);
  15409. if (dy) ix = ufbxi_insert_spatial_imp(map, kx, ky+dy, kz);
  15410. if (dz) ix = ufbxi_insert_spatial_imp(map, kx, ky, kz+dz);
  15411. if (dnum >= 2 && ix == UINT32_MAX) {
  15412. if (dx && dy) ix = ufbxi_insert_spatial_imp(map, kx+dx, ky+dy, kz);
  15413. if (dy && dz) ix = ufbxi_insert_spatial_imp(map, kx, ky+dy, kz+dz);
  15414. if (dx && dz) ix = ufbxi_insert_spatial_imp(map, kx+dx, ky, kz+dz);
  15415. if (dnum >= 3 && ix == UINT32_MAX) {
  15416. ix = ufbxi_insert_spatial_imp(map, kx+dx, ky+dy, kz+dz);
  15417. }
  15418. }
  15419. }
  15420. }
  15421. if (ix == UINT32_MAX) {
  15422. ix = map->size;
  15423. ufbxi_spatial_key key = { kx, ky, kz };
  15424. uint32_t hash = ufbxi_hash_spatial_key(key);
  15425. ufbxi_spatial_bucket *bucket = ufbxi_map_insert(map, ufbxi_spatial_bucket, hash, &key);
  15426. ufbxi_check_return_err(map->ator->error, bucket, UINT32_MAX);
  15427. bucket->key = key;
  15428. bucket->position = *pos;
  15429. }
  15430. return ix;
  15431. }
  15432. #endif
  15433. // -- NURBS
  15434. static ufbxi_forceinline ufbx_real ufbxi_nurbs_weight(const ufbx_real_list *knots, size_t knot, size_t degree, ufbx_real u)
  15435. {
  15436. if (knot >= knots->count) return 0.0f;
  15437. if (knots->count - knot < degree) return 0.0f;
  15438. ufbx_real prev_u = knots->data[knot], next_u = knots->data[knot + degree];
  15439. if (prev_u >= next_u) return 0.0f;
  15440. if (u <= prev_u) return 0.0f;
  15441. if (u >= next_u) return 1.0f;
  15442. return (u - prev_u) / (next_u - prev_u);
  15443. }
  15444. static ufbxi_forceinline ufbx_real ufbxi_nurbs_deriv(const ufbx_real_list *knots, size_t knot, size_t degree)
  15445. {
  15446. if (knot >= knots->count) return 0.0f;
  15447. if (knots->count - knot < degree) return 0.0f;
  15448. ufbx_real prev_u = knots->data[knot], next_u = knots->data[knot + degree];
  15449. if (prev_u >= next_u) return 0.0f;
  15450. return (ufbx_real)degree / (next_u - prev_u);
  15451. }
  15452. ufbxi_nodiscard static ufbxi_noinline int ufbxi_finalize_mesh(ufbxi_buf *buf, ufbx_error *error, ufbx_mesh *mesh)
  15453. {
  15454. size_t num_materials = mesh->materials.count;
  15455. mesh->vertex_first_index.count = mesh->num_vertices;
  15456. mesh->vertex_first_index.data = ufbxi_push(buf, uint32_t, mesh->num_vertices);
  15457. ufbxi_check_err(error, mesh->vertex_first_index.data);
  15458. ufbxi_for_list(uint32_t, p_vx_ix, mesh->vertex_first_index) {
  15459. *p_vx_ix = UFBX_NO_INDEX;
  15460. }
  15461. for (size_t ix = 0; ix < mesh->num_indices; ix++) {
  15462. uint32_t vx = mesh->vertex_indices.data[ix];
  15463. if (mesh->vertex_first_index.data[vx] == UFBX_NO_INDEX) {
  15464. mesh->vertex_first_index.data[vx] = (uint32_t)ix;
  15465. }
  15466. }
  15467. // See `ufbxi_finalize_scene()`
  15468. ufbxi_for_list(ufbx_mesh_material, mat, mesh->materials) {
  15469. mat->face_indices.count = mat->num_faces;
  15470. mat->face_indices.data = ufbxi_push(buf, uint32_t, mat->num_faces);
  15471. ufbxi_check_err(error, mat->face_indices.data);
  15472. mat->num_faces = 0;
  15473. }
  15474. for (size_t i = 0; i < mesh->num_faces; i++) {
  15475. uint32_t mat_ix = mesh->face_material.data ? mesh->face_material.data[i] : 0;
  15476. if (mat_ix < num_materials) {
  15477. ufbx_mesh_material *mat = &mesh->materials.data[mat_ix];
  15478. mat->face_indices.data[mat->num_faces++] = (uint32_t)i;
  15479. }
  15480. }
  15481. return 1;
  15482. }
  15483. typedef struct {
  15484. ufbxi_refcount refcount;
  15485. ufbx_line_curve curve;
  15486. uint32_t magic;
  15487. ufbxi_allocator ator;
  15488. ufbxi_buf result_buf;
  15489. } ufbxi_line_curve_imp;
  15490. ufbx_static_assert(line_curve_imp_offset, offsetof(ufbxi_line_curve_imp, curve) == sizeof(ufbxi_refcount));
  15491. #if UFBXI_FEATURE_TESSELLATION
  15492. typedef struct {
  15493. ufbx_error error;
  15494. ufbx_tessellate_curve_opts opts;
  15495. const ufbx_nurbs_curve *curve;
  15496. ufbxi_allocator ator_tmp;
  15497. ufbxi_allocator ator_result;
  15498. ufbxi_buf result;
  15499. ufbx_line_curve line;
  15500. ufbxi_line_curve_imp *imp;
  15501. } ufbxi_tessellate_curve_context;
  15502. typedef struct {
  15503. ufbx_error error;
  15504. ufbx_tessellate_surface_opts opts;
  15505. const ufbx_nurbs_surface *surface;
  15506. ufbxi_allocator ator_tmp;
  15507. ufbxi_allocator ator_result;
  15508. ufbxi_buf tmp;
  15509. ufbxi_buf result;
  15510. ufbxi_map position_map;
  15511. ufbx_mesh mesh;
  15512. ufbxi_mesh_imp *imp;
  15513. } ufbxi_tessellate_surface_context;
  15514. ufbxi_nodiscard static ufbxi_noinline int ufbxi_tessellate_nurbs_curve_imp(ufbxi_tessellate_curve_context *tc)
  15515. {
  15516. // `ufbx_tessellate_opts` must be cleared to zero first!
  15517. ufbx_assert(tc->opts._begin_zero == 0 && tc->opts._end_zero == 0);
  15518. ufbxi_check_err_msg(&tc->error, tc->opts._begin_zero == 0 && tc->opts._end_zero == 0, "Uninitialized options");
  15519. if (tc->opts.span_subdivision <= 0) {
  15520. tc->opts.span_subdivision = 4;
  15521. }
  15522. size_t num_sub = tc->opts.span_subdivision;
  15523. const ufbx_nurbs_curve *curve = tc->curve;
  15524. ufbx_line_curve *line = &tc->line;
  15525. ufbxi_check_err_msg(&tc->error, curve->basis.valid && curve->control_points.count > 0, "Bad NURBS geometry");
  15526. ufbxi_init_ator(&tc->error, &tc->ator_tmp, &tc->opts.temp_allocator);
  15527. ufbxi_init_ator(&tc->error, &tc->ator_result, &tc->opts.result_allocator);
  15528. tc->result.unordered = true;
  15529. tc->result.ator = &tc->ator_result;
  15530. size_t num_spans = curve->basis.spans.count;
  15531. // Check conservatively that we don't overflow anything
  15532. {
  15533. size_t over_spans = num_spans * 2 * sizeof(ufbx_real);
  15534. size_t over = over_spans * num_sub;
  15535. ufbxi_check_err(&tc->error, !ufbxi_does_overflow(over, over_spans, num_sub));
  15536. }
  15537. bool is_open = curve->basis.topology == UFBX_NURBS_TOPOLOGY_OPEN;
  15538. size_t num_indices = num_spans + (num_spans - 1) * (num_sub - 1);
  15539. size_t num_vertices = num_indices - (is_open ? 0u : 1u);
  15540. ufbxi_check_err(&tc->error, num_indices <= INT32_MAX);
  15541. uint32_t *indices = ufbxi_push(&tc->result, uint32_t, num_indices);
  15542. ufbx_vec3 *vertices = ufbxi_push(&tc->result, ufbx_vec3, num_vertices);
  15543. ufbx_line_segment *segments = ufbxi_push(&tc->result, ufbx_line_segment, 1);
  15544. ufbxi_check_err(&tc->error, indices && vertices && segments);
  15545. for (size_t span_ix = 0; span_ix < num_spans; span_ix++) {
  15546. size_t num_splits = span_ix + 1 == num_spans ? 1 : num_sub;
  15547. for (size_t sub_ix = 0; sub_ix < num_splits; sub_ix++) {
  15548. size_t ix = span_ix * num_sub + sub_ix;
  15549. if (ix < num_vertices) {
  15550. ufbx_real u = curve->basis.spans.data[span_ix];
  15551. if (sub_ix > 0) {
  15552. ufbx_real t = (ufbx_real)sub_ix / num_sub;
  15553. u = u * (1.0f - t) + t * curve->basis.spans.data[span_ix + 1];
  15554. }
  15555. ufbx_curve_point point = ufbx_evaluate_nurbs_curve(curve, u);
  15556. vertices[ix] = point.position;
  15557. indices[ix] = (uint32_t)ix;
  15558. } else {
  15559. indices[ix] = 0;
  15560. }
  15561. }
  15562. }
  15563. segments[0].index_begin = 0;
  15564. segments[0].num_indices = (uint32_t)num_indices;
  15565. line->element.name.data = ufbxi_empty_char;
  15566. line->element.type = UFBX_ELEMENT_LINE_CURVE;
  15567. line->element.typed_id = UINT32_MAX;
  15568. line->element.element_id = UINT32_MAX;
  15569. line->color.x = 1.0f;
  15570. line->color.y = 1.0f;
  15571. line->color.z = 1.0f;
  15572. line->control_points.data = vertices;
  15573. line->control_points.count = num_vertices;
  15574. line->point_indices.data = indices;
  15575. line->point_indices.count = num_indices;
  15576. line->segments.data = segments;
  15577. line->segments.count = 1;
  15578. line->from_tessellated_nurbs = true;
  15579. tc->imp = ufbxi_push(&tc->result, ufbxi_line_curve_imp, 1);
  15580. ufbxi_check_err(&tc->error, tc->imp);
  15581. ufbxi_init_ref(&tc->imp->refcount, UFBXI_LINE_CURVE_IMP_MAGIC, &(ufbxi_get_imp(ufbxi_scene_imp, curve->element.scene))->refcount);
  15582. tc->imp->magic = UFBXI_LINE_CURVE_IMP_MAGIC;
  15583. tc->imp->curve = tc->line;
  15584. tc->imp->ator = tc->ator_result;
  15585. tc->imp->result_buf = tc->result;
  15586. return 1;
  15587. }
  15588. ufbxi_nodiscard static ufbxi_noinline int ufbxi_tessellate_nurbs_surface_imp(ufbxi_tessellate_surface_context *tc)
  15589. {
  15590. // `ufbx_tessellate_opts` must be cleared to zero first!
  15591. ufbx_assert(tc->opts._begin_zero == 0 && tc->opts._end_zero == 0);
  15592. ufbxi_check_err_msg(&tc->error, tc->opts._begin_zero == 0 && tc->opts._end_zero == 0, "Uninitialized options");
  15593. if (tc->opts.span_subdivision_u <= 0) {
  15594. tc->opts.span_subdivision_u = 4;
  15595. }
  15596. if (tc->opts.span_subdivision_v <= 0) {
  15597. tc->opts.span_subdivision_v = 4;
  15598. }
  15599. size_t sub_u = tc->opts.span_subdivision_u;
  15600. size_t sub_v = tc->opts.span_subdivision_v;
  15601. const ufbx_nurbs_surface *surface = tc->surface;
  15602. ufbx_mesh *mesh = &tc->mesh;
  15603. ufbxi_check_err_msg(&tc->error, surface->basis_u.valid && surface->basis_v.valid
  15604. && surface->num_control_points_u > 0 && surface->num_control_points_v > 0, "Bad NURBS geometry");
  15605. ufbxi_init_ator(&tc->error, &tc->ator_tmp, &tc->opts.temp_allocator);
  15606. ufbxi_init_ator(&tc->error, &tc->ator_result, &tc->opts.result_allocator);
  15607. tc->result.unordered = true;
  15608. tc->tmp.unordered = true;
  15609. tc->result.ator = &tc->ator_result;
  15610. tc->tmp.ator = &tc->ator_tmp;
  15611. bool open_u = surface->basis_u.topology == UFBX_NURBS_TOPOLOGY_OPEN;
  15612. bool open_v = surface->basis_v.topology == UFBX_NURBS_TOPOLOGY_OPEN;
  15613. size_t spans_u = surface->basis_u.spans.count;
  15614. size_t spans_v = surface->basis_v.spans.count;
  15615. // Check conservatively that we don't overflow anything
  15616. {
  15617. size_t over_spans_u = spans_u * 2 * sizeof(ufbx_real);
  15618. size_t over_spans_v = spans_v * 2 * sizeof(ufbx_real);
  15619. size_t over_u = over_spans_u * sub_u;
  15620. size_t over_v = over_spans_v * sub_v;
  15621. size_t over_uv = over_u * over_v;
  15622. ufbxi_check_err(&tc->error, !ufbxi_does_overflow(over_u, over_spans_u, sub_u));
  15623. ufbxi_check_err(&tc->error, !ufbxi_does_overflow(over_v, over_spans_v, sub_v));
  15624. ufbxi_check_err(&tc->error, !ufbxi_does_overflow(over_uv, over_u, over_v));
  15625. }
  15626. ufbxi_map_init(&tc->position_map, &tc->ator_tmp, &ufbxi_map_cmp_spatial_key, NULL);
  15627. size_t faces_u = (spans_u - 1) * sub_u;
  15628. size_t faces_v = (spans_v - 1) * sub_v;
  15629. size_t indices_u = spans_u + (spans_u - 1) * sub_u;
  15630. size_t indices_v = spans_v + (spans_v - 1) * sub_v;
  15631. size_t num_faces = faces_u * faces_v;
  15632. size_t num_indices = indices_u * indices_v;
  15633. ufbxi_check_err(&tc->error, num_indices <= INT32_MAX);
  15634. uint32_t *position_ix = ufbxi_push(&tc->tmp, uint32_t, num_indices);
  15635. ufbx_vec2 *uvs = ufbxi_push(&tc->result, ufbx_vec2, num_indices + 1);
  15636. ufbx_vec3 *tangents = ufbxi_push(&tc->result, ufbx_vec3, num_indices + 1);
  15637. ufbx_vec3 *bitangents = ufbxi_push(&tc->result, ufbx_vec3, num_indices + 1);
  15638. ufbxi_check_err(&tc->error, position_ix && uvs && tangents && bitangents);
  15639. *uvs++ = ufbx_zero_vec2;
  15640. *tangents++ = ufbx_zero_vec3;
  15641. *bitangents++ = ufbx_zero_vec3;
  15642. for (size_t span_v = 0; span_v < spans_v; span_v++) {
  15643. size_t splits_v = span_v + 1 == spans_v ? 1 : sub_v;
  15644. for (size_t split_v = 0; split_v < splits_v; split_v++) {
  15645. size_t ix_v = span_v * sub_v + split_v;
  15646. ufbx_real v = surface->basis_v.spans.data[span_v];
  15647. if (split_v > 0) {
  15648. ufbx_real t = (ufbx_real)split_v / splits_v;
  15649. v = v * (1.0f - t) + t * surface->basis_v.spans.data[span_v + 1];
  15650. }
  15651. ufbx_real original_v = v;
  15652. if (span_v + 1 == spans_v && !open_v) {
  15653. v = surface->basis_v.spans.data[0];
  15654. }
  15655. for (size_t span_u = 0; span_u < spans_u; span_u++) {
  15656. size_t splits_u = span_u + 1 == spans_u ? 1 : sub_u;
  15657. for (size_t split_u = 0; split_u < splits_u; split_u++) {
  15658. size_t ix_u = span_u * sub_u + split_u;
  15659. ufbx_real u = surface->basis_u.spans.data[span_u];
  15660. if (split_u > 0) {
  15661. ufbx_real t = (ufbx_real)split_u / splits_u;
  15662. u = u * (1.0f - t) + t * surface->basis_u.spans.data[span_u + 1];
  15663. }
  15664. ufbx_real original_u = u;
  15665. if (span_u + 1 == spans_u && !open_u) {
  15666. u = surface->basis_u.spans.data[0];
  15667. }
  15668. ufbx_surface_point point = ufbx_evaluate_nurbs_surface(surface, u, v);
  15669. ufbx_vec3 pos = point.position;
  15670. uint32_t pos_ix = ufbxi_insert_spatial(&tc->position_map, &pos);
  15671. ufbxi_check_err(&tc->error, pos_ix != UINT32_MAX);
  15672. ufbx_vec3 tangent_u = ufbxi_slow_normalize3(&point.derivative_u);
  15673. ufbx_vec3 tangent_v = ufbxi_slow_normalize3(&point.derivative_v);
  15674. size_t ix = ix_v * indices_u + ix_u;
  15675. position_ix[ix] = (uint32_t)pos_ix;
  15676. uvs[ix].x = original_u;
  15677. uvs[ix].y = original_v;
  15678. tangents[ix] = tangent_u;
  15679. bitangents[ix] = tangent_v;
  15680. }
  15681. }
  15682. }
  15683. }
  15684. ufbx_face *faces = ufbxi_push(&tc->result, ufbx_face, num_faces);
  15685. uint32_t *vertex_ix = ufbxi_push(&tc->result, uint32_t, num_faces * 4);
  15686. uint32_t *attrib_ix = ufbxi_push(&tc->result, uint32_t, num_faces * 4);
  15687. ufbxi_check_err(&tc->error, faces && vertex_ix && attrib_ix);
  15688. size_t face_ix = 0;
  15689. size_t dst_index = 0;
  15690. size_t num_triangles = 0;
  15691. for (size_t face_v = 0; face_v < faces_v; face_v++) {
  15692. for (size_t face_u = 0; face_u < faces_u; face_u++) {
  15693. attrib_ix[dst_index + 0] = (uint32_t)((face_v + 0) * indices_u + (face_u + 0));
  15694. attrib_ix[dst_index + 1] = (uint32_t)((face_v + 0) * indices_u + (face_u + 1));
  15695. attrib_ix[dst_index + 2] = (uint32_t)((face_v + 1) * indices_u + (face_u + 1));
  15696. attrib_ix[dst_index + 3] = (uint32_t)((face_v + 1) * indices_u + (face_u + 0));
  15697. vertex_ix[dst_index + 0] = position_ix[attrib_ix[dst_index + 0]];
  15698. vertex_ix[dst_index + 1] = position_ix[attrib_ix[dst_index + 1]];
  15699. vertex_ix[dst_index + 2] = position_ix[attrib_ix[dst_index + 2]];
  15700. vertex_ix[dst_index + 3] = position_ix[attrib_ix[dst_index + 3]];
  15701. bool is_triangle = false;
  15702. for (size_t prev_ix = 0; prev_ix < 4; prev_ix++) {
  15703. size_t next_ix = (prev_ix + 1) % 4;
  15704. if (vertex_ix[dst_index + prev_ix] == vertex_ix[dst_index + next_ix]) {
  15705. for (size_t i = next_ix; i < 3; i++) {
  15706. attrib_ix[dst_index + i] = attrib_ix[dst_index + i + 1];
  15707. vertex_ix[dst_index + i] = vertex_ix[dst_index + i + 1];
  15708. }
  15709. is_triangle = true;
  15710. break;
  15711. }
  15712. }
  15713. faces[face_ix].index_begin = (uint32_t)dst_index;
  15714. faces[face_ix].num_indices = is_triangle ? 3 : 4;
  15715. dst_index += is_triangle ? 3 : 4;
  15716. num_triangles += is_triangle ? 1 : 2;
  15717. face_ix++;
  15718. }
  15719. }
  15720. size_t num_positions = tc->position_map.size;
  15721. ufbx_vec3 *positions = ufbxi_push(&tc->result, ufbx_vec3, num_positions + 1);
  15722. ufbx_vec3 *normals = ufbxi_push(&tc->result, ufbx_vec3, num_positions + 1);
  15723. ufbxi_check_err(&tc->error, positions && normals);
  15724. *positions++ = ufbx_zero_vec3;
  15725. *normals++ = ufbx_zero_vec3;
  15726. ufbxi_spatial_bucket *buckets = (ufbxi_spatial_bucket*)tc->position_map.items;
  15727. for (size_t i = 0; i < num_positions; i++) {
  15728. positions[i] = buckets[i].position;
  15729. }
  15730. mesh->element.name.data = ufbxi_empty_char;
  15731. mesh->element.type = UFBX_ELEMENT_MESH;
  15732. mesh->element.typed_id = UINT32_MAX;
  15733. mesh->element.element_id = UINT32_MAX;
  15734. mesh->vertices.data = positions;
  15735. mesh->vertices.count = num_positions;
  15736. mesh->num_vertices = num_positions;
  15737. mesh->vertex_indices.data = vertex_ix;
  15738. mesh->vertex_indices.count = dst_index;
  15739. mesh->faces.data = faces;
  15740. mesh->faces.count = num_faces;
  15741. mesh->vertex_position.exists = true;
  15742. mesh->vertex_position.values.data = positions;
  15743. mesh->vertex_position.values.count = num_positions;
  15744. mesh->vertex_position.indices.data = vertex_ix;
  15745. mesh->vertex_position.indices.count = dst_index;
  15746. mesh->vertex_position.unique_per_vertex = true;
  15747. mesh->vertex_uv.exists = true;
  15748. mesh->vertex_uv.values.data = uvs;
  15749. mesh->vertex_uv.values.count = dst_index;
  15750. mesh->vertex_uv.indices.data = attrib_ix;
  15751. mesh->vertex_uv.indices.count = dst_index;
  15752. mesh->vertex_normal.exists = true;
  15753. mesh->vertex_normal.values.data = normals;
  15754. mesh->vertex_normal.values.count = num_positions;
  15755. mesh->vertex_normal.indices.data = vertex_ix;
  15756. mesh->vertex_normal.indices.count = dst_index;
  15757. mesh->vertex_tangent.exists = true;
  15758. mesh->vertex_tangent.values.data = tangents;
  15759. mesh->vertex_tangent.values.count = dst_index;
  15760. mesh->vertex_tangent.indices.data = attrib_ix;
  15761. mesh->vertex_tangent.indices.count = dst_index;
  15762. mesh->vertex_bitangent.exists = true;
  15763. mesh->vertex_bitangent.values.data = bitangents;
  15764. mesh->vertex_bitangent.values.count = dst_index;
  15765. mesh->vertex_bitangent.indices.data = attrib_ix;
  15766. mesh->vertex_bitangent.indices.count = dst_index;
  15767. ufbx_uv_set *uv_set = ufbxi_push(&tc->result, ufbx_uv_set, 1);
  15768. ufbxi_check_err(&tc->error, uv_set);
  15769. uv_set->index = 0;
  15770. uv_set->name = ufbx_empty_string;
  15771. uv_set->vertex_uv = mesh->vertex_uv;
  15772. uv_set->vertex_tangent = mesh->vertex_tangent;
  15773. uv_set->vertex_bitangent = mesh->vertex_bitangent;
  15774. mesh->uv_sets.data = uv_set;
  15775. mesh->uv_sets.count = 1;
  15776. mesh->num_faces = num_faces;
  15777. mesh->num_triangles = num_triangles;
  15778. mesh->num_indices = dst_index;
  15779. mesh->max_face_triangles = 2;
  15780. if (surface->material) {
  15781. mesh->face_material.data = ufbxi_push_zero(&tc->result, uint32_t, num_faces);
  15782. ufbxi_check_err(&tc->error, mesh->face_material.data);
  15783. ufbx_mesh_material *mat = ufbxi_push_zero(&tc->result, ufbx_mesh_material, 1);
  15784. ufbxi_check_err(&tc->error, mat);
  15785. mat->material = surface->material;
  15786. mat->num_triangles = num_triangles;
  15787. mat->num_faces = num_faces;
  15788. mesh->materials.data = mat;
  15789. mesh->materials.count = 1;
  15790. }
  15791. mesh->skinned_is_local = true;
  15792. mesh->skinned_position = mesh->vertex_position;
  15793. mesh->skinned_normal = mesh->vertex_normal;
  15794. ufbxi_check_err(&tc->error, ufbxi_finalize_mesh(&tc->result, &tc->error, mesh));
  15795. ufbx_compute_normals(mesh, &mesh->vertex_position,
  15796. mesh->vertex_normal.indices.data, mesh->vertex_normal.indices.count,
  15797. mesh->vertex_normal.values.data, mesh->vertex_normal.values.count);
  15798. if (surface->flip_normals) {
  15799. ufbxi_nounroll ufbxi_for_list(ufbx_vec3, normal, mesh->vertex_normal.values) {
  15800. normal->x *= -1.0f;
  15801. normal->y *= -1.0f;
  15802. normal->z *= -1.0f;
  15803. }
  15804. }
  15805. tc->imp = ufbxi_push(&tc->result, ufbxi_mesh_imp, 1);
  15806. ufbxi_check_err(&tc->error, tc->imp);
  15807. ufbxi_patch_mesh_reals(mesh);
  15808. ufbxi_init_ref(&tc->imp->refcount, UFBXI_MESH_IMP_MAGIC, &(ufbxi_get_imp(ufbxi_scene_imp, surface->element.scene))->refcount);
  15809. tc->imp->magic = UFBXI_MESH_IMP_MAGIC;
  15810. tc->imp->mesh = tc->mesh;
  15811. tc->imp->ator = tc->ator_result;
  15812. tc->imp->result_buf = tc->result;
  15813. tc->imp->mesh.subdivision_evaluated = true;
  15814. return 1;
  15815. }
  15816. #endif
  15817. // -- Topology
  15818. #if UFBXI_FEATURE_KD
  15819. typedef struct {
  15820. ufbx_real split;
  15821. uint32_t index;
  15822. uint32_t slow_left;
  15823. uint32_t slow_right;
  15824. uint32_t slow_end;
  15825. } ufbxi_kd_node;
  15826. typedef struct {
  15827. ufbx_face face;
  15828. ufbx_vertex_vec3 positions;
  15829. ufbx_vec3 axes[3];
  15830. ufbxi_kd_node kd_nodes[1 << (UFBXI_KD_FAST_DEPTH + 1)];
  15831. uint32_t *kd_indices;
  15832. // Temporary
  15833. ufbx_vec3 cur_axis_dir;
  15834. ufbx_face cur_face;
  15835. } ufbxi_ngon_context;
  15836. typedef struct {
  15837. ufbx_real min_t[2];
  15838. ufbx_real max_t[2];
  15839. ufbx_vec2 points[3];
  15840. uint32_t indices[3];
  15841. } ufbxi_kd_triangle;
  15842. ufbxi_forceinline static ufbx_vec2 ufbxi_ngon_project(ufbxi_ngon_context *nc, ufbx_vec3 point)
  15843. {
  15844. ufbx_vec2 p;
  15845. p.x = ufbxi_dot3(nc->axes[0], point);
  15846. p.y = ufbxi_dot3(nc->axes[1], point);
  15847. return p;
  15848. }
  15849. ufbxi_forceinline static ufbx_real ufbxi_orient2d(ufbx_vec2 a, ufbx_vec2 b, ufbx_vec2 c)
  15850. {
  15851. return (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x);
  15852. }
  15853. ufbxi_forceinline static bool ufbxi_kd_check_point(ufbxi_ngon_context *nc, const ufbxi_kd_triangle *tri, uint32_t index, ufbx_vec3 point)
  15854. {
  15855. if (index == tri->indices[0] || index == tri->indices[1] || index == tri->indices[2]) return false;
  15856. ufbx_vec2 p = ufbxi_ngon_project(nc, point);
  15857. ufbx_real u = ufbxi_orient2d(p, tri->points[0], tri->points[1]);
  15858. ufbx_real v = ufbxi_orient2d(p, tri->points[1], tri->points[2]);
  15859. ufbx_real w = ufbxi_orient2d(p, tri->points[2], tri->points[0]);
  15860. if (u <= 0.0f && v <= 0.0f && w <= 0.0f) return true;
  15861. if (u >= 0.0f && v >= 0.0f && w >= 0.0f) return true;
  15862. return false;
  15863. }
  15864. ufbxi_noinline static bool ufbxi_kd_check_slow(ufbxi_ngon_context *nc, const ufbxi_kd_triangle *tri, uint32_t begin, uint32_t count, uint32_t axis)
  15865. {
  15866. ufbx_vertex_vec3 pos = nc->positions;
  15867. uint32_t *kd_indices = nc->kd_indices;
  15868. while (count > 0) {
  15869. uint32_t num_left = count / 2;
  15870. uint32_t begin_right = begin + num_left + 1;
  15871. uint32_t num_right = count - (num_left + 1);
  15872. uint32_t index = kd_indices[begin + num_left];
  15873. ufbx_vec3 point = pos.values.data[pos.indices.data[nc->face.index_begin + index]];
  15874. ufbx_real split = ufbxi_dot3(point, nc->axes[axis]);
  15875. bool hit_left = tri->min_t[axis] <= split;
  15876. bool hit_right = tri->max_t[axis] >= split;
  15877. if (hit_left && hit_right) {
  15878. if (ufbxi_kd_check_point(nc, tri, index, point)) {
  15879. return true;
  15880. }
  15881. if (ufbxi_kd_check_slow(nc, tri, begin_right, num_right, axis ^ 1)) {
  15882. return true;
  15883. }
  15884. }
  15885. axis ^= 1;
  15886. if (hit_left) {
  15887. count = num_left;
  15888. } else {
  15889. begin = begin_right;
  15890. count = num_right;
  15891. }
  15892. }
  15893. return false;
  15894. }
  15895. ufbxi_noinline static bool ufbxi_kd_check_fast(ufbxi_ngon_context *nc, const ufbxi_kd_triangle *tri, uint32_t kd_index, uint32_t axis, uint32_t depth)
  15896. {
  15897. ufbx_vertex_vec3 pos = nc->positions;
  15898. for (;;) {
  15899. ufbxi_kd_node node = nc->kd_nodes[kd_index];
  15900. if (node.slow_end == 0) return false;
  15901. bool hit_left = tri->min_t[axis] <= node.split;
  15902. bool hit_right = tri->max_t[axis] >= node.split;
  15903. uint32_t side = hit_left ? 0 : 1;
  15904. uint32_t child_kd_index = kd_index * 2 + 1 + side;
  15905. if (hit_left && hit_right) {
  15906. // Check for the point on the split plane
  15907. ufbx_vec3 point = pos.values.data[pos.indices.data[nc->face.index_begin + node.index]];
  15908. if(ufbxi_kd_check_point(nc, tri, node.index, point)) {
  15909. return true;
  15910. }
  15911. // Recurse always to the right if we hit both sides
  15912. if (depth + 1 == UFBXI_KD_FAST_DEPTH) {
  15913. if (ufbxi_kd_check_slow(nc, tri, node.slow_right, node.slow_end - node.slow_right, axis ^ 1)) {
  15914. return true;
  15915. }
  15916. } else {
  15917. if (ufbxi_kd_check_fast(nc, tri, child_kd_index + 1, axis ^ 1, depth + 1)) {
  15918. return true;
  15919. }
  15920. }
  15921. }
  15922. depth++;
  15923. axis ^= 1;
  15924. kd_index = child_kd_index;
  15925. if (depth == UFBXI_KD_FAST_DEPTH) {
  15926. if (hit_left) {
  15927. return ufbxi_kd_check_slow(nc, tri, node.slow_left, node.slow_right - node.slow_left, axis);
  15928. } else {
  15929. return ufbxi_kd_check_slow(nc, tri, node.slow_right, node.slow_end - node.slow_right, axis);
  15930. }
  15931. }
  15932. }
  15933. }
  15934. ufbxi_noinline static bool ufbxi_kd_index_less(void *user, const void *va, const void *vb)
  15935. {
  15936. ufbxi_ngon_context *nc = (ufbxi_ngon_context*)user;
  15937. ufbx_vertex_vec3 *pos = &nc->positions;
  15938. const uint32_t a = *(const uint32_t*)va, b = *(const uint32_t*)vb;
  15939. ufbx_real da = ufbxi_dot3(nc->cur_axis_dir, pos->values.data[pos->indices.data[nc->cur_face.index_begin + a]]);
  15940. ufbx_real db = ufbxi_dot3(nc->cur_axis_dir, pos->values.data[pos->indices.data[nc->cur_face.index_begin + b]]);
  15941. return da < db;
  15942. }
  15943. ufbxi_noinline static void ufbxi_kd_build(ufbxi_ngon_context *nc, uint32_t *indices, uint32_t *tmp, uint32_t num, uint32_t axis, uint32_t fast_index, uint32_t depth)
  15944. {
  15945. if (num == 0) return;
  15946. ufbx_vertex_vec3 pos = nc->positions;
  15947. ufbx_vec3 axis_dir = nc->axes[axis];
  15948. ufbx_face face = nc->face;
  15949. nc->cur_axis_dir = axis_dir;
  15950. nc->cur_face = face;
  15951. // Sort the remaining indices based on the axis
  15952. ufbxi_stable_sort(sizeof(uint32_t), 16, indices, tmp, num, &ufbxi_kd_index_less, nc);
  15953. uint32_t num_left = num / 2;
  15954. uint32_t begin_right = num_left + 1;
  15955. uint32_t num_right = num - begin_right;
  15956. uint32_t dst_right = num_left + 1;
  15957. if (depth < UFBXI_KD_FAST_DEPTH) {
  15958. uint32_t skip_left = 1u << (UFBXI_KD_FAST_DEPTH - depth - 1);
  15959. dst_right = dst_right > skip_left ? dst_right - skip_left : 0;
  15960. uint32_t index = indices[num_left];
  15961. ufbxi_kd_node *kd = &nc->kd_nodes[fast_index];
  15962. kd->split = ufbxi_dot3(axis_dir, pos.values.data[pos.indices.data[face.index_begin + index]]);
  15963. kd->index = index;
  15964. if (depth + 1 == UFBXI_KD_FAST_DEPTH) {
  15965. kd->slow_left = (uint32_t)(indices - nc->kd_indices);
  15966. kd->slow_right = kd->slow_left + num_left;
  15967. kd->slow_end = kd->slow_right + num_right;
  15968. } else {
  15969. kd->slow_left = UINT32_MAX;
  15970. kd->slow_right = UINT32_MAX;
  15971. kd->slow_end = UINT32_MAX;
  15972. }
  15973. }
  15974. uint32_t child_fast = fast_index * 2 + 1;
  15975. ufbxi_kd_build(nc, indices, tmp, num_left, axis ^ 1, child_fast + 0, depth + 1);
  15976. if (dst_right != begin_right) {
  15977. memmove(indices + dst_right, indices + begin_right, num_right * sizeof(uint32_t));
  15978. }
  15979. ufbxi_kd_build(nc, indices + dst_right, tmp, num_right, axis ^ 1, child_fast + 1, depth + 1);
  15980. }
  15981. #endif
  15982. #if UFBXI_FEATURE_TRIANGULATION
  15983. ufbxi_noinline static uint32_t ufbxi_triangulate_ngon(ufbxi_ngon_context *nc, uint32_t *indices, uint32_t num_indices)
  15984. {
  15985. ufbx_face face = nc->face;
  15986. // Form an orthonormal basis to project the polygon into a 2D plane
  15987. ufbx_vec3 normal = ufbx_get_weighted_face_normal(&nc->positions, face);
  15988. ufbx_real len = ufbxi_length3(normal);
  15989. if (len > 1e-20f) {
  15990. normal = ufbxi_mul3(normal, 1.0f / len);
  15991. } else {
  15992. normal.x = 1.0f;
  15993. normal.y = 0.0f;
  15994. normal.z = 0.0f;
  15995. }
  15996. ufbx_vec3 axis;
  15997. if (normal.x*normal.x < 0.5f) {
  15998. axis.x = 1.0f;
  15999. axis.y = 0.0f;
  16000. axis.z = 0.0f;
  16001. } else {
  16002. axis.x = 0.0f;
  16003. axis.y = 1.0f;
  16004. axis.z = 0.0f;
  16005. }
  16006. nc->axes[0] = ufbxi_slow_normalized_cross3(&axis, &normal);
  16007. nc->axes[1] = ufbxi_slow_normalized_cross3(&normal, &nc->axes[0]);
  16008. nc->axes[2] = normal;
  16009. uint32_t *kd_indices = indices;
  16010. nc->kd_indices = kd_indices;
  16011. uint32_t *kd_tmp = indices + face.num_indices;
  16012. ufbx_vertex_vec3 pos = nc->positions;
  16013. // Collect all the reflex corners for intersection testing.
  16014. uint32_t num_kd_indices = 0;
  16015. {
  16016. ufbx_vec2 a = ufbxi_ngon_project(nc, pos.values.data[pos.indices.data[face.index_begin + face.num_indices - 1]]);
  16017. ufbx_vec2 b = ufbxi_ngon_project(nc, pos.values.data[pos.indices.data[face.index_begin + 0]]);
  16018. for (uint32_t i = 0; i < face.num_indices; i++) {
  16019. uint32_t next = i + 1 < face.num_indices ? i + 1 : 0;
  16020. ufbx_vec2 c = ufbxi_ngon_project(nc, pos.values.data[pos.indices.data[face.index_begin + next]]);
  16021. if (ufbxi_orient2d(a, b, c) < 0.0f) {
  16022. kd_indices[num_kd_indices++] = i;
  16023. }
  16024. a = b;
  16025. b = c;
  16026. }
  16027. }
  16028. // Build a KD-tree out of the collected reflex vertices.
  16029. uint32_t num_skip_indices = (1u << (UFBXI_KD_FAST_DEPTH + 1)) - 1;
  16030. uint32_t kd_slow_indices = num_kd_indices > num_skip_indices ? num_kd_indices - num_skip_indices : 0;
  16031. ufbxi_ignore(kd_slow_indices);
  16032. ufbx_assert(kd_slow_indices + face.num_indices * 2 <= num_indices);
  16033. ufbxi_kd_build(nc, kd_indices, kd_tmp, num_kd_indices, 0, 0, 0);
  16034. uint32_t *edges = indices + num_indices - face.num_indices * 2;
  16035. // Initialize `edges` to be a connectivity structure where:
  16036. // `edges[2*i + 0]` is the prevous vertex of `i`
  16037. // `edges[2*i + 1]` is the next vertex of `i`
  16038. // When clipped we mark indices with the high bit (0x80000000)
  16039. for (uint32_t i = 0; i < face.num_indices; i++) {
  16040. edges[i*2 + 0] = i > 0 ? i - 1 : face.num_indices - 1;
  16041. edges[i*2 + 1] = i + 1 < face.num_indices ? i + 1 : 0;
  16042. }
  16043. // Core of the ear clipping algorithm.
  16044. // Iterate through the polygon corners looking for potential ears satisfying:
  16045. // - Angle must be less than 180deg
  16046. // - The triangle formed by the two edges must be contained within the polygon
  16047. // As these properties change only locally between modifications we only need
  16048. // to iterate the polygon once if we move backwards one step every time we clip an ear.
  16049. uint32_t indices_left = face.num_indices;
  16050. {
  16051. ufbxi_kd_triangle tri;
  16052. uint32_t ix = 1;
  16053. ufbx_vec2 a = ufbxi_ngon_project(nc, pos.values.data[pos.indices.data[face.index_begin + 0]]);
  16054. ufbx_vec2 b = ufbxi_ngon_project(nc, pos.values.data[pos.indices.data[face.index_begin + 1]]);
  16055. ufbx_vec2 c = ufbxi_ngon_project(nc, pos.values.data[pos.indices.data[face.index_begin + 2]]);
  16056. bool prev_was_reflex = false;
  16057. uint32_t num_steps = 0;
  16058. while (indices_left > 3) {
  16059. uint32_t prev = edges[ix*2 + 0];
  16060. uint32_t next = edges[ix*2 + 1];
  16061. if (ufbxi_orient2d(a, b, c) > 0.0f) {
  16062. tri.points[0] = a;
  16063. tri.points[1] = b;
  16064. tri.points[2] = c;
  16065. tri.indices[0] = prev;
  16066. tri.indices[1] = ix;
  16067. tri.indices[2] = next;
  16068. tri.min_t[0] = ufbxi_min_real(ufbxi_min_real(a.x, b.x), c.x);
  16069. tri.min_t[1] = ufbxi_min_real(ufbxi_min_real(a.y, b.y), c.y);
  16070. tri.max_t[0] = ufbxi_max_real(ufbxi_max_real(a.x, b.x), c.x);
  16071. tri.max_t[1] = ufbxi_max_real(ufbxi_max_real(a.y, b.y), c.y);
  16072. // If there is no reflex angle contained within the triangle formed
  16073. // by `{ a, b, c }` connect the vertices `a - c` (prev, next) directly.
  16074. if (!ufbxi_kd_check_fast(nc, &tri, 0, 0, 0)) {
  16075. // Mark as clipped
  16076. edges[ix*2 + 0] |= 0x80000000;
  16077. edges[ix*2 + 1] |= 0x80000000;
  16078. edges[next*2 + 0] = prev;
  16079. edges[prev*2 + 1] = next;
  16080. indices_left -= 1;
  16081. // Move backwards only if the previous was reflex as now it would
  16082. // cover a superset of the previous area, failing the intersection test.
  16083. if (prev_was_reflex) {
  16084. prev_was_reflex = false;
  16085. ix = prev;
  16086. b = a;
  16087. uint32_t prev_prev = edges[prev*2 + 0];
  16088. a = ufbxi_ngon_project(nc, pos.values.data[pos.indices.data[face.index_begin + prev_prev]]);
  16089. } else {
  16090. ix = next;
  16091. b = c;
  16092. uint32_t next_next = edges[next*2 + 1];
  16093. c = ufbxi_ngon_project(nc, pos.values.data[pos.indices.data[face.index_begin + next_next]]);
  16094. }
  16095. continue;
  16096. }
  16097. prev_was_reflex = false;
  16098. } else {
  16099. prev_was_reflex = true;
  16100. }
  16101. // Continue forward
  16102. ix = next;
  16103. a = b;
  16104. b = c;
  16105. next = edges[next*2 + 1];
  16106. c = ufbxi_ngon_project(nc, pos.values.data[pos.indices.data[face.index_begin + next]]);
  16107. num_steps++;
  16108. // If we have walked around the entire polygon it is irregular and
  16109. // ear cutting won't find any more triangles.
  16110. // TODO: This could be stricter?
  16111. if (num_steps >= face.num_indices*2) break;
  16112. }
  16113. // Fallback: Cut non-ears until the polygon is completed.
  16114. // TODO: Could do something better here..
  16115. while (indices_left > 3) {
  16116. uint32_t prev = edges[ix*2 + 0];
  16117. uint32_t next = edges[ix*2 + 1];
  16118. // Mark as clipped
  16119. edges[ix*2 + 0] |= 0x80000000;
  16120. edges[ix*2 + 1] |= 0x80000000;
  16121. edges[prev*2 + 1] = next;
  16122. edges[next*2 + 0] = prev;
  16123. indices_left -= 1;
  16124. ix = next;
  16125. }
  16126. // Now we have a single triangle left at `ix`.
  16127. edges[ix*2 + 0] |= 0x80000000;
  16128. edges[ix*2 + 1] |= 0x80000000;
  16129. }
  16130. // Expand the adjacency information `edges` into proper triangles.
  16131. // Care needs to be taken here as both refer to the same memory area:
  16132. // The last 4 triangles may overlap in source and destination so we write
  16133. // them to a stack buffer and copy them over in the end.
  16134. uint32_t max_triangles = face.num_indices - 2;
  16135. uint32_t num_triangles = 0, num_last_triangles = 0;
  16136. uint32_t last_triangles[4*3];
  16137. uint32_t index_begin = face.index_begin;
  16138. for (uint32_t ix = 0; ix < face.num_indices; ix++) {
  16139. uint32_t prev = edges[ix*2 + 0];
  16140. uint32_t next = edges[ix*2 + 1];
  16141. if (!(prev & 0x80000000)) continue;
  16142. uint32_t *dst = indices + num_triangles * 3;
  16143. if (num_triangles + 4 >= max_triangles) {
  16144. dst = last_triangles + num_last_triangles * 3;
  16145. num_last_triangles++;
  16146. }
  16147. dst[0] = index_begin + (prev & 0x7fffffff);
  16148. dst[1] = index_begin + ix;
  16149. dst[2] = index_begin + (next & 0x7fffffff);
  16150. num_triangles++;
  16151. }
  16152. // Copy over the last triangles
  16153. ufbx_assert(num_triangles == max_triangles);
  16154. memcpy(indices + (max_triangles - num_last_triangles) * 3, last_triangles, num_last_triangles * 3 * sizeof(uint32_t));
  16155. return num_triangles;
  16156. }
  16157. #endif
  16158. static int ufbxi_cmp_topo_index_prev_next(const void *va, const void *vb)
  16159. {
  16160. const ufbx_topo_edge *a = (const ufbx_topo_edge*)va, *b = (const ufbx_topo_edge*)vb;
  16161. if ((int32_t)a->prev != (int32_t)b->prev) return (int32_t)a->prev < (int32_t)b->prev ? -1 : +1;
  16162. if ((int32_t)a->next != (int32_t)b->next) return (int32_t)a->next < (int32_t)b->next ? -1 : +1;
  16163. return 0;
  16164. }
  16165. static int ufbxi_cmp_topo_index_index(const void *va, const void *vb)
  16166. {
  16167. const ufbx_topo_edge *a = (const ufbx_topo_edge*)va, *b = (const ufbx_topo_edge*)vb;
  16168. if ((int32_t)a->index != (int32_t)b->index) return (int32_t)a->index < (int32_t)b->index ? -1 : +1;
  16169. return 0;
  16170. }
  16171. ufbxi_noinline static void ufbxi_compute_topology(const ufbx_mesh *mesh, ufbx_topo_edge *topo)
  16172. {
  16173. size_t num_indices = mesh->num_indices;
  16174. // Temporarily use `prev` and `next` for vertices
  16175. for (uint32_t fi = 0; fi < mesh->num_faces; fi++) {
  16176. ufbx_face face = mesh->faces.data[fi];
  16177. for (uint32_t pi = 0; pi < face.num_indices; pi++) {
  16178. ufbx_topo_edge *te = &topo[face.index_begin + pi];
  16179. uint32_t ni = (pi + 1) % face.num_indices;
  16180. uint32_t va = mesh->vertex_indices.data[face.index_begin + pi];
  16181. uint32_t vb = mesh->vertex_indices.data[face.index_begin + ni];
  16182. if (vb < va) {
  16183. uint32_t vt = va; va = vb; vb = vt;
  16184. }
  16185. te->index = face.index_begin + pi;
  16186. te->twin = UFBX_NO_INDEX;
  16187. te->edge = UFBX_NO_INDEX;
  16188. te->prev = va;
  16189. te->next = vb;
  16190. te->face = fi;
  16191. te->flags = (ufbx_topo_flags)0;
  16192. }
  16193. }
  16194. // TODO: Macro unstable/non allocating sort
  16195. qsort(topo, num_indices, sizeof(ufbx_topo_edge), &ufbxi_cmp_topo_index_prev_next);
  16196. if (mesh->edges.data) {
  16197. for (uint32_t ei = 0; ei < mesh->num_edges; ei++) {
  16198. ufbx_edge edge = mesh->edges.data[ei];
  16199. uint32_t va = mesh->vertex_indices.data[edge.a];
  16200. uint32_t vb = mesh->vertex_indices.data[edge.b];
  16201. if (vb < va) {
  16202. uint32_t vt = va; va = vb; vb = vt;
  16203. }
  16204. size_t ix = num_indices;
  16205. ufbxi_macro_lower_bound_eq(ufbx_topo_edge, 32, &ix, topo, 0, num_indices,
  16206. (a->prev == va ? a->next < vb : a->prev < va), (a->prev == va && a->next == vb));
  16207. for (; ix < num_indices && topo[ix].prev == va && topo[ix].next == vb; ix++) {
  16208. topo[ix].edge = ei;
  16209. }
  16210. }
  16211. }
  16212. // Connect paired edges
  16213. for (size_t i0 = 0; i0 < num_indices; ) {
  16214. size_t i1 = i0;
  16215. uint32_t a = topo[i0].prev, b = topo[i0].next;
  16216. while (i1 + 1 < num_indices && topo[i1 + 1].prev == a && topo[i1 + 1].next == b) i1++;
  16217. if (i1 == i0 + 1) {
  16218. topo[i0].twin = topo[i1].index;
  16219. topo[i1].twin = topo[i0].index;
  16220. } else if (i1 > i0 + 1) {
  16221. for (size_t i = i0; i <= i1; i++) {
  16222. topo[i].flags = (ufbx_topo_flags)(topo[i].flags | UFBX_TOPO_NON_MANIFOLD);
  16223. }
  16224. }
  16225. i0 = i1 + 1;
  16226. }
  16227. // TODO: Macro unstable/non allocating sort
  16228. qsort(topo, num_indices, sizeof(ufbx_topo_edge), &ufbxi_cmp_topo_index_index);
  16229. // Fix `prev` and `next` to the actual index values
  16230. for (uint32_t fi = 0; fi < mesh->num_faces; fi++) {
  16231. ufbx_face face = mesh->faces.data[fi];
  16232. for (uint32_t i = 0; i < face.num_indices; i++) {
  16233. ufbx_topo_edge *to = &topo[face.index_begin + i];
  16234. to->prev = (uint32_t)(face.index_begin + (i + face.num_indices - 1) % face.num_indices);
  16235. to->next = (uint32_t)(face.index_begin + (i + 1) % face.num_indices);
  16236. }
  16237. }
  16238. }
  16239. static bool ufbxi_is_edge_smooth(const ufbx_mesh *mesh, const ufbx_topo_edge *topo, size_t num_topo, uint32_t index, bool assume_smooth)
  16240. {
  16241. ufbxi_ignore(num_topo);
  16242. ufbx_assert((size_t)index < num_topo);
  16243. if (mesh->edge_smoothing.data) {
  16244. uint32_t edge = topo[index].edge;
  16245. if (edge != UFBX_NO_INDEX && mesh->edge_smoothing.data[edge]) return true;
  16246. }
  16247. if (mesh->face_smoothing.data) {
  16248. if (mesh->face_smoothing.data[topo[index].face]) return true;
  16249. uint32_t twin = topo[index].twin;
  16250. if (twin != UFBX_NO_INDEX) {
  16251. if (mesh->face_smoothing.data[topo[twin].face]) return true;
  16252. }
  16253. }
  16254. if (!mesh->edge_smoothing.data && !mesh->face_smoothing.data && mesh->vertex_normal.exists) {
  16255. uint32_t twin = topo[index].twin;
  16256. if (twin != UFBX_NO_INDEX && mesh->vertex_normal.exists) {
  16257. ufbx_assert((size_t)twin < num_topo);
  16258. ufbx_vec3 a0 = ufbx_get_vertex_vec3(&mesh->vertex_normal, index);
  16259. ufbx_vec3 a1 = ufbx_get_vertex_vec3(&mesh->vertex_normal, topo[index].next);
  16260. ufbx_vec3 b0 = ufbx_get_vertex_vec3(&mesh->vertex_normal, topo[twin].next);
  16261. ufbx_vec3 b1 = ufbx_get_vertex_vec3(&mesh->vertex_normal, twin);
  16262. if (a0.x == b0.x && a0.y == b0.y && a0.z == b0.z) return true;
  16263. if (a1.x == b1.x && a1.y == b1.y && a1.z == b1.z) return true;
  16264. }
  16265. } else if (assume_smooth) {
  16266. return true;
  16267. }
  16268. return false;
  16269. }
  16270. // -- Subdivision
  16271. #if UFBXI_FEATURE_SUBDIVISION
  16272. typedef struct {
  16273. const void *data;
  16274. ufbx_real weight;
  16275. } ufbxi_subdivide_input;
  16276. typedef int ufbxi_subdivide_sum_fn(void *user, void *output, const ufbxi_subdivide_input *inputs, size_t num_inputs);
  16277. typedef struct {
  16278. ufbxi_subdivide_sum_fn *sum_fn;
  16279. void *sum_user;
  16280. const void *values;
  16281. size_t stride;
  16282. const uint32_t *indices;
  16283. bool check_split_data;
  16284. bool ignore_indices;
  16285. ufbx_subdivision_boundary boundary;
  16286. } ufbxi_subdivide_layer_input;
  16287. typedef struct {
  16288. void *values;
  16289. size_t num_values;
  16290. uint32_t *indices;
  16291. size_t num_indices;
  16292. bool unique_per_vertex;
  16293. } ufbxi_subdivide_layer_output;
  16294. typedef struct {
  16295. ufbx_subdivision_weight *weights;
  16296. size_t num_weights;
  16297. } ufbxi_subdivision_vertex_weights;
  16298. typedef struct {
  16299. ufbxi_mesh_imp *imp;
  16300. ufbx_error error;
  16301. ufbx_mesh *src_mesh_ptr;
  16302. ufbx_mesh src_mesh;
  16303. ufbx_mesh dst_mesh;
  16304. ufbx_topo_edge *topo;
  16305. size_t num_topo;
  16306. ufbx_subdivide_opts opts;
  16307. ufbxi_allocator ator_result;
  16308. ufbxi_allocator ator_tmp;
  16309. ufbxi_buf result;
  16310. ufbxi_buf tmp;
  16311. ufbxi_buf source;
  16312. ufbxi_subdivide_input *inputs;
  16313. size_t inputs_cap;
  16314. ufbx_real *tmp_vertex_weights;
  16315. ufbx_subdivision_weight *tmp_weights;
  16316. size_t total_weights;
  16317. size_t max_vertex_weights;
  16318. } ufbxi_subdivide_context;
  16319. static int ufbxi_subdivide_sum_real(void *user, void *output, const ufbxi_subdivide_input *inputs, size_t num_inputs)
  16320. {
  16321. (void)user;
  16322. ufbx_real dst = 0.0f;
  16323. ufbxi_nounroll for (size_t i = 0; i != num_inputs; i++) {
  16324. ufbx_real src = *(const ufbx_real*)inputs[i].data;
  16325. ufbx_real weight = inputs[i].weight;
  16326. dst += src * weight;
  16327. }
  16328. *(ufbx_real*)output = dst;
  16329. return 1;
  16330. }
  16331. static int ufbxi_subdivide_sum_vec2(void *user, void *output, const ufbxi_subdivide_input *inputs, size_t num_inputs)
  16332. {
  16333. (void)user;
  16334. ufbx_vec2 dst = { 0 };
  16335. ufbxi_nounroll for (size_t i = 0; i != num_inputs; i++) {
  16336. const ufbx_vec2 *src = (const ufbx_vec2*)inputs[i].data;
  16337. ufbx_real weight = inputs[i].weight;
  16338. dst.x += src->x * weight;
  16339. dst.y += src->y * weight;
  16340. }
  16341. *(ufbx_vec2*)output = dst;
  16342. return 1;
  16343. }
  16344. static int ufbxi_subdivide_sum_vec3(void *user, void *output, const ufbxi_subdivide_input *inputs, size_t num_inputs)
  16345. {
  16346. (void)user;
  16347. ufbx_vec3 dst = { 0 };
  16348. ufbxi_nounroll for (size_t i = 0; i != num_inputs; i++) {
  16349. const ufbx_vec3 *src = (const ufbx_vec3*)inputs[i].data;
  16350. ufbx_real weight = inputs[i].weight;
  16351. dst.x += src->x * weight;
  16352. dst.y += src->y * weight;
  16353. dst.z += src->z * weight;
  16354. }
  16355. *(ufbx_vec3*)output = dst;
  16356. return 1;
  16357. }
  16358. static int ufbxi_subdivide_sum_vec4(void *user, void *output, const ufbxi_subdivide_input *inputs, size_t num_inputs)
  16359. {
  16360. (void)user;
  16361. ufbx_vec4 dst = { 0 };
  16362. ufbxi_nounroll for (size_t i = 0; i != num_inputs; i++) {
  16363. const ufbx_vec4 *src = (const ufbx_vec4*)inputs[i].data;
  16364. ufbx_real weight = inputs[i].weight;
  16365. dst.x += src->x * weight;
  16366. dst.y += src->y * weight;
  16367. dst.z += src->z * weight;
  16368. dst.w += src->w * weight;
  16369. }
  16370. *(ufbx_vec4*)output = dst;
  16371. return 1;
  16372. }
  16373. static ufbxi_noinline int ufbxi_cmp_subdivision_weight(const void *va, const void *vb)
  16374. {
  16375. ufbx_subdivision_weight a = *(const ufbx_subdivision_weight*)va, b = *(const ufbx_subdivision_weight*)vb;
  16376. ufbxi_dev_assert(a.index != b.index);
  16377. if (a.weight != b.weight) return a.weight > b.weight ? -1 : +1;
  16378. return a.index < b.index ? -1 : +1;
  16379. }
  16380. static int ufbxi_subdivide_sum_vertex_weights(void *user, void *output, const ufbxi_subdivide_input *inputs, size_t num_inputs)
  16381. {
  16382. ufbxi_subdivide_context *sc = (ufbxi_subdivide_context*)user;
  16383. ufbx_real *vertex_weights = sc->tmp_vertex_weights;
  16384. ufbx_subdivision_weight *tmp_weights = sc->tmp_weights;
  16385. size_t num_weights = 0;
  16386. ufbxi_nounroll for (size_t input_ix = 0; input_ix != num_inputs; input_ix++) {
  16387. ufbxi_subdivision_vertex_weights src = *(const ufbxi_subdivision_vertex_weights*)inputs[input_ix].data;
  16388. ufbx_real input_weight = inputs[input_ix].weight;
  16389. for (size_t weight_ix = 0; weight_ix < src.num_weights; weight_ix++) {
  16390. ufbx_real weight = input_weight * src.weights[weight_ix].weight;
  16391. if (weight < 1.175494351e-38f) continue;
  16392. uint32_t vx = src.weights[weight_ix].index;
  16393. ufbxi_dev_assert(vx < sc->src_mesh.num_vertices);
  16394. ufbx_real prev = vertex_weights[vx];
  16395. vertex_weights[vx] = prev + weight;
  16396. if (prev == 0.0f) {
  16397. tmp_weights[num_weights++].index = vx;
  16398. }
  16399. }
  16400. }
  16401. ufbxi_nounroll for (size_t i = 0; i != num_weights; i++) {
  16402. uint32_t vx = tmp_weights[i].index;
  16403. tmp_weights[i].weight = vertex_weights[vx];
  16404. vertex_weights[vx] = 0.0f;
  16405. }
  16406. qsort(tmp_weights, num_weights, sizeof(ufbx_subdivision_weight), ufbxi_cmp_subdivision_weight);
  16407. if (num_weights > sc->max_vertex_weights) {
  16408. num_weights = sc->max_vertex_weights;
  16409. // Normalize weights
  16410. ufbx_real prefix_weight = 0.0f;
  16411. ufbxi_nounroll for (size_t i = 0; i != num_weights; i++) {
  16412. prefix_weight += tmp_weights[i].weight;
  16413. }
  16414. ufbxi_nounroll for (size_t i = 0; i != num_weights; i++) {
  16415. tmp_weights[i].weight /= prefix_weight;
  16416. }
  16417. }
  16418. sc->total_weights += num_weights;
  16419. ufbx_subdivision_weight *weights = ufbxi_push_copy(&sc->tmp, ufbx_subdivision_weight, num_weights, tmp_weights);
  16420. ufbxi_check_err(&sc->error, weights);
  16421. ufbxi_subdivision_vertex_weights *dst = (ufbxi_subdivision_vertex_weights*)output;
  16422. dst->weights = weights;
  16423. dst->num_weights = num_weights;
  16424. return 1;
  16425. }
  16426. static ufbxi_subdivide_sum_fn *ufbxi_real_sum_fns[] = {
  16427. &ufbxi_subdivide_sum_real,
  16428. &ufbxi_subdivide_sum_vec2,
  16429. &ufbxi_subdivide_sum_vec3,
  16430. &ufbxi_subdivide_sum_vec4,
  16431. };
  16432. ufbxi_noinline static bool ufbxi_is_edge_split(const ufbxi_subdivide_layer_input *input, const ufbx_topo_edge *topo, uint32_t index)
  16433. {
  16434. uint32_t twin = topo[index].twin;
  16435. if (twin != UFBX_NO_INDEX) {
  16436. uint32_t a0 = input->indices[index];
  16437. uint32_t a1 = input->indices[topo[index].next];
  16438. uint32_t b0 = input->indices[topo[twin].next];
  16439. uint32_t b1 = input->indices[twin];
  16440. if (a0 == b0 && a1 == b1) return false;
  16441. if (!input->check_split_data) return true;
  16442. size_t stride = input->stride;
  16443. char *da0 = (char*)input->values + a0 * stride;
  16444. char *da1 = (char*)input->values + a1 * stride;
  16445. char *db0 = (char*)input->values + b0 * stride;
  16446. char *db1 = (char*)input->values + b1 * stride;
  16447. if (!memcmp(da0, db0, stride) && !memcmp(da1, db1, stride)) return false;
  16448. return true;
  16449. }
  16450. return false;
  16451. }
  16452. static ufbx_real ufbxi_edge_crease(const ufbx_mesh *mesh, bool split, const ufbx_topo_edge *topo, uint32_t index)
  16453. {
  16454. if (topo[index].twin == UFBX_NO_INDEX) return 1.0f;
  16455. if (split) return 1.0f;
  16456. if (mesh->edge_crease.data && topo[index].edge != UFBX_NO_INDEX) return mesh->edge_crease.data[topo[index].edge] * (ufbx_real)10.0;
  16457. return 0.0f;
  16458. }
  16459. static ufbxi_noinline int ufbxi_subdivide_layer(ufbxi_subdivide_context *sc, ufbxi_subdivide_layer_output *output, const ufbxi_subdivide_layer_input *input)
  16460. {
  16461. ufbx_subdivision_boundary boundary = input->boundary;
  16462. const ufbx_mesh *mesh = &sc->src_mesh;
  16463. const ufbx_topo_edge *topo = sc->topo;
  16464. size_t num_topo = sc->num_topo;
  16465. uint32_t *edge_indices = ufbxi_push(&sc->result, uint32_t, mesh->num_indices);
  16466. ufbxi_check_err(&sc->error, edge_indices);
  16467. size_t num_edge_values = 0;
  16468. for (uint32_t ix = 0; ix < (uint32_t)mesh->num_indices; ix++) {
  16469. uint32_t twin = topo[ix].twin;
  16470. if (twin < ix && !ufbxi_is_edge_split(input, topo, ix)) {
  16471. edge_indices[ix] = edge_indices[twin];
  16472. } else {
  16473. edge_indices[ix] = (uint32_t)num_edge_values++;
  16474. }
  16475. }
  16476. size_t stride = input->stride;
  16477. size_t num_initial_values = (num_edge_values + mesh->num_faces + mesh->num_indices);
  16478. char *values = (char*)ufbxi_push_size(&sc->tmp, stride, num_initial_values);
  16479. ufbxi_check_err(&sc->error, values);
  16480. char *face_values = values;
  16481. char *edge_values = face_values + mesh->num_faces * stride;
  16482. char *vertex_values = edge_values + num_edge_values * stride;
  16483. size_t num_vertex_values = 0;
  16484. uint32_t *vertex_indices = ufbxi_push(&sc->result, uint32_t, mesh->num_indices);
  16485. ufbxi_check_err(&sc->error, vertex_indices);
  16486. size_t min_inputs = ufbxi_max_sz(32, mesh->max_face_triangles + 2);
  16487. ufbxi_check_err(&sc->error, ufbxi_grow_array(&sc->ator_tmp, &sc->inputs, &sc->inputs_cap, min_inputs));
  16488. ufbxi_subdivide_input *inputs = sc->inputs;
  16489. // Assume initially unique per vertex, remove if not the case
  16490. output->unique_per_vertex = true;
  16491. bool sharp_corners = false;
  16492. bool sharp_splits = false;
  16493. bool sharp_all = false;
  16494. switch (boundary) {
  16495. case UFBX_SUBDIVISION_BOUNDARY_DEFAULT:
  16496. case UFBX_SUBDIVISION_BOUNDARY_SHARP_NONE:
  16497. case UFBX_SUBDIVISION_BOUNDARY_LEGACY:
  16498. // All smooth
  16499. break;
  16500. case UFBX_SUBDIVISION_BOUNDARY_SHARP_CORNERS:
  16501. sharp_corners = true;
  16502. break;
  16503. case UFBX_SUBDIVISION_BOUNDARY_SHARP_BOUNDARY:
  16504. sharp_corners = true;
  16505. sharp_splits = true;
  16506. break;
  16507. case UFBX_SUBDIVISION_BOUNDARY_SHARP_INTERIOR:
  16508. sharp_all = true;
  16509. break;
  16510. default:
  16511. ufbx_assert(0 && "Bad boundary mode");
  16512. break;
  16513. }
  16514. ufbxi_subdivide_sum_fn *sum_fn = input->sum_fn;
  16515. void *sum_user = input->sum_user;
  16516. // Mark unused indices as `UFBX_NO_INDEX` so we can patch non-manifold
  16517. ufbxi_nounroll for (size_t i = 0; i < mesh->num_indices; i++) {
  16518. vertex_indices[i] = UFBX_NO_INDEX;
  16519. }
  16520. // Face points
  16521. for (size_t fi = 0; fi < mesh->num_faces; fi++) {
  16522. ufbx_face face = mesh->faces.data[fi];
  16523. char *dst = face_values + fi * stride;
  16524. ufbx_real weight = 1.0f / (ufbx_real)face.num_indices;
  16525. for (uint32_t ci = 0; ci < face.num_indices; ci++) {
  16526. uint32_t ix = face.index_begin + ci;
  16527. inputs[ci].data = (const char*)input->values + input->indices[ix] * stride;
  16528. inputs[ci].weight = weight;
  16529. }
  16530. ufbxi_check_err(&sc->error, sum_fn(sum_user, dst, inputs, face.num_indices));
  16531. }
  16532. // Edge points
  16533. for (uint32_t ix = 0; ix < mesh->num_indices; ix++) {
  16534. char *dst = edge_values + edge_indices[ix] * stride;
  16535. uint32_t twin = topo[ix].twin;
  16536. bool split = ufbxi_is_edge_split(input, topo, ix);
  16537. if (split || (topo[ix].flags & UFBX_TOPO_NON_MANIFOLD) != 0) {
  16538. output->unique_per_vertex = false;
  16539. }
  16540. ufbx_real crease = 0.0f;
  16541. if (split || twin == UFBX_NO_INDEX) {
  16542. crease = 1.0f;
  16543. } else if (topo[ix].edge != UFBX_NO_INDEX && mesh->edge_crease.data) {
  16544. crease = mesh->edge_crease.data[topo[ix].edge] * (ufbx_real)10.0;
  16545. }
  16546. if (sharp_all) crease = 1.0f;
  16547. const char *v0 = (const char*)input->values + input->indices[ix] * stride;
  16548. const char *v1 = (const char*)input->values + input->indices[topo[ix].next] * stride;
  16549. // TODO: Unify
  16550. if (twin < ix && !split) {
  16551. // Already calculated
  16552. } else if (crease <= 0.0f) {
  16553. const char *f0 = face_values + topo[ix].face * stride;
  16554. const char *f1 = face_values + topo[twin].face * stride;
  16555. inputs[0].data = v0;
  16556. inputs[0].weight = 0.25f;
  16557. inputs[1].data = v1;
  16558. inputs[1].weight = 0.25f;
  16559. inputs[2].data = f0;
  16560. inputs[2].weight = 0.25f;
  16561. inputs[3].data = f1;
  16562. inputs[3].weight = 0.25f;
  16563. ufbxi_check_err(&sc->error, sum_fn(sum_user, dst, inputs, 4));
  16564. } else if (crease >= 1.0f) {
  16565. inputs[0].data = v0;
  16566. inputs[0].weight = 0.5f;
  16567. inputs[1].data = v1;
  16568. inputs[1].weight = 0.5f;
  16569. ufbxi_check_err(&sc->error, sum_fn(sum_user, dst, inputs, 2));
  16570. } else if (crease < 1.0f) {
  16571. const char *f0 = face_values + topo[ix].face * stride;
  16572. const char *f1 = face_values + topo[twin].face * stride;
  16573. ufbx_real w0 = 0.25f + 0.25f * crease;
  16574. ufbx_real w1 = 0.25f - 0.25f * crease;
  16575. inputs[0].data = v0;
  16576. inputs[0].weight = w0;
  16577. inputs[1].data = v1;
  16578. inputs[1].weight = w0;
  16579. inputs[2].data = f0;
  16580. inputs[2].weight = w1;
  16581. inputs[3].data = f1;
  16582. inputs[3].weight = w1;
  16583. ufbxi_check_err(&sc->error, sum_fn(sum_user, dst, inputs, 4));
  16584. }
  16585. }
  16586. // Vertex points
  16587. for (size_t vi = 0; vi < mesh->num_vertices; vi++) {
  16588. uint32_t original_start = mesh->vertex_first_index.data[vi];
  16589. if (original_start == UFBX_NO_INDEX) continue;
  16590. // Find a topological boundary, or if not found a split edge
  16591. uint32_t start = original_start;
  16592. for (uint32_t cur = start;;) {
  16593. uint32_t prev = ufbx_topo_prev_vertex_edge(topo, num_topo, cur);
  16594. if (prev == UFBX_NO_INDEX) { start = cur; break; } // Topological boundary: Stop and use as start
  16595. if (ufbxi_is_edge_split(input, topo, prev)) start = cur; // Split edge: Consider as start
  16596. if (prev == original_start) break; // Loop: Stop, use original start or split if found
  16597. cur = prev;
  16598. }
  16599. original_start = start;
  16600. while (start != UFBX_NO_INDEX) {
  16601. if (start != original_start) {
  16602. output->unique_per_vertex = false;
  16603. }
  16604. uint32_t value_index = (uint32_t)num_vertex_values++;
  16605. char *dst = vertex_values + value_index * stride;
  16606. // We need to compute the average crease value and keep track of
  16607. // two creased edges, if there's more we use the corner rule that
  16608. // does not need the information.
  16609. ufbx_real total_crease = 0.0f;
  16610. size_t num_crease = 0;
  16611. size_t num_split = 0;
  16612. bool on_boundary = false;
  16613. bool non_manifold = false;
  16614. size_t crease_input_indices[2];
  16615. // At start we always have two edges and a single face
  16616. uint32_t start_prev = topo[start].prev;
  16617. uint32_t end_edge = topo[start_prev].twin;
  16618. size_t valence = 2;
  16619. non_manifold |= (topo[start].flags & UFBX_TOPO_NON_MANIFOLD) != 0;
  16620. non_manifold |= (topo[start_prev].flags & UFBX_TOPO_NON_MANIFOLD) != 0;
  16621. const char *v0 = (const char*)input->values + input->indices[start] * stride;
  16622. size_t num_inputs = 4;
  16623. {
  16624. const char *e0 = (const char*)input->values + input->indices[topo[start].next] * stride;
  16625. const char *e1 = (const char*)input->values + input->indices[start_prev] * stride;
  16626. const char *f0 = face_values + topo[start].face * stride;
  16627. inputs[0].data = v0;
  16628. inputs[1].data = e0;
  16629. inputs[2].data = e1;
  16630. inputs[3].data = f0;
  16631. }
  16632. bool start_split = ufbxi_is_edge_split(input, topo, start);
  16633. bool prev_split = end_edge != UFBX_NO_INDEX && ufbxi_is_edge_split(input, topo, end_edge);
  16634. // Either of the first two edges may be creased
  16635. ufbx_real start_crease = ufbxi_edge_crease(mesh, start_split, topo, start);
  16636. if (start_crease > 0.0f) {
  16637. total_crease += start_crease;
  16638. crease_input_indices[num_crease++] = 1;
  16639. }
  16640. ufbx_real prev_crease = ufbxi_edge_crease(mesh, prev_split, topo, start_prev);
  16641. if (prev_crease > 0.0f) {
  16642. total_crease += prev_crease;
  16643. crease_input_indices[num_crease++] = 2;
  16644. }
  16645. if (end_edge != UFBX_NO_INDEX) {
  16646. if (prev_split) {
  16647. num_split++;
  16648. }
  16649. } else {
  16650. on_boundary = true;
  16651. }
  16652. ufbxi_check_err(&sc->error, vertex_indices[start] == UFBX_NO_INDEX);
  16653. vertex_indices[start] = value_index;
  16654. if (start_split) {
  16655. // We need to special case if the first edge is split as we have
  16656. // handled it already in the code above..
  16657. start = ufbx_topo_next_vertex_edge(topo, num_topo, start);
  16658. num_split++;
  16659. } else {
  16660. // Follow vertex edges until we either hit a topological/split boundary
  16661. // or loop back to the left edge we accounted for in `start_prev`
  16662. uint32_t cur = start;
  16663. for (;;) {
  16664. cur = ufbx_topo_next_vertex_edge(topo, num_topo, cur);
  16665. // Topological boundary: Finished
  16666. if (cur == UFBX_NO_INDEX) {
  16667. on_boundary = true;
  16668. start = UFBX_NO_INDEX;
  16669. break;
  16670. }
  16671. non_manifold |= (topo[cur].flags & UFBX_TOPO_NON_MANIFOLD) != 0;
  16672. ufbxi_check_err(&sc->error, vertex_indices[cur] == UFBX_NO_INDEX);
  16673. vertex_indices[cur] = value_index;
  16674. bool split = ufbxi_is_edge_split(input, topo, cur);
  16675. // Looped: Add the face from the other side still if not split
  16676. if (cur == end_edge && !split) {
  16677. ufbxi_check_err(&sc->error, ufbxi_grow_array(&sc->ator_tmp, &sc->inputs, &sc->inputs_cap, num_inputs + 1));
  16678. const char *f0 = face_values + topo[cur].face * stride;
  16679. inputs[num_inputs].data = f0;
  16680. start = UFBX_NO_INDEX;
  16681. num_inputs += 1;
  16682. break;
  16683. }
  16684. // Add the edge crease, this also handles boundaries as they
  16685. // have an implicit crease of 1.0 using `ufbxi_edge_crease()`
  16686. ufbx_real cur_crease = ufbxi_edge_crease(mesh, split, topo, cur);
  16687. if (cur_crease > 0.0f) {
  16688. total_crease += cur_crease;
  16689. if (num_crease < 2) crease_input_indices[num_crease] = num_inputs;
  16690. num_crease++;
  16691. }
  16692. // Add the new edge and face to the sum
  16693. {
  16694. ufbxi_check_err(&sc->error, ufbxi_grow_array(&sc->ator_tmp, &sc->inputs, &sc->inputs_cap, num_inputs + 2));
  16695. inputs = sc->inputs;
  16696. const char *e0 = (char*)input->values + input->indices[topo[cur].next] * stride;
  16697. const char *f0 = face_values + topo[cur].face * stride;
  16698. inputs[num_inputs + 0].data = e0;
  16699. inputs[num_inputs + 1].data = f0;
  16700. num_inputs += 2;
  16701. }
  16702. valence++;
  16703. // If we landed at a split edge advance to the next one
  16704. // and continue from there in the outer loop
  16705. if (split) {
  16706. start = ufbx_topo_next_vertex_edge(topo, num_topo, cur);
  16707. num_split++;
  16708. break;
  16709. }
  16710. }
  16711. }
  16712. if (start == original_start) start = UFBX_NO_INDEX;
  16713. // Weights for various subdivision masks
  16714. ufbx_real fe_weight = 1.0f / (ufbx_real)(valence*valence);
  16715. ufbx_real v_weight = (ufbx_real)(valence - 2) / (ufbx_real)valence;
  16716. // Select the right subdivision mask depending on valence and crease
  16717. if (num_crease > 2
  16718. || (sharp_corners && valence == 2 && (num_split > 0 || on_boundary))
  16719. || (sharp_splits && (num_split > 0 || on_boundary))
  16720. || sharp_all
  16721. || non_manifold) {
  16722. // Corner: Copy as-is
  16723. inputs[0].data = v0;
  16724. inputs[0].weight = 1.0f;
  16725. num_inputs = 1;
  16726. } else if (num_crease == 2) {
  16727. // Boundary: Interpolate edge
  16728. total_crease *= 0.5f;
  16729. if (total_crease < 0.0f) total_crease = 0.0f;
  16730. if (total_crease > 1.0f) total_crease = 1.0f;
  16731. inputs[0].weight = v_weight * (1.0f - total_crease) + 0.75f * total_crease;
  16732. ufbx_real few = fe_weight * (1.0f - total_crease);
  16733. for (size_t i = 1; i < num_inputs; i++) {
  16734. inputs[i].weight = few;
  16735. }
  16736. // Add weight to the creased edges
  16737. inputs[crease_input_indices[0]].weight += 0.125f * total_crease;
  16738. inputs[crease_input_indices[1]].weight += 0.125f * total_crease;
  16739. } else {
  16740. // Regular: Weighted sum with the accumulated edge/face points
  16741. inputs[0].weight = v_weight;
  16742. for (size_t i = 1; i < num_inputs; i++) {
  16743. inputs[i].weight = fe_weight;
  16744. }
  16745. }
  16746. if (mesh->vertex_crease.exists) {
  16747. ufbx_real v = ufbx_get_vertex_real(&mesh->vertex_crease, original_start);
  16748. v *= (ufbx_real)10.0;
  16749. if (v > 0.0f) {
  16750. if (v > 1.0) v = 1.0f;
  16751. ufbx_real iv = 1.0f - v;
  16752. inputs[0].weight = 1.0f * v + (inputs[0].weight) * iv;
  16753. for (size_t i = 1; i < num_inputs; i++) {
  16754. inputs[i].weight *= iv;
  16755. }
  16756. }
  16757. }
  16758. #if defined(UFBX_REGRESSION)
  16759. {
  16760. ufbx_real total_weight = 0.0f;
  16761. for (size_t i = 0; i < num_inputs; i++) {
  16762. total_weight += inputs[i].weight;
  16763. }
  16764. ufbx_assert(ufbx_fabs(total_weight - 1.0f) < 0.001f);
  16765. }
  16766. #endif
  16767. ufbxi_check_err(&sc->error, sum_fn(sum_user, dst, inputs, num_inputs));
  16768. }
  16769. }
  16770. // Copy non-manifold vertex values as-is
  16771. for (size_t old_ix = 0; old_ix < mesh->num_indices; old_ix++) {
  16772. uint32_t ix = vertex_indices[old_ix];
  16773. if (ix == UFBX_NO_INDEX) {
  16774. ix = (uint32_t)num_vertex_values++;
  16775. vertex_indices[old_ix] = ix;
  16776. const char *src = (const char*)input->values + input->indices[old_ix] * stride;
  16777. char *dst = vertex_values + ix * stride;
  16778. inputs[0].data = src;
  16779. inputs[0].weight = 1.0f;
  16780. ufbxi_check_err(&sc->error, sum_fn(sum_user, dst, inputs, 1));
  16781. }
  16782. }
  16783. ufbx_assert(num_vertex_values <= mesh->num_indices);
  16784. size_t num_values = num_edge_values + mesh->num_faces + num_vertex_values;
  16785. char *new_values = (char*)ufbxi_push_size(&sc->result, stride, (num_values+1));
  16786. ufbxi_check_err(&sc->error, new_values);
  16787. memset(new_values, 0, stride);
  16788. new_values += stride;
  16789. memcpy(new_values, values, num_values * stride);
  16790. output->values = new_values;
  16791. output->num_values = num_values;
  16792. if (!input->ignore_indices) {
  16793. uint32_t *new_indices = ufbxi_push(&sc->result, uint32_t, mesh->num_indices * 4);
  16794. ufbxi_check_err(&sc->error, new_indices);
  16795. uint32_t face_start = 0;
  16796. uint32_t edge_start = (uint32_t)(face_start + mesh->num_faces);
  16797. uint32_t vert_start = (uint32_t)(edge_start + num_edge_values);
  16798. uint32_t *p_ix = new_indices;
  16799. for (size_t ix = 0; ix < mesh->num_indices; ix++) {
  16800. p_ix[0] = vert_start + vertex_indices[ix];
  16801. p_ix[1] = edge_start + edge_indices[ix];
  16802. p_ix[2] = face_start + topo[ix].face;
  16803. p_ix[3] = edge_start + edge_indices[topo[ix].prev];
  16804. p_ix += 4;
  16805. }
  16806. output->indices = new_indices;
  16807. output->num_indices = mesh->num_indices * 4;
  16808. } else {
  16809. output->indices = NULL;
  16810. output->num_indices = 0;
  16811. }
  16812. return 1;
  16813. }
  16814. static ufbxi_noinline int ufbxi_subdivide_attrib(ufbxi_subdivide_context *sc, ufbx_vertex_attrib *attrib, ufbx_subdivision_boundary boundary, bool check_split_data)
  16815. {
  16816. if (!attrib->exists) return 1;
  16817. ufbx_assert(attrib->value_reals >= 1 && attrib->value_reals <= 4);
  16818. ufbxi_subdivide_layer_input input;
  16819. input.sum_fn = ufbxi_real_sum_fns[attrib->value_reals - 1];
  16820. input.sum_user = NULL;
  16821. input.values = attrib->values.data;
  16822. input.indices = attrib->indices.data;
  16823. input.stride = attrib->value_reals * sizeof(ufbx_real);
  16824. input.boundary = boundary;
  16825. input.check_split_data = check_split_data;
  16826. input.ignore_indices = false;
  16827. ufbxi_subdivide_layer_output output;
  16828. ufbxi_check_err(&sc->error, ufbxi_subdivide_layer(sc, &output, &input));
  16829. attrib->values.data = output.values;
  16830. attrib->indices.data = output.indices;
  16831. attrib->values.count = output.num_values;
  16832. attrib->indices.count = output.num_indices;
  16833. return 1;
  16834. }
  16835. static ufbxi_noinline ufbxi_subdivision_vertex_weights *ufbxi_subdivision_copy_weights(ufbxi_subdivide_context *sc, ufbx_subdivision_weight_range_list ranges, ufbx_subdivision_weight_list weights)
  16836. {
  16837. ufbxi_subdivision_vertex_weights *dst = ufbxi_push(&sc->tmp, ufbxi_subdivision_vertex_weights, ranges.count);
  16838. ufbxi_check_return_err(&sc->error, dst, NULL);
  16839. ufbxi_nounroll for (size_t i = 0; i != ranges.count; i++) {
  16840. ufbx_subdivision_weight_range range = ranges.data[i];
  16841. dst[i].weights = weights.data + range.weight_begin;
  16842. dst[i].num_weights = range.num_weights;
  16843. }
  16844. return dst;
  16845. }
  16846. static ufbxi_noinline ufbxi_subdivision_vertex_weights *ufbxi_init_source_vertex_weights(ufbxi_subdivide_context *sc, size_t num_vertices)
  16847. {
  16848. ufbxi_subdivision_vertex_weights *dst = ufbxi_push(&sc->tmp, ufbxi_subdivision_vertex_weights, num_vertices);
  16849. ufbx_subdivision_weight *weights = ufbxi_push(&sc->tmp, ufbx_subdivision_weight, num_vertices);
  16850. ufbxi_check_return_err(&sc->error, dst && weights, NULL);
  16851. ufbxi_nounroll for (size_t i = 0; i != num_vertices; i++) {
  16852. dst[i].weights = weights + i;
  16853. dst[i].num_weights = 1;
  16854. weights[i].index = (uint32_t)i;
  16855. weights[i].weight = 1.0f;
  16856. }
  16857. return dst;
  16858. }
  16859. static ufbxi_noinline ufbxi_subdivision_vertex_weights *ufbxi_init_skin_weights(ufbxi_subdivide_context *sc, size_t num_vertices, const ufbx_skin_deformer *skin)
  16860. {
  16861. ufbxi_subdivision_vertex_weights *dst = ufbxi_push(&sc->tmp, ufbxi_subdivision_vertex_weights, num_vertices);
  16862. ufbxi_check_return_err(&sc->error, dst, NULL);
  16863. for (size_t i = 0; i < num_vertices; i++) {
  16864. ufbxi_dev_assert(i < skin->vertices.count);
  16865. ufbx_skin_vertex vertex = skin->vertices.data[i];
  16866. size_t num_weights = ufbxi_min_sz(sc->max_vertex_weights, vertex.num_weights);
  16867. ufbx_subdivision_weight *weights = ufbxi_push(&sc->tmp, ufbx_subdivision_weight, num_weights);
  16868. ufbxi_check_err(&sc->error, weights);
  16869. const ufbx_skin_weight *skin_weights = skin->weights.data + vertex.weight_begin;
  16870. dst[i].weights = weights;
  16871. dst[i].num_weights = num_weights;
  16872. ufbxi_nounroll for (size_t wi = 0; wi != num_weights; wi++) {
  16873. ufbxi_check_err(&sc->error, skin_weights[wi].cluster_index <= INT32_MAX);
  16874. weights[wi].index = skin_weights[wi].cluster_index;
  16875. weights[wi].weight = skin_weights[wi].weight;
  16876. }
  16877. }
  16878. return dst;
  16879. }
  16880. static ufbxi_noinline int ufbxi_subdivide_weights(ufbxi_subdivide_context *sc, ufbx_subdivision_weight_range_list *ranges,
  16881. ufbx_subdivision_weight_list *weights, const ufbxi_subdivision_vertex_weights *src)
  16882. {
  16883. ufbxi_check_err(&sc->error, src);
  16884. ufbxi_subdivide_layer_input input;
  16885. input.sum_fn = ufbxi_subdivide_sum_vertex_weights;
  16886. input.sum_user = sc;
  16887. input.values = src;
  16888. input.indices = sc->src_mesh.vertex_indices.data;
  16889. input.stride = sizeof(ufbxi_subdivision_vertex_weights);
  16890. input.boundary = sc->opts.boundary;
  16891. input.check_split_data = false;
  16892. input.ignore_indices = true;
  16893. sc->total_weights = 0;
  16894. ufbxi_subdivide_layer_output output;
  16895. ufbxi_check_err(&sc->error, ufbxi_subdivide_layer(sc, &output, &input));
  16896. size_t num_vertices = output.num_values;
  16897. ufbx_assert(num_vertices == sc->dst_mesh.vertex_position.values.count);
  16898. ufbx_subdivision_weight_range *dst_ranges = ufbxi_push(&sc->result, ufbx_subdivision_weight_range, num_vertices);
  16899. ufbx_subdivision_weight *dst_weights = ufbxi_push(&sc->result, ufbx_subdivision_weight, sc->total_weights);
  16900. ufbxi_check_err(&sc->error, ranges && weights);
  16901. ufbxi_subdivision_vertex_weights *src_weights = (ufbxi_subdivision_vertex_weights*)output.values;
  16902. size_t weight_offset = 0;
  16903. for (size_t vi = 0; vi < num_vertices; vi++) {
  16904. ufbxi_subdivision_vertex_weights ws = src_weights[vi];
  16905. ufbxi_check_err(&sc->error, (size_t)UINT32_MAX - weight_offset >= ws.num_weights);
  16906. dst_ranges[vi].weight_begin = (uint32_t)weight_offset;
  16907. dst_ranges[vi].num_weights = (uint32_t)ws.num_weights;
  16908. memcpy(dst_weights + weight_offset, ws.weights, ws.num_weights * sizeof(ufbx_subdivision_weight));
  16909. weight_offset += ws.num_weights;
  16910. }
  16911. ranges->data = dst_ranges;
  16912. ranges->count = num_vertices;
  16913. weights->data = dst_weights;
  16914. weights->count = sc->total_weights;
  16915. return 1;
  16916. }
  16917. ufbxi_nodiscard static ufbxi_noinline int ufbxi_subdivide_vertex_crease(ufbxi_subdivide_context *sc, ufbx_vertex_real *ufbxi_restrict dst, const ufbx_vertex_real *ufbxi_restrict src)
  16918. {
  16919. size_t src_indices = src->indices.count;
  16920. size_t src_values = src->values.count;
  16921. dst->values.count = src_values + 1;
  16922. dst->values.data = ufbxi_push(&sc->result, ufbx_real, dst->values.count);
  16923. ufbxi_check_err(&sc->error, dst->values.data);
  16924. dst->values.data[src_values] = 0.0f;
  16925. dst->indices.count = src_indices * 4;
  16926. dst->indices.data = ufbxi_push(&sc->result, uint32_t, dst->indices.count);
  16927. ufbxi_check_err(&sc->error, dst->indices.data);
  16928. // Reduce the amount of vertex crease on each iteration
  16929. ufbxi_nounroll for (size_t i = 0; i < src_values; i++) {
  16930. ufbx_real crease = src->values.data[i];
  16931. if (crease < 0.999f) crease -= 0.1f;
  16932. if (crease < 0.0f) crease = 0.0f;
  16933. dst->values.data[i] = crease;
  16934. }
  16935. // Write the crease at the vertex corner and zero (at `src_values`) on other ones
  16936. uint32_t zero_index = (uint32_t)src_values;
  16937. ufbxi_nounroll for (size_t i = 0; i < src_indices; i++) {
  16938. uint32_t *quad = dst->indices.data + i * 4;
  16939. quad[0] = src->indices.data[i];
  16940. quad[1] = zero_index;
  16941. quad[2] = zero_index;
  16942. quad[3] = zero_index;
  16943. }
  16944. return 1;
  16945. }
  16946. ufbxi_nodiscard static ufbxi_noinline int ufbxi_subdivide_mesh_level(ufbxi_subdivide_context *sc)
  16947. {
  16948. const ufbx_mesh *mesh = &sc->src_mesh;
  16949. ufbx_mesh *result = &sc->dst_mesh;
  16950. *result = *mesh;
  16951. ufbx_topo_edge *topo = ufbxi_push(&sc->tmp, ufbx_topo_edge, mesh->num_indices);
  16952. ufbxi_check_err(&sc->error, topo);
  16953. ufbx_compute_topology(mesh, topo, mesh->num_indices);
  16954. sc->topo = topo;
  16955. sc->num_topo = mesh->num_indices;
  16956. ufbxi_check_err(&sc->error, ufbxi_subdivide_attrib(sc, (ufbx_vertex_attrib*)&result->vertex_position, sc->opts.boundary, false));
  16957. memset(&result->vertex_uv, 0, sizeof(result->vertex_uv));
  16958. memset(&result->vertex_tangent, 0, sizeof(result->vertex_tangent));
  16959. memset(&result->vertex_bitangent, 0, sizeof(result->vertex_bitangent));
  16960. memset(&result->vertex_color, 0, sizeof(result->vertex_color));
  16961. result->uv_sets.data = ufbxi_push_copy(&sc->result, ufbx_uv_set, result->uv_sets.count, result->uv_sets.data);
  16962. ufbxi_check_err(&sc->error, result->uv_sets.data);
  16963. result->color_sets.data = ufbxi_push_copy(&sc->result, ufbx_color_set, result->color_sets.count, result->color_sets.data);
  16964. ufbxi_check_err(&sc->error, result->color_sets.data);
  16965. ufbxi_for_list(ufbx_uv_set, set, result->uv_sets) {
  16966. ufbxi_check_err(&sc->error, ufbxi_subdivide_attrib(sc, (ufbx_vertex_attrib*)&set->vertex_uv, sc->opts.uv_boundary, true));
  16967. if (sc->opts.interpolate_tangents) {
  16968. ufbxi_check_err(&sc->error, ufbxi_subdivide_attrib(sc, (ufbx_vertex_attrib*)&set->vertex_tangent, sc->opts.uv_boundary, true));
  16969. ufbxi_check_err(&sc->error, ufbxi_subdivide_attrib(sc, (ufbx_vertex_attrib*)&set->vertex_bitangent, sc->opts.uv_boundary, true));
  16970. } else {
  16971. memset(&set->vertex_tangent, 0, sizeof(set->vertex_tangent));
  16972. memset(&set->vertex_bitangent, 0, sizeof(set->vertex_bitangent));
  16973. }
  16974. }
  16975. ufbxi_for_list(ufbx_color_set, set, result->color_sets) {
  16976. ufbxi_check_err(&sc->error, ufbxi_subdivide_attrib(sc, (ufbx_vertex_attrib*)&set->vertex_color, sc->opts.uv_boundary, true));
  16977. }
  16978. if (result->uv_sets.count > 0) {
  16979. result->vertex_uv = result->uv_sets.data[0].vertex_uv;
  16980. result->vertex_bitangent = result->uv_sets.data[0].vertex_bitangent;
  16981. result->vertex_tangent = result->uv_sets.data[0].vertex_tangent;
  16982. }
  16983. if (result->color_sets.count > 0) {
  16984. result->vertex_color = result->color_sets.data[0].vertex_color;
  16985. }
  16986. if (sc->opts.interpolate_normals && !sc->opts.ignore_normals) {
  16987. ufbxi_check_err(&sc->error, ufbxi_subdivide_attrib(sc, (ufbx_vertex_attrib*)&result->vertex_normal, sc->opts.boundary, true));
  16988. ufbxi_for_list(ufbx_vec3, normal, result->vertex_normal.values) {
  16989. *normal = ufbxi_slow_normalize3(normal);
  16990. }
  16991. if (mesh->skinned_normal.values.data == mesh->vertex_normal.values.data) {
  16992. result->skinned_normal = result->vertex_normal;
  16993. } else {
  16994. ufbxi_check_err(&sc->error, ufbxi_subdivide_attrib(sc, (ufbx_vertex_attrib*)&result->skinned_normal, sc->opts.boundary, true));
  16995. ufbxi_for_list(ufbx_vec3, normal, result->skinned_normal.values) {
  16996. *normal = ufbxi_slow_normalize3(normal);
  16997. }
  16998. }
  16999. }
  17000. if (result->vertex_crease.exists) {
  17001. ufbxi_check_err(&sc->error, ufbxi_subdivide_vertex_crease(sc, &result->vertex_crease, &mesh->vertex_crease));
  17002. }
  17003. if (mesh->skinned_position.values.data == mesh->vertex_position.values.data) {
  17004. result->skinned_position = result->vertex_position;
  17005. } else {
  17006. ufbxi_check_err(&sc->error, ufbxi_subdivide_attrib(sc, (ufbx_vertex_attrib*)&result->skinned_position, sc->opts.boundary, false));
  17007. }
  17008. ufbx_subdivision_result *result_sub = ufbxi_push_zero(&sc->result, ufbx_subdivision_result, 1);
  17009. ufbxi_check_err(&sc->error, result_sub);
  17010. result->subdivision_result = result_sub;
  17011. if (sc->opts.evaluate_source_vertices || sc->opts.evaluate_skin_weights) {
  17012. ufbx_subdivision_result *mesh_sub = mesh->subdivision_result;
  17013. ufbx_skin_deformer *skin = NULL;
  17014. if (sc->opts.evaluate_skin_weights) {
  17015. if (mesh->skin_deformers.count > 0) {
  17016. ufbxi_check_err(&sc->error, sc->opts.skin_deformer_index < mesh->skin_deformers.count);
  17017. skin = mesh->skin_deformers.data[sc->opts.skin_deformer_index];
  17018. }
  17019. }
  17020. size_t max_weights = 0;
  17021. if (sc->opts.evaluate_source_vertices) {
  17022. max_weights = ufbxi_max_sz(max_weights, mesh->num_vertices);
  17023. }
  17024. if (skin) {
  17025. max_weights = ufbxi_max_sz(max_weights, skin->clusters.count);
  17026. }
  17027. sc->tmp_vertex_weights = ufbxi_push_zero(&sc->tmp, ufbx_real, mesh->num_vertices);
  17028. sc->tmp_weights = ufbxi_push(&sc->tmp, ufbx_subdivision_weight, max_weights);
  17029. ufbxi_check_err(&sc->error, sc->tmp_vertex_weights && sc->tmp_weights);
  17030. if (sc->opts.evaluate_source_vertices) {
  17031. sc->max_vertex_weights = sc->opts.max_source_vertices ? sc->opts.max_source_vertices : SIZE_MAX;
  17032. ufbxi_subdivision_vertex_weights *weights;
  17033. if (mesh_sub && mesh_sub->source_vertex_ranges.count > 0) {
  17034. weights = ufbxi_subdivision_copy_weights(sc, mesh_sub->source_vertex_ranges, mesh_sub->source_vertex_weights);
  17035. } else {
  17036. weights = ufbxi_init_source_vertex_weights(sc, mesh->num_vertices);
  17037. }
  17038. ufbxi_check_err(&sc->error, ufbxi_subdivide_weights(sc, &result_sub->source_vertex_ranges, &result_sub->source_vertex_weights, weights));
  17039. }
  17040. if (skin) {
  17041. sc->max_vertex_weights = sc->opts.max_skin_weights ? sc->opts.max_skin_weights : SIZE_MAX;
  17042. ufbxi_subdivision_vertex_weights *weights;
  17043. if (mesh_sub && mesh_sub->source_vertex_ranges.count > 0) {
  17044. weights = ufbxi_subdivision_copy_weights(sc, mesh_sub->skin_cluster_ranges, mesh_sub->skin_cluster_weights);
  17045. } else {
  17046. weights = ufbxi_init_skin_weights(sc, mesh->num_vertices, skin);
  17047. }
  17048. ufbxi_check_err(&sc->error, ufbxi_subdivide_weights(sc, &result_sub->skin_cluster_ranges, &result_sub->skin_cluster_weights, weights));
  17049. }
  17050. }
  17051. result->num_vertices = result->vertex_position.values.count;
  17052. result->num_indices = mesh->num_indices * 4;
  17053. result->num_faces = mesh->num_indices;
  17054. result->num_triangles = mesh->num_indices * 2;
  17055. result->vertex_indices.data = result->vertex_position.indices.data;
  17056. result->vertex_indices.count = result->num_indices;
  17057. result->vertices.data = result->vertex_position.values.data;
  17058. result->vertices.count = result->num_vertices;
  17059. result->faces.count = result->num_faces;
  17060. result->faces.data = ufbxi_push(&sc->result, ufbx_face, result->num_faces);
  17061. ufbxi_check_err(&sc->error, result->faces.data);
  17062. for (size_t i = 0; i < result->num_faces; i++) {
  17063. result->faces.data[i].index_begin = (uint32_t)(i * 4);
  17064. result->faces.data[i].num_indices = 4;
  17065. }
  17066. if (mesh->edges.data) {
  17067. result->num_edges = mesh->num_edges*2 + result->num_faces;
  17068. result->edges.count = result->num_edges;
  17069. result->edges.data = ufbxi_push(&sc->result, ufbx_edge, result->num_edges);
  17070. ufbxi_check_err(&sc->error, result->edges.data);
  17071. if (mesh->edge_crease.data) {
  17072. result->edge_crease.count = result->num_edges;
  17073. result->edge_crease.data = ufbxi_push(&sc->result, ufbx_real, result->num_edges);
  17074. ufbxi_check_err(&sc->error, result->edge_crease.data);
  17075. }
  17076. if (mesh->edge_smoothing.data) {
  17077. result->edge_smoothing.count = result->num_edges;
  17078. result->edge_smoothing.data = ufbxi_push(&sc->result, bool, result->num_edges);
  17079. ufbxi_check_err(&sc->error, result->edge_smoothing.data);
  17080. }
  17081. if (mesh->edge_visibility.data) {
  17082. result->edge_visibility.count = result->num_edges;
  17083. result->edge_visibility.data = ufbxi_push(&sc->result, bool, result->num_edges);
  17084. ufbxi_check_err(&sc->error, result->edge_visibility.data);
  17085. }
  17086. size_t di = 0;
  17087. for (size_t i = 0; i < mesh->num_edges; i++) {
  17088. ufbx_edge edge = mesh->edges.data[i];
  17089. uint32_t face_ix = topo[edge.a].face;
  17090. ufbx_face face = mesh->faces.data[face_ix];
  17091. uint32_t offset = edge.a - face.index_begin;
  17092. uint32_t next = (offset + 1) % (uint32_t)face.num_indices;
  17093. uint32_t a = (face.index_begin + offset) * 4;
  17094. uint32_t b = (face.index_begin + next) * 4;
  17095. result->edges.data[di + 0].a = a;
  17096. result->edges.data[di + 0].b = a + 1;
  17097. result->edges.data[di + 1].a = b + 3;
  17098. result->edges.data[di + 1].b = b;
  17099. if (mesh->edge_crease.data) {
  17100. ufbx_real crease = mesh->edge_crease.data[i];
  17101. if (crease < 0.999f) crease -= 0.1f;
  17102. if (crease < 0.0f) crease = 0.0f;
  17103. result->edge_crease.data[di + 0] = crease;
  17104. result->edge_crease.data[di + 1] = crease;
  17105. }
  17106. if (mesh->edge_smoothing.data) {
  17107. result->edge_smoothing.data[di + 0] = mesh->edge_smoothing.data[i];
  17108. result->edge_smoothing.data[di + 1] = mesh->edge_smoothing.data[i];
  17109. }
  17110. if (mesh->edge_visibility.data) {
  17111. result->edge_visibility.data[di + 0] = mesh->edge_visibility.data[i];
  17112. result->edge_visibility.data[di + 1] = mesh->edge_visibility.data[i];
  17113. }
  17114. di += 2;
  17115. }
  17116. for (size_t fi = 0; fi < result->num_faces; fi++) {
  17117. result->edges.data[di].a = (uint32_t)(fi * 4 + 1);
  17118. result->edges.data[di].b = (uint32_t)(fi * 4 + 2);
  17119. if (result->edge_crease.data) {
  17120. result->edge_crease.data[di] = 0.0f;
  17121. }
  17122. if (result->edge_smoothing.data) {
  17123. result->edge_smoothing.data[di + 0] = true;
  17124. }
  17125. if (result->edge_visibility.data) {
  17126. result->edge_visibility.data[di + 0] = false;
  17127. }
  17128. di++;
  17129. }
  17130. }
  17131. if (mesh->face_material.data) {
  17132. result->face_material.count = result->num_faces;
  17133. result->face_material.data = ufbxi_push(&sc->result, uint32_t, result->num_faces);
  17134. ufbxi_check_err(&sc->error, result->face_material.data);
  17135. }
  17136. if (mesh->face_smoothing.data) {
  17137. result->face_smoothing.count = result->num_faces;
  17138. result->face_smoothing.data = ufbxi_push(&sc->result, bool, result->num_faces);
  17139. ufbxi_check_err(&sc->error, result->face_smoothing.data);
  17140. }
  17141. if (mesh->face_group.data) {
  17142. result->face_group.count = result->num_faces;
  17143. result->face_group.data = ufbxi_push(&sc->result, uint32_t, result->num_faces);
  17144. ufbxi_check_err(&sc->error, result->face_group.data);
  17145. }
  17146. if (mesh->face_hole.data) {
  17147. result->face_hole.count = result->num_faces;
  17148. result->face_hole.data = ufbxi_push(&sc->result, bool, result->num_faces);
  17149. ufbxi_check_err(&sc->error, result->face_hole.data);
  17150. }
  17151. size_t num_materials = result->materials.count;
  17152. result->materials.data = ufbxi_push_copy(&sc->result, ufbx_mesh_material, num_materials, result->materials.data);
  17153. ufbxi_check_err(&sc->error, result->materials.data);
  17154. ufbxi_for_list(ufbx_mesh_material, mat, result->materials) {
  17155. mat->num_faces = 0;
  17156. mat->num_triangles = 0;
  17157. }
  17158. size_t index_offset = 0;
  17159. for (size_t i = 0; i < mesh->num_faces; i++) {
  17160. ufbx_face face = mesh->faces.data[i];
  17161. uint32_t mat = 0;
  17162. if (mesh->face_material.data) {
  17163. mat = mesh->face_material.data[i];
  17164. for (size_t ci = 0; ci < face.num_indices; ci++) {
  17165. result->face_material.data[index_offset + ci] = mat;
  17166. }
  17167. }
  17168. if (mat < num_materials) {
  17169. result->materials.data[mat].num_faces += face.num_indices;
  17170. }
  17171. if (mesh->face_smoothing.data) {
  17172. bool flag = mesh->face_smoothing.data[i];
  17173. for (size_t ci = 0; ci < face.num_indices; ci++) {
  17174. result->face_smoothing.data[index_offset + ci] = flag;
  17175. }
  17176. }
  17177. if (mesh->face_group.data) {
  17178. uint32_t group = mesh->face_group.data[i];
  17179. for (size_t ci = 0; ci < face.num_indices; ci++) {
  17180. result->face_group.data[index_offset + ci] = group;
  17181. }
  17182. }
  17183. if (mesh->face_hole.data) {
  17184. bool flag = mesh->face_hole.data[i];
  17185. for (size_t ci = 0; ci < face.num_indices; ci++) {
  17186. result->face_hole.data[index_offset + ci] = flag;
  17187. }
  17188. }
  17189. index_offset += face.num_indices;
  17190. }
  17191. ufbxi_check_err(&sc->error, ufbxi_finalize_mesh(&sc->result, &sc->error, result));
  17192. ufbxi_patch_mesh_reals(result);
  17193. return 1;
  17194. }
  17195. ufbxi_nodiscard static ufbxi_noinline int ufbxi_subdivide_mesh_imp(ufbxi_subdivide_context *sc, size_t level)
  17196. {
  17197. // `ufbx_subdivide_opts` must be cleared to zero first!
  17198. ufbx_assert(sc->opts._begin_zero == 0 && sc->opts._end_zero == 0);
  17199. ufbxi_check_err_msg(&sc->error, sc->opts._begin_zero == 0 && sc->opts._end_zero == 0, "Uninitialized options");
  17200. if (sc->opts.boundary == UFBX_SUBDIVISION_BOUNDARY_DEFAULT) {
  17201. sc->opts.boundary = sc->src_mesh.subdivision_boundary;
  17202. }
  17203. if (sc->opts.uv_boundary == UFBX_SUBDIVISION_BOUNDARY_DEFAULT) {
  17204. sc->opts.uv_boundary = sc->src_mesh.subdivision_uv_boundary;
  17205. }
  17206. ufbxi_init_ator(&sc->error, &sc->ator_tmp, &sc->opts.temp_allocator);
  17207. ufbxi_init_ator(&sc->error, &sc->ator_result, &sc->opts.result_allocator);
  17208. sc->result.unordered = true;
  17209. sc->source.unordered = true;
  17210. sc->tmp.unordered = true;
  17211. sc->source.ator = &sc->ator_tmp;
  17212. sc->tmp.ator = &sc->ator_tmp;
  17213. for (size_t i = 1; i < level; i++) {
  17214. sc->result.ator = &sc->ator_tmp;
  17215. ufbxi_check_err(&sc->error, ufbxi_subdivide_mesh_level(sc));
  17216. sc->src_mesh = sc->dst_mesh;
  17217. ufbxi_buf_free(&sc->source);
  17218. ufbxi_buf_free(&sc->tmp);
  17219. sc->source = sc->result;
  17220. memset(&sc->result, 0, sizeof(sc->result));
  17221. }
  17222. sc->result.ator = &sc->ator_result;
  17223. ufbxi_check_err(&sc->error, ufbxi_subdivide_mesh_level(sc));
  17224. ufbxi_buf_free(&sc->tmp);
  17225. ufbx_mesh *mesh = &sc->dst_mesh;
  17226. memset(&mesh->vertex_normal, 0, sizeof(mesh->vertex_normal));
  17227. memset(&mesh->skinned_normal, 0, sizeof(mesh->skinned_normal));
  17228. // Subdivision always results in a mesh that consists only of quads
  17229. mesh->max_face_triangles = 2;
  17230. mesh->num_bad_faces = 0;
  17231. if (!sc->opts.interpolate_normals && !sc->opts.ignore_normals) {
  17232. ufbx_topo_edge *topo = ufbxi_push(&sc->tmp, ufbx_topo_edge, mesh->num_indices);
  17233. ufbxi_check_err(&sc->error, topo);
  17234. ufbx_compute_topology(mesh, topo, mesh->num_indices);
  17235. uint32_t *normal_indices = ufbxi_push(&sc->result, uint32_t, mesh->num_indices);
  17236. ufbxi_check_err(&sc->error, normal_indices);
  17237. size_t num_normals = ufbx_generate_normal_mapping(mesh, topo, mesh->num_indices, normal_indices, mesh->num_indices, true);
  17238. if (num_normals == mesh->num_vertices) {
  17239. mesh->skinned_normal.unique_per_vertex = true;
  17240. }
  17241. ufbx_vec3 *normal_data = ufbxi_push(&sc->result, ufbx_vec3, num_normals + 1);
  17242. ufbxi_check_err(&sc->error, normal_data);
  17243. normal_data[0] = ufbx_zero_vec3;
  17244. normal_data++;
  17245. ufbx_compute_normals(mesh, &mesh->skinned_position, normal_indices, mesh->num_indices, normal_data, num_normals);
  17246. mesh->vertex_normal.exists = true;
  17247. mesh->vertex_normal.values.data = normal_data;
  17248. mesh->vertex_normal.values.count = num_normals;
  17249. mesh->vertex_normal.indices.data = normal_indices;
  17250. mesh->vertex_normal.indices.count = mesh->num_indices;
  17251. mesh->skinned_normal = mesh->vertex_normal;
  17252. }
  17253. ufbxi_refcount *parent = NULL;
  17254. if (sc->src_mesh_ptr->subdivision_evaluated && sc->src_mesh_ptr->from_tessellated_nurbs) {
  17255. parent = &(ufbxi_get_imp(ufbxi_mesh_imp, sc->src_mesh_ptr))->refcount;
  17256. } else {
  17257. parent = &(ufbxi_get_imp(ufbxi_scene_imp, sc->src_mesh_ptr->element.scene))->refcount;
  17258. }
  17259. ufbxi_patch_mesh_reals(mesh);
  17260. sc->imp = ufbxi_push(&sc->result, ufbxi_mesh_imp, 1);
  17261. ufbxi_check_err(&sc->error, sc->imp);
  17262. sc->dst_mesh.subdivision_result->result_memory_used = sc->ator_result.current_size;
  17263. sc->dst_mesh.subdivision_result->temp_memory_used = sc->ator_tmp.current_size;
  17264. sc->dst_mesh.subdivision_result->result_allocs = sc->ator_result.num_allocs;
  17265. sc->dst_mesh.subdivision_result->temp_allocs = sc->ator_tmp.num_allocs;
  17266. ufbxi_init_ref(&sc->imp->refcount, UFBXI_MESH_IMP_MAGIC, parent);
  17267. sc->imp->magic = UFBXI_MESH_IMP_MAGIC;
  17268. sc->imp->mesh = sc->dst_mesh;
  17269. sc->imp->ator = sc->ator_result;
  17270. sc->imp->result_buf = sc->result;
  17271. sc->imp->mesh.subdivision_evaluated = true;
  17272. return 1;
  17273. }
  17274. ufbxi_noinline static ufbx_mesh *ufbxi_subdivide_mesh(const ufbx_mesh *mesh, size_t level, const ufbx_subdivide_opts *user_opts, ufbx_error *p_error)
  17275. {
  17276. ufbxi_subdivide_context sc = { 0 };
  17277. if (user_opts) {
  17278. sc.opts = *user_opts;
  17279. }
  17280. sc.src_mesh_ptr = (ufbx_mesh*)mesh;
  17281. sc.src_mesh = *mesh;
  17282. int ok = ufbxi_subdivide_mesh_imp(&sc, level);
  17283. ufbxi_free(&sc.ator_tmp, ufbxi_subdivide_input, sc.inputs, sc.inputs_cap);
  17284. ufbxi_buf_free(&sc.tmp);
  17285. ufbxi_buf_free(&sc.source);
  17286. if (ok) {
  17287. ufbxi_free_ator(&sc.ator_tmp);
  17288. if (p_error) {
  17289. p_error->type = UFBX_ERROR_NONE;
  17290. p_error->description.data = ufbxi_empty_char;
  17291. p_error->description.length = 0;
  17292. p_error->stack_size = 0;
  17293. }
  17294. ufbxi_mesh_imp *imp = sc.imp;
  17295. return &imp->mesh;
  17296. } else {
  17297. ufbxi_fix_error_type(&sc.error, "Failed to subdivide");
  17298. if (p_error) *p_error = sc.error;
  17299. ufbxi_buf_free(&sc.result);
  17300. ufbxi_free_ator(&sc.ator_tmp);
  17301. ufbxi_free_ator(&sc.ator_result);
  17302. return NULL;
  17303. }
  17304. }
  17305. #else
  17306. ufbxi_noinline static ufbx_mesh *ufbxi_subdivide_mesh(const ufbx_mesh *mesh, size_t level, const ufbx_subdivide_opts *user_opts, ufbx_error *p_error)
  17307. {
  17308. if (p_error) {
  17309. memset(p_error, 0, sizeof(ufbx_error));
  17310. ufbxi_report_err_msg(p_error, "UFBXI_FEATURE_SUBDIVISION", "Feature disabled");
  17311. }
  17312. return NULL;
  17313. }
  17314. #endif
  17315. // -- Utility
  17316. static int ufbxi_map_cmp_vertex(void *user, const void *va, const void *vb)
  17317. {
  17318. size_t size = *(size_t*)user;
  17319. #if defined(UFBX_REGRESSION)
  17320. ufbx_assert(size % 8 == 0);
  17321. #endif
  17322. for (size_t i = 0; i < size; i += 8) {
  17323. uint64_t a = *(const uint64_t*)((const char*)va + i);
  17324. uint64_t b = *(const uint64_t*)((const char*)vb + i);
  17325. if (a != b) return a < b ? -1 : +1;
  17326. }
  17327. return 0;
  17328. }
  17329. typedef struct {
  17330. char *begin, *ptr;
  17331. size_t vertex_size;
  17332. size_t packed_offset;
  17333. } ufbxi_vertex_stream;
  17334. static ufbxi_noinline size_t ufbxi_generate_indices(const ufbx_vertex_stream *user_streams, size_t num_streams, uint32_t *indices, size_t num_indices, const ufbx_allocator_opts *allocator, ufbx_error *error)
  17335. {
  17336. bool fail = false;
  17337. ufbxi_allocator ator = { 0 };
  17338. ufbxi_init_ator(error, &ator, allocator);
  17339. ufbxi_vertex_stream local_streams[16];
  17340. uint64_t local_packed_vertex[64];
  17341. ufbxi_vertex_stream *streams = NULL;
  17342. if (num_streams > ufbxi_arraycount(local_streams)) {
  17343. streams = ufbxi_alloc(&ator, ufbxi_vertex_stream, num_streams);
  17344. if (!streams) fail = true;
  17345. } else {
  17346. streams = local_streams;
  17347. }
  17348. size_t packed_size = 0;
  17349. if (!fail) {
  17350. for (size_t i = 0; i < num_streams; i++) {
  17351. size_t vertex_size = user_streams[i].vertex_size;
  17352. size_t align = ufbxi_size_align_mask(vertex_size);
  17353. packed_size = ufbxi_align_to_mask(packed_size, align);
  17354. streams[i].ptr = streams[i].begin = (char*)user_streams[i].data;
  17355. streams[i].vertex_size = vertex_size;
  17356. streams[i].packed_offset = packed_size;
  17357. packed_size += vertex_size;
  17358. }
  17359. packed_size = ufbxi_align_to_mask(packed_size, 7);
  17360. }
  17361. if (!fail && packed_size == 0) {
  17362. ufbxi_report_err_msg(error, "packed_size != 0", "Zero vertex size");
  17363. fail = true;
  17364. }
  17365. char *packed_vertex = NULL;
  17366. if (!fail) {
  17367. if (packed_size > sizeof(local_packed_vertex)) {
  17368. ufbx_assert(packed_size % 8 == 0);
  17369. packed_vertex = (char*)ufbxi_alloc(&ator, uint64_t, packed_size / 8);
  17370. if (!packed_vertex) fail = true;
  17371. } else {
  17372. packed_vertex = (char*)local_packed_vertex;
  17373. }
  17374. }
  17375. ufbxi_map map = { 0 };
  17376. ufbxi_map_init(&map, &ator, &ufbxi_map_cmp_vertex, &packed_size);
  17377. if (num_indices > 0 && !ufbxi_map_grow_size(&map, packed_size, num_indices)) {
  17378. fail = true;
  17379. }
  17380. if (!fail) {
  17381. ufbx_assert(packed_vertex != NULL);
  17382. memset(packed_vertex, 0, packed_size);
  17383. for (size_t i = 0; i < num_indices; i++) {
  17384. for (size_t si = 0; si < num_streams; si++) {
  17385. size_t size = streams[si].vertex_size, offset = streams[si].packed_offset;
  17386. char *ptr = streams[si].ptr;
  17387. memcpy(packed_vertex + offset, ptr, size);
  17388. streams[si].ptr = ptr + size;
  17389. }
  17390. uint32_t hash = ufbxi_hash_string(packed_vertex, packed_size);
  17391. void *entry = ufbxi_map_find_size(&map, packed_size, hash, packed_vertex);
  17392. if (!entry) {
  17393. entry = ufbxi_map_insert_size(&map, packed_size, hash, packed_vertex);
  17394. if (!entry) {
  17395. fail = true;
  17396. break;
  17397. }
  17398. memcpy(entry, packed_vertex, packed_size);
  17399. }
  17400. uint32_t index = (uint32_t)(ufbxi_to_size((char*)entry - (char*)map.items) / packed_size);
  17401. indices[i] = index;
  17402. }
  17403. }
  17404. size_t result_vertices = 0;
  17405. if (!fail) {
  17406. result_vertices = map.size;
  17407. for (size_t si = 0; si < num_streams; si++) {
  17408. size_t vertex_size = streams[si].vertex_size;
  17409. char *dst = streams[si].begin;
  17410. char *src = (char*)map.items + streams[si].packed_offset;
  17411. for (size_t i = 0; i < result_vertices; i++) {
  17412. memcpy(dst, src, vertex_size);
  17413. dst += vertex_size;
  17414. src += packed_size;
  17415. }
  17416. }
  17417. error->stack_size = 0;
  17418. error->description.data = ufbxi_empty_char;
  17419. error->description.length = 0;
  17420. error->type = UFBX_ERROR_NONE;
  17421. } else {
  17422. ufbxi_fix_error_type(error, "Failed to generate indices");
  17423. }
  17424. if (streams && streams != local_streams) {
  17425. ufbxi_free(&ator, ufbxi_vertex_stream, streams, num_streams);
  17426. }
  17427. if (packed_vertex && packed_vertex != (char*)local_packed_vertex) {
  17428. ufbxi_free(&ator, uint64_t, packed_vertex, packed_size / 8);
  17429. }
  17430. ufbxi_map_free(&map);
  17431. ufbxi_free_ator(&ator);
  17432. return result_vertices;
  17433. }
  17434. static ufbxi_noinline void ufbxi_free_scene_imp(ufbxi_scene_imp *imp)
  17435. {
  17436. ufbx_assert(imp->magic == UFBXI_SCENE_IMP_MAGIC);
  17437. if (imp->magic != UFBXI_SCENE_IMP_MAGIC) return;
  17438. imp->magic = 0;
  17439. ufbxi_buf_free(&imp->string_buf);
  17440. // We need to free `result_buf` last and be careful to copy it to
  17441. // the stack since the `ufbxi_scene_imp` that contains it is allocated
  17442. // from the same result buffer!
  17443. ufbxi_allocator ator = imp->ator;
  17444. ufbxi_buf result = imp->result_buf;
  17445. result.ator = &ator;
  17446. ufbxi_buf_free(&result);
  17447. ufbxi_free_ator(&ator);
  17448. }
  17449. static ufbxi_noinline void ufbxi_free_mesh_imp(ufbxi_mesh_imp *imp)
  17450. {
  17451. ufbx_assert(imp->magic == UFBXI_MESH_IMP_MAGIC);
  17452. if (imp->magic != UFBXI_MESH_IMP_MAGIC) return;
  17453. imp->magic = 0;
  17454. // See `ufbxi_free_scene()` for more information
  17455. ufbxi_allocator ator = imp->ator;
  17456. ufbxi_buf result = imp->result_buf;
  17457. result.ator = &ator;
  17458. ufbxi_buf_free(&result);
  17459. ufbxi_free_ator(&ator);
  17460. }
  17461. static ufbxi_noinline void ufbxi_free_line_curve_imp(ufbxi_line_curve_imp *imp)
  17462. {
  17463. ufbx_assert(imp->magic == UFBXI_LINE_CURVE_IMP_MAGIC);
  17464. if (imp->magic != UFBXI_LINE_CURVE_IMP_MAGIC) return;
  17465. imp->magic = 0;
  17466. // See `ufbxi_free_scene()` for more information
  17467. ufbxi_allocator ator = imp->ator;
  17468. ufbxi_buf result = imp->result_buf;
  17469. result.ator = &ator;
  17470. ufbxi_buf_free(&result);
  17471. ufbxi_free_ator(&ator);
  17472. }
  17473. static ufbxi_noinline void ufbxi_init_ref(ufbxi_refcount *refcount, uint32_t magic, ufbxi_refcount *parent)
  17474. {
  17475. if (parent) {
  17476. ufbxi_retain_ref(parent);
  17477. }
  17478. ufbxi_atomic_counter_init(&refcount->refcount);
  17479. refcount->self_magic = UFBXI_REFCOUNT_IMP_MAGIC;
  17480. refcount->type_magic = magic;
  17481. refcount->parent = parent;
  17482. }
  17483. static ufbxi_noinline void ufbxi_retain_ref(ufbxi_refcount *refcount)
  17484. {
  17485. ufbx_assert(refcount->self_magic == UFBXI_REFCOUNT_IMP_MAGIC);
  17486. size_t count = ufbxi_atomic_counter_inc(&refcount->refcount);
  17487. ufbxi_ignore(count);
  17488. ufbx_assert(count < SIZE_MAX / 2);
  17489. }
  17490. static ufbxi_noinline void ufbxi_release_ref(ufbxi_refcount *refcount)
  17491. {
  17492. while (refcount) {
  17493. ufbx_assert(refcount->self_magic == UFBXI_REFCOUNT_IMP_MAGIC);
  17494. if (ufbxi_atomic_counter_dec(&refcount->refcount) > 0) return;
  17495. ufbxi_refcount *parent = refcount->parent;
  17496. uint32_t type_magic = refcount->type_magic;
  17497. refcount->self_magic = 0;
  17498. refcount->type_magic = 0;
  17499. switch (type_magic) {
  17500. case UFBXI_SCENE_IMP_MAGIC: ufbxi_free_scene_imp((ufbxi_scene_imp*)refcount); break;
  17501. case UFBXI_MESH_IMP_MAGIC: ufbxi_free_mesh_imp((ufbxi_mesh_imp*)refcount); break;
  17502. case UFBXI_LINE_CURVE_IMP_MAGIC: ufbxi_free_line_curve_imp((ufbxi_line_curve_imp*)refcount); break;
  17503. case UFBXI_CACHE_IMP_MAGIC: ufbxi_free_geometry_cache_imp((ufbxi_geometry_cache_imp*)refcount); break;
  17504. default: ufbx_assert(0 && "Bad refcount type_magic"); break;
  17505. }
  17506. refcount = parent;
  17507. }
  17508. }
  17509. // -- API
  17510. #ifdef __cplusplus
  17511. extern "C" {
  17512. #endif
  17513. const ufbx_string ufbx_empty_string = { ufbxi_empty_char, 0 };
  17514. const ufbx_blob ufbx_empty_blob = { NULL, 0 };
  17515. const ufbx_matrix ufbx_identity_matrix = { 1,0,0, 0,1,0, 0,0,1, 0,0,0 };
  17516. const ufbx_transform ufbx_identity_transform = { {0,0,0}, {0,0,0,1}, {1,1,1} };
  17517. const ufbx_vec2 ufbx_zero_vec2 = { 0,0 };
  17518. const ufbx_vec3 ufbx_zero_vec3 = { 0,0,0 };
  17519. const ufbx_vec4 ufbx_zero_vec4 = { 0,0,0,0 };
  17520. const ufbx_quat ufbx_identity_quat = { 0,0,0,1 };
  17521. const ufbx_coordinate_axes ufbx_axes_right_handed_y_up = {
  17522. UFBX_COORDINATE_AXIS_POSITIVE_X, UFBX_COORDINATE_AXIS_POSITIVE_Y, UFBX_COORDINATE_AXIS_POSITIVE_Z,
  17523. };
  17524. const ufbx_coordinate_axes ufbx_axes_right_handed_z_up = {
  17525. UFBX_COORDINATE_AXIS_POSITIVE_X, UFBX_COORDINATE_AXIS_POSITIVE_Z, UFBX_COORDINATE_AXIS_NEGATIVE_Y,
  17526. };
  17527. const ufbx_coordinate_axes ufbx_axes_left_handed_y_up = {
  17528. UFBX_COORDINATE_AXIS_POSITIVE_X, UFBX_COORDINATE_AXIS_POSITIVE_Y, UFBX_COORDINATE_AXIS_NEGATIVE_Z,
  17529. };
  17530. const ufbx_coordinate_axes ufbx_axes_left_handed_z_up = {
  17531. UFBX_COORDINATE_AXIS_POSITIVE_X, UFBX_COORDINATE_AXIS_POSITIVE_Z, UFBX_COORDINATE_AXIS_POSITIVE_Y,
  17532. };
  17533. const size_t ufbx_element_type_size[UFBX_ELEMENT_TYPE_COUNT] = {
  17534. sizeof(ufbx_unknown),
  17535. sizeof(ufbx_node),
  17536. sizeof(ufbx_mesh),
  17537. sizeof(ufbx_light),
  17538. sizeof(ufbx_camera),
  17539. sizeof(ufbx_bone),
  17540. sizeof(ufbx_empty),
  17541. sizeof(ufbx_line_curve),
  17542. sizeof(ufbx_nurbs_curve),
  17543. sizeof(ufbx_nurbs_surface),
  17544. sizeof(ufbx_nurbs_trim_surface),
  17545. sizeof(ufbx_nurbs_trim_boundary),
  17546. sizeof(ufbx_procedural_geometry),
  17547. sizeof(ufbx_stereo_camera),
  17548. sizeof(ufbx_camera_switcher),
  17549. sizeof(ufbx_marker),
  17550. sizeof(ufbx_lod_group),
  17551. sizeof(ufbx_skin_deformer),
  17552. sizeof(ufbx_skin_cluster),
  17553. sizeof(ufbx_blend_deformer),
  17554. sizeof(ufbx_blend_channel),
  17555. sizeof(ufbx_blend_shape),
  17556. sizeof(ufbx_cache_deformer),
  17557. sizeof(ufbx_cache_file),
  17558. sizeof(ufbx_material),
  17559. sizeof(ufbx_texture),
  17560. sizeof(ufbx_video),
  17561. sizeof(ufbx_shader),
  17562. sizeof(ufbx_shader_binding),
  17563. sizeof(ufbx_anim_stack),
  17564. sizeof(ufbx_anim_layer),
  17565. sizeof(ufbx_anim_value),
  17566. sizeof(ufbx_anim_curve),
  17567. sizeof(ufbx_display_layer),
  17568. sizeof(ufbx_selection_set),
  17569. sizeof(ufbx_selection_node),
  17570. sizeof(ufbx_character),
  17571. sizeof(ufbx_constraint),
  17572. sizeof(ufbx_pose),
  17573. sizeof(ufbx_metadata_object),
  17574. };
  17575. ufbx_abi bool ufbx_open_file(void *user, ufbx_stream *stream, const char *path, size_t path_len)
  17576. {
  17577. (void)user;
  17578. ufbxi_allocator tmp_ator = { 0 };
  17579. ufbx_error tmp_error = { UFBX_ERROR_NONE };
  17580. ufbxi_init_ator(&tmp_error, &tmp_ator, NULL);
  17581. FILE *f = ufbxi_fopen(path, path_len, &tmp_ator);
  17582. if (!f) return false;
  17583. stream->read_fn = &ufbxi_file_read;
  17584. stream->skip_fn = &ufbxi_file_skip;
  17585. stream->close_fn = &ufbxi_file_close;
  17586. stream->user = f;
  17587. return true;
  17588. }
  17589. ufbx_abi bool ufbx_is_thread_safe(void)
  17590. {
  17591. return UFBXI_THREAD_SAFE != 0;
  17592. }
  17593. ufbx_abi ufbx_scene *ufbx_load_memory(const void *data, size_t size, const ufbx_load_opts *opts, ufbx_error *error)
  17594. {
  17595. ufbxi_context uc = { UFBX_ERROR_NONE };
  17596. uc.data_begin = uc.data = (const char *)data;
  17597. uc.data_size = size;
  17598. uc.progress_bytes_total = size;
  17599. return ufbxi_load(&uc, opts, error);
  17600. }
  17601. ufbx_abi ufbx_scene *ufbx_load_file(const char *filename, const ufbx_load_opts *opts, ufbx_error *error)
  17602. {
  17603. return ufbx_load_file_len(filename, SIZE_MAX, opts, error);
  17604. }
  17605. ufbx_abi ufbx_scene *ufbx_load_file_len(const char *filename, size_t filename_len, const ufbx_load_opts *opts, ufbx_error *error)
  17606. {
  17607. ufbxi_allocator tmp_ator = { 0 };
  17608. ufbx_error tmp_error = { UFBX_ERROR_NONE };
  17609. ufbxi_init_ator(&tmp_error, &tmp_ator, opts ? &opts->temp_allocator : NULL);
  17610. FILE *file = ufbxi_fopen(filename, filename_len, &tmp_ator);
  17611. if (!file) {
  17612. if (error) {
  17613. error->stack_size = 1;
  17614. error->type = UFBX_ERROR_FILE_NOT_FOUND;
  17615. error->description.data = "File not found";
  17616. error->description.length = strlen(error->description.data);
  17617. error->stack[0].description.data = "File not found";
  17618. error->stack[0].description.length = strlen(error->stack[0].description.data);
  17619. error->stack[0].function.data = ufbxi_function;
  17620. error->stack[0].function.length = strlen(ufbxi_function);
  17621. error->stack[0].source_line = ufbxi_line;
  17622. }
  17623. return NULL;
  17624. }
  17625. ufbx_load_opts opts_copy;
  17626. if (opts) {
  17627. opts_copy = *opts;
  17628. } else {
  17629. memset(&opts_copy, 0, sizeof(opts_copy));
  17630. }
  17631. if (opts_copy.filename.length == 0 || opts_copy.filename.data == NULL) {
  17632. opts_copy.filename.data = filename;
  17633. opts_copy.filename.length = filename_len;
  17634. }
  17635. ufbx_scene *scene = ufbx_load_stdio(file, &opts_copy, error);
  17636. fclose(file);
  17637. return scene;
  17638. }
  17639. ufbx_abi ufbx_scene *ufbx_load_stdio(void *file_void, const ufbx_load_opts *opts, ufbx_error *error)
  17640. {
  17641. return ufbx_load_stdio_prefix(file_void, NULL, 0, opts, error);
  17642. }
  17643. ufbx_abi ufbx_scene *ufbx_load_stdio_prefix(void *file_void, const void *prefix, size_t prefix_size, const ufbx_load_opts *opts, ufbx_error *error)
  17644. {
  17645. FILE *file = (FILE*)file_void;
  17646. ufbxi_context uc = { UFBX_ERROR_NONE };
  17647. uc.data_begin = uc.data = (const char *)prefix;
  17648. uc.data_size = prefix_size;
  17649. uc.read_fn = &ufbxi_file_read;
  17650. uc.skip_fn = &ufbxi_file_skip;
  17651. uc.read_user = file;
  17652. if (opts && opts->progress_cb.fn && opts->file_size_estimate == 0) {
  17653. uint64_t begin = ufbxi_ftell(file);
  17654. if (begin < UINT64_MAX) {
  17655. fpos_t pos;
  17656. if (fgetpos(file, &pos) == 0) {
  17657. if (fseek(file, 0, SEEK_END) == 0) {
  17658. uint64_t end = ufbxi_ftell(file);
  17659. if (end != UINT64_MAX && begin < end) {
  17660. uc.progress_bytes_total = end - begin;
  17661. }
  17662. // Both `rewind()` and `fsetpos()` to reset error and EOF
  17663. rewind(file);
  17664. fsetpos(file, &pos);
  17665. }
  17666. }
  17667. }
  17668. }
  17669. ufbx_scene *scene = ufbxi_load(&uc, opts, error);
  17670. return scene;
  17671. }
  17672. ufbx_abi ufbx_scene *ufbx_load_stream(const ufbx_stream *stream, const ufbx_load_opts *opts, ufbx_error *error)
  17673. {
  17674. return ufbx_load_stream_prefix(stream, NULL, 0, opts, error);
  17675. }
  17676. ufbx_abi ufbx_scene *ufbx_load_stream_prefix(const ufbx_stream *stream, const void *prefix, size_t prefix_size, const ufbx_load_opts *opts, ufbx_error *error)
  17677. {
  17678. ufbxi_context uc = { UFBX_ERROR_NONE };
  17679. uc.data_begin = uc.data = (const char *)prefix;
  17680. uc.data_size = prefix_size;
  17681. uc.read_fn = stream->read_fn;
  17682. uc.skip_fn = stream->skip_fn;
  17683. uc.close_fn = stream->close_fn;
  17684. uc.read_user = stream->user;
  17685. ufbx_scene *scene = ufbxi_load(&uc, opts, error);
  17686. return scene;
  17687. }
  17688. ufbx_abi void ufbx_free_scene(ufbx_scene *scene)
  17689. {
  17690. if (!scene) return;
  17691. ufbxi_scene_imp *imp = ufbxi_get_imp(ufbxi_scene_imp, scene);
  17692. ufbx_assert(imp->magic == UFBXI_SCENE_IMP_MAGIC);
  17693. if (imp->magic != UFBXI_SCENE_IMP_MAGIC) return;
  17694. ufbxi_release_ref(&imp->refcount);
  17695. }
  17696. ufbx_abi void ufbx_retain_scene(ufbx_scene *scene)
  17697. {
  17698. if (!scene) return;
  17699. ufbxi_scene_imp *imp = ufbxi_get_imp(ufbxi_scene_imp, scene);
  17700. ufbx_assert(imp->magic == UFBXI_SCENE_IMP_MAGIC);
  17701. if (imp->magic != UFBXI_SCENE_IMP_MAGIC) return;
  17702. ufbxi_retain_ref(&imp->refcount);
  17703. }
  17704. ufbx_abi ufbxi_noinline size_t ufbx_format_error(char *dst, size_t dst_size, const ufbx_error *error)
  17705. {
  17706. if (!dst || !dst_size) return 0;
  17707. if (!error) {
  17708. *dst = '\0';
  17709. return 0;
  17710. }
  17711. size_t offset = 0;
  17712. {
  17713. int num = snprintf(dst + offset, dst_size - offset, "ufbx v%u.%u.%u error: %s\n",
  17714. UFBX_SOURCE_VERSION/1000000, UFBX_SOURCE_VERSION/1000%1000, UFBX_SOURCE_VERSION%1000,
  17715. error->description.data ? error->description.data : "Unknown error");
  17716. if (num > 0) offset = ufbxi_min_sz(offset + (size_t)num, dst_size - 1);
  17717. }
  17718. size_t stack_size = ufbxi_min_sz(error->stack_size, UFBX_ERROR_STACK_MAX_DEPTH);
  17719. for (size_t i = 0; i < stack_size; i++) {
  17720. const ufbx_error_frame *frame = &error->stack[i];
  17721. int num = snprintf(dst + offset, dst_size - offset, "%6u:%s: %s\n", frame->source_line, frame->function.data, frame->description.data);
  17722. if (num > 0) offset = ufbxi_min_sz(offset + (size_t)num, dst_size - 1);
  17723. }
  17724. // HACK: On some MSYS/MinGW implementations `snprintf` is broken and does
  17725. // not write the null terminator on trunctation, it's always safe to do so
  17726. // let's just do it unconditionally here...
  17727. dst[offset] = '\0';
  17728. return offset;
  17729. }
  17730. ufbx_abi ufbx_prop *ufbx_find_prop_len(const ufbx_props *props, const char *name, size_t name_len)
  17731. {
  17732. uint32_t key = ufbxi_get_name_key(name, name_len);
  17733. do {
  17734. ufbx_prop *prop_data = props->props.data;
  17735. size_t begin = 0;
  17736. size_t end = props->props.count;
  17737. while (end - begin >= 16) {
  17738. size_t mid = (begin + end) >> 1;
  17739. const ufbx_prop *p = &prop_data[mid];
  17740. if (p->_internal_key < key) {
  17741. begin = mid + 1;
  17742. } else {
  17743. end = mid;
  17744. }
  17745. }
  17746. end = props->props.count;
  17747. for (; begin < end; begin++) {
  17748. const ufbx_prop *p = &prop_data[begin];
  17749. if (p->_internal_key > key) break;
  17750. if (p->_internal_key == key && p->name.length == name_len && !memcmp(p->name.data, name, name_len)) {
  17751. return (ufbx_prop*)p;
  17752. }
  17753. }
  17754. props = props->defaults;
  17755. } while (props);
  17756. return NULL;
  17757. }
  17758. ufbx_abi ufbx_real ufbx_find_real_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_real def)
  17759. {
  17760. ufbx_prop *prop = ufbx_find_prop_len(props, name, name_len);
  17761. if (prop) {
  17762. return prop->value_real;
  17763. } else {
  17764. return def;
  17765. }
  17766. }
  17767. ufbx_abi ufbxi_noinline ufbx_vec3 ufbx_find_vec3_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_vec3 def)
  17768. {
  17769. ufbx_prop *prop = ufbx_find_prop_len(props, name, name_len);
  17770. if (prop) {
  17771. return prop->value_vec3;
  17772. } else {
  17773. return def;
  17774. }
  17775. }
  17776. ufbx_abi ufbxi_noinline int64_t ufbx_find_int_len(const ufbx_props *props, const char *name, size_t name_len, int64_t def)
  17777. {
  17778. ufbx_prop *prop = ufbx_find_prop_len(props, name, name_len);
  17779. if (prop) {
  17780. return prop->value_int;
  17781. } else {
  17782. return def;
  17783. }
  17784. }
  17785. ufbx_abi bool ufbx_find_bool_len(const ufbx_props *props, const char *name, size_t name_len, bool def)
  17786. {
  17787. ufbx_prop *prop = ufbx_find_prop_len(props, name, name_len);
  17788. if (prop) {
  17789. return prop->value_int != 0;
  17790. } else {
  17791. return def;
  17792. }
  17793. }
  17794. ufbx_abi ufbxi_noinline ufbx_string ufbx_find_string_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_string def)
  17795. {
  17796. ufbx_prop *prop = ufbx_find_prop_len(props, name, name_len);
  17797. if (prop) {
  17798. return prop->value_str;
  17799. } else {
  17800. return def;
  17801. }
  17802. }
  17803. ufbx_abi ufbx_blob ufbx_find_blob_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_blob def)
  17804. {
  17805. ufbx_prop *prop = ufbx_find_prop_len(props, name, name_len);
  17806. if (prop) {
  17807. return prop->value_blob;
  17808. } else {
  17809. return def;
  17810. }
  17811. }
  17812. ufbx_abi ufbx_element *ufbx_find_element_len(const ufbx_scene *scene, ufbx_element_type type, const char *name, size_t name_len)
  17813. {
  17814. if (!scene) return NULL;
  17815. ufbx_string name_str = { name, name_len };
  17816. uint32_t key = ufbxi_get_name_key(name, name_len);
  17817. size_t index = SIZE_MAX;
  17818. ufbxi_macro_lower_bound_eq(ufbx_name_element, 16, &index, scene->elements_by_name.data, 0, scene->elements_by_name.count,
  17819. ( ufbxi_cmp_name_element_less_ref(a, name_str, type, key) ), ( ufbxi_str_equal(a->name, name_str) && a->type == type ));
  17820. return index < SIZE_MAX ? scene->elements_by_name.data[index].element : NULL;
  17821. }
  17822. ufbx_abi ufbx_element *ufbx_get_prop_element(const ufbx_element *element, const ufbx_prop *prop, ufbx_element_type type)
  17823. {
  17824. ufbx_assert(element && prop);
  17825. if (!element || !prop) return NULL;
  17826. return ufbxi_fetch_dst_element((ufbx_element*)element, false, prop->name.data, type);
  17827. }
  17828. ufbx_abi ufbx_node *ufbx_find_node_len(const ufbx_scene *scene, const char *name, size_t name_len)
  17829. {
  17830. return (ufbx_node*)ufbx_find_element_len(scene, UFBX_ELEMENT_NODE, name, name_len);
  17831. }
  17832. ufbx_abi ufbx_anim_stack *ufbx_find_anim_stack_len(const ufbx_scene *scene, const char *name, size_t name_len)
  17833. {
  17834. return (ufbx_anim_stack*)ufbx_find_element_len(scene, UFBX_ELEMENT_ANIM_STACK, name, name_len);
  17835. }
  17836. ufbx_abi ufbx_anim_prop *ufbx_find_anim_prop_len(const ufbx_anim_layer *layer, const ufbx_element *element, const char *prop, size_t prop_len)
  17837. {
  17838. ufbx_assert(layer);
  17839. ufbx_assert(element);
  17840. if (!layer || !element) return NULL;
  17841. ufbx_string prop_str = { prop, prop_len };
  17842. size_t index = SIZE_MAX;
  17843. ufbxi_macro_lower_bound_eq(ufbx_anim_prop, 16, &index, layer->anim_props.data, 0, layer->anim_props.count,
  17844. ( a->element != element ? a->element < element : ufbxi_str_less(a->prop_name, prop_str) ),
  17845. ( a->element == element && ufbxi_str_equal(a->prop_name, prop_str) ));
  17846. if (index == SIZE_MAX) return NULL;
  17847. return &layer->anim_props.data[index];
  17848. }
  17849. ufbx_abi ufbxi_noinline ufbx_anim_prop_list ufbx_find_anim_props(const ufbx_anim_layer *layer, const ufbx_element *element)
  17850. {
  17851. ufbx_anim_prop_list result = { 0 };
  17852. ufbx_assert(layer);
  17853. ufbx_assert(element);
  17854. if (!layer || !element) return result;
  17855. size_t begin = layer->anim_props.count, end = begin;
  17856. ufbxi_macro_lower_bound_eq(ufbx_anim_prop, 16, &begin, layer->anim_props.data, 0, layer->anim_props.count,
  17857. ( a->element < element ), ( a->element == element ));
  17858. ufbxi_macro_upper_bound_eq(ufbx_anim_prop, 16, &end, layer->anim_props.data, begin, layer->anim_props.count,
  17859. ( a->element == element ));
  17860. if (begin != end) {
  17861. result.data = layer->anim_props.data + begin;
  17862. result.count = end - begin;
  17863. }
  17864. return result;
  17865. }
  17866. ufbx_abi ufbxi_noinline ufbx_matrix ufbx_get_compatible_matrix_for_normals(const ufbx_node *node)
  17867. {
  17868. if (!node) return ufbx_identity_matrix;
  17869. ufbx_transform geom_rot = ufbx_identity_transform;
  17870. geom_rot.rotation = node->geometry_transform.rotation;
  17871. ufbx_matrix geom_rot_mat = ufbx_transform_to_matrix(&geom_rot);
  17872. ufbx_matrix norm_mat = ufbx_matrix_mul(&node->node_to_world, &geom_rot_mat);
  17873. norm_mat = ufbx_matrix_for_normals(&norm_mat);
  17874. return norm_mat;
  17875. }
  17876. ufbx_abi ufbx_real ufbx_evaluate_curve(const ufbx_anim_curve *curve, double time, ufbx_real default_value)
  17877. {
  17878. if (!curve) return default_value;
  17879. if (curve->keyframes.count <= 1) {
  17880. if (curve->keyframes.count == 1) {
  17881. return curve->keyframes.data[0].value;
  17882. } else {
  17883. return default_value;
  17884. }
  17885. }
  17886. size_t begin = 0;
  17887. size_t end = curve->keyframes.count;
  17888. const ufbx_keyframe *keys = curve->keyframes.data;
  17889. while (end - begin >= 8) {
  17890. size_t mid = (begin + end) >> 1;
  17891. if (keys[mid].time < time) {
  17892. begin = mid + 1;
  17893. } else {
  17894. end = mid;
  17895. }
  17896. }
  17897. end = curve->keyframes.count;
  17898. for (; begin < end; begin++) {
  17899. const ufbx_keyframe *next = &keys[begin];
  17900. if (next->time < time) continue;
  17901. // First keyframe
  17902. if (begin == 0) return next->value;
  17903. const ufbx_keyframe *prev = next - 1;
  17904. double rcp_delta = 1.0 / (next->time - prev->time);
  17905. double t = (time - prev->time) * rcp_delta;
  17906. switch (prev->interpolation) {
  17907. case UFBX_INTERPOLATION_CONSTANT_PREV:
  17908. return prev->value;
  17909. case UFBX_INTERPOLATION_CONSTANT_NEXT:
  17910. return next->value;
  17911. case UFBX_INTERPOLATION_LINEAR:
  17912. return (ufbx_real)(prev->value*(1.0 - t) + next->value*t);
  17913. case UFBX_INTERPOLATION_CUBIC:
  17914. {
  17915. double x1 = prev->right.dx * rcp_delta;
  17916. double x2 = 1.0 - next->left.dx * rcp_delta;
  17917. t = ufbxi_find_cubic_bezier_t(x1, x2, t);
  17918. double t2 = t*t, t3 = t2*t;
  17919. double u = 1.0 - t, u2 = u*u, u3 = u2*u;
  17920. double y0 = prev->value;
  17921. double y3 = next->value;
  17922. double y1 = y0 + prev->right.dy;
  17923. double y2 = y3 - next->left.dy;
  17924. return (ufbx_real)(u3*y0 + 3.0 * (u2*t*y1 + u*t2*y2) + t3*y3);
  17925. }
  17926. default:
  17927. ufbx_assert(0 && "Bad interpolation mode");
  17928. return 0.0f;
  17929. }
  17930. }
  17931. // Last keyframe
  17932. return curve->keyframes.data[curve->keyframes.count - 1].value;
  17933. }
  17934. ufbx_abi ufbx_real ufbx_evaluate_anim_value_real(const ufbx_anim_value *anim_value, double time)
  17935. {
  17936. if (!anim_value) {
  17937. return 0.0f;
  17938. }
  17939. ufbx_real res = anim_value->default_value.x;
  17940. if (anim_value->curves[0]) res = ufbx_evaluate_curve(anim_value->curves[0], time, res);
  17941. return res;
  17942. }
  17943. ufbx_abi ufbxi_noinline ufbx_vec2 ufbx_evaluate_anim_value_vec2(const ufbx_anim_value *anim_value, double time)
  17944. {
  17945. if (!anim_value) {
  17946. ufbx_vec2 zero = { 0.0f };
  17947. return zero;
  17948. }
  17949. ufbx_vec2 res = { anim_value->default_value.x, anim_value->default_value.y };
  17950. if (anim_value->curves[0]) res.x = ufbx_evaluate_curve(anim_value->curves[0], time, res.x);
  17951. if (anim_value->curves[1]) res.y = ufbx_evaluate_curve(anim_value->curves[1], time, res.y);
  17952. return res;
  17953. }
  17954. ufbx_abi ufbxi_noinline ufbx_vec3 ufbx_evaluate_anim_value_vec3(const ufbx_anim_value *anim_value, double time)
  17955. {
  17956. if (!anim_value) {
  17957. ufbx_vec3 zero = { 0.0f };
  17958. return zero;
  17959. }
  17960. ufbx_vec3 res = anim_value->default_value;
  17961. if (anim_value->curves[0]) res.x = ufbx_evaluate_curve(anim_value->curves[0], time, res.x);
  17962. if (anim_value->curves[1]) res.y = ufbx_evaluate_curve(anim_value->curves[1], time, res.y);
  17963. if (anim_value->curves[2]) res.z = ufbx_evaluate_curve(anim_value->curves[2], time, res.z);
  17964. return res;
  17965. }
  17966. ufbx_abi ufbxi_noinline ufbx_prop ufbx_evaluate_prop_len(const ufbx_anim *anim, const ufbx_element *element, const char *name, size_t name_len, double time)
  17967. {
  17968. ufbx_prop result;
  17969. ufbx_prop *prop = ufbx_find_prop_len(&element->props, name, name_len);
  17970. if (prop) {
  17971. result = *prop;
  17972. } else {
  17973. memset(&result, 0, sizeof(result));
  17974. result.name.data = name;
  17975. result.name.length = name_len;
  17976. result._internal_key = ufbxi_get_name_key(name, name_len);
  17977. result.flags = UFBX_PROP_FLAG_NOT_FOUND;
  17978. result.value_str.data = ufbxi_empty_char;
  17979. result.value_str.length = 0;
  17980. result.value_blob.data = NULL;
  17981. result.value_blob.size = 0;
  17982. }
  17983. if (anim->prop_overrides.count > 0) {
  17984. ufbxi_find_prop_override(&anim->prop_overrides, element->element_id, &result);
  17985. return result;
  17986. }
  17987. if ((result.flags & (UFBX_PROP_FLAG_ANIMATED|UFBX_PROP_FLAG_CONNECTED)) == 0) return result;
  17988. if ((prop->flags & UFBX_PROP_FLAG_CONNECTED) != 0 && !anim->ignore_connections) {
  17989. ufbxi_evaluate_connected_prop(&result, anim, element, prop->name.data, time);
  17990. }
  17991. ufbxi_evaluate_props(anim, element, time, &result, 1);
  17992. return result;
  17993. }
  17994. ufbx_abi ufbxi_noinline ufbx_props ufbx_evaluate_props(const ufbx_anim *anim, const ufbx_element *element, double time, ufbx_prop *buffer, size_t buffer_size)
  17995. {
  17996. ufbx_props ret = { NULL };
  17997. if (!element) return ret;
  17998. const ufbx_prop_override *over = NULL, *over_end = NULL;
  17999. if (anim->prop_overrides.count > 0) {
  18000. ufbx_const_prop_override_list list = ufbxi_find_element_prop_overrides(&anim->prop_overrides, element->element_id);
  18001. over = list.data;
  18002. over_end = over + list.count;
  18003. }
  18004. size_t num_anim = 0;
  18005. ufbxi_for_list(ufbx_prop, prop, element->props.props) {
  18006. bool found_override = false;
  18007. for (; over != over_end && num_anim < buffer_size; over++) {
  18008. ufbx_prop *dst = &buffer[num_anim];
  18009. if (over->_internal_key < prop->_internal_key
  18010. || (over->_internal_key == prop->_internal_key && strcmp(over->prop_name, prop->name.data) < 0)) {
  18011. dst->name = ufbxi_str_c(over->prop_name);
  18012. dst->_internal_key = over->_internal_key;
  18013. dst->type = UFBX_PROP_UNKNOWN;
  18014. dst->flags = UFBX_PROP_FLAG_OVERRIDDEN;
  18015. } else if (over->_internal_key == prop->_internal_key && strcmp(over->prop_name, prop->name.data) == 0) {
  18016. *dst = *prop;
  18017. dst->flags = (ufbx_prop_flags)(dst->flags | UFBX_PROP_FLAG_OVERRIDDEN);
  18018. } else {
  18019. break;
  18020. }
  18021. dst->value_str = ufbxi_str_c(over->value_str);
  18022. dst->value_blob.data = dst->value_str.data;
  18023. dst->value_blob.size = dst->value_str.length;
  18024. dst->value_int = over->value_int;
  18025. dst->value_vec3 = over->value;
  18026. dst->value_real_arr[3] = 0.0f;
  18027. num_anim++;
  18028. found_override = true;
  18029. }
  18030. if (!(prop->flags & (UFBX_PROP_FLAG_ANIMATED|UFBX_PROP_FLAG_CONNECTED))) continue;
  18031. if (num_anim >= buffer_size) break;
  18032. if (found_override) continue;
  18033. ufbx_prop *dst = &buffer[num_anim++];
  18034. *dst = *prop;
  18035. if ((prop->flags & UFBX_PROP_FLAG_CONNECTED) != 0 && !anim->ignore_connections) {
  18036. ufbxi_evaluate_connected_prop(dst, anim, element, prop->name.data, time);
  18037. }
  18038. }
  18039. for (; over != over_end && num_anim < buffer_size; over++) {
  18040. ufbx_prop *dst = &buffer[num_anim++];
  18041. dst->name = ufbxi_str_c(over->prop_name);
  18042. dst->_internal_key = over->_internal_key;
  18043. dst->type = UFBX_PROP_UNKNOWN;
  18044. dst->flags = UFBX_PROP_FLAG_OVERRIDDEN;
  18045. dst->value_str = ufbxi_str_c(over->value_str);
  18046. dst->value_blob.data = dst->value_str.data;
  18047. dst->value_blob.size = dst->value_str.length;
  18048. dst->value_int = over->value_int;
  18049. dst->value_vec3 = over->value;
  18050. dst->value_real_arr[3] = 0.0f;
  18051. }
  18052. ufbxi_evaluate_props(anim, element, time, buffer, num_anim);
  18053. ret.props.data = buffer;
  18054. ret.props.count = ret.num_animated = num_anim;
  18055. ret.defaults = (ufbx_props*)&element->props;
  18056. return ret;
  18057. }
  18058. ufbx_abi ufbxi_noinline ufbx_transform ufbx_evaluate_transform(const ufbx_anim *anim, const ufbx_node *node, double time)
  18059. {
  18060. ufbx_assert(anim);
  18061. ufbx_assert(node);
  18062. if (!node) return ufbx_identity_transform;
  18063. if (!anim) return node->local_transform;
  18064. if (node->is_root) return node->local_transform;
  18065. const char *prop_names[] = {
  18066. ufbxi_Lcl_Rotation,
  18067. ufbxi_Lcl_Scaling,
  18068. ufbxi_Lcl_Translation,
  18069. ufbxi_PostRotation,
  18070. ufbxi_PreRotation,
  18071. ufbxi_RotationOffset,
  18072. ufbxi_RotationOrder,
  18073. ufbxi_RotationPivot,
  18074. ufbxi_ScalingOffset,
  18075. ufbxi_ScalingPivot,
  18076. };
  18077. ufbx_prop buf[ufbxi_arraycount(prop_names)];
  18078. ufbx_props props = ufbxi_evaluate_selected_props(anim, &node->element, time, buf, prop_names, ufbxi_arraycount(prop_names));
  18079. ufbx_rotation_order order = (ufbx_rotation_order)ufbxi_find_enum(&props, ufbxi_RotationOrder, UFBX_ROTATION_XYZ, UFBX_ROTATION_SPHERIC);
  18080. return ufbxi_get_transform(&props, order);
  18081. }
  18082. ufbx_abi ufbx_real ufbx_evaluate_blend_weight(const ufbx_anim *anim, const ufbx_blend_channel *channel, double time)
  18083. {
  18084. const char *prop_names[] = {
  18085. ufbxi_DeformPercent,
  18086. };
  18087. ufbx_prop buf[ufbxi_arraycount(prop_names)];
  18088. ufbx_props props = ufbxi_evaluate_selected_props(anim, &channel->element, time, buf, prop_names, ufbxi_arraycount(prop_names));
  18089. return ufbxi_find_real(&props, ufbxi_DeformPercent, channel->weight * (ufbx_real)100.0) * (ufbx_real)0.01;
  18090. }
  18091. ufbx_abi ufbx_const_prop_override_list ufbx_prepare_prop_overrides(ufbx_prop_override *overrides, size_t num_overrides)
  18092. {
  18093. ufbxi_for(ufbx_prop_override, over, overrides, num_overrides) {
  18094. if (over->prop_name == NULL) {
  18095. over->prop_name = ufbxi_empty_char;
  18096. }
  18097. if (over->value_str == NULL) {
  18098. over->value_str = ufbxi_empty_char;
  18099. }
  18100. if (over->value_int == 0) {
  18101. over->value_int = ufbxi_f64_to_i64(over->value.x);
  18102. } else if (over->value.x == 0.0) {
  18103. over->value.x = (ufbx_real)over->value_int;
  18104. }
  18105. size_t len = strlen(over->prop_name);
  18106. over->prop_name = ufbxi_find_canonical_string(over->prop_name, len);
  18107. over->_internal_key = ufbxi_get_name_key(over->prop_name, len);
  18108. }
  18109. // TODO: Macro for non-stable sort
  18110. qsort(overrides, num_overrides, sizeof(ufbx_prop_override), &ufbxi_cmp_prop_override);
  18111. ufbx_const_prop_override_list result;
  18112. result.data = overrides;
  18113. result.count = num_overrides;
  18114. return result;
  18115. }
  18116. ufbx_abi ufbx_scene *ufbx_evaluate_scene(const ufbx_scene *scene, const ufbx_anim *anim, double time, const ufbx_evaluate_opts *opts, ufbx_error *error)
  18117. {
  18118. #if UFBXI_FEATURE_SCENE_EVALUATION
  18119. ufbxi_eval_context ec = { 0 };
  18120. return ufbxi_evaluate_scene(&ec, (ufbx_scene*)scene, anim, time, opts, error);
  18121. #else
  18122. if (error) {
  18123. memset(error, 0, sizeof(ufbx_error));
  18124. ufbxi_report_err_msg(error, "UFBXI_FEATURE_SCENE_EVALUATION", "Feature disabled");
  18125. }
  18126. return NULL;
  18127. #endif
  18128. }
  18129. ufbx_abi ufbx_texture *ufbx_find_prop_texture_len(const ufbx_material *material, const char *name, size_t name_len)
  18130. {
  18131. ufbx_string name_str = { name, name_len };
  18132. if (!material) return NULL;
  18133. size_t index = SIZE_MAX;
  18134. ufbxi_macro_lower_bound_eq(ufbx_material_texture, 4, &index, material->textures.data, 0, material->textures.count,
  18135. ( ufbxi_str_less(a->material_prop, name_str) ), ( ufbxi_str_equal(a->material_prop, name_str) ));
  18136. return index < SIZE_MAX ? material->textures.data[index].texture : NULL;
  18137. }
  18138. ufbx_abi ufbx_string ufbx_find_shader_prop_len(const ufbx_shader *shader, const char *name, size_t name_len)
  18139. {
  18140. ufbx_string name_str = { name, name_len };
  18141. ufbx_shader_prop_binding_list bindings = ufbx_find_shader_prop_bindings_len(shader, name, name_len);
  18142. if (bindings.count > 0) {
  18143. return bindings.data[0].shader_prop;
  18144. }
  18145. return name_str;
  18146. }
  18147. ufbx_abi ufbx_shader_prop_binding_list ufbx_find_shader_prop_bindings_len(const ufbx_shader *shader, const char *name, size_t name_len)
  18148. {
  18149. ufbx_shader_prop_binding_list bindings = { NULL, 0 };
  18150. ufbx_string name_str = { name, name_len };
  18151. if (!shader) return bindings;
  18152. ufbxi_for_ptr_list(ufbx_shader_binding, p_bind, shader->bindings) {
  18153. ufbx_shader_binding *bind = *p_bind;
  18154. size_t begin = SIZE_MAX;
  18155. ufbxi_macro_lower_bound_eq(ufbx_shader_prop_binding, 4, &begin, bind->prop_bindings.data, 0, bind->prop_bindings.count,
  18156. ( ufbxi_str_less(a->shader_prop, name_str) ), ( ufbxi_str_equal(a->shader_prop, name_str) ));
  18157. if (begin != SIZE_MAX) {
  18158. size_t end = begin;
  18159. ufbxi_macro_upper_bound_eq(ufbx_shader_prop_binding, 4, &end, bind->prop_bindings.data, begin, bind->prop_bindings.count,
  18160. ( ufbxi_str_equal(a->shader_prop, name_str) ));
  18161. bindings.data = bind->prop_bindings.data + begin;
  18162. bindings.count = end - begin;
  18163. break;
  18164. }
  18165. }
  18166. return bindings;
  18167. }
  18168. ufbx_abi ufbx_shader_texture_input *ufbx_find_shader_texture_input_len(const ufbx_shader_texture *shader, const char *name, size_t name_len)
  18169. {
  18170. ufbx_string name_str = { name, name_len };
  18171. size_t index = SIZE_MAX;
  18172. ufbxi_macro_lower_bound_eq(ufbx_shader_texture_input, 4, &index, shader->inputs.data, 0, shader->inputs.count,
  18173. ( ufbxi_str_less(a->name, name_str) ), ( ufbxi_str_equal(a->name, name_str) ));
  18174. if (index != SIZE_MAX) {
  18175. return &shader->inputs.data[index];
  18176. }
  18177. return NULL;
  18178. }
  18179. ufbx_abi bool ufbx_coordinate_axes_valid(ufbx_coordinate_axes axes)
  18180. {
  18181. if (axes.right < UFBX_COORDINATE_AXIS_POSITIVE_X || axes.right > UFBX_COORDINATE_AXIS_NEGATIVE_Z) return false;
  18182. if (axes.up < UFBX_COORDINATE_AXIS_POSITIVE_X || axes.up > UFBX_COORDINATE_AXIS_NEGATIVE_Z) return false;
  18183. if (axes.front < UFBX_COORDINATE_AXIS_POSITIVE_X || axes.front > UFBX_COORDINATE_AXIS_NEGATIVE_Z) return false;
  18184. // Check that all the positive/negative axes are used
  18185. uint32_t mask = 0;
  18186. mask |= 1u << ((uint32_t)axes.right >> 1);
  18187. mask |= 1u << ((uint32_t)axes.up >> 1);
  18188. mask |= 1u << ((uint32_t)axes.front >> 1);
  18189. return (mask & 0x7u) == 0x7u;
  18190. }
  18191. ufbx_abi ufbx_quat ufbx_quat_mul(ufbx_quat a, ufbx_quat b)
  18192. {
  18193. return ufbxi_mul_quat(a, b);
  18194. }
  18195. ufbx_abi ufbxi_noinline ufbx_real ufbx_quat_dot(ufbx_quat a, ufbx_quat b)
  18196. {
  18197. return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
  18198. }
  18199. ufbx_abi ufbxi_noinline ufbx_quat ufbx_quat_normalize(ufbx_quat q)
  18200. {
  18201. ufbx_real norm = ufbx_quat_dot(q, q);
  18202. if (norm == 0.0) return ufbx_identity_quat;
  18203. q.x /= norm;
  18204. q.y /= norm;
  18205. q.z /= norm;
  18206. q.w /= norm;
  18207. return q;
  18208. }
  18209. ufbx_abi ufbxi_noinline ufbx_quat ufbx_quat_fix_antipodal(ufbx_quat q, ufbx_quat reference)
  18210. {
  18211. if (ufbx_quat_dot(q, reference) < 0.0f) {
  18212. q.x = -q.x; q.y = -q.y; q.z = -q.z; q.w = -q.w;
  18213. }
  18214. return q;
  18215. }
  18216. ufbx_abi ufbxi_noinline ufbx_quat ufbx_quat_slerp(ufbx_quat a, ufbx_quat b, ufbx_real t)
  18217. {
  18218. double dot = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
  18219. if (dot < 0.0) {
  18220. dot = -dot;
  18221. b.x = -b.x; b.y = -b.y; b.z = -b.z; b.w = -b.w;
  18222. }
  18223. double omega = ufbx_acos(ufbx_fmin(ufbx_fmax(dot, 0.0), 1.0));
  18224. if (omega <= 1.175494351e-38f) return a;
  18225. double rcp_so = 1.0 / ufbx_sin(omega);
  18226. double af = ufbx_sin((1.0 - t) * omega) * rcp_so;
  18227. double bf = ufbx_sin(t * omega) * rcp_so;
  18228. double x = af*a.x + bf*b.x;
  18229. double y = af*a.y + bf*b.y;
  18230. double z = af*a.z + bf*b.z;
  18231. double w = af*a.w + bf*b.w;
  18232. double rcp_len = 1.0 / ufbx_sqrt(x*x + y*y + z*z + w*w);
  18233. ufbx_quat ret;
  18234. ret.x = (ufbx_real)(x * rcp_len);
  18235. ret.y = (ufbx_real)(y * rcp_len);
  18236. ret.z = (ufbx_real)(z * rcp_len);
  18237. ret.w = (ufbx_real)(w * rcp_len);
  18238. return ret;
  18239. }
  18240. ufbx_abi ufbxi_noinline ufbx_vec3 ufbx_quat_rotate_vec3(ufbx_quat q, ufbx_vec3 v)
  18241. {
  18242. ufbx_real xy = q.x*v.y - q.y*v.x;
  18243. ufbx_real xz = q.x*v.z - q.z*v.x;
  18244. ufbx_real yz = q.y*v.z - q.z*v.y;
  18245. ufbx_vec3 r;
  18246. r.x = 2.0f * (+ q.w*yz + q.y*xy + q.z*xz) + v.x;
  18247. r.y = 2.0f * (- q.x*xy - q.w*xz + q.z*yz) + v.y;
  18248. r.z = 2.0f * (- q.x*xz - q.y*yz + q.w*xy) + v.z;
  18249. return r;
  18250. }
  18251. ufbx_abi ufbxi_noinline ufbx_quat ufbx_euler_to_quat(ufbx_vec3 v, ufbx_rotation_order order)
  18252. {
  18253. v.x *= UFBXI_DEG_TO_RAD * 0.5;
  18254. v.y *= UFBXI_DEG_TO_RAD * 0.5;
  18255. v.z *= UFBXI_DEG_TO_RAD * 0.5;
  18256. double cx = ufbx_cos((double)v.x), sx = ufbx_sin((double)v.x);
  18257. double cy = ufbx_cos((double)v.y), sy = ufbx_sin((double)v.y);
  18258. double cz = ufbx_cos((double)v.z), sz = ufbx_sin((double)v.z);
  18259. ufbx_quat q;
  18260. // Generated by `misc/gen_rotation_order.py`
  18261. switch (order) {
  18262. case UFBX_ROTATION_XYZ:
  18263. q.x = (ufbx_real)(-cx*sy*sz + cy*cz*sx);
  18264. q.y = (ufbx_real)(cx*cz*sy + cy*sx*sz);
  18265. q.z = (ufbx_real)(cx*cy*sz - cz*sx*sy);
  18266. q.w = (ufbx_real)(cx*cy*cz + sx*sy*sz);
  18267. break;
  18268. case UFBX_ROTATION_XZY:
  18269. q.x = (ufbx_real)(cx*sy*sz + cy*cz*sx);
  18270. q.y = (ufbx_real)(cx*cz*sy + cy*sx*sz);
  18271. q.z = (ufbx_real)(cx*cy*sz - cz*sx*sy);
  18272. q.w = (ufbx_real)(cx*cy*cz - sx*sy*sz);
  18273. break;
  18274. case UFBX_ROTATION_YZX:
  18275. q.x = (ufbx_real)(-cx*sy*sz + cy*cz*sx);
  18276. q.y = (ufbx_real)(cx*cz*sy - cy*sx*sz);
  18277. q.z = (ufbx_real)(cx*cy*sz + cz*sx*sy);
  18278. q.w = (ufbx_real)(cx*cy*cz + sx*sy*sz);
  18279. break;
  18280. case UFBX_ROTATION_YXZ:
  18281. q.x = (ufbx_real)(-cx*sy*sz + cy*cz*sx);
  18282. q.y = (ufbx_real)(cx*cz*sy + cy*sx*sz);
  18283. q.z = (ufbx_real)(cx*cy*sz + cz*sx*sy);
  18284. q.w = (ufbx_real)(cx*cy*cz - sx*sy*sz);
  18285. break;
  18286. case UFBX_ROTATION_ZXY:
  18287. q.x = (ufbx_real)(cx*sy*sz + cy*cz*sx);
  18288. q.y = (ufbx_real)(cx*cz*sy - cy*sx*sz);
  18289. q.z = (ufbx_real)(cx*cy*sz - cz*sx*sy);
  18290. q.w = (ufbx_real)(cx*cy*cz + sx*sy*sz);
  18291. break;
  18292. case UFBX_ROTATION_ZYX:
  18293. q.x = (ufbx_real)(cx*sy*sz + cy*cz*sx);
  18294. q.y = (ufbx_real)(cx*cz*sy - cy*sx*sz);
  18295. q.z = (ufbx_real)(cx*cy*sz + cz*sx*sy);
  18296. q.w = (ufbx_real)(cx*cy*cz - sx*sy*sz);
  18297. break;
  18298. default:
  18299. q.x = q.y = q.z = 0.0f; q.w = 1.0f;
  18300. break;
  18301. }
  18302. return q;
  18303. }
  18304. ufbx_abi ufbxi_noinline ufbx_vec3 ufbx_quat_to_euler(ufbx_quat q, ufbx_rotation_order order)
  18305. {
  18306. const double eps = 0.999999999;
  18307. ufbx_vec3 v;
  18308. double t;
  18309. double qx = q.x, qy = q.y, qz = q.z, qw = q.w;
  18310. // Generated by `misc/gen_quat_to_euler.py`
  18311. switch (order) {
  18312. case UFBX_ROTATION_XYZ:
  18313. t = 2.0f*(qw*qy - qx*qz);
  18314. if (ufbx_fabs(t) < eps) {
  18315. v.y = (ufbx_real)ufbx_asin(t);
  18316. v.z = (ufbx_real)ufbx_atan2(2.0f*(qw*qz + qx*qy), 2.0f*(qw*qw + qx*qx) - 1.0f);
  18317. v.x = (ufbx_real)-ufbx_atan2(-2.0f*(qw*qx + qy*qz), 2.0f*(qw*qw + qz*qz) - 1.0f);
  18318. } else {
  18319. v.y = (ufbx_real)ufbx_copysign(UFBXI_DPI*0.5, t);
  18320. v.z = (ufbx_real)(ufbx_atan2(-2.0f*t*(qw*qx - qy*qz), t*(2.0f*qw*qy + 2.0f*qx*qz)));
  18321. v.x = 0.0f;
  18322. }
  18323. break;
  18324. case UFBX_ROTATION_XZY:
  18325. t = 2.0f*(qw*qz + qx*qy);
  18326. if (ufbx_fabs(t) < eps) {
  18327. v.z = (ufbx_real)ufbx_asin(t);
  18328. v.y = (ufbx_real)ufbx_atan2(2.0f*(qw*qy - qx*qz), 2.0f*(qw*qw + qx*qx) - 1.0f);
  18329. v.x = (ufbx_real)-ufbx_atan2(-2.0f*(qw*qx - qy*qz), 2.0f*(qw*qw + qy*qy) - 1.0f);
  18330. } else {
  18331. v.z = (ufbx_real)ufbx_copysign(UFBXI_DPI*0.5, t);
  18332. v.y = (ufbx_real)(ufbx_atan2(2.0f*t*(qw*qx + qy*qz), -t*(2.0f*qx*qy - 2.0f*qw*qz)));
  18333. v.x = 0.0f;
  18334. }
  18335. break;
  18336. case UFBX_ROTATION_YZX:
  18337. t = 2.0f*(qw*qz - qx*qy);
  18338. if (ufbx_fabs(t) < eps) {
  18339. v.z = (ufbx_real)ufbx_asin(t);
  18340. v.x = (ufbx_real)ufbx_atan2(2.0f*(qw*qx + qy*qz), 2.0f*(qw*qw + qy*qy) - 1.0f);
  18341. v.y = (ufbx_real)-ufbx_atan2(-2.0f*(qw*qy + qx*qz), 2.0f*(qw*qw + qx*qx) - 1.0f);
  18342. } else {
  18343. v.z = (ufbx_real)ufbx_copysign(UFBXI_DPI*0.5, t);
  18344. v.x = (ufbx_real)(ufbx_atan2(-2.0f*t*(qw*qy - qx*qz), t*(2.0f*qw*qz + 2.0f*qx*qy)));
  18345. v.y = 0.0f;
  18346. }
  18347. break;
  18348. case UFBX_ROTATION_YXZ:
  18349. t = 2.0f*(qw*qx + qy*qz);
  18350. if (ufbx_fabs(t) < eps) {
  18351. v.x = (ufbx_real)ufbx_asin(t);
  18352. v.z = (ufbx_real)ufbx_atan2(2.0f*(qw*qz - qx*qy), 2.0f*(qw*qw + qy*qy) - 1.0f);
  18353. v.y = (ufbx_real)-ufbx_atan2(-2.0f*(qw*qy - qx*qz), 2.0f*(qw*qw + qz*qz) - 1.0f);
  18354. } else {
  18355. v.x = (ufbx_real)ufbx_copysign(UFBXI_DPI*0.5, t);
  18356. v.z = (ufbx_real)(ufbx_atan2(2.0f*t*(qw*qy + qx*qz), -t*(2.0f*qy*qz - 2.0f*qw*qx)));
  18357. v.y = 0.0f;
  18358. }
  18359. break;
  18360. case UFBX_ROTATION_ZXY:
  18361. t = 2.0f*(qw*qx - qy*qz);
  18362. if (ufbx_fabs(t) < eps) {
  18363. v.x = (ufbx_real)ufbx_asin(t);
  18364. v.y = (ufbx_real)ufbx_atan2(2.0f*(qw*qy + qx*qz), 2.0f*(qw*qw + qz*qz) - 1.0f);
  18365. v.z = (ufbx_real)-ufbx_atan2(-2.0f*(qw*qz + qx*qy), 2.0f*(qw*qw + qy*qy) - 1.0f);
  18366. } else {
  18367. v.x = (ufbx_real)ufbx_copysign(UFBXI_DPI*0.5, t);
  18368. v.y = (ufbx_real)(ufbx_atan2(-2.0f*t*(qw*qz - qx*qy), t*(2.0f*qw*qx + 2.0f*qy*qz)));
  18369. v.z = 0.0f;
  18370. }
  18371. break;
  18372. case UFBX_ROTATION_ZYX:
  18373. t = 2.0f*(qw*qy + qx*qz);
  18374. if (ufbx_fabs(t) < eps) {
  18375. v.y = (ufbx_real)ufbx_asin(t);
  18376. v.x = (ufbx_real)ufbx_atan2(2.0f*(qw*qx - qy*qz), 2.0f*(qw*qw + qz*qz) - 1.0f);
  18377. v.z = (ufbx_real)-ufbx_atan2(-2.0f*(qw*qz - qx*qy), 2.0f*(qw*qw + qx*qx) - 1.0f);
  18378. } else {
  18379. v.y = (ufbx_real)ufbx_copysign(UFBXI_DPI*0.5, t);
  18380. v.x = (ufbx_real)(ufbx_atan2(2.0f*t*(qw*qz + qx*qy), -t*(2.0f*qx*qz - 2.0f*qw*qy)));
  18381. v.z = 0.0f;
  18382. }
  18383. break;
  18384. default:
  18385. v.x = v.y = v.z = 0.0;
  18386. break;
  18387. }
  18388. v.x *= UFBXI_RAD_TO_DEG;
  18389. v.y *= UFBXI_RAD_TO_DEG;
  18390. v.z *= UFBXI_RAD_TO_DEG;
  18391. return v;
  18392. }
  18393. ufbx_abi ufbxi_noinline ufbx_matrix ufbx_matrix_mul(const ufbx_matrix *a, const ufbx_matrix *b)
  18394. {
  18395. ufbx_assert(a && b);
  18396. if (!a || !b) return ufbx_identity_matrix;
  18397. ufbx_matrix dst;
  18398. dst.m03 = a->m00*b->m03 + a->m01*b->m13 + a->m02*b->m23 + a->m03;
  18399. dst.m13 = a->m10*b->m03 + a->m11*b->m13 + a->m12*b->m23 + a->m13;
  18400. dst.m23 = a->m20*b->m03 + a->m21*b->m13 + a->m22*b->m23 + a->m23;
  18401. dst.m00 = a->m00*b->m00 + a->m01*b->m10 + a->m02*b->m20;
  18402. dst.m10 = a->m10*b->m00 + a->m11*b->m10 + a->m12*b->m20;
  18403. dst.m20 = a->m20*b->m00 + a->m21*b->m10 + a->m22*b->m20;
  18404. dst.m01 = a->m00*b->m01 + a->m01*b->m11 + a->m02*b->m21;
  18405. dst.m11 = a->m10*b->m01 + a->m11*b->m11 + a->m12*b->m21;
  18406. dst.m21 = a->m20*b->m01 + a->m21*b->m11 + a->m22*b->m21;
  18407. dst.m02 = a->m00*b->m02 + a->m01*b->m12 + a->m02*b->m22;
  18408. dst.m12 = a->m10*b->m02 + a->m11*b->m12 + a->m12*b->m22;
  18409. dst.m22 = a->m20*b->m02 + a->m21*b->m12 + a->m22*b->m22;
  18410. return dst;
  18411. }
  18412. ufbx_abi ufbx_real ufbx_matrix_determinant(const ufbx_matrix *m)
  18413. {
  18414. return
  18415. - m->m02*m->m11*m->m20 + m->m01*m->m12*m->m20 + m->m02*m->m10*m->m21
  18416. - m->m00*m->m12*m->m21 - m->m01*m->m10*m->m22 + m->m00*m->m11*m->m22;
  18417. }
  18418. ufbx_abi ufbx_matrix ufbx_matrix_invert(const ufbx_matrix *m)
  18419. {
  18420. ufbx_real det = ufbx_matrix_determinant(m);
  18421. ufbx_matrix r;
  18422. if (det == 0.0) {
  18423. memset(&r, 0, sizeof(r));
  18424. return r;
  18425. }
  18426. ufbx_real rcp_det = 1.0f / det;
  18427. r.m00 = ( - m->m12*m->m21 + m->m11*m->m22) * rcp_det;
  18428. r.m10 = ( + m->m12*m->m20 - m->m10*m->m22) * rcp_det;
  18429. r.m20 = ( - m->m11*m->m20 + m->m10*m->m21) * rcp_det;
  18430. r.m01 = ( + m->m02*m->m21 - m->m01*m->m22) * rcp_det;
  18431. r.m11 = ( - m->m02*m->m20 + m->m00*m->m22) * rcp_det;
  18432. r.m21 = ( + m->m01*m->m20 - m->m00*m->m21) * rcp_det;
  18433. r.m02 = ( - m->m02*m->m11 + m->m01*m->m12) * rcp_det;
  18434. r.m12 = ( + m->m02*m->m10 - m->m00*m->m12) * rcp_det;
  18435. r.m22 = ( - m->m01*m->m10 + m->m00*m->m11) * rcp_det;
  18436. r.m03 = (m->m03*m->m12*m->m21 - m->m02*m->m13*m->m21 - m->m03*m->m11*m->m22 + m->m01*m->m13*m->m22 + m->m02*m->m11*m->m23 - m->m01*m->m12*m->m23) * rcp_det;
  18437. r.m13 = (m->m02*m->m13*m->m20 - m->m03*m->m12*m->m20 + m->m03*m->m10*m->m22 - m->m00*m->m13*m->m22 - m->m02*m->m10*m->m23 + m->m00*m->m12*m->m23) * rcp_det;
  18438. r.m23 = (m->m03*m->m11*m->m20 - m->m01*m->m13*m->m20 - m->m03*m->m10*m->m21 + m->m00*m->m13*m->m21 + m->m01*m->m10*m->m23 - m->m00*m->m11*m->m23) * rcp_det;
  18439. return r;
  18440. }
  18441. ufbx_abi ufbxi_noinline ufbx_matrix ufbx_matrix_for_normals(const ufbx_matrix *m)
  18442. {
  18443. ufbx_real det = ufbx_matrix_determinant(m);
  18444. ufbx_matrix r;
  18445. if (det == 0.0) {
  18446. memset(&r, 0, sizeof(r));
  18447. return r;
  18448. }
  18449. ufbx_real rcp_det = 1.0f / det;
  18450. r.m00 = ( - m->m12*m->m21 + m->m11*m->m22) * rcp_det;
  18451. r.m01 = ( + m->m12*m->m20 - m->m10*m->m22) * rcp_det;
  18452. r.m02 = ( - m->m11*m->m20 + m->m10*m->m21) * rcp_det;
  18453. r.m10 = ( + m->m02*m->m21 - m->m01*m->m22) * rcp_det;
  18454. r.m11 = ( - m->m02*m->m20 + m->m00*m->m22) * rcp_det;
  18455. r.m12 = ( + m->m01*m->m20 - m->m00*m->m21) * rcp_det;
  18456. r.m20 = ( - m->m02*m->m11 + m->m01*m->m12) * rcp_det;
  18457. r.m21 = ( + m->m02*m->m10 - m->m00*m->m12) * rcp_det;
  18458. r.m22 = ( - m->m01*m->m10 + m->m00*m->m11) * rcp_det;
  18459. r.m03 = r.m13 = r.m23 = 0.0f;
  18460. return r;
  18461. }
  18462. ufbx_abi ufbxi_noinline ufbx_vec3 ufbx_transform_position(const ufbx_matrix *m, ufbx_vec3 v)
  18463. {
  18464. ufbx_assert(m);
  18465. if (!m) return ufbx_zero_vec3;
  18466. ufbx_vec3 r;
  18467. r.x = m->m00*v.x + m->m01*v.y + m->m02*v.z + m->m03;
  18468. r.y = m->m10*v.x + m->m11*v.y + m->m12*v.z + m->m13;
  18469. r.z = m->m20*v.x + m->m21*v.y + m->m22*v.z + m->m23;
  18470. return r;
  18471. }
  18472. ufbx_abi ufbxi_noinline ufbx_vec3 ufbx_transform_direction(const ufbx_matrix *m, ufbx_vec3 v)
  18473. {
  18474. ufbx_assert(m);
  18475. if (!m) return ufbx_zero_vec3;
  18476. ufbx_vec3 r;
  18477. r.x = m->m00*v.x + m->m01*v.y + m->m02*v.z;
  18478. r.y = m->m10*v.x + m->m11*v.y + m->m12*v.z;
  18479. r.z = m->m20*v.x + m->m21*v.y + m->m22*v.z;
  18480. return r;
  18481. }
  18482. ufbx_abi ufbxi_noinline ufbx_matrix ufbx_transform_to_matrix(const ufbx_transform *t)
  18483. {
  18484. ufbx_assert(t);
  18485. if (!t) return ufbx_identity_matrix;
  18486. ufbx_quat q = t->rotation;
  18487. ufbx_real sx = 2.0f * t->scale.x, sy = 2.0f * t->scale.y, sz = 2.0f * t->scale.z;
  18488. ufbx_real xx = q.x*q.x, xy = q.x*q.y, xz = q.x*q.z, xw = q.x*q.w;
  18489. ufbx_real yy = q.y*q.y, yz = q.y*q.z, yw = q.y*q.w;
  18490. ufbx_real zz = q.z*q.z, zw = q.z*q.w;
  18491. ufbx_matrix m;
  18492. m.m00 = sx * (- yy - zz + 0.5f);
  18493. m.m10 = sx * (+ xy + zw);
  18494. m.m20 = sx * (- yw + xz);
  18495. m.m01 = sy * (- zw + xy);
  18496. m.m11 = sy * (- xx - zz + 0.5f);
  18497. m.m21 = sy * (+ xw + yz);
  18498. m.m02 = sz * (+ xz + yw);
  18499. m.m12 = sz * (- xw + yz);
  18500. m.m22 = sz * (- xx - yy + 0.5f);
  18501. m.m03 = t->translation.x;
  18502. m.m13 = t->translation.y;
  18503. m.m23 = t->translation.z;
  18504. return m;
  18505. }
  18506. ufbx_abi ufbxi_noinline ufbx_transform ufbx_matrix_to_transform(const ufbx_matrix *m)
  18507. {
  18508. ufbx_assert(m);
  18509. if (!m) return ufbx_identity_transform;
  18510. ufbx_real det = ufbx_matrix_determinant(m);
  18511. ufbx_transform t;
  18512. t.translation = m->cols[3];
  18513. t.scale.x = ufbxi_length3(m->cols[0]);
  18514. t.scale.y = ufbxi_length3(m->cols[1]);
  18515. t.scale.z = ufbxi_length3(m->cols[2]);
  18516. // Flip a single non-zero axis if negative determinant
  18517. ufbx_real sign_x = 1.0f;
  18518. ufbx_real sign_y = 1.0f;
  18519. ufbx_real sign_z = 1.0f;
  18520. if (det < 0.0f) {
  18521. if (t.scale.x > 0.0f) sign_x = -1.0f;
  18522. else if (t.scale.y > 0.0f) sign_y = -1.0f;
  18523. else if (t.scale.z > 0.0f) sign_z = -1.0f;
  18524. }
  18525. ufbx_vec3 x = ufbxi_mul3(m->cols[0], t.scale.x > 0.0f ? sign_x / t.scale.x : 0.0f);
  18526. ufbx_vec3 y = ufbxi_mul3(m->cols[1], t.scale.y > 0.0f ? sign_y / t.scale.y : 0.0f);
  18527. ufbx_vec3 z = ufbxi_mul3(m->cols[2], t.scale.z > 0.0f ? sign_z / t.scale.z : 0.0f);
  18528. ufbx_real trace = x.x + y.y + z.z;
  18529. if (trace > 0.0f) {
  18530. ufbx_real a = (ufbx_real)ufbx_sqrt(ufbx_fmax(0.0, trace + 1.0)), b = (a != 0.0f) ? 0.5f / a : 0.0f;
  18531. t.rotation.x = (y.z - z.y) * b;
  18532. t.rotation.y = (z.x - x.z) * b;
  18533. t.rotation.z = (x.y - y.x) * b;
  18534. t.rotation.w = 0.5f * a;
  18535. } else if (x.x > y.y && x.x > z.z) {
  18536. ufbx_real a = (ufbx_real)ufbx_sqrt(ufbx_fmax(0.0, 1.0 + x.x - y.y - z.z)), b = (a != 0.0f) ? 0.5f / a : 0.0f;
  18537. t.rotation.x = 0.5f * a;
  18538. t.rotation.y = (y.x + x.y) * b;
  18539. t.rotation.z = (z.x + x.z) * b;
  18540. t.rotation.w = (y.z - z.y) * b;
  18541. }
  18542. else if (y.y > z.z) {
  18543. ufbx_real a = (ufbx_real)ufbx_sqrt(ufbx_fmax(0.0, 1.0 - x.x + y.y - z.z)), b = (a != 0.0f) ? 0.5f / a : 0.0f;
  18544. t.rotation.x = (y.x + x.y) * b;
  18545. t.rotation.y = 0.5f * a;
  18546. t.rotation.z = (z.y + y.z) * b;
  18547. t.rotation.w = (z.x - x.z) * b;
  18548. }
  18549. else {
  18550. ufbx_real a = (ufbx_real)ufbx_sqrt(ufbx_fmax(0.0, 1.0 - x.x - y.y + z.z)), b = (a != 0.0f) ? 0.5f / a : 0.0f;
  18551. t.rotation.x = (z.x + x.z) * b;
  18552. t.rotation.y = (z.y + y.z) * b;
  18553. t.rotation.z = 0.5f * a;
  18554. t.rotation.w = (x.y - y.x) * b;
  18555. }
  18556. ufbx_real len = t.rotation.x*t.rotation.x + t.rotation.y*t.rotation.y + t.rotation.z*t.rotation.z + t.rotation.w*t.rotation.w;
  18557. if (ufbx_fabs(len - 1.0f) > (ufbx_real)1e-20) {
  18558. if (len == 0.0f) {
  18559. t.rotation = ufbx_identity_quat;
  18560. } else {
  18561. t.rotation.x /= len;
  18562. t.rotation.y /= len;
  18563. t.rotation.z /= len;
  18564. t.rotation.w /= len;
  18565. }
  18566. }
  18567. t.scale.x *= sign_x;
  18568. t.scale.y *= sign_y;
  18569. t.scale.z *= sign_z;
  18570. return t;
  18571. }
  18572. ufbx_abi ufbxi_noinline ufbx_matrix ufbx_catch_get_skin_vertex_matrix(ufbx_panic *panic, const ufbx_skin_deformer *skin, size_t vertex, const ufbx_matrix *fallback)
  18573. {
  18574. ufbx_assert(skin);
  18575. if (ufbxi_panicf(panic, vertex < skin->vertices.count, "vertex (%zu) out of bounds (%zu)", vertex, skin->vertices.count)) return ufbx_identity_matrix;
  18576. if (!skin || vertex >= skin->vertices.count) return ufbx_identity_matrix;
  18577. ufbx_skin_vertex skin_vertex = skin->vertices.data[vertex];
  18578. ufbx_matrix mat = { 0.0f };
  18579. ufbx_quat q0 = { 0.0f }, qe = { 0.0f };
  18580. ufbx_quat first_q0 = { 0.0f };
  18581. ufbx_vec3 qs = { 0.0f, 0.0f, 0.0f };
  18582. ufbx_real total_weight = 0.0f;
  18583. for (uint32_t i = 0; i < skin_vertex.num_weights; i++) {
  18584. ufbx_skin_weight weight = skin->weights.data[skin_vertex.weight_begin + i];
  18585. ufbx_skin_cluster *cluster = skin->clusters.data[weight.cluster_index];
  18586. const ufbx_node *node = cluster->bone_node;
  18587. if (!node) continue;
  18588. total_weight += weight.weight;
  18589. if (skin_vertex.dq_weight > 0.0f) {
  18590. ufbx_transform t = cluster->geometry_to_world_transform;
  18591. ufbx_quat vq0 = t.rotation;
  18592. if (i == 0) first_q0 = vq0;
  18593. if (ufbx_quat_dot(first_q0, vq0) < 0.0f) {
  18594. vq0.x = -vq0.x;
  18595. vq0.y = -vq0.y;
  18596. vq0.z = -vq0.z;
  18597. vq0.w = -vq0.w;
  18598. }
  18599. ufbx_quat vqt = { 0.5f * t.translation.x, 0.5f * t.translation.y, 0.5f * t.translation.z };
  18600. ufbx_quat vqe = ufbxi_mul_quat(vqt, vq0);
  18601. ufbxi_add_weighted_quat(&q0, vq0, weight.weight);
  18602. ufbxi_add_weighted_quat(&qe, vqe, weight.weight);
  18603. ufbxi_add_weighted_vec3(&qs, t.scale, weight.weight);
  18604. }
  18605. if (skin_vertex.dq_weight < 1.0f) {
  18606. ufbxi_add_weighted_mat(&mat, &cluster->geometry_to_world, (1.0f-skin_vertex.dq_weight) * weight.weight);
  18607. }
  18608. }
  18609. if (total_weight <= 0.0f) {
  18610. if (fallback) {
  18611. return *fallback;
  18612. } else {
  18613. return ufbx_identity_matrix;
  18614. }
  18615. }
  18616. if (ufbx_fabs(total_weight - 1.0f) > (ufbx_real)1e-20) {
  18617. ufbx_real rcp_weight = 1.0f / total_weight;
  18618. if (skin_vertex.dq_weight > 0.0f) {
  18619. q0.x *= rcp_weight; q0.y *= rcp_weight; q0.z *= rcp_weight; q0.w *= rcp_weight;
  18620. qe.x *= rcp_weight; qe.y *= rcp_weight; qe.z *= rcp_weight; qe.w *= rcp_weight;
  18621. qs.x *= rcp_weight; qs.y *= rcp_weight; qs.z *= rcp_weight;
  18622. }
  18623. if (skin_vertex.dq_weight < 1.0f) {
  18624. mat.m00 *= rcp_weight; mat.m01 *= rcp_weight; mat.m02 *= rcp_weight; mat.m03 *= rcp_weight;
  18625. mat.m10 *= rcp_weight; mat.m11 *= rcp_weight; mat.m12 *= rcp_weight; mat.m13 *= rcp_weight;
  18626. mat.m20 *= rcp_weight; mat.m21 *= rcp_weight; mat.m22 *= rcp_weight; mat.m23 *= rcp_weight;
  18627. }
  18628. }
  18629. if (skin_vertex.dq_weight > 0.0f) {
  18630. ufbx_transform dqt;
  18631. ufbx_real rcp_len = (ufbx_real)(1.0 / ufbx_sqrt(q0.x*q0.x + q0.y*q0.y + q0.z*q0.z + q0.w*q0.w));
  18632. ufbx_real rcp_len2x2 = 2.0f * rcp_len * rcp_len;
  18633. dqt.rotation.x = q0.x * rcp_len;
  18634. dqt.rotation.y = q0.y * rcp_len;
  18635. dqt.rotation.z = q0.z * rcp_len;
  18636. dqt.rotation.w = q0.w * rcp_len;
  18637. dqt.scale.x = qs.x;
  18638. dqt.scale.y = qs.y;
  18639. dqt.scale.z = qs.z;
  18640. dqt.translation.x = rcp_len2x2 * (- qe.w*q0.x + qe.x*q0.w - qe.y*q0.z + qe.z*q0.y);
  18641. dqt.translation.y = rcp_len2x2 * (- qe.w*q0.y + qe.x*q0.z + qe.y*q0.w - qe.z*q0.x);
  18642. dqt.translation.z = rcp_len2x2 * (- qe.w*q0.z - qe.x*q0.y + qe.y*q0.x + qe.z*q0.w);
  18643. ufbx_matrix dqm = ufbx_transform_to_matrix(&dqt);
  18644. if (skin_vertex.dq_weight < 1.0f) {
  18645. ufbxi_add_weighted_mat(&mat, &dqm, skin_vertex.dq_weight);
  18646. } else {
  18647. mat = dqm;
  18648. }
  18649. }
  18650. return mat;
  18651. }
  18652. ufbx_abi ufbxi_noinline ufbx_vec3 ufbx_get_blend_shape_vertex_offset(const ufbx_blend_shape *shape, size_t vertex)
  18653. {
  18654. ufbx_assert(shape);
  18655. if (!shape) return ufbx_zero_vec3;
  18656. size_t index = SIZE_MAX;
  18657. uint32_t vertex_ix = (uint32_t)vertex;
  18658. ufbxi_macro_lower_bound_eq(uint32_t, 16, &index, shape->offset_vertices.data, 0, shape->num_offsets,
  18659. ( *a < vertex_ix ), ( *a == vertex_ix ));
  18660. if (index == SIZE_MAX) return ufbx_zero_vec3;
  18661. return shape->position_offsets.data[index];
  18662. }
  18663. ufbx_abi ufbxi_noinline ufbx_vec3 ufbx_get_blend_vertex_offset(const ufbx_blend_deformer *blend, size_t vertex)
  18664. {
  18665. ufbx_assert(blend);
  18666. if (!blend) return ufbx_zero_vec3;
  18667. ufbx_vec3 offset = ufbx_zero_vec3;
  18668. ufbxi_for_ptr_list(ufbx_blend_channel, p_chan, blend->channels) {
  18669. ufbx_blend_channel *chan = *p_chan;
  18670. ufbxi_for_list(ufbx_blend_keyframe, key, chan->keyframes) {
  18671. if (key->effective_weight == 0.0f) continue;
  18672. ufbx_vec3 key_offset = ufbx_get_blend_shape_vertex_offset(key->shape, vertex);
  18673. ufbxi_add_weighted_vec3(&offset, key_offset, key->effective_weight);
  18674. }
  18675. }
  18676. return offset;
  18677. }
  18678. ufbx_abi void ufbx_add_blend_shape_vertex_offsets(const ufbx_blend_shape *shape, ufbx_vec3 *vertices, size_t num_vertices, ufbx_real weight)
  18679. {
  18680. if (weight == 0.0f) return;
  18681. if (!vertices) return;
  18682. size_t num_offsets = shape->num_offsets;
  18683. uint32_t *vertex_indices = shape->offset_vertices.data;
  18684. ufbx_vec3 *offsets = shape->position_offsets.data;
  18685. for (size_t i = 0; i < num_offsets; i++) {
  18686. uint32_t index = vertex_indices[i];
  18687. if (index < num_vertices) {
  18688. ufbxi_add_weighted_vec3(&vertices[index], offsets[i], weight);
  18689. }
  18690. }
  18691. }
  18692. ufbx_abi void ufbx_add_blend_vertex_offsets(const ufbx_blend_deformer *blend, ufbx_vec3 *vertices, size_t num_vertices, ufbx_real weight)
  18693. {
  18694. ufbx_assert(blend);
  18695. if (!blend) return;
  18696. ufbxi_for_ptr_list(ufbx_blend_channel, p_chan, blend->channels) {
  18697. ufbx_blend_channel *chan = *p_chan;
  18698. ufbxi_for_list(ufbx_blend_keyframe, key, chan->keyframes) {
  18699. if (key->effective_weight == 0.0f) continue;
  18700. ufbx_add_blend_shape_vertex_offsets(key->shape, vertices, num_vertices, weight * key->effective_weight);
  18701. }
  18702. }
  18703. }
  18704. ufbx_abi size_t ufbx_evaluate_nurbs_basis(const ufbx_nurbs_basis *basis, ufbx_real u, ufbx_real *weights, size_t num_weights, ufbx_real *derivatives, size_t num_derivatives)
  18705. {
  18706. ufbx_assert(basis);
  18707. if (!basis) return SIZE_MAX;
  18708. if (basis->order == 0) return SIZE_MAX;
  18709. if (!basis->valid) return SIZE_MAX;
  18710. size_t degree = basis->order - 1;
  18711. ufbx_assert(degree >= 1);
  18712. // Binary search for the knot span `[min_u, max_u]` where `min_u <= u < max_u`
  18713. ufbx_real_list knots = basis->knot_vector;
  18714. size_t knot = SIZE_MAX;
  18715. if (u <= basis->t_min) {
  18716. knot = degree;
  18717. u = basis->t_min;
  18718. } else if (u >= basis->t_max) {
  18719. knot = basis->knot_vector.count - degree - 2;
  18720. u = basis->t_max;
  18721. } else {
  18722. ufbxi_macro_lower_bound_eq(ufbx_real, 8, &knot, knots.data, 0, knots.count - 1,
  18723. ( a[1] <= u ), ( a[0] <= u && u < a[1] ));
  18724. }
  18725. // The found effective control points are found left from `knot`, locally
  18726. // we use `knot - ix` here as it's more convenient for the following algorithm
  18727. // but we return it as `knot - degree` so that users can find the control points
  18728. // at `points[knot], points[knot+1], ..., points[knot+degree]`
  18729. if (knot < degree) return SIZE_MAX;
  18730. if (num_derivatives == 0) derivatives = NULL;
  18731. if (num_weights < basis->order) return knot - degree;
  18732. if (!weights) return knot - degree;
  18733. weights[0] = 1.0f;
  18734. for (size_t p = 1; p <= degree; p++) {
  18735. ufbx_real prev = 0.0f;
  18736. ufbx_real g = 1.0f - ufbxi_nurbs_weight(&knots, knot - p + 1, p, u);
  18737. ufbx_real dg = 0.0f;
  18738. if (derivatives && p == degree) {
  18739. dg = ufbxi_nurbs_deriv(&knots, knot - p + 1, p);
  18740. }
  18741. for (size_t i = p; i > 0; i--) {
  18742. ufbx_real f = ufbxi_nurbs_weight(&knots, knot - p + i, p, u);
  18743. ufbx_real weight = weights[i - 1];
  18744. weights[i] = f*weight + g*prev;
  18745. if (derivatives && p == degree) {
  18746. ufbx_real df = ufbxi_nurbs_deriv(&knots, knot - p + i, p);
  18747. if (i < num_derivatives) {
  18748. derivatives[i] = df*weight - dg*prev;
  18749. }
  18750. dg = df;
  18751. }
  18752. prev = weight;
  18753. g = 1.0f - f;
  18754. }
  18755. weights[0] = g*prev;
  18756. if (derivatives && p == degree) {
  18757. derivatives[0] = -dg*prev;
  18758. }
  18759. }
  18760. return knot - degree;
  18761. }
  18762. ufbx_abi ufbxi_noinline ufbx_curve_point ufbx_evaluate_nurbs_curve(const ufbx_nurbs_curve *curve, ufbx_real u)
  18763. {
  18764. ufbx_curve_point result = { false };
  18765. ufbx_assert(curve);
  18766. if (!curve) return result;
  18767. ufbx_real weights[UFBXI_MAX_NURBS_ORDER];
  18768. ufbx_real derivs[UFBXI_MAX_NURBS_ORDER];
  18769. size_t base = ufbx_evaluate_nurbs_basis(&curve->basis, u, weights, UFBXI_MAX_NURBS_ORDER, derivs, UFBXI_MAX_NURBS_ORDER);
  18770. if (base == SIZE_MAX) return result;
  18771. ufbx_vec4 p = { 0 };
  18772. ufbx_vec4 d = { 0 };
  18773. size_t order = curve->basis.order;
  18774. if (order > UFBXI_MAX_NURBS_ORDER) return result;
  18775. if (curve->control_points.count == 0) return result;
  18776. for (size_t i = 0; i < order; i++) {
  18777. size_t ix = (base + i) % curve->control_points.count;
  18778. ufbx_vec4 cp = curve->control_points.data[ix];
  18779. ufbx_real weight = weights[i] * cp.w, deriv = derivs[i] * cp.w;
  18780. p.x += cp.x * weight;
  18781. p.y += cp.y * weight;
  18782. p.z += cp.z * weight;
  18783. p.w += weight;
  18784. d.x += cp.x * deriv;
  18785. d.y += cp.y * deriv;
  18786. d.z += cp.z * deriv;
  18787. d.w += deriv;
  18788. }
  18789. ufbx_real rcp_w = 1.0f / p.w;
  18790. result.valid = true;
  18791. result.position.x = p.x * rcp_w;
  18792. result.position.y = p.y * rcp_w;
  18793. result.position.z = p.z * rcp_w;
  18794. result.derivative.x = (d.x - d.w*result.position.x) * rcp_w;
  18795. result.derivative.y = (d.y - d.w*result.position.y) * rcp_w;
  18796. result.derivative.z = (d.z - d.w*result.position.z) * rcp_w;
  18797. return result;
  18798. }
  18799. ufbx_abi ufbxi_noinline ufbx_surface_point ufbx_evaluate_nurbs_surface(const ufbx_nurbs_surface *surface, ufbx_real u, ufbx_real v)
  18800. {
  18801. ufbx_surface_point result = { false };
  18802. ufbx_assert(surface);
  18803. if (!surface) return result;
  18804. ufbx_real weights_u[UFBXI_MAX_NURBS_ORDER], weights_v[UFBXI_MAX_NURBS_ORDER];
  18805. ufbx_real derivs_u[UFBXI_MAX_NURBS_ORDER], derivs_v[UFBXI_MAX_NURBS_ORDER];
  18806. size_t base_u = ufbx_evaluate_nurbs_basis(&surface->basis_u, u, weights_u, UFBXI_MAX_NURBS_ORDER, derivs_u, UFBXI_MAX_NURBS_ORDER);
  18807. size_t base_v = ufbx_evaluate_nurbs_basis(&surface->basis_v, v, weights_v, UFBXI_MAX_NURBS_ORDER, derivs_v, UFBXI_MAX_NURBS_ORDER);
  18808. if (base_u == SIZE_MAX || base_v == SIZE_MAX) return result;
  18809. ufbx_vec4 p = { 0 };
  18810. ufbx_vec4 du = { 0 };
  18811. ufbx_vec4 dv = { 0 };
  18812. size_t num_u = surface->num_control_points_u;
  18813. size_t num_v = surface->num_control_points_v;
  18814. size_t order_u = surface->basis_u.order;
  18815. size_t order_v = surface->basis_v.order;
  18816. if (order_u > UFBXI_MAX_NURBS_ORDER || order_v > UFBXI_MAX_NURBS_ORDER) return result;
  18817. if (num_u == 0 || num_v == 0) return result;
  18818. for (size_t vi = 0; vi < order_v; vi++) {
  18819. size_t vix = (base_v + vi) % num_v;
  18820. ufbx_real weight_v = weights_v[vi], deriv_v = derivs_v[vi];
  18821. for (size_t ui = 0; ui < order_u; ui++) {
  18822. size_t uix = (base_u + ui) % num_u;
  18823. ufbx_real weight_u = weights_u[ui], deriv_u = derivs_u[ui];
  18824. ufbx_vec4 cp = surface->control_points.data[vix * num_u + uix];
  18825. ufbx_real weight = weight_u * weight_v * cp.w;
  18826. ufbx_real wderiv_u = deriv_u * weight_v * cp.w;
  18827. ufbx_real wderiv_v = deriv_v * weight_u * cp.w;
  18828. p.x += cp.x * weight;
  18829. p.y += cp.y * weight;
  18830. p.z += cp.z * weight;
  18831. p.w += weight;
  18832. du.x += cp.x * wderiv_u;
  18833. du.y += cp.y * wderiv_u;
  18834. du.z += cp.z * wderiv_u;
  18835. du.w += wderiv_u;
  18836. dv.x += cp.x * wderiv_v;
  18837. dv.y += cp.y * wderiv_v;
  18838. dv.z += cp.z * wderiv_v;
  18839. dv.w += wderiv_v;
  18840. }
  18841. }
  18842. ufbx_real rcp_w = 1.0f / p.w;
  18843. result.valid = true;
  18844. result.position.x = p.x * rcp_w;
  18845. result.position.y = p.y * rcp_w;
  18846. result.position.z = p.z * rcp_w;
  18847. result.derivative_u.x = (du.x - du.w*result.position.x) * rcp_w;
  18848. result.derivative_u.y = (du.y - du.w*result.position.y) * rcp_w;
  18849. result.derivative_u.z = (du.z - du.w*result.position.z) * rcp_w;
  18850. result.derivative_v.x = (dv.x - dv.w*result.position.x) * rcp_w;
  18851. result.derivative_v.y = (dv.y - dv.w*result.position.y) * rcp_w;
  18852. result.derivative_v.z = (dv.z - dv.w*result.position.z) * rcp_w;
  18853. return result;
  18854. }
  18855. ufbx_abi ufbx_line_curve *ufbx_tessellate_nurbs_curve(const ufbx_nurbs_curve *curve, const ufbx_tessellate_curve_opts *opts, ufbx_error *error)
  18856. {
  18857. #if UFBXI_FEATURE_TESSELLATION
  18858. ufbx_assert(curve);
  18859. if (!curve) return NULL;
  18860. ufbxi_tessellate_curve_context tc = { UFBX_ERROR_NONE };
  18861. if (opts) {
  18862. tc.opts = *opts;
  18863. }
  18864. tc.curve = curve;
  18865. int ok = ufbxi_tessellate_nurbs_curve_imp(&tc);
  18866. ufbxi_free_ator(&tc.ator_tmp);
  18867. if (ok) {
  18868. if (error) {
  18869. error->type = UFBX_ERROR_NONE;
  18870. error->description.data = ufbxi_empty_char;
  18871. error->description.length = 0;
  18872. error->stack_size = 0;
  18873. }
  18874. ufbxi_line_curve_imp *imp = tc.imp;
  18875. return &imp->curve;
  18876. } else {
  18877. ufbxi_fix_error_type(&tc.error, "Failed to tessellate");
  18878. if (error) *error = tc.error;
  18879. ufbxi_buf_free(&tc.result);
  18880. ufbxi_free_ator(&tc.ator_result);
  18881. return NULL;
  18882. }
  18883. #else
  18884. if (error) {
  18885. memset(error, 0, sizeof(ufbx_error));
  18886. ufbxi_report_err_msg(error, "UFBXI_FEATURE_TESSELLATION", "Feature disabled");
  18887. }
  18888. return NULL;
  18889. #endif
  18890. }
  18891. ufbx_abi ufbx_mesh *ufbx_tessellate_nurbs_surface(const ufbx_nurbs_surface *surface, const ufbx_tessellate_surface_opts *opts, ufbx_error *error)
  18892. {
  18893. #if UFBXI_FEATURE_TESSELLATION
  18894. ufbx_assert(surface);
  18895. if (!surface) return NULL;
  18896. ufbxi_tessellate_surface_context tc = { UFBX_ERROR_NONE };
  18897. if (opts) {
  18898. tc.opts = *opts;
  18899. }
  18900. tc.surface = surface;
  18901. int ok = ufbxi_tessellate_nurbs_surface_imp(&tc);
  18902. ufbxi_buf_free(&tc.tmp);
  18903. ufbxi_map_free(&tc.position_map);
  18904. ufbxi_free_ator(&tc.ator_tmp);
  18905. if (ok) {
  18906. if (error) {
  18907. error->type = UFBX_ERROR_NONE;
  18908. error->description.data = ufbxi_empty_char;
  18909. error->description.length = 0;
  18910. error->stack_size = 0;
  18911. }
  18912. ufbxi_mesh_imp *imp = tc.imp;
  18913. return &imp->mesh;
  18914. } else {
  18915. ufbxi_fix_error_type(&tc.error, "Failed to tessellate");
  18916. if (error) *error = tc.error;
  18917. ufbxi_buf_free(&tc.result);
  18918. ufbxi_free_ator(&tc.ator_result);
  18919. return NULL;
  18920. }
  18921. #else
  18922. if (error) {
  18923. memset(error, 0, sizeof(ufbx_error));
  18924. ufbxi_report_err_msg(error, "UFBXI_FEATURE_TESSELLATION", "Feature disabled");
  18925. }
  18926. return NULL;
  18927. #endif
  18928. }
  18929. ufbx_abi void ufbx_free_line_curve(ufbx_line_curve *line_curve)
  18930. {
  18931. if (!line_curve) return;
  18932. if (!line_curve->from_tessellated_nurbs) return;
  18933. ufbxi_line_curve_imp *imp = ufbxi_get_imp(ufbxi_line_curve_imp, line_curve);
  18934. ufbx_assert(imp->magic == UFBXI_LINE_CURVE_IMP_MAGIC);
  18935. if (imp->magic != UFBXI_LINE_CURVE_IMP_MAGIC) return;
  18936. ufbxi_release_ref(&imp->refcount);
  18937. }
  18938. ufbx_abi void ufbx_retain_line_curve(ufbx_line_curve *line_curve)
  18939. {
  18940. if (!line_curve) return;
  18941. if (!line_curve->from_tessellated_nurbs) return;
  18942. ufbxi_line_curve_imp *imp = ufbxi_get_imp(ufbxi_line_curve_imp, line_curve);
  18943. ufbx_assert(imp->magic == UFBXI_LINE_CURVE_IMP_MAGIC);
  18944. if (imp->magic != UFBXI_LINE_CURVE_IMP_MAGIC) return;
  18945. ufbxi_retain_ref(&imp->refcount);
  18946. }
  18947. ufbx_abi ufbxi_noinline uint32_t ufbx_catch_triangulate_face(ufbx_panic *panic, uint32_t *indices, size_t num_indices, const ufbx_mesh *mesh, ufbx_face face)
  18948. {
  18949. #if UFBXI_FEATURE_TRIANGULATION
  18950. if (face.num_indices < 3) return 0;
  18951. size_t required_indices = ((size_t)face.num_indices - 2) * 3;
  18952. if (ufbxi_panicf(panic, num_indices >= required_indices, "Face needs at least %zu indices for triangles, got space for %zu", required_indices, num_indices)) return 0;
  18953. if (ufbxi_panicf(panic, face.index_begin < mesh->num_indices, "Face index begin (%u) out of bounds (%zu)", face.index_begin, mesh->num_indices)) return 0;
  18954. if (ufbxi_panicf(panic, mesh->num_indices - face.index_begin >= face.num_indices, "Face index end (%u + %u) out of bounds (%zu)", face.index_begin, face.num_indices, mesh->num_indices)) return 0;
  18955. if (face.num_indices == 3) {
  18956. // Fast case: Already a triangle
  18957. indices[0] = face.index_begin + 0;
  18958. indices[1] = face.index_begin + 1;
  18959. indices[2] = face.index_begin + 2;
  18960. return 1;
  18961. } else if (face.num_indices == 4) {
  18962. // Quad: Split along the shortest axis unless a vertex crosses the axis
  18963. uint32_t i0 = face.index_begin + 0;
  18964. uint32_t i1 = face.index_begin + 1;
  18965. uint32_t i2 = face.index_begin + 2;
  18966. uint32_t i3 = face.index_begin + 3;
  18967. ufbx_vec3 v0 = mesh->vertex_position.values.data[mesh->vertex_position.indices.data[i0]];
  18968. ufbx_vec3 v1 = mesh->vertex_position.values.data[mesh->vertex_position.indices.data[i1]];
  18969. ufbx_vec3 v2 = mesh->vertex_position.values.data[mesh->vertex_position.indices.data[i2]];
  18970. ufbx_vec3 v3 = mesh->vertex_position.values.data[mesh->vertex_position.indices.data[i3]];
  18971. ufbx_vec3 a = ufbxi_sub3(v2, v0);
  18972. ufbx_vec3 b = ufbxi_sub3(v3, v1);
  18973. ufbx_vec3 na1 = ufbxi_normalize3(ufbxi_cross3(a, ufbxi_sub3(v1, v0)));
  18974. ufbx_vec3 na3 = ufbxi_normalize3(ufbxi_cross3(a, ufbxi_sub3(v0, v3)));
  18975. ufbx_vec3 nb0 = ufbxi_normalize3(ufbxi_cross3(b, ufbxi_sub3(v1, v0)));
  18976. ufbx_vec3 nb2 = ufbxi_normalize3(ufbxi_cross3(b, ufbxi_sub3(v2, v1)));
  18977. ufbx_real dot_aa = ufbxi_dot3(a, a);
  18978. ufbx_real dot_bb = ufbxi_dot3(b, b);
  18979. ufbx_real dot_na = ufbxi_dot3(na1, na3);
  18980. ufbx_real dot_nb = ufbxi_dot3(nb0, nb2);
  18981. bool split_a = dot_aa <= dot_bb;
  18982. if (dot_na < 0.0f || dot_nb < 0.0f) {
  18983. split_a = dot_na >= dot_nb;
  18984. }
  18985. if (split_a) {
  18986. indices[0] = i0;
  18987. indices[1] = i1;
  18988. indices[2] = i2;
  18989. indices[3] = i2;
  18990. indices[4] = i3;
  18991. indices[5] = i0;
  18992. } else {
  18993. indices[0] = i1;
  18994. indices[1] = i2;
  18995. indices[2] = i3;
  18996. indices[3] = i3;
  18997. indices[4] = i0;
  18998. indices[5] = i1;
  18999. }
  19000. return 2;
  19001. } else {
  19002. ufbxi_ngon_context nc = { 0 };
  19003. nc.positions = mesh->vertex_position;
  19004. nc.face = face;
  19005. uint32_t num_indices_u32 = num_indices < UINT32_MAX ? (uint32_t)num_indices : UINT32_MAX;
  19006. uint32_t local_indices[12];
  19007. if (num_indices_u32 < 12) {
  19008. uint32_t num_tris = ufbxi_triangulate_ngon(&nc, local_indices, 12);
  19009. memcpy(indices, local_indices, num_tris * 3 * sizeof(uint32_t));
  19010. return num_tris;
  19011. } else {
  19012. return ufbxi_triangulate_ngon(&nc, indices, num_indices_u32);
  19013. }
  19014. }
  19015. #else
  19016. ufbxi_panicf_imp(panic, "Triangulation disabled");
  19017. return 0;
  19018. #endif
  19019. }
  19020. ufbx_abi void ufbx_catch_compute_topology(ufbx_panic *panic, const ufbx_mesh *mesh, ufbx_topo_edge *indices, size_t num_indices)
  19021. {
  19022. if (ufbxi_panicf(panic, num_indices >= mesh->num_indices, "Required mesh.num_indices (%zu) indices, got %zu", mesh->num_indices, num_indices)) return;
  19023. ufbxi_compute_topology(mesh, indices);
  19024. }
  19025. ufbx_abi uint32_t ufbx_catch_topo_next_vertex_edge(ufbx_panic *panic, const ufbx_topo_edge *topo, size_t num_topo, uint32_t index)
  19026. {
  19027. if (index == UFBX_NO_INDEX) return UFBX_NO_INDEX;
  19028. if (ufbxi_panicf(panic, (size_t)index < num_topo, "index (%d) out of bounds (%zu)", index, num_topo)) return UFBX_NO_INDEX;
  19029. uint32_t twin = topo[index].twin;
  19030. if (twin == UFBX_NO_INDEX) return UFBX_NO_INDEX;
  19031. if (ufbxi_panicf(panic, (size_t)twin < num_topo, "Corrupted topology structure")) return UFBX_NO_INDEX;
  19032. return topo[twin].next;
  19033. }
  19034. ufbx_abi uint32_t ufbx_catch_topo_prev_vertex_edge(ufbx_panic *panic, const ufbx_topo_edge *topo, size_t num_topo, uint32_t index)
  19035. {
  19036. if (index == UFBX_NO_INDEX) return UFBX_NO_INDEX;
  19037. if (ufbxi_panicf(panic, (size_t)index < num_topo, "index (%d) out of bounds (%zu)", index, num_topo)) return UFBX_NO_INDEX;
  19038. return topo[topo[index].prev].twin;
  19039. }
  19040. ufbx_abi ufbxi_noinline ufbx_vec3 ufbx_catch_get_weighted_face_normal(ufbx_panic *panic, const ufbx_vertex_vec3 *positions, ufbx_face face)
  19041. {
  19042. if (ufbxi_panicf(panic, face.index_begin < positions->indices.count, "Face index begin (%u) out of bounds (%zu)", face.index_begin, positions->indices.count)) return ufbx_zero_vec3;
  19043. if (ufbxi_panicf(panic, positions->indices.count - face.index_begin >= face.num_indices, "Face index end (%u + %u) out of bounds (%zu)", face.index_begin, face.num_indices, positions->indices.count)) return ufbx_zero_vec3;
  19044. if (face.num_indices < 3) {
  19045. return ufbx_zero_vec3;
  19046. } else if (face.num_indices == 3) {
  19047. ufbx_vec3 a, b, c;
  19048. if (panic) {
  19049. a = ufbx_catch_get_vertex_vec3(panic, positions, face.index_begin + 0);
  19050. b = ufbx_catch_get_vertex_vec3(panic, positions, face.index_begin + 1);
  19051. c = ufbx_catch_get_vertex_vec3(panic, positions, face.index_begin + 2);
  19052. } else {
  19053. a = ufbx_get_vertex_vec3(positions, face.index_begin + 0);
  19054. b = ufbx_get_vertex_vec3(positions, face.index_begin + 1);
  19055. c = ufbx_get_vertex_vec3(positions, face.index_begin + 2);
  19056. }
  19057. return ufbxi_cross3(ufbxi_sub3(b, a), ufbxi_sub3(c, a));
  19058. } else if (face.num_indices == 4) {
  19059. ufbx_vec3 a, b, c, d;
  19060. if (panic) {
  19061. a = ufbx_catch_get_vertex_vec3(panic, positions, face.index_begin + 0);
  19062. b = ufbx_catch_get_vertex_vec3(panic, positions, face.index_begin + 1);
  19063. c = ufbx_catch_get_vertex_vec3(panic, positions, face.index_begin + 2);
  19064. d = ufbx_catch_get_vertex_vec3(panic, positions, face.index_begin + 3);
  19065. } else {
  19066. a = ufbx_get_vertex_vec3(positions, face.index_begin + 0);
  19067. b = ufbx_get_vertex_vec3(positions, face.index_begin + 1);
  19068. c = ufbx_get_vertex_vec3(positions, face.index_begin + 2);
  19069. d = ufbx_get_vertex_vec3(positions, face.index_begin + 3);
  19070. }
  19071. return ufbxi_cross3(ufbxi_sub3(c, a), ufbxi_sub3(d, b));
  19072. } else {
  19073. ufbx_vec3 a, b;
  19074. // Newell's Method
  19075. ufbx_vec3 result = ufbx_zero_vec3;
  19076. for (size_t i = 0; i < face.num_indices; i++) {
  19077. size_t next = i + 1 < face.num_indices ? i + 1 : 0;
  19078. if (panic) {
  19079. a = ufbx_catch_get_vertex_vec3(panic, positions, face.index_begin + i);
  19080. b = ufbx_catch_get_vertex_vec3(panic, positions, face.index_begin + next);
  19081. } else {
  19082. a = ufbx_get_vertex_vec3(positions, face.index_begin + i);
  19083. b = ufbx_get_vertex_vec3(positions, face.index_begin + next);
  19084. }
  19085. result.x += (a.y - b.y) * (a.z + b.z);
  19086. result.y += (a.z - b.z) * (a.x + b.x);
  19087. result.z += (a.x - b.x) * (a.y + b.y);
  19088. }
  19089. return result;
  19090. }
  19091. }
  19092. size_t ufbx_catch_generate_normal_mapping(ufbx_panic *panic, const ufbx_mesh *mesh, const ufbx_topo_edge *topo, size_t num_topo, uint32_t *normal_indices, size_t num_normal_indices, bool assume_smooth)
  19093. {
  19094. uint32_t next_index = 0;
  19095. if (ufbxi_panicf(panic, num_normal_indices >= mesh->num_indices, "Expected at least mesh.num_indices (%zu), got %zu", mesh->num_indices, num_normal_indices)) return 0;
  19096. for (size_t i = 0; i < mesh->num_indices; i++) {
  19097. normal_indices[i] = UFBX_NO_INDEX;
  19098. }
  19099. // Walk around vertices and merge around smooth edges
  19100. for (size_t vi = 0; vi < mesh->num_vertices; vi++) {
  19101. uint32_t original_start = mesh->vertex_first_index.data[vi];
  19102. if (original_start == UFBX_NO_INDEX) continue;
  19103. uint32_t start = original_start, cur = start;
  19104. for (;;) {
  19105. uint32_t prev = ufbx_topo_next_vertex_edge(topo, num_topo, cur);
  19106. if (!ufbxi_is_edge_smooth(mesh, topo, num_topo, cur, assume_smooth)) start = cur;
  19107. if (prev == UFBX_NO_INDEX) { start = cur; break; }
  19108. if (prev == original_start) break;
  19109. cur = prev;
  19110. }
  19111. normal_indices[start] = next_index++;
  19112. uint32_t next = start;
  19113. for (;;) {
  19114. next = ufbx_topo_prev_vertex_edge(topo, num_topo, next);
  19115. if (next == UFBX_NO_INDEX || next == start) break;
  19116. if (!ufbxi_is_edge_smooth(mesh, topo, num_topo, next, assume_smooth)) {
  19117. ++next_index;
  19118. }
  19119. normal_indices[next] = next_index - 1;
  19120. }
  19121. }
  19122. // Assign non-manifold indices
  19123. for (size_t i = 0; i < mesh->num_indices; i++) {
  19124. if (normal_indices[i] == UFBX_NO_INDEX) {
  19125. normal_indices[i] = next_index++;
  19126. }
  19127. }
  19128. return (size_t)next_index;
  19129. }
  19130. ufbx_abi size_t ufbx_generate_normal_mapping(const ufbx_mesh *mesh, const ufbx_topo_edge *topo, size_t num_topo, uint32_t *normal_indices, size_t num_normal_indices, bool assume_smooth)
  19131. {
  19132. return ufbx_catch_generate_normal_mapping(NULL, mesh, topo, num_topo, normal_indices, num_normal_indices, assume_smooth);
  19133. }
  19134. ufbx_abi void ufbx_catch_compute_normals(ufbx_panic *panic, const ufbx_mesh *mesh, const ufbx_vertex_vec3 *positions, const uint32_t *normal_indices, size_t num_normal_indices, ufbx_vec3 *normals, size_t num_normals)
  19135. {
  19136. if (ufbxi_panicf(panic, num_normal_indices >= mesh->num_indices, "Expected at least mesh.num_indices (%zu), got %zu", mesh->num_indices, num_normal_indices)) return;
  19137. memset(normals, 0, sizeof(ufbx_vec3)*num_normals);
  19138. for (size_t fi = 0; fi < mesh->num_faces; fi++) {
  19139. ufbx_face face = mesh->faces.data[fi];
  19140. ufbx_vec3 normal = ufbx_get_weighted_face_normal(positions, face);
  19141. for (size_t ix = 0; ix < face.num_indices; ix++) {
  19142. uint32_t index = normal_indices[face.index_begin + ix];
  19143. if (ufbxi_panicf(panic, index < num_normals, "Normal index (%d) out of bounds (%zu) at %zu", index, num_normals, ix)) return;
  19144. ufbx_vec3 *n = &normals[index];
  19145. *n = ufbxi_add3(*n, normal);
  19146. }
  19147. }
  19148. for (size_t i = 0; i < num_normals; i++) {
  19149. ufbx_real len = ufbxi_length3(normals[i]);
  19150. if (len > 0.0f) {
  19151. normals[i].x /= len;
  19152. normals[i].y /= len;
  19153. normals[i].z /= len;
  19154. }
  19155. }
  19156. }
  19157. ufbx_abi void ufbx_compute_normals(const ufbx_mesh *mesh, const ufbx_vertex_vec3 *positions, const uint32_t *normal_indices, size_t num_normal_indices, ufbx_vec3 *normals, size_t num_normals)
  19158. {
  19159. ufbx_catch_compute_normals(NULL, mesh, positions, normal_indices, num_normal_indices, normals, num_normals);
  19160. }
  19161. ufbx_abi ufbx_mesh *ufbx_subdivide_mesh(const ufbx_mesh *mesh, size_t level, const ufbx_subdivide_opts *opts, ufbx_error *error)
  19162. {
  19163. if (!mesh) return NULL;
  19164. if (level == 0) return (ufbx_mesh*)mesh;
  19165. return ufbxi_subdivide_mesh(mesh, level, opts, error);
  19166. }
  19167. ufbx_abi void ufbx_free_mesh(ufbx_mesh *mesh)
  19168. {
  19169. if (!mesh) return;
  19170. if (!mesh->subdivision_evaluated && !mesh->from_tessellated_nurbs) return;
  19171. ufbxi_mesh_imp *imp = ufbxi_get_imp(ufbxi_mesh_imp, mesh);
  19172. ufbx_assert(imp->magic == UFBXI_MESH_IMP_MAGIC);
  19173. if (imp->magic != UFBXI_MESH_IMP_MAGIC) return;
  19174. ufbxi_release_ref(&imp->refcount);
  19175. }
  19176. ufbx_abi void ufbx_retain_mesh(ufbx_mesh *mesh)
  19177. {
  19178. if (!mesh) return;
  19179. if (!mesh->subdivision_evaluated && !mesh->from_tessellated_nurbs) return;
  19180. ufbxi_mesh_imp *imp = ufbxi_get_imp(ufbxi_mesh_imp, mesh);
  19181. ufbx_assert(imp->magic == UFBXI_MESH_IMP_MAGIC);
  19182. if (imp->magic != UFBXI_MESH_IMP_MAGIC) return;
  19183. ufbxi_retain_ref(&imp->refcount);
  19184. }
  19185. ufbx_abi ufbx_geometry_cache *ufbx_load_geometry_cache(
  19186. const char *filename,
  19187. const ufbx_geometry_cache_opts *opts, ufbx_error *error)
  19188. {
  19189. return ufbx_load_geometry_cache_len(filename, strlen(filename),
  19190. opts, error);
  19191. }
  19192. ufbx_abi ufbx_geometry_cache *ufbx_load_geometry_cache_len(
  19193. const char *filename, size_t filename_len,
  19194. const ufbx_geometry_cache_opts *opts, ufbx_error *error)
  19195. {
  19196. ufbx_string str = { filename, filename_len };
  19197. return ufbxi_load_geometry_cache(str, opts, error);
  19198. }
  19199. ufbx_abi void ufbx_free_geometry_cache(ufbx_geometry_cache *cache)
  19200. {
  19201. if (!cache) return;
  19202. ufbxi_geometry_cache_imp *imp = ufbxi_get_imp(ufbxi_geometry_cache_imp, cache);
  19203. ufbx_assert(imp->magic == UFBXI_CACHE_IMP_MAGIC);
  19204. if (imp->magic != UFBXI_CACHE_IMP_MAGIC) return;
  19205. if (imp->owned_by_scene) return;
  19206. ufbxi_release_ref(&imp->refcount);
  19207. }
  19208. ufbx_abi void ufbx_retain_geometry_cache(ufbx_geometry_cache *cache)
  19209. {
  19210. if (!cache) return;
  19211. ufbxi_geometry_cache_imp *imp = ufbxi_get_imp(ufbxi_geometry_cache_imp, cache);
  19212. ufbx_assert(imp->magic == UFBXI_CACHE_IMP_MAGIC);
  19213. if (imp->magic != UFBXI_CACHE_IMP_MAGIC) return;
  19214. if (imp->owned_by_scene) return;
  19215. ufbxi_retain_ref(&imp->refcount);
  19216. }
  19217. ufbx_abi ufbxi_noinline size_t ufbx_get_read_geometry_cache_real_num_data(const ufbx_cache_frame *frame)
  19218. {
  19219. if (!frame) return 0;
  19220. switch (frame->data_format) {
  19221. case UFBX_CACHE_DATA_FORMAT_UNKNOWN: return 0;
  19222. case UFBX_CACHE_DATA_FORMAT_REAL_FLOAT: return frame->data_count;
  19223. case UFBX_CACHE_DATA_FORMAT_VEC3_FLOAT: return frame->data_count * 3;
  19224. case UFBX_CACHE_DATA_FORMAT_REAL_DOUBLE: return frame->data_count;
  19225. case UFBX_CACHE_DATA_FORMAT_VEC3_DOUBLE: return frame->data_count * 3;
  19226. default: return 0;
  19227. }
  19228. }
  19229. ufbx_abi ufbxi_noinline size_t ufbx_get_sample_geometry_cache_real_num_data(const ufbx_cache_channel *channel, double time)
  19230. {
  19231. if (!channel) return 0;
  19232. if (channel->frames.count == 0) return 0;
  19233. size_t begin = 0;
  19234. size_t end = channel->frames.count;
  19235. const ufbx_cache_frame *frames = channel->frames.data;
  19236. while (end - begin >= 8) {
  19237. size_t mid = (begin + end) >> 1;
  19238. if (frames[mid].time < time) {
  19239. begin = mid + 1;
  19240. } else {
  19241. end = mid;
  19242. }
  19243. }
  19244. const double eps = 0.00000001;
  19245. end = channel->frames.count;
  19246. for (; begin < end; begin++) {
  19247. const ufbx_cache_frame *next = &frames[begin];
  19248. if (next->time < time) continue;
  19249. // First keyframe
  19250. if (begin == 0) {
  19251. return ufbx_get_read_geometry_cache_real_num_data(next);
  19252. }
  19253. const ufbx_cache_frame *prev = next - 1;
  19254. // Snap to exact frames if near
  19255. if (ufbx_fabs(next->time - time) < eps) {
  19256. return ufbx_get_read_geometry_cache_real_num_data(next);
  19257. }
  19258. if (ufbx_fabs(prev->time - time) < eps) {
  19259. return ufbx_get_read_geometry_cache_real_num_data(prev);
  19260. }
  19261. size_t num_prev = ufbx_get_read_geometry_cache_real_num_data(prev);
  19262. size_t num_next = ufbx_get_read_geometry_cache_real_num_data(next);
  19263. return ufbxi_min_sz(num_prev, num_next);
  19264. }
  19265. // Last frame
  19266. const ufbx_cache_frame *last = &frames[end - 1];
  19267. return ufbx_get_read_geometry_cache_real_num_data(last);
  19268. }
  19269. ufbx_abi size_t ufbx_get_read_geometry_cache_vec3_num_data(const ufbx_cache_frame *frame)
  19270. {
  19271. if (!frame) return 0;
  19272. switch (frame->data_format) {
  19273. case UFBX_CACHE_DATA_FORMAT_UNKNOWN: return 0;
  19274. case UFBX_CACHE_DATA_FORMAT_REAL_FLOAT: return frame->data_count / 3;
  19275. case UFBX_CACHE_DATA_FORMAT_VEC3_FLOAT: return frame->data_count;
  19276. case UFBX_CACHE_DATA_FORMAT_REAL_DOUBLE: return frame->data_count / 3;
  19277. case UFBX_CACHE_DATA_FORMAT_VEC3_DOUBLE: return frame->data_count;
  19278. default: return 0;
  19279. }
  19280. }
  19281. ufbx_abi size_t ufbx_get_sample_geometry_cache_vec3_num_data(const ufbx_cache_channel *channel, double time)
  19282. {
  19283. if (!channel) return 0;
  19284. if (channel->frames.count == 0) return 0;
  19285. size_t begin = 0;
  19286. size_t end = channel->frames.count;
  19287. const ufbx_cache_frame *frames = channel->frames.data;
  19288. while (end - begin >= 8) {
  19289. size_t mid = (begin + end) >> 1;
  19290. if (frames[mid].time < time) {
  19291. begin = mid + 1;
  19292. } else {
  19293. end = mid;
  19294. }
  19295. }
  19296. const double eps = 0.00000001;
  19297. end = channel->frames.count;
  19298. for (; begin < end; begin++) {
  19299. const ufbx_cache_frame *next = &frames[begin];
  19300. if (next->time < time) continue;
  19301. // First keyframe
  19302. if (begin == 0) {
  19303. return ufbx_get_read_geometry_cache_vec3_num_data(next);
  19304. }
  19305. const ufbx_cache_frame *prev = next - 1;
  19306. // Snap to exact frames if near
  19307. if (ufbx_fabs(next->time - time) < eps) {
  19308. return ufbx_get_read_geometry_cache_vec3_num_data(next);
  19309. }
  19310. if (ufbx_fabs(prev->time - time) < eps) {
  19311. return ufbx_get_read_geometry_cache_vec3_num_data(prev);
  19312. }
  19313. size_t num_prev = ufbx_get_read_geometry_cache_vec3_num_data(prev);
  19314. size_t num_next = ufbx_get_read_geometry_cache_vec3_num_data(next);
  19315. return ufbxi_min_sz(num_prev, num_next);
  19316. }
  19317. // Last frame
  19318. const ufbx_cache_frame *last = &frames[end - 1];
  19319. return ufbx_get_read_geometry_cache_vec3_num_data(last);
  19320. }
  19321. ufbx_abi ufbxi_noinline size_t ufbx_read_geometry_cache_real(const ufbx_cache_frame *frame, ufbx_real *data, size_t count, const ufbx_geometry_cache_data_opts *user_opts)
  19322. {
  19323. if (!frame || count == 0) return 0;
  19324. ufbx_assert(data);
  19325. if (!data) return 0;
  19326. ufbx_geometry_cache_data_opts opts;
  19327. if (user_opts) {
  19328. opts = *user_opts;
  19329. } else {
  19330. memset(&opts, 0, sizeof(opts));
  19331. }
  19332. if (!opts.open_file_cb.fn) {
  19333. opts.open_file_cb.fn = ufbx_open_file;
  19334. }
  19335. // `ufbx_geometry_cache_data_opts` must be cleared to zero first!
  19336. ufbx_assert(opts._begin_zero == 0 && opts._end_zero == 0);
  19337. if (!(opts._begin_zero == 0 && opts._end_zero == 0)) return 0;
  19338. bool use_double = false;
  19339. size_t src_count = 0;
  19340. switch (frame->data_format) {
  19341. case UFBX_CACHE_DATA_FORMAT_UNKNOWN: src_count = 0; break;
  19342. case UFBX_CACHE_DATA_FORMAT_REAL_FLOAT: src_count = frame->data_count; break;
  19343. case UFBX_CACHE_DATA_FORMAT_VEC3_FLOAT: src_count = frame->data_count * 3; break;
  19344. case UFBX_CACHE_DATA_FORMAT_REAL_DOUBLE: src_count = frame->data_count; use_double = true; break;
  19345. case UFBX_CACHE_DATA_FORMAT_VEC3_DOUBLE: src_count = frame->data_count * 3; use_double = true; break;
  19346. default: ufbx_assert(0 && "Bad data_format"); break;
  19347. }
  19348. bool src_big_endian = false;
  19349. switch (frame->data_encoding) {
  19350. case UFBX_CACHE_DATA_ENCODING_UNKNOWN: return 0;
  19351. case UFBX_CACHE_DATA_ENCODING_LITTLE_ENDIAN: src_big_endian = false; break;
  19352. case UFBX_CACHE_DATA_ENCODING_BIG_ENDIAN: src_big_endian = true; break;
  19353. default: ufbx_assert(0 && "Bad data_encoding"); break;
  19354. }
  19355. // Test endianness
  19356. bool dst_big_endian;
  19357. {
  19358. uint8_t buf[2];
  19359. uint16_t val = 0xbbaa;
  19360. memcpy(buf, &val, 2);
  19361. dst_big_endian = buf[0] == 0xbb;
  19362. }
  19363. if (src_count == 0) return 0;
  19364. src_count = ufbxi_min_sz(src_count, count);
  19365. ufbx_stream stream = { 0 };
  19366. if (!opts.open_file_cb.fn(opts.open_file_cb.user, &stream, frame->filename.data, frame->filename.length)) {
  19367. return 0;
  19368. }
  19369. // Skip to the correct point in the file
  19370. uint64_t offset = frame->data_offset;
  19371. if (stream.skip_fn) {
  19372. while (offset > 0) {
  19373. size_t to_skip = (size_t)ufbxi_min64(offset, UFBXI_MAX_SKIP_SIZE);
  19374. if (!stream.skip_fn(stream.user, to_skip)) break;
  19375. offset -= to_skip;
  19376. }
  19377. } else {
  19378. char buffer[4096];
  19379. while (offset > 0) {
  19380. size_t to_skip = (size_t)ufbxi_min64(offset, sizeof(buffer));
  19381. size_t num_read = stream.read_fn(stream.user, buffer, to_skip);
  19382. if (num_read != to_skip) break;
  19383. offset -= to_skip;
  19384. }
  19385. }
  19386. // Failed to skip all the way
  19387. if (offset > 0) {
  19388. if (stream.close_fn) {
  19389. stream.close_fn(stream.user);
  19390. }
  19391. return 0;
  19392. }
  19393. ufbx_real *dst = data;
  19394. if (use_double) {
  19395. double buffer[512];
  19396. while (src_count > 0) {
  19397. size_t to_read = ufbxi_min_sz(src_count, ufbxi_arraycount(buffer));
  19398. src_count -= to_read;
  19399. size_t bytes_read = stream.read_fn(stream.user, buffer, to_read * sizeof(double));
  19400. if (bytes_read == SIZE_MAX) bytes_read = 0;
  19401. size_t num_read = bytes_read / sizeof(double);
  19402. if (src_big_endian != dst_big_endian) {
  19403. for (size_t i = 0; i < num_read; i++) {
  19404. char t, *v = (char*)&buffer[i];
  19405. t = v[0]; v[0] = v[7]; v[7] = t;
  19406. t = v[1]; v[1] = v[6]; v[6] = t;
  19407. t = v[2]; v[2] = v[5]; v[5] = t;
  19408. t = v[3]; v[3] = v[4]; v[4] = t;
  19409. }
  19410. }
  19411. ufbx_real weight = opts.weight;
  19412. if (opts.additive && opts.use_weight) {
  19413. for (size_t i = 0; i < num_read; i++) {
  19414. dst[i] += (ufbx_real)buffer[i] * weight;
  19415. }
  19416. } else if (opts.additive) {
  19417. for (size_t i = 0; i < num_read; i++) {
  19418. dst[i] += (ufbx_real)buffer[i];
  19419. }
  19420. } else if (opts.use_weight) {
  19421. for (size_t i = 0; i < num_read; i++) {
  19422. dst[i] = (ufbx_real)buffer[i] * weight;
  19423. }
  19424. } else {
  19425. for (size_t i = 0; i < num_read; i++) {
  19426. dst[i] = (ufbx_real)buffer[i];
  19427. }
  19428. }
  19429. dst += num_read;
  19430. if (num_read != to_read) break;
  19431. }
  19432. } else {
  19433. float buffer[1024];
  19434. while (src_count > 0) {
  19435. size_t to_read = ufbxi_min_sz(src_count, ufbxi_arraycount(buffer));
  19436. src_count -= to_read;
  19437. size_t bytes_read = stream.read_fn(stream.user, buffer, to_read * sizeof(float));
  19438. if (bytes_read == SIZE_MAX) bytes_read = 0;
  19439. size_t num_read = bytes_read / sizeof(float);
  19440. if (src_big_endian != dst_big_endian) {
  19441. for (size_t i = 0; i < num_read; i++) {
  19442. char t, *v = (char*)&buffer[i];
  19443. t = v[0]; v[0] = v[3]; v[3] = t;
  19444. t = v[1]; v[1] = v[2]; v[2] = t;
  19445. }
  19446. }
  19447. ufbx_real weight = opts.weight;
  19448. if (opts.additive && opts.use_weight) {
  19449. for (size_t i = 0; i < num_read; i++) {
  19450. dst[i] += (ufbx_real)buffer[i] * weight;
  19451. }
  19452. } else if (opts.additive) {
  19453. for (size_t i = 0; i < num_read; i++) {
  19454. dst[i] += (ufbx_real)buffer[i];
  19455. }
  19456. } else if (opts.use_weight) {
  19457. for (size_t i = 0; i < num_read; i++) {
  19458. dst[i] = (ufbx_real)buffer[i] * weight;
  19459. }
  19460. } else {
  19461. for (size_t i = 0; i < num_read; i++) {
  19462. dst[i] = (ufbx_real)buffer[i];
  19463. }
  19464. }
  19465. dst += num_read;
  19466. if (num_read != to_read) break;
  19467. }
  19468. }
  19469. if (stream.close_fn) {
  19470. stream.close_fn(stream.user);
  19471. }
  19472. return ufbxi_to_size(dst - data);
  19473. }
  19474. ufbx_abi ufbxi_noinline size_t ufbx_sample_geometry_cache_real(const ufbx_cache_channel *channel, double time, ufbx_real *data, size_t count, const ufbx_geometry_cache_data_opts *user_opts)
  19475. {
  19476. if (!channel || count == 0) return 0;
  19477. ufbx_assert(data);
  19478. if (!data) return 0;
  19479. if (channel->frames.count == 0) return 0;
  19480. ufbx_geometry_cache_data_opts opts;
  19481. if (user_opts) {
  19482. opts = *user_opts;
  19483. } else {
  19484. memset(&opts, 0, sizeof(opts));
  19485. }
  19486. // `ufbx_geometry_cache_data_opts` must be cleared to zero first!
  19487. ufbx_assert(opts._begin_zero == 0 && opts._end_zero == 0);
  19488. if (!(opts._begin_zero == 0 && opts._end_zero == 0)) return 0;
  19489. size_t begin = 0;
  19490. size_t end = channel->frames.count;
  19491. const ufbx_cache_frame *frames = channel->frames.data;
  19492. while (end - begin >= 8) {
  19493. size_t mid = (begin + end) >> 1;
  19494. if (frames[mid].time < time) {
  19495. begin = mid + 1;
  19496. } else {
  19497. end = mid;
  19498. }
  19499. }
  19500. const double eps = 0.00000001;
  19501. end = channel->frames.count;
  19502. for (; begin < end; begin++) {
  19503. const ufbx_cache_frame *next = &frames[begin];
  19504. if (next->time < time) continue;
  19505. // First keyframe
  19506. if (begin == 0) {
  19507. return ufbx_read_geometry_cache_real(next, data, count, &opts);
  19508. }
  19509. const ufbx_cache_frame *prev = next - 1;
  19510. // Snap to exact frames if near
  19511. if (ufbx_fabs(next->time - time) < eps) {
  19512. return ufbx_read_geometry_cache_real(next, data, count, &opts);
  19513. }
  19514. if (ufbx_fabs(prev->time - time) < eps) {
  19515. return ufbx_read_geometry_cache_real(prev, data, count, &opts);
  19516. }
  19517. double rcp_delta = 1.0 / (next->time - prev->time);
  19518. double t = (time - prev->time) * rcp_delta;
  19519. ufbx_real original_weight = opts.use_weight ? opts.weight : 1.0f;
  19520. opts.use_weight = true;
  19521. opts.weight = (ufbx_real)(original_weight * (1.0 - t));
  19522. size_t num_prev = ufbx_read_geometry_cache_real(prev, data, count, &opts);
  19523. opts.additive = true;
  19524. opts.weight = (ufbx_real)(original_weight * t);
  19525. return ufbx_read_geometry_cache_real(next, data, num_prev, &opts);
  19526. }
  19527. // Last frame
  19528. const ufbx_cache_frame *last = &frames[end - 1];
  19529. return ufbx_read_geometry_cache_real(last, data, count, &opts);
  19530. }
  19531. ufbx_abi ufbxi_noinline size_t ufbx_read_geometry_cache_vec3(const ufbx_cache_frame *frame, ufbx_vec3 *data, size_t count, const ufbx_geometry_cache_data_opts *opts)
  19532. {
  19533. if (!frame || count == 0) return 0;
  19534. ufbx_assert(data);
  19535. if (!data) return 0;
  19536. return ufbx_read_geometry_cache_real(frame, (ufbx_real*)data, count * 3, opts) / 3;
  19537. }
  19538. ufbx_abi ufbxi_noinline size_t ufbx_sample_geometry_cache_vec3(const ufbx_cache_channel *channel, double time, ufbx_vec3 *data, size_t count, const ufbx_geometry_cache_data_opts *opts)
  19539. {
  19540. if (!channel || count == 0) return 0;
  19541. ufbx_assert(data);
  19542. if (!data) return 0;
  19543. return ufbx_sample_geometry_cache_real(channel, time, (ufbx_real*)data, count * 3, opts) / 3;
  19544. }
  19545. ufbx_abi ufbx_dom_node *ufbx_dom_find_len(const ufbx_dom_node *parent, const char *name, size_t name_len)
  19546. {
  19547. ufbx_string ref = { name, name_len };
  19548. ufbxi_for_ptr_list(ufbx_dom_node, p_child, parent->children) {
  19549. if (ufbxi_str_equal((*p_child)->name, ref)) return (ufbx_dom_node*)*p_child;
  19550. }
  19551. return NULL;
  19552. }
  19553. ufbx_abi size_t ufbx_generate_indices(const ufbx_vertex_stream *streams, size_t num_streams, uint32_t *indices, size_t num_indices, const ufbx_allocator_opts *allocator, ufbx_error *error)
  19554. {
  19555. ufbx_error local_error;
  19556. if (!error) {
  19557. memset(&local_error, 0, sizeof(local_error));
  19558. }
  19559. return ufbxi_generate_indices(streams, num_streams, indices, num_indices, allocator, error ? error : &local_error);
  19560. }
  19561. ufbx_abi ufbx_real ufbx_catch_get_vertex_real(ufbx_panic *panic, const ufbx_vertex_real *v, size_t index)
  19562. {
  19563. if (ufbxi_panicf(panic, index < v->indices.count, "index (%zu) out of range (%zu)", index, v->indices.count)) return 0.0f;
  19564. uint32_t ix = v->indices.data[index];
  19565. if (ufbxi_panicf(panic, (size_t)ix < v->values.count || ix == UFBX_NO_INDEX, "Corrupted or missing vertex attribute (%u) at %zu", ix, index)) return 0.0f;
  19566. return v->values.data[(int32_t)ix];
  19567. }
  19568. ufbx_abi ufbx_vec2 ufbx_catch_get_vertex_vec2(ufbx_panic *panic, const ufbx_vertex_vec2 *v, size_t index)
  19569. {
  19570. if (ufbxi_panicf(panic, index < v->indices.count, "index (%zu) out of range (%zu)", index, v->indices.count)) return ufbx_zero_vec2;
  19571. uint32_t ix = v->indices.data[index];
  19572. if (ufbxi_panicf(panic, (size_t)ix < v->values.count || ix == UFBX_NO_INDEX, "Corrupted or missing vertex attribute (%u) at %zu", ix, index)) return ufbx_zero_vec2;
  19573. return v->values.data[(int32_t)ix];
  19574. }
  19575. ufbx_abi ufbx_vec3 ufbx_catch_get_vertex_vec3(ufbx_panic *panic, const ufbx_vertex_vec3 *v, size_t index)
  19576. {
  19577. if (ufbxi_panicf(panic, index < v->indices.count, "index (%zu) out of range (%zu)", index, v->indices.count)) return ufbx_zero_vec3;
  19578. uint32_t ix = v->indices.data[index];
  19579. if (ufbxi_panicf(panic, (size_t)ix < v->values.count || ix == UFBX_NO_INDEX, "Corrupted or missing vertex attribute (%u) at %zu", ix, index)) return ufbx_zero_vec3;
  19580. return v->values.data[(int32_t)ix];
  19581. }
  19582. ufbx_abi ufbx_vec4 ufbx_catch_get_vertex_vec4(ufbx_panic *panic, const ufbx_vertex_vec4 *v, size_t index)
  19583. {
  19584. if (ufbxi_panicf(panic, index < v->indices.count, "index (%zu) out of range (%zu)", index, v->indices.count)) return ufbx_zero_vec4;
  19585. uint32_t ix = v->indices.data[index];
  19586. if (ufbxi_panicf(panic, (size_t)ix < v->values.count || ix == UFBX_NO_INDEX, "Corrupted or missing vertex attribute (%u) at %zu", ix, index)) return ufbx_zero_vec4;
  19587. return v->values.data[(int32_t)ix];
  19588. }
  19589. ufbx_abi size_t ufbx_get_triangulate_face_num_indices(ufbx_face face)
  19590. {
  19591. if (face.num_indices < 3) return 0;
  19592. return (face.num_indices - 2) * 3;
  19593. }
  19594. ufbx_abi ufbx_unknown *ufbx_as_unknown(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_UNKNOWN ? (ufbx_unknown*)element : NULL; }
  19595. ufbx_abi ufbx_node *ufbx_as_node(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_NODE ? (ufbx_node*)element : NULL; }
  19596. ufbx_abi ufbx_mesh *ufbx_as_mesh(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_MESH ? (ufbx_mesh*)element : NULL; }
  19597. ufbx_abi ufbx_light *ufbx_as_light(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_LIGHT ? (ufbx_light*)element : NULL; }
  19598. ufbx_abi ufbx_camera *ufbx_as_camera(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_CAMERA ? (ufbx_camera*)element : NULL; }
  19599. ufbx_abi ufbx_bone *ufbx_as_bone(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_BONE ? (ufbx_bone*)element : NULL; }
  19600. ufbx_abi ufbx_empty *ufbx_as_empty(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_EMPTY ? (ufbx_empty*)element : NULL; }
  19601. ufbx_abi ufbx_line_curve *ufbx_as_line_curve(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_LINE_CURVE ? (ufbx_line_curve*)element : NULL; }
  19602. ufbx_abi ufbx_nurbs_curve *ufbx_as_nurbs_curve(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_NURBS_CURVE ? (ufbx_nurbs_curve*)element : NULL; }
  19603. ufbx_abi ufbx_nurbs_surface *ufbx_as_nurbs_surface(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_NURBS_SURFACE ? (ufbx_nurbs_surface*)element : NULL; }
  19604. ufbx_abi ufbx_nurbs_trim_surface *ufbx_as_nurbs_trim_surface(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_NURBS_TRIM_SURFACE ? (ufbx_nurbs_trim_surface*)element : NULL; }
  19605. ufbx_abi ufbx_nurbs_trim_boundary *ufbx_as_nurbs_trim_boundary(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_NURBS_TRIM_BOUNDARY ? (ufbx_nurbs_trim_boundary*)element : NULL; }
  19606. ufbx_abi ufbx_procedural_geometry *ufbx_as_procedural_geometry(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_PROCEDURAL_GEOMETRY ? (ufbx_procedural_geometry*)element : NULL; }
  19607. ufbx_abi ufbx_stereo_camera *ufbx_as_stereo_camera(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_STEREO_CAMERA ? (ufbx_stereo_camera*)element : NULL; }
  19608. ufbx_abi ufbx_camera_switcher *ufbx_as_camera_switcher(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_CAMERA_SWITCHER ? (ufbx_camera_switcher*)element : NULL; }
  19609. ufbx_abi ufbx_marker *ufbx_as_marker(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_MARKER ? (ufbx_marker*)element : NULL; }
  19610. ufbx_abi ufbx_lod_group *ufbx_as_lod_group(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_LOD_GROUP ? (ufbx_lod_group*)element : NULL; }
  19611. ufbx_abi ufbx_skin_deformer *ufbx_as_skin_deformer(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_SKIN_DEFORMER ? (ufbx_skin_deformer*)element : NULL; }
  19612. ufbx_abi ufbx_skin_cluster *ufbx_as_skin_cluster(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_SKIN_CLUSTER ? (ufbx_skin_cluster*)element : NULL; }
  19613. ufbx_abi ufbx_blend_deformer *ufbx_as_blend_deformer(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_BLEND_DEFORMER ? (ufbx_blend_deformer*)element : NULL; }
  19614. ufbx_abi ufbx_blend_channel *ufbx_as_blend_channel(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_BLEND_CHANNEL ? (ufbx_blend_channel*)element : NULL; }
  19615. ufbx_abi ufbx_blend_shape *ufbx_as_blend_shape(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_BLEND_SHAPE ? (ufbx_blend_shape*)element : NULL; }
  19616. ufbx_abi ufbx_cache_deformer *ufbx_as_cache_deformer(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_CACHE_DEFORMER ? (ufbx_cache_deformer*)element : NULL; }
  19617. ufbx_abi ufbx_cache_file *ufbx_as_cache_file(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_CACHE_FILE ? (ufbx_cache_file*)element : NULL; }
  19618. ufbx_abi ufbx_material *ufbx_as_material(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_MATERIAL ? (ufbx_material*)element : NULL; }
  19619. ufbx_abi ufbx_texture *ufbx_as_texture(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_TEXTURE ? (ufbx_texture*)element : NULL; }
  19620. ufbx_abi ufbx_video *ufbx_as_video(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_VIDEO ? (ufbx_video*)element : NULL; }
  19621. ufbx_abi ufbx_shader *ufbx_as_shader(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_SHADER ? (ufbx_shader*)element : NULL; }
  19622. ufbx_abi ufbx_shader_binding *ufbx_as_shader_binding(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_SHADER_BINDING ? (ufbx_shader_binding*)element : NULL; }
  19623. ufbx_abi ufbx_anim_stack *ufbx_as_anim_stack(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_ANIM_STACK ? (ufbx_anim_stack*)element : NULL; }
  19624. ufbx_abi ufbx_anim_layer *ufbx_as_anim_layer(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_ANIM_LAYER ? (ufbx_anim_layer*)element : NULL; }
  19625. ufbx_abi ufbx_anim_value *ufbx_as_anim_value(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_ANIM_VALUE ? (ufbx_anim_value*)element : NULL; }
  19626. ufbx_abi ufbx_anim_curve *ufbx_as_anim_curve(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_ANIM_CURVE ? (ufbx_anim_curve*)element : NULL; }
  19627. ufbx_abi ufbx_display_layer *ufbx_as_display_layer(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_DISPLAY_LAYER ? (ufbx_display_layer*)element : NULL; }
  19628. ufbx_abi ufbx_selection_set *ufbx_as_selection_set(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_SELECTION_SET ? (ufbx_selection_set*)element : NULL; }
  19629. ufbx_abi ufbx_selection_node *ufbx_as_selection_node(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_SELECTION_NODE ? (ufbx_selection_node*)element : NULL; }
  19630. ufbx_abi ufbx_character *ufbx_as_character(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_CHARACTER ? (ufbx_character*)element : NULL; }
  19631. ufbx_abi ufbx_constraint *ufbx_as_constraint(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_CONSTRAINT ? (ufbx_constraint*)element : NULL; }
  19632. ufbx_abi ufbx_pose *ufbx_as_pose(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_POSE ? (ufbx_pose*)element : NULL; }
  19633. ufbx_abi ufbx_metadata_object *ufbx_as_metadata_object(const ufbx_element *element) { return element && element->type == UFBX_ELEMENT_METADATA_OBJECT ? (ufbx_metadata_object*)element : NULL; }
  19634. ufbx_abi void ufbx_ffi_find_int_len(int64_t *retval, const ufbx_props *props, const char *name, size_t name_len, const int64_t *def)
  19635. {
  19636. *retval = ufbx_find_int_len(props, name, name_len, *def);
  19637. }
  19638. ufbx_abi void ufbx_ffi_find_vec3_len(ufbx_vec3 *retval, const ufbx_props *props, const char *name, size_t name_len, const ufbx_vec3 *def)
  19639. {
  19640. *retval = ufbx_find_vec3_len(props, name, name_len, *def);
  19641. }
  19642. ufbx_abi void ufbx_ffi_find_string_len(ufbx_string *retval, const ufbx_props *props, const char *name, size_t name_len, const ufbx_string *def)
  19643. {
  19644. *retval = ufbx_find_string_len(props, name, name_len, *def);
  19645. }
  19646. ufbx_abi void ufbx_ffi_find_anim_props(ufbx_anim_prop_list *retval, const ufbx_anim_layer *layer, const ufbx_element *element)
  19647. {
  19648. *retval = ufbx_find_anim_props(layer, element);
  19649. }
  19650. ufbx_abi void ufbx_ffi_get_compatible_matrix_for_normals(ufbx_matrix *retval, const ufbx_node *node)
  19651. {
  19652. *retval = ufbx_get_compatible_matrix_for_normals(node);
  19653. }
  19654. ufbx_abi void ufbx_ffi_evaluate_anim_value_vec2(ufbx_vec2 *retval, const ufbx_anim_value *anim_value, double time)
  19655. {
  19656. *retval = ufbx_evaluate_anim_value_vec2(anim_value, time);
  19657. }
  19658. ufbx_abi void ufbx_ffi_evaluate_anim_value_vec3(ufbx_vec3 *retval, const ufbx_anim_value *anim_value, double time)
  19659. {
  19660. *retval = ufbx_evaluate_anim_value_vec3(anim_value, time);
  19661. }
  19662. ufbx_abi void ufbx_ffi_evaluate_prop_len(ufbx_prop *retval, const ufbx_anim *anim, const ufbx_element *element, const char *name, size_t name_len, double time)
  19663. {
  19664. *retval = ufbx_evaluate_prop_len(anim, element, name, name_len, time);
  19665. }
  19666. ufbx_abi void ufbx_ffi_evaluate_props(ufbx_props *retval, const ufbx_anim *anim, ufbx_element *element, double time, ufbx_prop *buffer, size_t buffer_size)
  19667. {
  19668. *retval = ufbx_evaluate_props(anim, element, time, buffer, buffer_size);
  19669. }
  19670. ufbx_abi void ufbx_ffi_evaluate_transform(ufbx_transform *retval, const ufbx_anim *anim, const ufbx_node *node, double time)
  19671. {
  19672. *retval = ufbx_evaluate_transform(anim, node, time);
  19673. }
  19674. ufbx_abi ufbx_real ufbx_ffi_evaluate_blend_weight(const ufbx_anim *anim, const ufbx_blend_channel *channel, double time)
  19675. {
  19676. return ufbx_evaluate_blend_weight(anim, channel, time);
  19677. }
  19678. ufbx_abi void ufbx_ffi_prepare_prop_overrides(ufbx_const_prop_override_list *retval, ufbx_prop_override *overrides, size_t num_overrides)
  19679. {
  19680. *retval = ufbx_prepare_prop_overrides(overrides, num_overrides);
  19681. }
  19682. ufbx_abi void ufbx_ffi_quat_mul(ufbx_quat *retval, const ufbx_quat *a, const ufbx_quat *b)
  19683. {
  19684. *retval = ufbx_quat_mul(*a, *b);
  19685. }
  19686. ufbx_abi void ufbx_ffi_quat_normalize(ufbx_quat *retval, const ufbx_quat *q)
  19687. {
  19688. *retval = ufbx_quat_normalize(*q);
  19689. }
  19690. ufbx_abi void ufbx_ffi_quat_fix_antipodal(ufbx_quat *retval, const ufbx_quat *q, const ufbx_quat *reference)
  19691. {
  19692. *retval = ufbx_quat_fix_antipodal(*q, *reference);
  19693. }
  19694. ufbx_abi void ufbx_ffi_quat_slerp(ufbx_quat *retval, const ufbx_quat *a, const ufbx_quat *b, ufbx_real t)
  19695. {
  19696. *retval = ufbx_quat_slerp(*a, *b, t);
  19697. }
  19698. ufbx_abi void ufbx_ffi_quat_rotate_vec3(ufbx_vec3 *retval, const ufbx_quat *q, const ufbx_vec3 *v)
  19699. {
  19700. *retval = ufbx_quat_rotate_vec3(*q, *v);
  19701. }
  19702. ufbx_abi void ufbx_ffi_quat_to_euler(ufbx_vec3 *retval, const ufbx_quat *q, ufbx_rotation_order order)
  19703. {
  19704. *retval = ufbx_quat_to_euler(*q, order);
  19705. }
  19706. ufbx_abi void ufbx_ffi_euler_to_quat(ufbx_quat *retval, const ufbx_vec3 *v, ufbx_rotation_order order)
  19707. {
  19708. *retval = ufbx_euler_to_quat(*v, order);
  19709. }
  19710. ufbx_abi void ufbx_ffi_matrix_mul(ufbx_matrix *retval, const ufbx_matrix *a, const ufbx_matrix *b)
  19711. {
  19712. *retval = ufbx_matrix_mul(a, b);
  19713. }
  19714. ufbx_abi void ufbx_ffi_matrix_invert(ufbx_matrix *retval, const ufbx_matrix *m)
  19715. {
  19716. *retval = ufbx_matrix_invert(m);
  19717. }
  19718. ufbx_abi void ufbx_ffi_matrix_for_normals(ufbx_matrix *retval, const ufbx_matrix *m)
  19719. {
  19720. *retval = ufbx_matrix_for_normals(m);
  19721. }
  19722. ufbx_abi void ufbx_ffi_transform_position(ufbx_vec3 *retval, const ufbx_matrix *m, const ufbx_vec3 *v)
  19723. {
  19724. *retval = ufbx_transform_position(m, *v);
  19725. }
  19726. ufbx_abi void ufbx_ffi_transform_direction(ufbx_vec3 *retval, const ufbx_matrix *m, const ufbx_vec3 *v)
  19727. {
  19728. *retval = ufbx_transform_direction(m, *v);
  19729. }
  19730. ufbx_abi void ufbx_ffi_transform_to_matrix(ufbx_matrix *retval, const ufbx_transform *t)
  19731. {
  19732. *retval = ufbx_transform_to_matrix(t);
  19733. }
  19734. ufbx_abi void ufbx_ffi_matrix_to_transform(ufbx_transform *retval, const ufbx_matrix *m)
  19735. {
  19736. *retval = ufbx_matrix_to_transform(m);
  19737. }
  19738. ufbx_abi void ufbx_ffi_get_skin_vertex_matrix(ufbx_matrix *retval, const ufbx_skin_deformer *skin, size_t vertex, const ufbx_matrix *fallback)
  19739. {
  19740. *retval = ufbx_get_skin_vertex_matrix(skin, vertex, fallback);
  19741. }
  19742. ufbx_abi void ufbx_ffi_get_blend_shape_vertex_offset(ufbx_vec3 *retval, const ufbx_blend_shape *shape, size_t vertex)
  19743. {
  19744. *retval = ufbx_get_blend_shape_vertex_offset(shape, vertex);
  19745. }
  19746. ufbx_abi void ufbx_ffi_get_blend_vertex_offset(ufbx_vec3 *retval, const ufbx_blend_deformer *blend, size_t vertex)
  19747. {
  19748. *retval = ufbx_get_blend_vertex_offset(blend, vertex);
  19749. }
  19750. ufbx_abi void ufbx_ffi_evaluate_nurbs_curve(ufbx_curve_point *retval, const ufbx_nurbs_curve *curve, ufbx_real u)
  19751. {
  19752. *retval = ufbx_evaluate_nurbs_curve(curve, u);
  19753. }
  19754. ufbx_abi void ufbx_ffi_evaluate_nurbs_surface(ufbx_surface_point *retval, const ufbx_nurbs_surface *surface, ufbx_real u, ufbx_real v)
  19755. {
  19756. *retval = ufbx_evaluate_nurbs_surface(surface, u, v);
  19757. }
  19758. ufbx_abi void ufbx_ffi_get_weighted_face_normal(ufbx_vec3 *retval, const ufbx_vertex_vec3 *positions, const ufbx_face *face)
  19759. {
  19760. *retval = ufbx_get_weighted_face_normal(positions, *face);
  19761. }
  19762. ufbx_abi uint32_t ufbx_ffi_triangulate_face(uint32_t *indices, size_t num_indices, const ufbx_mesh *mesh, const ufbx_face *face)
  19763. {
  19764. return ufbx_triangulate_face(indices, num_indices, mesh, *face);
  19765. }
  19766. ufbx_abi size_t ufbx_ffi_get_triangulate_face_num_indices(const ufbx_face *face)
  19767. {
  19768. return ufbx_get_triangulate_face_num_indices(*face);
  19769. }
  19770. #ifdef __cplusplus
  19771. }
  19772. #endif
  19773. #endif
  19774. #if defined(_MSC_VER)
  19775. #pragma warning(pop)
  19776. #elif defined(__clang__)
  19777. #pragma clang diagnostic pop
  19778. #elif defined(__GNUC__)
  19779. #pragma GCC diagnostic pop
  19780. #endif