m3d.h 260 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126
  1. /*
  2. * m3d.h
  3. *
  4. * Copyright (C) 2019 bzt (bztsrc@gitlab)
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies
  11. * of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. * DEALINGS IN THE SOFTWARE.
  25. *
  26. * @brief ANSI C89 / C++11 single header importer / exporter SDK for the Model 3D (.M3D) format
  27. * https://gitlab.com/bztsrc/model3d
  28. *
  29. * PNG decompressor included from (with minor modifications to make it C89 valid):
  30. * stb_image - v2.13 - public domain image loader - http://nothings.org/stb_image.h
  31. *
  32. * @version: 1.0.0
  33. */
  34. #ifndef _M3D_H_
  35. #define _M3D_H_
  36. #ifdef __cplusplus
  37. extern "C" {
  38. #endif
  39. #include <stdint.h>
  40. /*** configuration ***/
  41. #ifndef M3D_MALLOC
  42. #define M3D_MALLOC(sz) malloc(sz)
  43. #endif
  44. #ifndef M3D_REALLOC
  45. #define M3D_REALLOC(p, nsz) realloc(p, nsz)
  46. #endif
  47. #ifndef M3D_FREE
  48. #define M3D_FREE(p) free(p)
  49. #endif
  50. #ifndef M3D_LOG
  51. #define M3D_LOG(x)
  52. #endif
  53. #ifndef M3D_APIVERSION
  54. #define M3D_APIVERSION 0x0100
  55. #ifndef M3D_DOUBLE
  56. typedef float M3D_FLOAT;
  57. #ifndef M3D_EPSILON
  58. /* carefully choosen for IEEE 754 don't change */
  59. #define M3D_EPSILON ((M3D_FLOAT)1e-7)
  60. #endif
  61. #else
  62. typedef double M3D_FLOAT;
  63. #ifndef M3D_EPSILON
  64. #define M3D_EPSILON ((M3D_FLOAT)1e-14)
  65. #endif
  66. #endif
  67. #if !defined(M3D_SMALLINDEX)
  68. typedef uint32_t M3D_INDEX;
  69. #define M3D_UNDEF 0xffffffff
  70. #define M3D_INDEXMAX 0xfffffffe
  71. #else
  72. typedef uint16_t M3D_INDEX;
  73. #define M3D_UNDEF 0xffff
  74. #define M3D_INDEXMAX 0xfffe
  75. #endif
  76. #define M3D_NOTDEFINED 0xffffffff
  77. #ifndef M3D_NUMBONE
  78. #define M3D_NUMBONE 4
  79. #endif
  80. #ifndef M3D_BONEMAXLEVEL
  81. #define M3D_BONEMAXLEVEL 8
  82. #endif
  83. #if !defined(_MSC_VER) || defined(__clang__)
  84. #ifndef _inline
  85. #define _inline __inline__
  86. #endif
  87. #define _pack __attribute__((packed))
  88. #define _unused __attribute__((unused))
  89. #else
  90. #define _inline
  91. #define _pack
  92. #define _unused __pragma(warning(suppress : 4100))
  93. #endif
  94. #ifndef __cplusplus
  95. #define _register register
  96. #else
  97. #define _register
  98. #endif
  99. #if _MSC_VER > 1920 && !defined(__clang__)
  100. # pragma warning(push)
  101. # pragma warning(disable : 4100 4127 4189 4505 4244 4403 4701 4703)
  102. # if (_MSC_VER > 1800 )
  103. # pragma warning(disable : 5573 5744)
  104. # endif
  105. #endif // _MSC_VER
  106. /*** File format structures ***/
  107. /**
  108. * M3D file format structure
  109. * 3DMO m3dchunk_t file header chunk, may followed by compressed data
  110. * HEAD m3dhdr_t model header chunk
  111. * n x m3dchunk_t more chunks follow
  112. * PRVW preview chunk (optional)
  113. * CMAP color map chunk (optional)
  114. * TMAP texture map chunk (optional)
  115. * VRTS vertex data chunk (optional if it's a material library)
  116. * BONE bind-pose skeleton, bone hierarchy chunk (optional)
  117. * n x m3db_t contains propably more, but at least one bone
  118. * n x m3ds_t skin group records
  119. * MTRL* material chunk(s), can be more (optional)
  120. * n x m3dp_t each material contains propapbly more, but at least one property
  121. * the properties are configurable with a static array, see m3d_propertytypes
  122. * n x m3dchunk_t at least one, but maybe more face chunks
  123. * PROC* procedural face, or
  124. * MESH* triangle mesh (vertex index list) or
  125. * SHPE* mathematical shapes like parameterized surfaces
  126. * LBLS* annotation label chunks, can be more (optional)
  127. * ACTN* action chunk(s), animation-pose skeletons, can be more (optional)
  128. * n x m3dfr_t each action contains probably more, but at least one frame
  129. * n x m3dtr_t each frame contains probably more, but at least one transformation
  130. * ASET* inlined asset chunk(s), can be more (optional)
  131. * OMD3 end chunk
  132. *
  133. * Typical chunks for a game engine: 3DMO, HEAD, CMAP, TMAP, VRTS, BONE, MTRL, MESH, ACTN, OMD3
  134. * Typical chunks for CAD software: 3DMO, HEAD, PRVW, CMAP, TMAP, VRTS, MTRL, SHPE, LBLS, OMD3
  135. */
  136. #ifdef _MSC_VER
  137. #pragma pack(push)
  138. #pragma pack(1)
  139. #endif
  140. typedef struct {
  141. char magic[4];
  142. uint32_t length;
  143. float scale; /* deliberately not M3D_FLOAT */
  144. uint32_t types;
  145. } _pack m3dhdr_t;
  146. typedef struct {
  147. char magic[4];
  148. uint32_t length;
  149. } _pack m3dchunk_t;
  150. #ifdef _MSC_VER
  151. #pragma pack(pop)
  152. #endif
  153. /*** in-memory model structure ***/
  154. /* textmap entry */
  155. typedef struct {
  156. M3D_FLOAT u;
  157. M3D_FLOAT v;
  158. } m3dti_t;
  159. #define m3d_textureindex_t m3dti_t
  160. /* texture */
  161. typedef struct {
  162. char *name; /* texture name */
  163. uint8_t *d; /* pixels data */
  164. uint16_t w; /* width */
  165. uint16_t h; /* height */
  166. uint8_t f; /* format, 1 = grayscale, 2 = grayscale+alpha, 3 = rgb, 4 = rgba */
  167. } m3dtx_t;
  168. #define m3d_texturedata_t m3dtx_t
  169. typedef struct {
  170. M3D_INDEX vertexid;
  171. M3D_FLOAT weight;
  172. } m3dw_t;
  173. #define m3d_weight_t m3dw_t
  174. /* bone entry */
  175. typedef struct {
  176. M3D_INDEX parent; /* parent bone index */
  177. char *name; /* name for this bone */
  178. M3D_INDEX pos; /* vertex index position */
  179. M3D_INDEX ori; /* vertex index orientation (quaternion) */
  180. M3D_INDEX numweight; /* number of controlled vertices */
  181. m3dw_t *weight; /* weights for those vertices */
  182. M3D_FLOAT mat4[16]; /* transformation matrix */
  183. } m3db_t;
  184. #define m3d_bone_t m3db_t
  185. /* skin: bone per vertex entry */
  186. typedef struct {
  187. M3D_INDEX boneid[M3D_NUMBONE];
  188. M3D_FLOAT weight[M3D_NUMBONE];
  189. } m3ds_t;
  190. #define m3d_skin_t m3ds_t
  191. /* vertex entry */
  192. typedef struct {
  193. M3D_FLOAT x; /* 3D coordinates and weight */
  194. M3D_FLOAT y;
  195. M3D_FLOAT z;
  196. M3D_FLOAT w;
  197. uint32_t color; /* default vertex color */
  198. M3D_INDEX skinid; /* skin index */
  199. #ifdef M3D_VERTEXTYPE
  200. uint8_t type;
  201. #endif
  202. } m3dv_t;
  203. #define m3d_vertex_t m3dv_t
  204. /* material property formats */
  205. enum {
  206. m3dpf_color,
  207. m3dpf_uint8,
  208. m3dpf_uint16,
  209. m3dpf_uint32,
  210. m3dpf_float,
  211. m3dpf_map
  212. };
  213. typedef struct {
  214. uint8_t format;
  215. uint8_t id;
  216. #define M3D_PROPERTYDEF(f, i, n) \
  217. { (f), (i), (char *)(n) }
  218. char *key;
  219. } m3dpd_t;
  220. /* material property types */
  221. /* You shouldn't change the first 8 display and first 4 physical property. Assign the rest as you like. */
  222. enum {
  223. m3dp_Kd = 0, /* scalar display properties */
  224. m3dp_Ka,
  225. m3dp_Ks,
  226. m3dp_Ns,
  227. m3dp_Ke,
  228. m3dp_Tf,
  229. m3dp_Km,
  230. m3dp_d,
  231. m3dp_il,
  232. m3dp_Pr = 64, /* scalar physical properties */
  233. m3dp_Pm,
  234. m3dp_Ps,
  235. m3dp_Ni,
  236. m3dp_Nt,
  237. m3dp_map_Kd = 128, /* textured display map properties */
  238. m3dp_map_Ka,
  239. m3dp_map_Ks,
  240. m3dp_map_Ns,
  241. m3dp_map_Ke,
  242. m3dp_map_Tf,
  243. m3dp_map_Km, /* bump map */
  244. m3dp_map_D,
  245. m3dp_map_N, /* normal map */
  246. m3dp_map_Pr = 192, /* textured physical map properties */
  247. m3dp_map_Pm,
  248. m3dp_map_Ps,
  249. m3dp_map_Ni,
  250. m3dp_map_Nt
  251. };
  252. enum { /* aliases */
  253. m3dp_bump = m3dp_map_Km,
  254. m3dp_map_il = m3dp_map_N,
  255. m3dp_refl = m3dp_map_Pm
  256. };
  257. /* material property */
  258. typedef struct {
  259. uint8_t type; /* property type, see "m3dp_*" enumeration */
  260. union {
  261. uint32_t color; /* if value is a color, m3dpf_color */
  262. uint32_t num; /* if value is a number, m3dpf_uint8, m3pf_uint16, m3dpf_uint32 */
  263. float fnum; /* if value is a floating point number, m3dpf_float */
  264. M3D_INDEX textureid; /* if value is a texture, m3dpf_map */
  265. } value;
  266. } m3dp_t;
  267. #define m3d_property_t m3dp_t
  268. /* material entry */
  269. typedef struct {
  270. char *name; /* name of the material */
  271. uint8_t numprop; /* number of properties */
  272. m3dp_t *prop; /* properties array */
  273. } m3dm_t;
  274. #define m3d_material_t m3dm_t
  275. /* face entry */
  276. typedef struct {
  277. M3D_INDEX materialid; /* material index */
  278. M3D_INDEX vertex[3]; /* 3D points of the triangle in CCW order */
  279. M3D_INDEX normal[3]; /* normal vectors */
  280. M3D_INDEX texcoord[3]; /* UV coordinates */
  281. } m3df_t;
  282. #define m3d_face_t m3df_t
  283. /* shape command types. must match the row in m3d_commandtypes */
  284. enum {
  285. /* special commands */
  286. m3dc_use = 0, /* use material */
  287. m3dc_inc, /* include another shape */
  288. m3dc_mesh, /* include part of polygon mesh */
  289. /* approximations */
  290. m3dc_div, /* subdivision by constant resolution for both u, v */
  291. m3dc_sub, /* subdivision by constant, different for u and v */
  292. m3dc_len, /* spacial subdivision by maxlength */
  293. m3dc_dist, /* subdivision by maxdistance and maxangle */
  294. /* modifiers */
  295. m3dc_degu, /* degree for both u, v */
  296. m3dc_deg, /* separate degree for u and v */
  297. m3dc_rangeu, /* range for u */
  298. m3dc_range, /* range for u and v */
  299. m3dc_paru, /* u parameters (knots) */
  300. m3dc_parv, /* v parameters */
  301. m3dc_trim, /* outer trimming curve */
  302. m3dc_hole, /* inner trimming curve */
  303. m3dc_scrv, /* spacial curve */
  304. m3dc_sp, /* special points */
  305. /* helper curves */
  306. m3dc_bez1, /* Bezier 1D */
  307. m3dc_bsp1, /* B-spline 1D */
  308. m3dc_bez2, /* bezier 2D */
  309. m3dc_bsp2, /* B-spline 2D */
  310. /* surfaces */
  311. m3dc_bezun, /* Bezier 3D with control, UV, normal */
  312. m3dc_bezu, /* with control and UV */
  313. m3dc_bezn, /* with control and normal */
  314. m3dc_bez, /* control points only */
  315. m3dc_nurbsun, /* B-spline 3D */
  316. m3dc_nurbsu,
  317. m3dc_nurbsn,
  318. m3dc_nurbs,
  319. m3dc_conn, /* connect surfaces */
  320. /* geometrical */
  321. m3dc_line,
  322. m3dc_polygon,
  323. m3dc_circle,
  324. m3dc_cylinder,
  325. m3dc_shpere,
  326. m3dc_torus,
  327. m3dc_cone,
  328. m3dc_cube
  329. };
  330. /* shape command argument types */
  331. enum {
  332. m3dcp_mi_t = 1, /* material index */
  333. m3dcp_hi_t, /* shape index */
  334. m3dcp_fi_t, /* face index */
  335. m3dcp_ti_t, /* texture map index */
  336. m3dcp_vi_t, /* vertex index */
  337. m3dcp_qi_t, /* vertex index for quaternions */
  338. m3dcp_vc_t, /* coordinate or radius, float scalar */
  339. m3dcp_i1_t, /* int8 scalar */
  340. m3dcp_i2_t, /* int16 scalar */
  341. m3dcp_i4_t, /* int32 scalar */
  342. m3dcp_va_t /* variadic arguments */
  343. };
  344. #define M3D_CMDMAXARG 8 /* if you increase this, add more arguments to the macro below */
  345. typedef struct {
  346. #define M3D_CMDDEF(t, n, p, a, b, c, d, e, f, g, h) \
  347. { \
  348. (char *)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } \
  349. }
  350. char *key;
  351. uint8_t p;
  352. uint8_t a[M3D_CMDMAXARG];
  353. } m3dcd_t;
  354. /* shape command */
  355. typedef struct {
  356. uint16_t type; /* shape type */
  357. uint32_t *arg; /* arguments array */
  358. } m3dc_t;
  359. #define m3d_shapecommand_t m3dc_t
  360. /* shape entry */
  361. typedef struct {
  362. char *name; /* name of the mathematical shape */
  363. M3D_INDEX group; /* group this shape belongs to or -1 */
  364. uint32_t numcmd; /* number of commands */
  365. m3dc_t *cmd; /* commands array */
  366. } m3dh_t;
  367. #define m3d_shape_t m3dh_t
  368. /* label entry */
  369. typedef struct {
  370. char *name; /* name of the annotation layer or NULL */
  371. char *lang; /* language code or NULL */
  372. char *text; /* the label text */
  373. uint32_t color; /* color */
  374. M3D_INDEX vertexid; /* the vertex the label refers to */
  375. } m3dl_t;
  376. #define m3d_label_t m3dl_t
  377. /* frame transformations / working copy skeleton entry */
  378. typedef struct {
  379. M3D_INDEX boneid; /* selects a node in bone hierarchy */
  380. M3D_INDEX pos; /* vertex index new position */
  381. M3D_INDEX ori; /* vertex index new orientation (quaternion) */
  382. } m3dtr_t;
  383. #define m3d_transform_t m3dtr_t
  384. /* animation frame entry */
  385. typedef struct {
  386. uint32_t msec; /* frame's position on the timeline, timestamp */
  387. M3D_INDEX numtransform; /* number of transformations in this frame */
  388. m3dtr_t *transform; /* transformations */
  389. } m3dfr_t;
  390. #define m3d_frame_t m3dfr_t
  391. /* model action entry */
  392. typedef struct {
  393. char *name; /* name of the action */
  394. uint32_t durationmsec; /* duration in millisec (1/1000 sec) */
  395. M3D_INDEX numframe; /* number of frames in this animation */
  396. m3dfr_t *frame; /* frames array */
  397. } m3da_t;
  398. #define m3d_action_t m3da_t
  399. /* inlined asset */
  400. typedef struct {
  401. char *name; /* asset name (same pointer as in texture[].name) */
  402. uint8_t *data; /* compressed asset data */
  403. uint32_t length; /* compressed data length */
  404. } m3di_t;
  405. #define m3d_inlinedasset_t m3di_t
  406. /*** in-memory model structure ***/
  407. #define M3D_FLG_FREERAW (1 << 0)
  408. #define M3D_FLG_FREESTR (1 << 1)
  409. #define M3D_FLG_MTLLIB (1 << 2)
  410. #define M3D_FLG_GENNORM (1 << 3)
  411. typedef struct {
  412. m3dhdr_t *raw; /* pointer to raw data */
  413. char flags; /* internal flags */
  414. signed char errcode; /* returned error code */
  415. char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s, fi_s; /* decoded sizes for types */
  416. char *name; /* name of the model, like "Utah teapot" */
  417. char *license; /* usage condition or license, like "MIT", "LGPL" or "BSD-3clause" */
  418. char *author; /* nickname, email, homepage or github URL etc. */
  419. char *desc; /* comments, descriptions. May contain '\n' newline character */
  420. M3D_FLOAT scale; /* the model's bounding cube's size in SI meters */
  421. M3D_INDEX numcmap;
  422. uint32_t *cmap; /* color map */
  423. M3D_INDEX numtmap;
  424. m3dti_t *tmap; /* texture map indices */
  425. M3D_INDEX numtexture;
  426. m3dtx_t *texture; /* uncompressed textures */
  427. M3D_INDEX numbone;
  428. m3db_t *bone; /* bone hierarchy */
  429. M3D_INDEX numvertex;
  430. m3dv_t *vertex; /* vertex data */
  431. M3D_INDEX numskin;
  432. m3ds_t *skin; /* skin data */
  433. M3D_INDEX nummaterial;
  434. m3dm_t *material; /* material list */
  435. M3D_INDEX numface;
  436. m3df_t *face; /* model face, polygon (triangle) mesh */
  437. M3D_INDEX numshape;
  438. m3dh_t *shape; /* model face, shape commands */
  439. M3D_INDEX numlabel;
  440. m3dl_t *label; /* annotation labels */
  441. M3D_INDEX numaction;
  442. m3da_t *action; /* action animations */
  443. M3D_INDEX numinlined;
  444. m3di_t *inlined; /* inlined assets */
  445. M3D_INDEX numextra;
  446. m3dchunk_t **extra; /* unknown chunks, application / engine specific data probably */
  447. m3di_t preview; /* preview chunk */
  448. } m3d_t;
  449. /*** export parameters ***/
  450. #define M3D_EXP_INT8 0
  451. #define M3D_EXP_INT16 1
  452. #define M3D_EXP_FLOAT 2
  453. #define M3D_EXP_DOUBLE 3
  454. #define M3D_EXP_NOCMAP (1 << 0)
  455. #define M3D_EXP_NOMATERIAL (1 << 1)
  456. #define M3D_EXP_NOFACE (1 << 2)
  457. #define M3D_EXP_NONORMAL (1 << 3)
  458. #define M3D_EXP_NOTXTCRD (1 << 4)
  459. #define M3D_EXP_FLIPTXTCRD (1 << 5)
  460. #define M3D_EXP_NORECALC (1 << 6)
  461. #define M3D_EXP_IDOSUCK (1 << 7)
  462. #define M3D_EXP_NOBONE (1 << 8)
  463. #define M3D_EXP_NOACTION (1 << 9)
  464. #define M3D_EXP_INLINE (1 << 10)
  465. #define M3D_EXP_EXTRA (1 << 11)
  466. #define M3D_EXP_NOZLIB (1 << 14)
  467. #define M3D_EXP_ASCII (1 << 15)
  468. /*** error codes ***/
  469. #define M3D_SUCCESS 0
  470. #define M3D_ERR_ALLOC -1
  471. #define M3D_ERR_BADFILE -2
  472. #define M3D_ERR_UNIMPL -65
  473. #define M3D_ERR_UNKPROP -66
  474. #define M3D_ERR_UNKMESH -67
  475. #define M3D_ERR_UNKIMG -68
  476. #define M3D_ERR_UNKFRAME -69
  477. #define M3D_ERR_UNKCMD -70
  478. #define M3D_ERR_TRUNC -71
  479. #define M3D_ERR_CMAP -72
  480. #define M3D_ERR_TMAP -73
  481. #define M3D_ERR_VRTS -74
  482. #define M3D_ERR_BONE -75
  483. #define M3D_ERR_MTRL -76
  484. #define M3D_ERR_SHPE -77
  485. #define M3D_ERR_ISFATAL(x) ((x) < 0 && (x) > -65)
  486. /* callbacks */
  487. typedef unsigned char *(*m3dread_t)(char *filename, unsigned int *size); /* read file contents into buffer */
  488. typedef void (*m3dfree_t)(void *buffer); /* free file contents buffer */
  489. typedef int (*m3dtxsc_t)(const char *name, const void *script, uint32_t len, m3dtx_t *output); /* interpret texture script */
  490. typedef int (*m3dprsc_t)(const char *name, const void *script, uint32_t len, m3d_t *model); /* interpret surface script */
  491. #endif /* ifndef M3D_APIVERSION */
  492. /*** C prototypes ***/
  493. /* import / export */
  494. m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d_t *mtllib);
  495. unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size);
  496. void m3d_free(m3d_t *model);
  497. /* generate animation pose skeleton */
  498. m3dtr_t *m3d_frame(m3d_t *model, M3D_INDEX actionid, M3D_INDEX frameid, m3dtr_t *skeleton);
  499. m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec);
  500. /* private prototypes used by both importer and exporter */
  501. char *_m3d_safestr(char *in, int morelines);
  502. /*** C implementation ***/
  503. #ifdef M3D_IMPLEMENTATION
  504. #if !defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER)
  505. /* material property definitions */
  506. static m3dpd_t m3d_propertytypes[] = {
  507. M3D_PROPERTYDEF(m3dpf_color, m3dp_Kd, "Kd"), /* diffuse color */
  508. M3D_PROPERTYDEF(m3dpf_color, m3dp_Ka, "Ka"), /* ambient color */
  509. M3D_PROPERTYDEF(m3dpf_color, m3dp_Ks, "Ks"), /* specular color */
  510. M3D_PROPERTYDEF(m3dpf_float, m3dp_Ns, "Ns"), /* specular exponent */
  511. M3D_PROPERTYDEF(m3dpf_color, m3dp_Ke, "Ke"), /* emissive (emitting light of this color) */
  512. M3D_PROPERTYDEF(m3dpf_color, m3dp_Tf, "Tf"), /* transmission color */
  513. M3D_PROPERTYDEF(m3dpf_float, m3dp_Km, "Km"), /* bump strength */
  514. M3D_PROPERTYDEF(m3dpf_float, m3dp_d, "d"), /* dissolve (transparency) */
  515. M3D_PROPERTYDEF(m3dpf_uint8, m3dp_il, "il"), /* illumination model (informational, ignored by PBR-shaders) */
  516. M3D_PROPERTYDEF(m3dpf_float, m3dp_Pr, "Pr"), /* roughness */
  517. M3D_PROPERTYDEF(m3dpf_float, m3dp_Pm, "Pm"), /* metallic, also reflection */
  518. M3D_PROPERTYDEF(m3dpf_float, m3dp_Ps, "Ps"), /* sheen */
  519. M3D_PROPERTYDEF(m3dpf_float, m3dp_Ni, "Ni"), /* index of refraction (optical density) */
  520. M3D_PROPERTYDEF(m3dpf_float, m3dp_Nt, "Nt"), /* thickness of face in millimeter, for printing */
  521. /* aliases, note that "map_*" aliases are handled automatically */
  522. M3D_PROPERTYDEF(m3dpf_map, m3dp_map_Km, "bump"),
  523. M3D_PROPERTYDEF(m3dpf_map, m3dp_map_N, "map_N"), /* as normal map has no scalar version, it's counterpart is 'il' */
  524. M3D_PROPERTYDEF(m3dpf_map, m3dp_map_Pm, "refl")
  525. };
  526. /* shape command definitions. if more commands start with the same string, the longer must come first */
  527. static m3dcd_t m3d_commandtypes[] = {
  528. /* technical */
  529. M3D_CMDDEF(m3dc_use, "use", 1, m3dcp_mi_t, 0, 0, 0, 0, 0, 0, 0),
  530. M3D_CMDDEF(m3dc_inc, "inc", 3, m3dcp_hi_t, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vi_t, 0, 0, 0, 0),
  531. M3D_CMDDEF(m3dc_mesh, "mesh", 1, m3dcp_fi_t, m3dcp_fi_t, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vi_t, 0, 0, 0),
  532. /* approximations */
  533. M3D_CMDDEF(m3dc_div, "div", 1, m3dcp_vc_t, 0, 0, 0, 0, 0, 0, 0),
  534. M3D_CMDDEF(m3dc_sub, "sub", 2, m3dcp_vc_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0),
  535. M3D_CMDDEF(m3dc_len, "len", 1, m3dcp_vc_t, 0, 0, 0, 0, 0, 0, 0),
  536. M3D_CMDDEF(m3dc_dist, "dist", 2, m3dcp_vc_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0),
  537. /* modifiers */
  538. M3D_CMDDEF(m3dc_degu, "degu", 1, m3dcp_i1_t, 0, 0, 0, 0, 0, 0, 0),
  539. M3D_CMDDEF(m3dc_deg, "deg", 2, m3dcp_i1_t, m3dcp_i1_t, 0, 0, 0, 0, 0, 0),
  540. M3D_CMDDEF(m3dc_rangeu, "rangeu", 1, m3dcp_ti_t, 0, 0, 0, 0, 0, 0, 0),
  541. M3D_CMDDEF(m3dc_range, "range", 2, m3dcp_ti_t, m3dcp_ti_t, 0, 0, 0, 0, 0, 0),
  542. M3D_CMDDEF(m3dc_paru, "paru", 2, m3dcp_va_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0),
  543. M3D_CMDDEF(m3dc_parv, "parv", 2, m3dcp_va_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0),
  544. M3D_CMDDEF(m3dc_trim, "trim", 3, m3dcp_va_t, m3dcp_ti_t, m3dcp_i2_t, 0, 0, 0, 0, 0),
  545. M3D_CMDDEF(m3dc_hole, "hole", 3, m3dcp_va_t, m3dcp_ti_t, m3dcp_i2_t, 0, 0, 0, 0, 0),
  546. M3D_CMDDEF(m3dc_scrv, "scrv", 3, m3dcp_va_t, m3dcp_ti_t, m3dcp_i2_t, 0, 0, 0, 0, 0),
  547. M3D_CMDDEF(m3dc_sp, "sp", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0),
  548. /* helper curves */
  549. M3D_CMDDEF(m3dc_bez1, "bez1", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0),
  550. M3D_CMDDEF(m3dc_bsp1, "bsp1", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0),
  551. M3D_CMDDEF(m3dc_bez2, "bez2", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0),
  552. M3D_CMDDEF(m3dc_bsp2, "bsp2", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0),
  553. /* surfaces */
  554. M3D_CMDDEF(m3dc_bezun, "bezun", 4, m3dcp_va_t, m3dcp_vi_t, m3dcp_ti_t, m3dcp_vi_t, 0, 0, 0, 0),
  555. M3D_CMDDEF(m3dc_bezu, "bezu", 3, m3dcp_va_t, m3dcp_vi_t, m3dcp_ti_t, 0, 0, 0, 0, 0),
  556. M3D_CMDDEF(m3dc_bezn, "bezn", 3, m3dcp_va_t, m3dcp_vi_t, m3dcp_vi_t, 0, 0, 0, 0, 0),
  557. M3D_CMDDEF(m3dc_bez, "bez", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0),
  558. M3D_CMDDEF(m3dc_nurbsun, "nurbsun", 4, m3dcp_va_t, m3dcp_vi_t, m3dcp_ti_t, m3dcp_vi_t, 0, 0, 0, 0),
  559. M3D_CMDDEF(m3dc_nurbsu, "nurbsu", 3, m3dcp_va_t, m3dcp_vi_t, m3dcp_ti_t, 0, 0, 0, 0, 0),
  560. M3D_CMDDEF(m3dc_nurbsn, "nurbsn", 3, m3dcp_va_t, m3dcp_vi_t, m3dcp_vi_t, 0, 0, 0, 0, 0),
  561. M3D_CMDDEF(m3dc_nurbs, "nurbs", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0),
  562. M3D_CMDDEF(m3dc_conn, "conn", 6, m3dcp_i2_t, m3dcp_ti_t, m3dcp_i2_t, m3dcp_i2_t, m3dcp_ti_t, m3dcp_i2_t, 0, 0),
  563. /* geometrical */
  564. M3D_CMDDEF(m3dc_line, "line", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0),
  565. M3D_CMDDEF(m3dc_polygon, "polygon", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0),
  566. M3D_CMDDEF(m3dc_circle, "circle", 3, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, 0, 0, 0, 0, 0),
  567. M3D_CMDDEF(m3dc_cylinder, "cylinder", 6, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, 0, 0),
  568. M3D_CMDDEF(m3dc_shpere, "shpere", 2, m3dcp_vi_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0),
  569. M3D_CMDDEF(m3dc_torus, "torus", 4, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, m3dcp_vc_t, 0, 0, 0, 0),
  570. M3D_CMDDEF(m3dc_cone, "cone", 3, m3dcp_vi_t, m3dcp_vi_t, m3dcp_vi_t, 0, 0, 0, 0, 0),
  571. M3D_CMDDEF(m3dc_cube, "cube", 3, m3dcp_vi_t, m3dcp_vi_t, m3dcp_vi_t, 0, 0, 0, 0, 0)
  572. };
  573. #endif
  574. #include <stdlib.h>
  575. #include <string.h>
  576. #if !defined(M3D_NOIMPORTER) && !defined(STBI_INCLUDE_STB_IMAGE_H)
  577. /* PNG decompressor from
  578. stb_image - v2.23 - public domain image loader - http://nothings.org/stb_image.h
  579. */
  580. static const char *_m3dstbi__g_failure_reason;
  581. enum {
  582. STBI_default = 0,
  583. STBI_grey = 1,
  584. STBI_grey_alpha = 2,
  585. STBI_rgb = 3,
  586. STBI_rgb_alpha = 4
  587. };
  588. enum {
  589. STBI__SCAN_load = 0,
  590. STBI__SCAN_type,
  591. STBI__SCAN_header
  592. };
  593. typedef unsigned short _m3dstbi_us;
  594. typedef uint16_t _m3dstbi__uint16;
  595. typedef int16_t _m3dstbi__int16;
  596. typedef uint32_t _m3dstbi__uint32;
  597. typedef int32_t _m3dstbi__int32;
  598. typedef struct
  599. {
  600. _m3dstbi__uint32 img_x, img_y;
  601. int img_n, img_out_n;
  602. void *io_user_data;
  603. int read_from_callbacks;
  604. int buflen;
  605. unsigned char buffer_start[128];
  606. unsigned char *img_buffer, *img_buffer_end;
  607. unsigned char *img_buffer_original, *img_buffer_original_end;
  608. } _m3dstbi__context;
  609. typedef struct
  610. {
  611. int bits_per_channel;
  612. int num_channels;
  613. int channel_order;
  614. } _m3dstbi__result_info;
  615. #define STBI_ASSERT(v)
  616. #ifdef _MSC_VER
  617. #define STBI_NOTUSED(v) (void)(v)
  618. #else
  619. #define STBI_NOTUSED(v) (void)sizeof(v)
  620. #endif
  621. #define STBI__BYTECAST(x) ((unsigned char)((x)&255))
  622. #define STBI_MALLOC(sz) M3D_MALLOC(sz)
  623. #define STBI_REALLOC(p, newsz) M3D_REALLOC(p, newsz)
  624. #define STBI_FREE(p) M3D_FREE(p)
  625. #define STBI_REALLOC_SIZED(p, oldsz, newsz) STBI_REALLOC(p, newsz)
  626. _inline static unsigned char _m3dstbi__get8(_m3dstbi__context *s) {
  627. if (s->img_buffer < s->img_buffer_end)
  628. return *s->img_buffer++;
  629. return 0;
  630. }
  631. static void _m3dstbi__skip(_m3dstbi__context *s, int n) {
  632. if (n < 0) {
  633. s->img_buffer = s->img_buffer_end;
  634. return;
  635. }
  636. s->img_buffer += n;
  637. }
  638. static int _m3dstbi__getn(_m3dstbi__context *s, unsigned char *buffer, int n) {
  639. if (s->img_buffer + n <= s->img_buffer_end) {
  640. memcpy(buffer, s->img_buffer, n);
  641. s->img_buffer += n;
  642. return 1;
  643. } else
  644. return 0;
  645. }
  646. static int _m3dstbi__get16be(_m3dstbi__context *s) {
  647. int z = _m3dstbi__get8(s);
  648. return (z << 8) + _m3dstbi__get8(s);
  649. }
  650. static _m3dstbi__uint32 _m3dstbi__get32be(_m3dstbi__context *s) {
  651. _m3dstbi__uint32 z = _m3dstbi__get16be(s);
  652. return (z << 16) + _m3dstbi__get16be(s);
  653. }
  654. #define _m3dstbi__err(x, y) _m3dstbi__errstr(y)
  655. static int _m3dstbi__errstr(const char *str) {
  656. _m3dstbi__g_failure_reason = str;
  657. return 0;
  658. }
  659. _inline static void *_m3dstbi__malloc(size_t size) {
  660. return STBI_MALLOC(size);
  661. }
  662. static int _m3dstbi__addsizes_valid(int a, int b) {
  663. if (b < 0) return 0;
  664. return a <= 2147483647 - b;
  665. }
  666. static int _m3dstbi__mul2sizes_valid(int a, int b) {
  667. if (a < 0 || b < 0) return 0;
  668. if (b == 0) return 1;
  669. return a <= 2147483647 / b;
  670. }
  671. static int _m3dstbi__mad2sizes_valid(int a, int b, int add) {
  672. return _m3dstbi__mul2sizes_valid(a, b) && _m3dstbi__addsizes_valid(a * b, add);
  673. }
  674. static int _m3dstbi__mad3sizes_valid(int a, int b, int c, int add) {
  675. return _m3dstbi__mul2sizes_valid(a, b) && _m3dstbi__mul2sizes_valid(a * b, c) &&
  676. _m3dstbi__addsizes_valid(a * b * c, add);
  677. }
  678. static void *_m3dstbi__malloc_mad2(int a, int b, int add) {
  679. if (!_m3dstbi__mad2sizes_valid(a, b, add)) return NULL;
  680. return _m3dstbi__malloc(a * b + add);
  681. }
  682. static void *_m3dstbi__malloc_mad3(int a, int b, int c, int add) {
  683. if (!_m3dstbi__mad3sizes_valid(a, b, c, add)) return NULL;
  684. return _m3dstbi__malloc(a * b * c + add);
  685. }
  686. static unsigned char _m3dstbi__compute_y(int r, int g, int b) {
  687. return (unsigned char)(((r * 77) + (g * 150) + (29 * b)) >> 8);
  688. }
  689. static unsigned char *_m3dstbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) {
  690. int i, j;
  691. unsigned char *good;
  692. if (req_comp == img_n) return data;
  693. STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
  694. good = (unsigned char *)_m3dstbi__malloc_mad3(req_comp, x, y, 0);
  695. if (good == NULL) {
  696. STBI_FREE(data);
  697. _m3dstbi__err("outofmem", "Out of memory");
  698. return NULL;
  699. }
  700. for (j = 0; j < (int)y; ++j) {
  701. unsigned char *src = data + j * x * img_n;
  702. unsigned char *dest = good + j * x * req_comp;
  703. #define STBI__COMBO(a, b) ((a)*8 + (b))
  704. #define STBI__CASE(a, b) \
  705. case STBI__COMBO(a, b): \
  706. for (i = x - 1; i >= 0; --i, src += a, dest += b)
  707. switch (STBI__COMBO(img_n, req_comp)) {
  708. STBI__CASE(1, 2) { dest[0] = src[0], dest[1] = 255; }
  709. break;
  710. STBI__CASE(1, 3) { dest[0] = dest[1] = dest[2] = src[0]; }
  711. break;
  712. STBI__CASE(1, 4) { dest[0] = dest[1] = dest[2] = src[0], dest[3] = 255; }
  713. break;
  714. STBI__CASE(2, 1) { dest[0] = src[0]; }
  715. break;
  716. STBI__CASE(2, 3) { dest[0] = dest[1] = dest[2] = src[0]; }
  717. break;
  718. STBI__CASE(2, 4) { dest[0] = dest[1] = dest[2] = src[0], dest[3] = src[1]; }
  719. break;
  720. STBI__CASE(3, 4) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2], dest[3] = 255; }
  721. break;
  722. STBI__CASE(3, 1) { dest[0] = _m3dstbi__compute_y(src[0], src[1], src[2]); }
  723. break;
  724. STBI__CASE(3, 2) { dest[0] = _m3dstbi__compute_y(src[0], src[1], src[2]), dest[1] = 255; }
  725. break;
  726. STBI__CASE(4, 1) { dest[0] = _m3dstbi__compute_y(src[0], src[1], src[2]); }
  727. break;
  728. STBI__CASE(4, 2) { dest[0] = _m3dstbi__compute_y(src[0], src[1], src[2]), dest[1] = src[3]; }
  729. break;
  730. STBI__CASE(4, 3) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2]; }
  731. break;
  732. default: STBI_ASSERT(0);
  733. }
  734. #undef STBI__CASE
  735. }
  736. STBI_FREE(data);
  737. return good;
  738. }
  739. static _m3dstbi__uint16 _m3dstbi__compute_y_16(int r, int g, int b) {
  740. return (_m3dstbi__uint16)(((r * 77) + (g * 150) + (29 * b)) >> 8);
  741. }
  742. static _m3dstbi__uint16 *_m3dstbi__convert_format16(_m3dstbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) {
  743. int i, j;
  744. _m3dstbi__uint16 *good;
  745. if (req_comp == img_n) return data;
  746. STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
  747. good = (_m3dstbi__uint16 *)_m3dstbi__malloc(req_comp * x * y * 2);
  748. if (good == NULL) {
  749. STBI_FREE(data);
  750. _m3dstbi__err("outofmem", "Out of memory");
  751. return NULL;
  752. }
  753. for (j = 0; j < (int)y; ++j) {
  754. _m3dstbi__uint16 *src = data + j * x * img_n;
  755. _m3dstbi__uint16 *dest = good + j * x * req_comp;
  756. #define STBI__COMBO(a, b) ((a)*8 + (b))
  757. #define STBI__CASE(a, b) \
  758. case STBI__COMBO(a, b): \
  759. for (i = x - 1; i >= 0; --i, src += a, dest += b)
  760. switch (STBI__COMBO(img_n, req_comp)) {
  761. STBI__CASE(1, 2) { dest[0] = src[0], dest[1] = 0xffff; }
  762. break;
  763. STBI__CASE(1, 3) { dest[0] = dest[1] = dest[2] = src[0]; }
  764. break;
  765. STBI__CASE(1, 4) { dest[0] = dest[1] = dest[2] = src[0], dest[3] = 0xffff; }
  766. break;
  767. STBI__CASE(2, 1) { dest[0] = src[0]; }
  768. break;
  769. STBI__CASE(2, 3) { dest[0] = dest[1] = dest[2] = src[0]; }
  770. break;
  771. STBI__CASE(2, 4) { dest[0] = dest[1] = dest[2] = src[0], dest[3] = src[1]; }
  772. break;
  773. STBI__CASE(3, 4) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2], dest[3] = 0xffff; }
  774. break;
  775. STBI__CASE(3, 1) { dest[0] = _m3dstbi__compute_y_16(src[0], src[1], src[2]); }
  776. break;
  777. STBI__CASE(3, 2) { dest[0] = _m3dstbi__compute_y_16(src[0], src[1], src[2]), dest[1] = 0xffff; }
  778. break;
  779. STBI__CASE(4, 1) { dest[0] = _m3dstbi__compute_y_16(src[0], src[1], src[2]); }
  780. break;
  781. STBI__CASE(4, 2) { dest[0] = _m3dstbi__compute_y_16(src[0], src[1], src[2]), dest[1] = src[3]; }
  782. break;
  783. STBI__CASE(4, 3) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2]; }
  784. break;
  785. default: STBI_ASSERT(0);
  786. }
  787. #undef STBI__CASE
  788. }
  789. STBI_FREE(data);
  790. return good;
  791. }
  792. #define STBI__ZFAST_BITS 9
  793. #define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1)
  794. typedef struct
  795. {
  796. _m3dstbi__uint16 fast[1 << STBI__ZFAST_BITS];
  797. _m3dstbi__uint16 firstcode[16];
  798. int maxcode[17];
  799. _m3dstbi__uint16 firstsymbol[16];
  800. unsigned char size[288];
  801. _m3dstbi__uint16 value[288];
  802. } _m3dstbi__zhuffman;
  803. _inline static int _m3dstbi__bitreverse16(int n) {
  804. n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);
  805. n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);
  806. n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4);
  807. n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8);
  808. return n;
  809. }
  810. _inline static int _m3dstbi__bit_reverse(int v, int bits) {
  811. STBI_ASSERT(bits <= 16);
  812. return _m3dstbi__bitreverse16(v) >> (16 - bits);
  813. }
  814. static int _m3dstbi__zbuild_huffman(_m3dstbi__zhuffman *z, unsigned char *sizelist, int num) {
  815. int i, k = 0;
  816. int code, next_code[16], sizes[17];
  817. memset(sizes, 0, sizeof(sizes));
  818. memset(z->fast, 0, sizeof(z->fast));
  819. for (i = 0; i < num; ++i)
  820. ++sizes[sizelist[i]];
  821. sizes[0] = 0;
  822. for (i = 1; i < 16; ++i)
  823. if (sizes[i] > (1 << i))
  824. return _m3dstbi__err("bad sizes", "Corrupt PNG");
  825. code = 0;
  826. for (i = 1; i < 16; ++i) {
  827. next_code[i] = code;
  828. z->firstcode[i] = (_m3dstbi__uint16)code;
  829. z->firstsymbol[i] = (_m3dstbi__uint16)k;
  830. code = (code + sizes[i]);
  831. if (sizes[i])
  832. if (code - 1 >= (1 << i)) return _m3dstbi__err("bad codelengths", "Corrupt PNG");
  833. z->maxcode[i] = code << (16 - i);
  834. code <<= 1;
  835. k += sizes[i];
  836. }
  837. z->maxcode[16] = 0x10000;
  838. for (i = 0; i < num; ++i) {
  839. int s = sizelist[i];
  840. if (s) {
  841. int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
  842. _m3dstbi__uint16 fastv = (_m3dstbi__uint16)((s << 9) | i);
  843. z->size[c] = (unsigned char)s;
  844. z->value[c] = (_m3dstbi__uint16)i;
  845. if (s <= STBI__ZFAST_BITS) {
  846. int j = _m3dstbi__bit_reverse(next_code[s], s);
  847. while (j < (1 << STBI__ZFAST_BITS)) {
  848. z->fast[j] = fastv;
  849. j += (1 << s);
  850. }
  851. }
  852. ++next_code[s];
  853. }
  854. }
  855. return 1;
  856. }
  857. typedef struct
  858. {
  859. unsigned char *zbuffer, *zbuffer_end;
  860. int num_bits;
  861. _m3dstbi__uint32 code_buffer;
  862. char *zout;
  863. char *zout_start;
  864. char *zout_end;
  865. int z_expandable;
  866. _m3dstbi__zhuffman z_length, z_distance;
  867. } _m3dstbi__zbuf;
  868. _inline static unsigned char _m3dstbi__zget8(_m3dstbi__zbuf *z) {
  869. if (z->zbuffer >= z->zbuffer_end) return 0;
  870. return *z->zbuffer++;
  871. }
  872. static void _m3dstbi__fill_bits(_m3dstbi__zbuf *z) {
  873. do {
  874. STBI_ASSERT(z->code_buffer < (1U << z->num_bits));
  875. z->code_buffer |= (unsigned int)_m3dstbi__zget8(z) << z->num_bits;
  876. z->num_bits += 8;
  877. } while (z->num_bits <= 24);
  878. }
  879. _inline static unsigned int _m3dstbi__zreceive(_m3dstbi__zbuf *z, int n) {
  880. unsigned int k;
  881. if (z->num_bits < n) _m3dstbi__fill_bits(z);
  882. k = z->code_buffer & ((1 << n) - 1);
  883. z->code_buffer >>= n;
  884. z->num_bits -= n;
  885. return k;
  886. }
  887. static int _m3dstbi__zhuffman_decode_slowpath(_m3dstbi__zbuf *a, _m3dstbi__zhuffman *z) {
  888. int b, s, k;
  889. k = _m3dstbi__bit_reverse(a->code_buffer, 16);
  890. for (s = STBI__ZFAST_BITS + 1;; ++s)
  891. if (k < z->maxcode[s])
  892. break;
  893. if (s == 16) return -1;
  894. b = (k >> (16 - s)) - z->firstcode[s] + z->firstsymbol[s];
  895. STBI_ASSERT(z->size[b] == s);
  896. a->code_buffer >>= s;
  897. a->num_bits -= s;
  898. return z->value[b];
  899. }
  900. _inline static int _m3dstbi__zhuffman_decode(_m3dstbi__zbuf *a, _m3dstbi__zhuffman *z) {
  901. int b, s;
  902. if (a->num_bits < 16) _m3dstbi__fill_bits(a);
  903. b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
  904. if (b) {
  905. s = b >> 9;
  906. a->code_buffer >>= s;
  907. a->num_bits -= s;
  908. return b & 511;
  909. }
  910. return _m3dstbi__zhuffman_decode_slowpath(a, z);
  911. }
  912. static int _m3dstbi__zexpand(_m3dstbi__zbuf *z, char *zout, int n) {
  913. char *q;
  914. int cur, limit, old_limit;
  915. z->zout = zout;
  916. if (!z->z_expandable) return _m3dstbi__err("output buffer limit", "Corrupt PNG");
  917. cur = (int)(z->zout - z->zout_start);
  918. limit = old_limit = (int)(z->zout_end - z->zout_start);
  919. while (cur + n > limit)
  920. limit *= 2;
  921. q = (char *)STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
  922. STBI_NOTUSED(old_limit);
  923. if (q == NULL) return _m3dstbi__err("outofmem", "Out of memory");
  924. z->zout_start = q;
  925. z->zout = q + cur;
  926. z->zout_end = q + limit;
  927. return 1;
  928. }
  929. static int _m3dstbi__zlength_base[31] = {
  930. 3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
  931. 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
  932. 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
  933. };
  934. static int _m3dstbi__zlength_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 };
  935. static int _m3dstbi__zdist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
  936. 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 };
  937. static int _m3dstbi__zdist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
  938. static int _m3dstbi__parse_huffman_block(_m3dstbi__zbuf *a) {
  939. char *zout = a->zout;
  940. for (;;) {
  941. int z = _m3dstbi__zhuffman_decode(a, &a->z_length);
  942. if (z < 256) {
  943. if (z < 0) return _m3dstbi__err("bad huffman code", "Corrupt PNG");
  944. if (zout >= a->zout_end) {
  945. if (!_m3dstbi__zexpand(a, zout, 1)) return 0;
  946. zout = a->zout;
  947. }
  948. *zout++ = (char)z;
  949. } else {
  950. unsigned char *p;
  951. int len, dist;
  952. if (z == 256) {
  953. a->zout = zout;
  954. return 1;
  955. }
  956. z -= 257;
  957. len = _m3dstbi__zlength_base[z];
  958. if (_m3dstbi__zlength_extra[z]) len += _m3dstbi__zreceive(a, _m3dstbi__zlength_extra[z]);
  959. z = _m3dstbi__zhuffman_decode(a, &a->z_distance);
  960. if (z < 0) return _m3dstbi__err("bad huffman code", "Corrupt PNG");
  961. dist = _m3dstbi__zdist_base[z];
  962. if (_m3dstbi__zdist_extra[z]) dist += _m3dstbi__zreceive(a, _m3dstbi__zdist_extra[z]);
  963. if (zout - a->zout_start < dist) return _m3dstbi__err("bad dist", "Corrupt PNG");
  964. if (zout + len > a->zout_end) {
  965. if (!_m3dstbi__zexpand(a, zout, len)) return 0;
  966. zout = a->zout;
  967. }
  968. p = (unsigned char *)(zout - dist);
  969. if (dist == 1) {
  970. unsigned char v = *p;
  971. if (len) {
  972. do
  973. *zout++ = v;
  974. while (--len);
  975. }
  976. } else {
  977. if (len) {
  978. do
  979. *zout++ = *p++;
  980. while (--len);
  981. }
  982. }
  983. }
  984. }
  985. }
  986. static int _m3dstbi__compute_huffman_codes(_m3dstbi__zbuf *a) {
  987. static unsigned char length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
  988. _m3dstbi__zhuffman z_codelength;
  989. unsigned char lencodes[286 + 32 + 137];
  990. unsigned char codelength_sizes[19];
  991. int i, n;
  992. int hlit = _m3dstbi__zreceive(a, 5) + 257;
  993. int hdist = _m3dstbi__zreceive(a, 5) + 1;
  994. int hclen = _m3dstbi__zreceive(a, 4) + 4;
  995. int ntot = hlit + hdist;
  996. memset(codelength_sizes, 0, sizeof(codelength_sizes));
  997. for (i = 0; i < hclen; ++i) {
  998. int s = _m3dstbi__zreceive(a, 3);
  999. codelength_sizes[length_dezigzag[i]] = (unsigned char)s;
  1000. }
  1001. if (!_m3dstbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
  1002. n = 0;
  1003. while (n < ntot) {
  1004. int c = _m3dstbi__zhuffman_decode(a, &z_codelength);
  1005. if (c < 0 || c >= 19) return _m3dstbi__err("bad codelengths", "Corrupt PNG");
  1006. if (c < 16)
  1007. lencodes[n++] = (unsigned char)c;
  1008. else {
  1009. unsigned char fill = 0;
  1010. if (c == 16) {
  1011. c = _m3dstbi__zreceive(a, 2) + 3;
  1012. if (n == 0) return _m3dstbi__err("bad codelengths", "Corrupt PNG");
  1013. fill = lencodes[n - 1];
  1014. } else if (c == 17)
  1015. c = _m3dstbi__zreceive(a, 3) + 3;
  1016. else {
  1017. STBI_ASSERT(c == 18);
  1018. c = _m3dstbi__zreceive(a, 7) + 11;
  1019. }
  1020. if (ntot - n < c) return _m3dstbi__err("bad codelengths", "Corrupt PNG");
  1021. memset(lencodes + n, fill, c);
  1022. n += c;
  1023. }
  1024. }
  1025. if (n != ntot) return _m3dstbi__err("bad codelengths", "Corrupt PNG");
  1026. if (!_m3dstbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
  1027. if (!_m3dstbi__zbuild_huffman(&a->z_distance, lencodes + hlit, hdist)) return 0;
  1028. return 1;
  1029. }
  1030. _inline static int _m3dstbi__parse_uncompressed_block(_m3dstbi__zbuf *a) {
  1031. unsigned char header[4];
  1032. int len, nlen, k;
  1033. if (a->num_bits & 7)
  1034. _m3dstbi__zreceive(a, a->num_bits & 7);
  1035. k = 0;
  1036. while (a->num_bits > 0) {
  1037. header[k++] = (unsigned char)(a->code_buffer & 255);
  1038. a->code_buffer >>= 8;
  1039. a->num_bits -= 8;
  1040. }
  1041. STBI_ASSERT(a->num_bits == 0);
  1042. while (k < 4)
  1043. header[k++] = _m3dstbi__zget8(a);
  1044. len = header[1] * 256 + header[0];
  1045. nlen = header[3] * 256 + header[2];
  1046. if (nlen != (len ^ 0xffff)) return _m3dstbi__err("zlib corrupt", "Corrupt PNG");
  1047. if (a->zbuffer + len > a->zbuffer_end) return _m3dstbi__err("read past buffer", "Corrupt PNG");
  1048. if (a->zout + len > a->zout_end)
  1049. if (!_m3dstbi__zexpand(a, a->zout, len)) return 0;
  1050. memcpy(a->zout, a->zbuffer, len);
  1051. a->zbuffer += len;
  1052. a->zout += len;
  1053. return 1;
  1054. }
  1055. static int _m3dstbi__parse_zlib_header(_m3dstbi__zbuf *a) {
  1056. int cmf = _m3dstbi__zget8(a);
  1057. int cm = cmf & 15;
  1058. /* int cinfo = cmf >> 4; */
  1059. int flg = _m3dstbi__zget8(a);
  1060. if ((cmf * 256 + flg) % 31 != 0) return _m3dstbi__err("bad zlib header", "Corrupt PNG");
  1061. if (flg & 32) return _m3dstbi__err("no preset dict", "Corrupt PNG");
  1062. if (cm != 8) return _m3dstbi__err("bad compression", "Corrupt PNG");
  1063. return 1;
  1064. }
  1065. static unsigned char _m3dstbi__zdefault_length[288], _m3dstbi__zdefault_distance[32];
  1066. static void _m3dstbi__init_zdefaults(void) {
  1067. int i;
  1068. for (i = 0; i <= 143; ++i)
  1069. _m3dstbi__zdefault_length[i] = 8;
  1070. for (; i <= 255; ++i)
  1071. _m3dstbi__zdefault_length[i] = 9;
  1072. for (; i <= 279; ++i)
  1073. _m3dstbi__zdefault_length[i] = 7;
  1074. for (; i <= 287; ++i)
  1075. _m3dstbi__zdefault_length[i] = 8;
  1076. for (i = 0; i <= 31; ++i)
  1077. _m3dstbi__zdefault_distance[i] = 5;
  1078. }
  1079. static int _m3dstbi__parse_zlib(_m3dstbi__zbuf *a, int parse_header) {
  1080. int final, type;
  1081. if (parse_header)
  1082. if (!_m3dstbi__parse_zlib_header(a)) return 0;
  1083. a->num_bits = 0;
  1084. a->code_buffer = 0;
  1085. do {
  1086. final = _m3dstbi__zreceive(a, 1);
  1087. type = _m3dstbi__zreceive(a, 2);
  1088. if (type == 0) {
  1089. if (!_m3dstbi__parse_uncompressed_block(a)) return 0;
  1090. } else if (type == 3) {
  1091. return 0;
  1092. } else {
  1093. if (type == 1) {
  1094. if (!_m3dstbi__zbuild_huffman(&a->z_length, _m3dstbi__zdefault_length, 288)) return 0;
  1095. if (!_m3dstbi__zbuild_huffman(&a->z_distance, _m3dstbi__zdefault_distance, 32)) return 0;
  1096. } else {
  1097. if (!_m3dstbi__compute_huffman_codes(a)) return 0;
  1098. }
  1099. if (!_m3dstbi__parse_huffman_block(a)) return 0;
  1100. }
  1101. } while (!final);
  1102. return 1;
  1103. }
  1104. static int _m3dstbi__do_zlib(_m3dstbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) {
  1105. a->zout_start = obuf;
  1106. a->zout = obuf;
  1107. a->zout_end = obuf + olen;
  1108. a->z_expandable = exp;
  1109. _m3dstbi__init_zdefaults();
  1110. return _m3dstbi__parse_zlib(a, parse_header);
  1111. }
  1112. char *_m3dstbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) {
  1113. _m3dstbi__zbuf a;
  1114. char *p = (char *)_m3dstbi__malloc(initial_size);
  1115. if (p == NULL) return NULL;
  1116. a.zbuffer = (unsigned char *)buffer;
  1117. a.zbuffer_end = (unsigned char *)buffer + len;
  1118. if (_m3dstbi__do_zlib(&a, p, initial_size, 1, parse_header)) {
  1119. if (outlen) *outlen = (int)(a.zout - a.zout_start);
  1120. return a.zout_start;
  1121. } else {
  1122. STBI_FREE(a.zout_start);
  1123. return NULL;
  1124. }
  1125. }
  1126. typedef struct
  1127. {
  1128. _m3dstbi__uint32 length;
  1129. _m3dstbi__uint32 type;
  1130. } _m3dstbi__pngchunk;
  1131. static _m3dstbi__pngchunk _m3dstbi__get_chunk_header(_m3dstbi__context *s) {
  1132. _m3dstbi__pngchunk c;
  1133. c.length = _m3dstbi__get32be(s);
  1134. c.type = _m3dstbi__get32be(s);
  1135. return c;
  1136. }
  1137. _inline static int _m3dstbi__check_png_header(_m3dstbi__context *s) {
  1138. static unsigned char png_sig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
  1139. int i;
  1140. for (i = 0; i < 8; ++i)
  1141. if (_m3dstbi__get8(s) != png_sig[i]) return _m3dstbi__err("bad png sig", "Not a PNG");
  1142. return 1;
  1143. }
  1144. typedef struct
  1145. {
  1146. _m3dstbi__context *s;
  1147. unsigned char *idata, *expanded, *out;
  1148. int depth;
  1149. } _m3dstbi__png;
  1150. enum {
  1151. STBI__F_none = 0,
  1152. STBI__F_sub = 1,
  1153. STBI__F_up = 2,
  1154. STBI__F_avg = 3,
  1155. STBI__F_paeth = 4,
  1156. STBI__F_avg_first,
  1157. STBI__F_paeth_first
  1158. };
  1159. static unsigned char first_row_filter[5] = {
  1160. STBI__F_none,
  1161. STBI__F_sub,
  1162. STBI__F_none,
  1163. STBI__F_avg_first,
  1164. STBI__F_paeth_first
  1165. };
  1166. static int _m3dstbi__paeth(int a, int b, int c) {
  1167. int p = a + b - c;
  1168. int pa = abs(p - a);
  1169. int pb = abs(p - b);
  1170. int pc = abs(p - c);
  1171. if (pa <= pb && pa <= pc) return a;
  1172. if (pb <= pc) return b;
  1173. return c;
  1174. }
  1175. static unsigned char _m3dstbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0, 0, 0, 0x01 };
  1176. static int _m3dstbi__create_png_image_raw(_m3dstbi__png *a, unsigned char *raw, _m3dstbi__uint32 raw_len, int out_n, _m3dstbi__uint32 x, _m3dstbi__uint32 y, int depth, int color) {
  1177. int bytes = (depth == 16 ? 2 : 1);
  1178. _m3dstbi__context *s = a->s;
  1179. _m3dstbi__uint32 i, j, stride = x * out_n * bytes;
  1180. _m3dstbi__uint32 img_len, img_width_bytes;
  1181. int k;
  1182. int img_n = s->img_n;
  1183. int output_bytes = out_n * bytes;
  1184. int filter_bytes = img_n * bytes;
  1185. int width = x;
  1186. STBI_ASSERT(out_n == s->img_n || out_n == s->img_n + 1);
  1187. a->out = (unsigned char *)_m3dstbi__malloc_mad3(x, y, output_bytes, 0);
  1188. if (!a->out) return _m3dstbi__err("outofmem", "Out of memory");
  1189. if (!_m3dstbi__mad3sizes_valid(img_n, x, depth, 7)) return _m3dstbi__err("too large", "Corrupt PNG");
  1190. img_width_bytes = (((img_n * x * depth) + 7) >> 3);
  1191. img_len = (img_width_bytes + 1) * y;
  1192. if (s->img_x == x && s->img_y == y) {
  1193. if (raw_len != img_len) return _m3dstbi__err("not enough pixels", "Corrupt PNG");
  1194. } else {
  1195. if (raw_len < img_len) return _m3dstbi__err("not enough pixels", "Corrupt PNG");
  1196. }
  1197. for (j = 0; j < y; ++j) {
  1198. unsigned char *cur = a->out + stride * j;
  1199. unsigned char *prior = cur - stride;
  1200. int filter = *raw++;
  1201. if (filter > 4)
  1202. return _m3dstbi__err("invalid filter", "Corrupt PNG");
  1203. if (depth < 8) {
  1204. STBI_ASSERT(img_width_bytes <= x);
  1205. cur += x * out_n - img_width_bytes;
  1206. filter_bytes = 1;
  1207. width = img_width_bytes;
  1208. }
  1209. prior = cur - stride;
  1210. if (j == 0) filter = first_row_filter[filter];
  1211. for (k = 0; k < filter_bytes; ++k) {
  1212. switch (filter) {
  1213. case STBI__F_none: cur[k] = raw[k]; break;
  1214. case STBI__F_sub: cur[k] = raw[k]; break;
  1215. case STBI__F_up: cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
  1216. case STBI__F_avg: cur[k] = STBI__BYTECAST(raw[k] + (prior[k] >> 1)); break;
  1217. case STBI__F_paeth: cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(0, prior[k], 0)); break;
  1218. case STBI__F_avg_first: cur[k] = raw[k]; break;
  1219. case STBI__F_paeth_first: cur[k] = raw[k]; break;
  1220. }
  1221. }
  1222. if (depth == 8) {
  1223. if (img_n != out_n)
  1224. cur[img_n] = 255;
  1225. raw += img_n;
  1226. cur += out_n;
  1227. prior += out_n;
  1228. } else if (depth == 16) {
  1229. if (img_n != out_n) {
  1230. cur[filter_bytes] = 255;
  1231. cur[filter_bytes + 1] = 255;
  1232. }
  1233. raw += filter_bytes;
  1234. cur += output_bytes;
  1235. prior += output_bytes;
  1236. } else {
  1237. raw += 1;
  1238. cur += 1;
  1239. prior += 1;
  1240. }
  1241. if (depth < 8 || img_n == out_n) {
  1242. int nk = (width - 1) * filter_bytes;
  1243. #define STBI__CASE(f) \
  1244. case f: \
  1245. for (k = 0; k < nk; ++k)
  1246. switch (filter) {
  1247. case STBI__F_none:
  1248. memcpy(cur, raw, nk);
  1249. break;
  1250. STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k - filter_bytes]); }
  1251. break;
  1252. STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); }
  1253. break;
  1254. STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k - filter_bytes]) >> 1)); }
  1255. break;
  1256. STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(cur[k - filter_bytes], prior[k], prior[k - filter_bytes])); }
  1257. break;
  1258. STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k - filter_bytes] >> 1)); }
  1259. break;
  1260. STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(cur[k - filter_bytes], 0, 0)); }
  1261. break;
  1262. }
  1263. #undef STBI__CASE
  1264. raw += nk;
  1265. } else {
  1266. STBI_ASSERT(img_n + 1 == out_n);
  1267. #define STBI__CASE(f) \
  1268. case f: \
  1269. for (i = x - 1; i >= 1; --i, cur[filter_bytes] = 255, raw += filter_bytes, cur += output_bytes, prior += output_bytes) \
  1270. for (k = 0; k < filter_bytes; ++k)
  1271. switch (filter) {
  1272. STBI__CASE(STBI__F_none) { cur[k] = raw[k]; }
  1273. break;
  1274. STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k - output_bytes]); }
  1275. break;
  1276. STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); }
  1277. break;
  1278. STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k - output_bytes]) >> 1)); }
  1279. break;
  1280. STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(cur[k - output_bytes], prior[k], prior[k - output_bytes])); }
  1281. break;
  1282. STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k - output_bytes] >> 1)); }
  1283. break;
  1284. STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(cur[k - output_bytes], 0, 0)); }
  1285. break;
  1286. }
  1287. #undef STBI__CASE
  1288. if (depth == 16) {
  1289. cur = a->out + stride * j;
  1290. for (i = 0; i < x; ++i, cur += output_bytes) {
  1291. cur[filter_bytes + 1] = 255;
  1292. }
  1293. }
  1294. }
  1295. }
  1296. if (depth < 8) {
  1297. for (j = 0; j < y; ++j) {
  1298. unsigned char *cur = a->out + stride * j;
  1299. unsigned char *in = a->out + stride * j + x * out_n - img_width_bytes;
  1300. unsigned char scale = (color == 0) ? _m3dstbi__depth_scale_table[depth] : 1;
  1301. if (depth == 4) {
  1302. for (k = x * img_n; k >= 2; k -= 2, ++in) {
  1303. *cur++ = scale * ((*in >> 4));
  1304. *cur++ = scale * ((*in) & 0x0f);
  1305. }
  1306. if (k > 0) *cur++ = scale * ((*in >> 4));
  1307. } else if (depth == 2) {
  1308. for (k = x * img_n; k >= 4; k -= 4, ++in) {
  1309. *cur++ = scale * ((*in >> 6));
  1310. *cur++ = scale * ((*in >> 4) & 0x03);
  1311. *cur++ = scale * ((*in >> 2) & 0x03);
  1312. *cur++ = scale * ((*in) & 0x03);
  1313. }
  1314. if (k > 0) *cur++ = scale * ((*in >> 6));
  1315. if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
  1316. if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
  1317. } else if (depth == 1) {
  1318. for (k = x * img_n; k >= 8; k -= 8, ++in) {
  1319. *cur++ = scale * ((*in >> 7));
  1320. *cur++ = scale * ((*in >> 6) & 0x01);
  1321. *cur++ = scale * ((*in >> 5) & 0x01);
  1322. *cur++ = scale * ((*in >> 4) & 0x01);
  1323. *cur++ = scale * ((*in >> 3) & 0x01);
  1324. *cur++ = scale * ((*in >> 2) & 0x01);
  1325. *cur++ = scale * ((*in >> 1) & 0x01);
  1326. *cur++ = scale * ((*in) & 0x01);
  1327. }
  1328. if (k > 0) *cur++ = scale * ((*in >> 7));
  1329. if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
  1330. if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
  1331. if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
  1332. if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
  1333. if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
  1334. if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
  1335. }
  1336. if (img_n != out_n) {
  1337. int q;
  1338. cur = a->out + stride * j;
  1339. if (img_n == 1) {
  1340. for (q = x - 1; q >= 0; --q) {
  1341. cur[q * 2 + 1] = 255;
  1342. cur[q * 2 + 0] = cur[q];
  1343. }
  1344. } else {
  1345. STBI_ASSERT(img_n == 3);
  1346. for (q = x - 1; q >= 0; --q) {
  1347. cur[q * 4 + 3] = 255;
  1348. cur[q * 4 + 2] = cur[q * 3 + 2];
  1349. cur[q * 4 + 1] = cur[q * 3 + 1];
  1350. cur[q * 4 + 0] = cur[q * 3 + 0];
  1351. }
  1352. }
  1353. }
  1354. }
  1355. } else if (depth == 16) {
  1356. unsigned char *cur = a->out;
  1357. _m3dstbi__uint16 *cur16 = (_m3dstbi__uint16 *)cur;
  1358. for (i = 0; i < x * y * out_n; ++i, cur16++, cur += 2) {
  1359. *cur16 = (cur[0] << 8) | cur[1];
  1360. }
  1361. }
  1362. return 1;
  1363. }
  1364. static int _m3dstbi__create_png_image(_m3dstbi__png *a, unsigned char *image_data, _m3dstbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) {
  1365. int bytes = (depth == 16 ? 2 : 1);
  1366. int out_bytes = out_n * bytes;
  1367. unsigned char *final;
  1368. int p;
  1369. if (!interlaced)
  1370. return _m3dstbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
  1371. final = (unsigned char *)_m3dstbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
  1372. for (p = 0; p < 7; ++p) {
  1373. int xorig[] = { 0, 4, 0, 2, 0, 1, 0 };
  1374. int yorig[] = { 0, 0, 4, 0, 2, 0, 1 };
  1375. int xspc[] = { 8, 8, 4, 4, 2, 2, 1 };
  1376. int yspc[] = { 8, 8, 8, 4, 4, 2, 2 };
  1377. int i, j, x, y;
  1378. x = (a->s->img_x - xorig[p] + xspc[p] - 1) / xspc[p];
  1379. y = (a->s->img_y - yorig[p] + yspc[p] - 1) / yspc[p];
  1380. if (x && y) {
  1381. _m3dstbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y;
  1382. if (!_m3dstbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) {
  1383. STBI_FREE(final);
  1384. return 0;
  1385. }
  1386. for (j = 0; j < y; ++j) {
  1387. for (i = 0; i < x; ++i) {
  1388. int out_y = j * yspc[p] + yorig[p];
  1389. int out_x = i * xspc[p] + xorig[p];
  1390. memcpy(final + out_y * a->s->img_x * out_bytes + out_x * out_bytes,
  1391. a->out + (j * x + i) * out_bytes, out_bytes);
  1392. }
  1393. }
  1394. STBI_FREE(a->out);
  1395. image_data += img_len;
  1396. image_data_len -= img_len;
  1397. }
  1398. }
  1399. a->out = final;
  1400. return 1;
  1401. }
  1402. static int _m3dstbi__compute_transparency(_m3dstbi__png *z, unsigned char* tc, int out_n) {
  1403. _m3dstbi__context *s = z->s;
  1404. _m3dstbi__uint32 i, pixel_count = s->img_x * s->img_y;
  1405. unsigned char *p = z->out;
  1406. STBI_ASSERT(out_n == 2 || out_n == 4);
  1407. if (out_n == 2) {
  1408. for (i = 0; i < pixel_count; ++i) {
  1409. p[1] = (p[0] == tc[0] ? 0 : 255);
  1410. p += 2;
  1411. }
  1412. } else {
  1413. for (i = 0; i < pixel_count; ++i) {
  1414. if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
  1415. p[3] = 0;
  1416. p += 4;
  1417. }
  1418. }
  1419. return 1;
  1420. }
  1421. static int _m3dstbi__compute_transparency16(_m3dstbi__png *z, _m3dstbi__uint16 tc[3], int out_n) {
  1422. _m3dstbi__context *s = z->s;
  1423. _m3dstbi__uint32 i, pixel_count = s->img_x * s->img_y;
  1424. _m3dstbi__uint16 *p = (_m3dstbi__uint16 *)z->out;
  1425. STBI_ASSERT(out_n == 2 || out_n == 4);
  1426. if (out_n == 2) {
  1427. for (i = 0; i < pixel_count; ++i) {
  1428. p[1] = (p[0] == tc[0] ? 0 : 65535);
  1429. p += 2;
  1430. }
  1431. } else {
  1432. for (i = 0; i < pixel_count; ++i) {
  1433. if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
  1434. p[3] = 0;
  1435. p += 4;
  1436. }
  1437. }
  1438. return 1;
  1439. }
  1440. static int _m3dstbi__expand_png_palette(_m3dstbi__png *a, unsigned char *palette, int len, int pal_img_n) {
  1441. _m3dstbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
  1442. unsigned char *p, *temp_out, *orig = a->out;
  1443. p = (unsigned char *)_m3dstbi__malloc_mad2(pixel_count, pal_img_n, 0);
  1444. if (p == NULL) return _m3dstbi__err("outofmem", "Out of memory");
  1445. temp_out = p;
  1446. if (pal_img_n == 3) {
  1447. for (i = 0; i < pixel_count; ++i) {
  1448. int n = orig[i] * 4;
  1449. p[0] = palette[n];
  1450. p[1] = palette[n + 1];
  1451. p[2] = palette[n + 2];
  1452. p += 3;
  1453. }
  1454. } else {
  1455. for (i = 0; i < pixel_count; ++i) {
  1456. int n = orig[i] * 4;
  1457. p[0] = palette[n];
  1458. p[1] = palette[n + 1];
  1459. p[2] = palette[n + 2];
  1460. p[3] = palette[n + 3];
  1461. p += 4;
  1462. }
  1463. }
  1464. STBI_FREE(a->out);
  1465. a->out = temp_out;
  1466. STBI_NOTUSED(len);
  1467. return 1;
  1468. }
  1469. #define STBI__PNG_TYPE(a, b, c, d) (((unsigned)(a) << 24) + ((unsigned)(b) << 16) + ((unsigned)(c) << 8) + (unsigned)(d))
  1470. static int _m3dstbi__parse_png_file(_m3dstbi__png *z, int scan, int req_comp) {
  1471. unsigned char palette[1024], pal_img_n = 0;
  1472. unsigned char has_trans = 0, tc[3] = {};
  1473. _m3dstbi__uint16 tc16[3] = {};
  1474. _m3dstbi__uint32 ioff = 0, idata_limit = 0, i, pal_len = 0;
  1475. int first = 1, k, interlace = 0, color = 0;
  1476. _m3dstbi__context *s = z->s;
  1477. z->expanded = NULL;
  1478. z->idata = NULL;
  1479. z->out = NULL;
  1480. if (!_m3dstbi__check_png_header(s)) return 0;
  1481. if (scan == STBI__SCAN_type) return 1;
  1482. for (;;) {
  1483. _m3dstbi__pngchunk c = _m3dstbi__get_chunk_header(s);
  1484. switch (c.type) {
  1485. case STBI__PNG_TYPE('C', 'g', 'B', 'I'):
  1486. _m3dstbi__skip(s, c.length);
  1487. break;
  1488. case STBI__PNG_TYPE('I', 'H', 'D', 'R'): {
  1489. int comp, filter;
  1490. if (!first) return _m3dstbi__err("multiple IHDR", "Corrupt PNG");
  1491. first = 0;
  1492. if (c.length != 13) return _m3dstbi__err("bad IHDR len", "Corrupt PNG");
  1493. s->img_x = _m3dstbi__get32be(s);
  1494. if (s->img_x > (1 << 24)) return _m3dstbi__err("too large", "Very large image (corrupt?)");
  1495. s->img_y = _m3dstbi__get32be(s);
  1496. if (s->img_y > (1 << 24)) return _m3dstbi__err("too large", "Very large image (corrupt?)");
  1497. z->depth = _m3dstbi__get8(s);
  1498. if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return _m3dstbi__err("1/2/4/8/16-bit only", "PNG not supported: 1/2/4/8/16-bit only");
  1499. color = _m3dstbi__get8(s);
  1500. if (color > 6) return _m3dstbi__err("bad ctype", "Corrupt PNG");
  1501. if (color == 3 && z->depth == 16) return _m3dstbi__err("bad ctype", "Corrupt PNG");
  1502. if (color == 3)
  1503. pal_img_n = 3;
  1504. else if (color & 1)
  1505. return _m3dstbi__err("bad ctype", "Corrupt PNG");
  1506. comp = _m3dstbi__get8(s);
  1507. if (comp) return _m3dstbi__err("bad comp method", "Corrupt PNG");
  1508. filter = _m3dstbi__get8(s);
  1509. if (filter) return _m3dstbi__err("bad filter method", "Corrupt PNG");
  1510. interlace = _m3dstbi__get8(s);
  1511. if (interlace > 1) return _m3dstbi__err("bad interlace method", "Corrupt PNG");
  1512. if (!s->img_x || !s->img_y) return _m3dstbi__err("0-pixel image", "Corrupt PNG");
  1513. if (!pal_img_n) {
  1514. s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
  1515. if ((1 << 30) / s->img_x / s->img_n < s->img_y) return _m3dstbi__err("too large", "Image too large to decode");
  1516. if (scan == STBI__SCAN_header) return 1;
  1517. } else {
  1518. s->img_n = 1;
  1519. if ((1 << 30) / s->img_x / 4 < s->img_y) return _m3dstbi__err("too large", "Corrupt PNG");
  1520. }
  1521. break;
  1522. }
  1523. case STBI__PNG_TYPE('P', 'L', 'T', 'E'): {
  1524. if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG");
  1525. if (c.length > 256 * 3) return _m3dstbi__err("invalid PLTE", "Corrupt PNG");
  1526. pal_len = c.length / 3;
  1527. if (pal_len * 3 != c.length) return _m3dstbi__err("invalid PLTE", "Corrupt PNG");
  1528. for (i = 0; i < pal_len; ++i) {
  1529. palette[i * 4 + 0] = _m3dstbi__get8(s);
  1530. palette[i * 4 + 1] = _m3dstbi__get8(s);
  1531. palette[i * 4 + 2] = _m3dstbi__get8(s);
  1532. palette[i * 4 + 3] = 255;
  1533. }
  1534. break;
  1535. }
  1536. case STBI__PNG_TYPE('t', 'R', 'N', 'S'): {
  1537. if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG");
  1538. if (z->idata) return _m3dstbi__err("tRNS after IDAT", "Corrupt PNG");
  1539. if (pal_img_n) {
  1540. if (scan == STBI__SCAN_header) {
  1541. s->img_n = 4;
  1542. return 1;
  1543. }
  1544. if (pal_len == 0) return _m3dstbi__err("tRNS before PLTE", "Corrupt PNG");
  1545. if (c.length > pal_len) return _m3dstbi__err("bad tRNS len", "Corrupt PNG");
  1546. pal_img_n = 4;
  1547. for (i = 0; i < c.length; ++i)
  1548. palette[i * 4 + 3] = _m3dstbi__get8(s);
  1549. } else {
  1550. if (!(s->img_n & 1)) return _m3dstbi__err("tRNS with alpha", "Corrupt PNG");
  1551. if (c.length != (_m3dstbi__uint32)s->img_n * 2) return _m3dstbi__err("bad tRNS len", "Corrupt PNG");
  1552. has_trans = 1;
  1553. if (z->depth == 16) {
  1554. for (k = 0; k < s->img_n; ++k)
  1555. tc16[k] = (_m3dstbi__uint16)_m3dstbi__get16be(s);
  1556. } else {
  1557. for (k = 0; k < s->img_n; ++k)
  1558. tc[k] = (unsigned char)(_m3dstbi__get16be(s) & 255) * _m3dstbi__depth_scale_table[z->depth];
  1559. }
  1560. }
  1561. break;
  1562. }
  1563. case STBI__PNG_TYPE('I', 'D', 'A', 'T'): {
  1564. if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG");
  1565. if (pal_img_n && !pal_len) return _m3dstbi__err("no PLTE", "Corrupt PNG");
  1566. if (scan == STBI__SCAN_header) {
  1567. s->img_n = pal_img_n;
  1568. return 1;
  1569. }
  1570. if ((int)(ioff + c.length) < (int)ioff) return 0;
  1571. if (ioff + c.length > idata_limit) {
  1572. _m3dstbi__uint32 idata_limit_old = idata_limit;
  1573. unsigned char *p;
  1574. if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
  1575. while (ioff + c.length > idata_limit)
  1576. idata_limit *= 2;
  1577. STBI_NOTUSED(idata_limit_old);
  1578. p = (unsigned char *)STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit);
  1579. if (p == NULL) return _m3dstbi__err("outofmem", "Out of memory");
  1580. z->idata = p;
  1581. }
  1582. if (!_m3dstbi__getn(s, z->idata + ioff, c.length)) return _m3dstbi__err("outofdata", "Corrupt PNG");
  1583. ioff += c.length;
  1584. break;
  1585. }
  1586. case STBI__PNG_TYPE('I', 'E', 'N', 'D'): {
  1587. _m3dstbi__uint32 raw_len, bpl;
  1588. if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG");
  1589. if (scan != STBI__SCAN_load) return 1;
  1590. if (z->idata == NULL) return _m3dstbi__err("no IDAT", "Corrupt PNG");
  1591. bpl = (s->img_x * z->depth + 7) / 8;
  1592. raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
  1593. z->expanded = (unsigned char *)_m3dstbi_zlib_decode_malloc_guesssize_headerflag((char *)z->idata, ioff, raw_len, (int *)&raw_len, 1);
  1594. if (z->expanded == NULL) return 0;
  1595. STBI_FREE(z->idata);
  1596. z->idata = NULL;
  1597. if ((req_comp == s->img_n + 1 && req_comp != 3 && !pal_img_n) || has_trans)
  1598. s->img_out_n = s->img_n + 1;
  1599. else
  1600. s->img_out_n = s->img_n;
  1601. if (!_m3dstbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
  1602. if (has_trans) {
  1603. if (z->depth == 16) {
  1604. if (!_m3dstbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
  1605. } else {
  1606. if (!_m3dstbi__compute_transparency(z, tc, s->img_out_n)) return 0;
  1607. }
  1608. }
  1609. if (pal_img_n) {
  1610. s->img_n = pal_img_n;
  1611. s->img_out_n = pal_img_n;
  1612. if (req_comp >= 3) s->img_out_n = req_comp;
  1613. if (!_m3dstbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
  1614. return 0;
  1615. } else if (has_trans) {
  1616. ++s->img_n;
  1617. }
  1618. STBI_FREE(z->expanded);
  1619. z->expanded = NULL;
  1620. return 1;
  1621. }
  1622. default:
  1623. if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG");
  1624. if ((c.type & (1 << 29)) == 0) {
  1625. return _m3dstbi__err("invalid_chunk", "PNG not supported: unknown PNG chunk type");
  1626. }
  1627. _m3dstbi__skip(s, c.length);
  1628. break;
  1629. }
  1630. _m3dstbi__get32be(s);
  1631. }
  1632. }
  1633. static void *_m3dstbi__do_png(_m3dstbi__png *p, int *x, int *y, int *n, int req_comp, _m3dstbi__result_info *ri) {
  1634. void *result = NULL;
  1635. if (req_comp < 0 || req_comp > 4) {
  1636. _m3dstbi__err("bad req_comp", "Internal error");
  1637. return NULL;
  1638. }
  1639. if (_m3dstbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
  1640. if (p->depth < 8)
  1641. ri->bits_per_channel = 8;
  1642. else
  1643. ri->bits_per_channel = p->depth;
  1644. result = p->out;
  1645. p->out = NULL;
  1646. if (req_comp && req_comp != p->s->img_out_n) {
  1647. if (ri->bits_per_channel == 8)
  1648. result = _m3dstbi__convert_format((unsigned char *)result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
  1649. else
  1650. result = _m3dstbi__convert_format16((_m3dstbi__uint16 *)result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
  1651. p->s->img_out_n = req_comp;
  1652. if (result == NULL) return result;
  1653. }
  1654. *x = p->s->img_x;
  1655. *y = p->s->img_y;
  1656. if (n) *n = p->s->img_n;
  1657. }
  1658. STBI_FREE(p->out);
  1659. p->out = NULL;
  1660. STBI_FREE(p->expanded);
  1661. p->expanded = NULL;
  1662. STBI_FREE(p->idata);
  1663. p->idata = NULL;
  1664. return result;
  1665. }
  1666. static void *_m3dstbi__png_load(_m3dstbi__context *s, int *x, int *y, int *comp, int req_comp, _m3dstbi__result_info *ri) {
  1667. _m3dstbi__png p;
  1668. p.s = s;
  1669. return _m3dstbi__do_png(&p, x, y, comp, req_comp, ri);
  1670. }
  1671. #define stbi__context _m3dstbi__context
  1672. #define stbi__result_info _m3dstbi__result_info
  1673. #define stbi__png_load _m3dstbi__png_load
  1674. #define stbi_zlib_decode_malloc_guesssize_headerflag _m3dstbi_zlib_decode_malloc_guesssize_headerflag
  1675. #endif
  1676. #if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H)
  1677. /* zlib_compressor from
  1678. stb_image_write - v1.13 - public domain - http://nothings.org/stb/stb_image_write.h
  1679. */
  1680. typedef unsigned char _m3dstbiw__uc;
  1681. typedef unsigned short _m3dstbiw__us;
  1682. typedef uint16_t _m3dstbiw__uint16;
  1683. typedef int16_t _m3dstbiw__int16;
  1684. typedef uint32_t _m3dstbiw__uint32;
  1685. typedef int32_t _m3dstbiw__int32;
  1686. #define STBIW_MALLOC(s) M3D_MALLOC(s)
  1687. #define STBIW_REALLOC(p, ns) M3D_REALLOC(p, ns)
  1688. #define STBIW_REALLOC_SIZED(p, oldsz, newsz) STBIW_REALLOC(p, newsz)
  1689. #define STBIW_FREE M3D_FREE
  1690. #define STBIW_MEMMOVE memmove
  1691. #define STBIW_UCHAR (uint8_t)
  1692. #define STBIW_ASSERT(x)
  1693. #define _m3dstbiw___sbraw(a) ((int *)(a)-2)
  1694. #define _m3dstbiw___sbm(a) _m3dstbiw___sbraw(a)[0]
  1695. #define _m3dstbiw___sbn(a) _m3dstbiw___sbraw(a)[1]
  1696. #define _m3dstbiw___sbneedgrow(a, n) ((a) == 0 || _m3dstbiw___sbn(a) + n >= _m3dstbiw___sbm(a))
  1697. #define _m3dstbiw___sbmaybegrow(a, n) (_m3dstbiw___sbneedgrow(a, (n)) ? _m3dstbiw___sbgrow(a, n) : 0)
  1698. #define _m3dstbiw___sbgrow(a, n) _m3dstbiw___sbgrowf((void **)&(a), (n), sizeof(*(a)))
  1699. #define _m3dstbiw___sbpush(a, v) (_m3dstbiw___sbmaybegrow(a, 1), (a)[_m3dstbiw___sbn(a)++] = (v))
  1700. #define _m3dstbiw___sbcount(a) ((a) ? _m3dstbiw___sbn(a) : 0)
  1701. #define _m3dstbiw___sbfree(a) ((a) ? STBIW_FREE(_m3dstbiw___sbraw(a)), 0 : 0)
  1702. static void *_m3dstbiw___sbgrowf(void **arr, int increment, int itemsize) {
  1703. int m = *arr ? 2 * _m3dstbiw___sbm(*arr) + increment : increment + 1;
  1704. void *p = STBIW_REALLOC_SIZED(*arr ? _m3dstbiw___sbraw(*arr) : 0, *arr ? (_m3dstbiw___sbm(*arr) * itemsize + sizeof(int) * 2) : 0, itemsize * m + sizeof(int) * 2);
  1705. STBIW_ASSERT(p);
  1706. if (p) {
  1707. if (!*arr) ((int *)p)[1] = 0;
  1708. *arr = (void *)((int *)p + 2);
  1709. _m3dstbiw___sbm(*arr) = m;
  1710. }
  1711. return *arr;
  1712. }
  1713. static unsigned char *_m3dstbiw___zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) {
  1714. while (*bitcount >= 8) {
  1715. _m3dstbiw___sbpush(data, STBIW_UCHAR(*bitbuffer));
  1716. *bitbuffer >>= 8;
  1717. *bitcount -= 8;
  1718. }
  1719. return data;
  1720. }
  1721. static int _m3dstbiw___zlib_bitrev(int code, int codebits) {
  1722. int res = 0;
  1723. while (codebits--) {
  1724. res = (res << 1) | (code & 1);
  1725. code >>= 1;
  1726. }
  1727. return res;
  1728. }
  1729. static unsigned int _m3dstbiw___zlib_countm(unsigned char *a, unsigned char *b, int limit) {
  1730. int i;
  1731. for (i = 0; i < limit && i < 258; ++i)
  1732. if (a[i] != b[i]) break;
  1733. return i;
  1734. }
  1735. static unsigned int _m3dstbiw___zhash(unsigned char *data) {
  1736. _m3dstbiw__uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
  1737. hash ^= hash << 3;
  1738. hash += hash >> 5;
  1739. hash ^= hash << 4;
  1740. hash += hash >> 17;
  1741. hash ^= hash << 25;
  1742. hash += hash >> 6;
  1743. return hash;
  1744. }
  1745. #define _m3dstbiw___zlib_flush() (out = _m3dstbiw___zlib_flushf(out, &bitbuf, &bitcount))
  1746. #define _m3dstbiw___zlib_add(code, codebits) \
  1747. (bitbuf |= (code) << bitcount, bitcount += (codebits), _m3dstbiw___zlib_flush())
  1748. #define _m3dstbiw___zlib_huffa(b, c) _m3dstbiw___zlib_add(_m3dstbiw___zlib_bitrev(b, c), c)
  1749. #define _m3dstbiw___zlib_huff1(n) _m3dstbiw___zlib_huffa(0x30 + (n), 8)
  1750. #define _m3dstbiw___zlib_huff2(n) _m3dstbiw___zlib_huffa(0x190 + (n)-144, 9)
  1751. #define _m3dstbiw___zlib_huff3(n) _m3dstbiw___zlib_huffa(0 + (n)-256, 7)
  1752. #define _m3dstbiw___zlib_huff4(n) _m3dstbiw___zlib_huffa(0xc0 + (n)-280, 8)
  1753. #define _m3dstbiw___zlib_huff(n) ((n) <= 143 ? _m3dstbiw___zlib_huff1(n) : (n) <= 255 ? _m3dstbiw___zlib_huff2(n) : (n) <= 279 ? _m3dstbiw___zlib_huff3(n) : _m3dstbiw___zlib_huff4(n))
  1754. #define _m3dstbiw___zlib_huffb(n) ((n) <= 143 ? _m3dstbiw___zlib_huff1(n) : _m3dstbiw___zlib_huff2(n))
  1755. #define _m3dstbiw___ZHASH 16384
  1756. unsigned char *_m3dstbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) {
  1757. static unsigned short lengthc[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 259 };
  1758. static unsigned char lengtheb[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
  1759. static unsigned short distc[] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32768 };
  1760. static unsigned char disteb[] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
  1761. unsigned int bitbuf = 0;
  1762. int i, j, bitcount = 0;
  1763. unsigned char *out = NULL;
  1764. unsigned char ***hash_table = (unsigned char ***)STBIW_MALLOC(_m3dstbiw___ZHASH * sizeof(char **));
  1765. if (hash_table == NULL)
  1766. return NULL;
  1767. if (quality < 5) quality = 5;
  1768. _m3dstbiw___sbpush(out, 0x78);
  1769. _m3dstbiw___sbpush(out, 0x5e);
  1770. _m3dstbiw___zlib_add(1, 1);
  1771. _m3dstbiw___zlib_add(1, 2);
  1772. for (i = 0; i < _m3dstbiw___ZHASH; ++i)
  1773. hash_table[i] = NULL;
  1774. i = 0;
  1775. while (i < data_len - 3) {
  1776. int h = _m3dstbiw___zhash(data + i) & (_m3dstbiw___ZHASH - 1), best = 3;
  1777. unsigned char *bestloc = 0;
  1778. unsigned char **hlist = hash_table[h];
  1779. int n = _m3dstbiw___sbcount(hlist);
  1780. for (j = 0; j < n; ++j) {
  1781. if (hlist[j] - data > i - 32768) {
  1782. int d = _m3dstbiw___zlib_countm(hlist[j], data + i, data_len - i);
  1783. if (d >= best) best = d, bestloc = hlist[j];
  1784. }
  1785. }
  1786. if (hash_table[h] && _m3dstbiw___sbn(hash_table[h]) == 2 * quality) {
  1787. STBIW_MEMMOVE(hash_table[h], hash_table[h] + quality, sizeof(hash_table[h][0]) * quality);
  1788. _m3dstbiw___sbn(hash_table[h]) = quality;
  1789. }
  1790. _m3dstbiw___sbpush(hash_table[h], data + i);
  1791. if (bestloc) {
  1792. h = _m3dstbiw___zhash(data + i + 1) & (_m3dstbiw___ZHASH - 1);
  1793. hlist = hash_table[h];
  1794. n = _m3dstbiw___sbcount(hlist);
  1795. for (j = 0; j < n; ++j) {
  1796. if (hlist[j] - data > i - 32767) {
  1797. int e = _m3dstbiw___zlib_countm(hlist[j], data + i + 1, data_len - i - 1);
  1798. if (e > best) {
  1799. bestloc = NULL;
  1800. break;
  1801. }
  1802. }
  1803. }
  1804. }
  1805. if (bestloc) {
  1806. int d = (int)(data + i - bestloc);
  1807. STBIW_ASSERT(d <= 32767 && best <= 258);
  1808. for (j = 0; best > lengthc[j + 1] - 1; ++j)
  1809. ;
  1810. _m3dstbiw___zlib_huff(j + 257);
  1811. if (lengtheb[j]) _m3dstbiw___zlib_add(best - lengthc[j], lengtheb[j]);
  1812. for (j = 0; d > distc[j + 1] - 1; ++j)
  1813. ;
  1814. _m3dstbiw___zlib_add(_m3dstbiw___zlib_bitrev(j, 5), 5);
  1815. if (disteb[j]) _m3dstbiw___zlib_add(d - distc[j], disteb[j]);
  1816. i += best;
  1817. } else {
  1818. _m3dstbiw___zlib_huffb(data[i]);
  1819. ++i;
  1820. }
  1821. }
  1822. for (; i < data_len; ++i)
  1823. _m3dstbiw___zlib_huffb(data[i]);
  1824. _m3dstbiw___zlib_huff(256);
  1825. while (bitcount)
  1826. _m3dstbiw___zlib_add(0, 1);
  1827. for (i = 0; i < _m3dstbiw___ZHASH; ++i)
  1828. (void)_m3dstbiw___sbfree(hash_table[i]);
  1829. STBIW_FREE(hash_table);
  1830. {
  1831. unsigned int s1 = 1, s2 = 0;
  1832. int blocklen = (int)(data_len % 5552);
  1833. j = 0;
  1834. while (j < data_len) {
  1835. for (i = 0; i < blocklen; ++i)
  1836. s1 += data[j + i], s2 += s1;
  1837. s1 %= 65521, s2 %= 65521;
  1838. j += blocklen;
  1839. blocklen = 5552;
  1840. }
  1841. _m3dstbiw___sbpush(out, STBIW_UCHAR(s2 >> 8));
  1842. _m3dstbiw___sbpush(out, STBIW_UCHAR(s2));
  1843. _m3dstbiw___sbpush(out, STBIW_UCHAR(s1 >> 8));
  1844. _m3dstbiw___sbpush(out, STBIW_UCHAR(s1));
  1845. }
  1846. *out_len = _m3dstbiw___sbn(out);
  1847. STBIW_MEMMOVE(_m3dstbiw___sbraw(out), out, *out_len);
  1848. return (unsigned char *)_m3dstbiw___sbraw(out);
  1849. }
  1850. #define stbi_zlib_compress _m3dstbi_zlib_compress
  1851. #else
  1852. unsigned char *_m3dstbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality);
  1853. #endif
  1854. #define M3D_CHUNKMAGIC(m, a, b, c, d) ((m)[0] == (a) && (m)[1] == (b) && (m)[2] == (c) && (m)[3] == (d))
  1855. #include <locale.h> /* sprintf and strtod cares about number locale */
  1856. #include <stdio.h> /* get sprintf */
  1857. #ifdef M3D_PROFILING
  1858. #include <sys/time.h>
  1859. #endif
  1860. #if !defined(M3D_NOIMPORTER)
  1861. /* helper functions for the ASCII parser */
  1862. static char *_m3d_findarg(char *s) {
  1863. while (s && *s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n')
  1864. s++;
  1865. while (s && *s && (*s == ' ' || *s == '\t'))
  1866. s++;
  1867. return s;
  1868. }
  1869. static char *_m3d_findnl(char *s) {
  1870. while (s && *s && *s != '\r' && *s != '\n')
  1871. s++;
  1872. if (*s == '\r') s++;
  1873. if (*s == '\n') s++;
  1874. return s;
  1875. }
  1876. static char *_m3d_gethex(char *s, uint32_t *ret) {
  1877. if (*s == '#') s++;
  1878. *ret = 0;
  1879. for (; *s; s++) {
  1880. if (*s >= '0' && *s <= '9') {
  1881. *ret <<= 4;
  1882. *ret += (uint32_t)(*s - '0');
  1883. } else if (*s >= 'a' && *s <= 'f') {
  1884. *ret <<= 4;
  1885. *ret += (uint32_t)(*s - 'a' + 10);
  1886. } else if (*s >= 'A' && *s <= 'F') {
  1887. *ret <<= 4;
  1888. *ret += (uint32_t)(*s - 'A' + 10);
  1889. } else
  1890. break;
  1891. }
  1892. return _m3d_findarg(s);
  1893. }
  1894. static char *_m3d_getint(char *s, uint32_t *ret) {
  1895. char *e = s;
  1896. if (!s || !*s || *s == '\r' || *s == '\n') return s;
  1897. for (; *e >= '0' && *e <= '9'; e++)
  1898. ;
  1899. *ret = atoi(s);
  1900. return e;
  1901. }
  1902. static char *_m3d_getfloat(char *s, M3D_FLOAT *ret) {
  1903. char *e = s;
  1904. if (!s || !*s || *s == '\r' || *s == '\n') return s;
  1905. for (; *e == '-' || *e == '+' || *e == '.' || (*e >= '0' && *e <= '9') || *e == 'e' || *e == 'E'; e++)
  1906. ;
  1907. *ret = (M3D_FLOAT)strtod(s, NULL);
  1908. return _m3d_findarg(e);
  1909. }
  1910. #endif
  1911. #if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER))
  1912. /* helper function to create safe strings */
  1913. char *_m3d_safestr(char *in, int morelines) {
  1914. char *out, *o, *i = in;
  1915. int l;
  1916. if (!in || !*in) {
  1917. out = (char *)M3D_MALLOC(1);
  1918. if (!out) return NULL;
  1919. out[0] = 0;
  1920. } else {
  1921. for (o = in, l = 0; *o && ((morelines & 1) || (*o != '\r' && *o != '\n')) && l < 256; o++, l++)
  1922. ;
  1923. out = o = (char *)M3D_MALLOC(l + 1);
  1924. if (!out) return NULL;
  1925. while (*i == ' ' || *i == '\t' || *i == '\r' || (morelines && *i == '\n'))
  1926. i++;
  1927. for (; *i && (morelines || (*i != '\r' && *i != '\n')); i++) {
  1928. if (*i == '\r') continue;
  1929. if (*i == '\n') {
  1930. if (morelines >= 3 && o > out && *(o - 1) == '\n') break;
  1931. if (i > in && *(i - 1) == '\n') continue;
  1932. if (morelines & 1) {
  1933. if (morelines == 1) *o++ = '\r';
  1934. *o++ = '\n';
  1935. } else
  1936. break;
  1937. } else if (*i == ' ' || *i == '\t') {
  1938. *o++ = morelines ? ' ' : '_';
  1939. } else
  1940. *o++ = !morelines && (*i == '/' || *i == '\\') ? '_' : *i;
  1941. }
  1942. for (; o > out && (*(o - 1) == ' ' || *(o - 1) == '\t' || *(o - 1) == '\r' || *(o - 1) == '\n'); o--)
  1943. ;
  1944. *o = 0;
  1945. out = (char *)M3D_REALLOC(out, (uintptr_t)o - (uintptr_t)out + 1);
  1946. }
  1947. return out;
  1948. }
  1949. #endif
  1950. #ifndef M3D_NOIMPORTER
  1951. /* helper function to load and decode/generate a texture */
  1952. M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char *fn) {
  1953. unsigned int i, len = 0;
  1954. unsigned char *buff = NULL;
  1955. char *fn2;
  1956. #ifdef STBI__PNG_TYPE
  1957. unsigned int w, h;
  1958. stbi__context s;
  1959. stbi__result_info ri;
  1960. #endif
  1961. /* do we have loaded this texture already? */
  1962. for (i = 0; i < model->numtexture; i++)
  1963. if (!strcmp(fn, model->texture[i].name)) return i;
  1964. /* see if it's inlined in the model */
  1965. if (model->inlined) {
  1966. for (i = 0; i < model->numinlined; i++)
  1967. if (!strcmp(fn, model->inlined[i].name)) {
  1968. buff = model->inlined[i].data;
  1969. len = model->inlined[i].length;
  1970. freecb = NULL;
  1971. break;
  1972. }
  1973. }
  1974. /* try to load from external source */
  1975. if (!buff && readfilecb) {
  1976. i = (unsigned int)strlen(fn);
  1977. if (i < 5 || fn[i - 4] != '.') {
  1978. fn2 = (char *)M3D_MALLOC(i + 5);
  1979. if (!fn2) {
  1980. model->errcode = M3D_ERR_ALLOC;
  1981. return M3D_UNDEF;
  1982. }
  1983. memcpy(fn2, fn, i);
  1984. memcpy(fn2 + i, ".png", 5);
  1985. buff = (*readfilecb)(fn2, &len);
  1986. M3D_FREE(fn2);
  1987. }
  1988. if (!buff) {
  1989. buff = (*readfilecb)(fn, &len);
  1990. if (!buff) return M3D_UNDEF;
  1991. }
  1992. }
  1993. /* add to textures array */
  1994. i = model->numtexture++;
  1995. model->texture = (m3dtx_t *)M3D_REALLOC(model->texture, model->numtexture * sizeof(m3dtx_t));
  1996. if (!model->texture) {
  1997. if (buff && freecb) (*freecb)(buff);
  1998. model->errcode = M3D_ERR_ALLOC;
  1999. return M3D_UNDEF;
  2000. }
  2001. model->texture[i].name = fn;
  2002. model->texture[i].w = model->texture[i].h = 0;
  2003. model->texture[i].d = NULL;
  2004. if (buff) {
  2005. if (buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
  2006. #ifdef STBI__PNG_TYPE
  2007. s.read_from_callbacks = 0;
  2008. s.img_buffer = s.img_buffer_original = (unsigned char *)buff;
  2009. s.img_buffer_end = s.img_buffer_original_end = (unsigned char *)buff + len;
  2010. /* don't use model->texture[i].w directly, it's a uint16_t */
  2011. w = h = len = 0;
  2012. ri.bits_per_channel = 8;
  2013. model->texture[i].d = (uint8_t *)stbi__png_load(&s, (int *)&w, (int *)&h, (int *)&len, 0, &ri);
  2014. model->texture[i].w = (uint16_t)w;
  2015. model->texture[i].h = (uint16_t)h;
  2016. model->texture[i].f = (uint8_t)len;
  2017. #endif
  2018. } else {
  2019. #ifdef M3D_TX_INTERP
  2020. if ((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
  2021. M3D_LOG("Unable to generate texture");
  2022. M3D_LOG(fn);
  2023. }
  2024. #else
  2025. M3D_LOG("Unimplemented interpreter");
  2026. M3D_LOG(fn);
  2027. #endif
  2028. }
  2029. if (freecb) (*freecb)(buff);
  2030. }
  2031. if (!model->texture[i].d)
  2032. model->errcode = M3D_ERR_UNKIMG;
  2033. return i;
  2034. }
  2035. /* helper function to load and generate a procedural surface */
  2036. void _m3d_getpr(m3d_t *model, _unused m3dread_t readfilecb, _unused m3dfree_t freecb, _unused char *fn) {
  2037. #ifdef M3D_PR_INTERP
  2038. unsigned int i, len = 0;
  2039. unsigned char *buff = readfilecb ? (*readfilecb)(fn, &len) : NULL;
  2040. if (!buff && model->inlined) {
  2041. for (i = 0; i < model->numinlined; i++)
  2042. if (!strcmp(fn, model->inlined[i].name)) {
  2043. buff = model->inlined[i].data;
  2044. len = model->inlined[i].length;
  2045. freecb = NULL;
  2046. break;
  2047. }
  2048. }
  2049. if (!buff || !len || (model->errcode = M3D_PR_INTERP(fn, buff, len, model)) != M3D_SUCCESS) {
  2050. M3D_LOG("Unable to generate procedural surface");
  2051. M3D_LOG(fn);
  2052. model->errcode = M3D_ERR_UNKIMG;
  2053. }
  2054. if (freecb && buff) (*freecb)(buff);
  2055. #else
  2056. (void)readfilecb;
  2057. (void)freecb;
  2058. (void)fn;
  2059. M3D_LOG("Unimplemented interpreter");
  2060. M3D_LOG(fn);
  2061. model->errcode = M3D_ERR_UNIMPL;
  2062. #endif
  2063. }
  2064. /* helpers to read indices from data stream */
  2065. #define M3D_GETSTR(x) \
  2066. do { \
  2067. offs = 0; \
  2068. data = _m3d_getidx(data, model->si_s, &offs); \
  2069. x = offs ? ((char *)model->raw + 16 + offs) : NULL; \
  2070. } while (0)
  2071. _inline static unsigned char *_m3d_getidx(unsigned char *data, char type, M3D_INDEX *idx) {
  2072. switch (type) {
  2073. case 1:
  2074. *idx = data[0] > 253 ? (int8_t)data[0] : data[0];
  2075. data++;
  2076. break;
  2077. case 2:
  2078. *idx = *((uint16_t *)data) > 65533 ? *((int16_t *)data) : *((uint16_t *)data);
  2079. data += 2;
  2080. break;
  2081. case 4:
  2082. *idx = *((int32_t *)data);
  2083. data += 4;
  2084. break;
  2085. }
  2086. return data;
  2087. }
  2088. #ifndef M3D_NOANIMATION
  2089. /* multiply 4 x 4 matrices. Do not use float *r[16] as argument, because some compilers misinterpret that as
  2090. * 16 pointers each pointing to a float, but we need a single pointer to 16 floats. */
  2091. void _m3d_mul(M3D_FLOAT *r, M3D_FLOAT *a, M3D_FLOAT *b) {
  2092. r[0] = b[0] * a[0] + b[4] * a[1] + b[8] * a[2] + b[12] * a[3];
  2093. r[1] = b[1] * a[0] + b[5] * a[1] + b[9] * a[2] + b[13] * a[3];
  2094. r[2] = b[2] * a[0] + b[6] * a[1] + b[10] * a[2] + b[14] * a[3];
  2095. r[3] = b[3] * a[0] + b[7] * a[1] + b[11] * a[2] + b[15] * a[3];
  2096. r[4] = b[0] * a[4] + b[4] * a[5] + b[8] * a[6] + b[12] * a[7];
  2097. r[5] = b[1] * a[4] + b[5] * a[5] + b[9] * a[6] + b[13] * a[7];
  2098. r[6] = b[2] * a[4] + b[6] * a[5] + b[10] * a[6] + b[14] * a[7];
  2099. r[7] = b[3] * a[4] + b[7] * a[5] + b[11] * a[6] + b[15] * a[7];
  2100. r[8] = b[0] * a[8] + b[4] * a[9] + b[8] * a[10] + b[12] * a[11];
  2101. r[9] = b[1] * a[8] + b[5] * a[9] + b[9] * a[10] + b[13] * a[11];
  2102. r[10] = b[2] * a[8] + b[6] * a[9] + b[10] * a[10] + b[14] * a[11];
  2103. r[11] = b[3] * a[8] + b[7] * a[9] + b[11] * a[10] + b[15] * a[11];
  2104. r[12] = b[0] * a[12] + b[4] * a[13] + b[8] * a[14] + b[12] * a[15];
  2105. r[13] = b[1] * a[12] + b[5] * a[13] + b[9] * a[14] + b[13] * a[15];
  2106. r[14] = b[2] * a[12] + b[6] * a[13] + b[10] * a[14] + b[14] * a[15];
  2107. r[15] = b[3] * a[12] + b[7] * a[13] + b[11] * a[14] + b[15] * a[15];
  2108. }
  2109. /* calculate 4 x 4 matrix inverse */
  2110. void _m3d_inv(M3D_FLOAT *m) {
  2111. M3D_FLOAT r[16];
  2112. M3D_FLOAT det =
  2113. m[0] * m[5] * m[10] * m[15] - m[0] * m[5] * m[11] * m[14] + m[0] * m[6] * m[11] * m[13] - m[0] * m[6] * m[9] * m[15] + m[0] * m[7] * m[9] * m[14] - m[0] * m[7] * m[10] * m[13] - m[1] * m[6] * m[11] * m[12] + m[1] * m[6] * m[8] * m[15] - m[1] * m[7] * m[8] * m[14] + m[1] * m[7] * m[10] * m[12] - m[1] * m[4] * m[10] * m[15] + m[1] * m[4] * m[11] * m[14] + m[2] * m[7] * m[8] * m[13] - m[2] * m[7] * m[9] * m[12] + m[2] * m[4] * m[9] * m[15] - m[2] * m[4] * m[11] * m[13] + m[2] * m[5] * m[11] * m[12] - m[2] * m[5] * m[8] * m[15] - m[3] * m[4] * m[9] * m[14] + m[3] * m[4] * m[10] * m[13] - m[3] * m[5] * m[10] * m[12] + m[3] * m[5] * m[8] * m[14] - m[3] * m[6] * m[8] * m[13] + m[3] * m[6] * m[9] * m[12];
  2114. if (det == (M3D_FLOAT)0.0 || det == (M3D_FLOAT)-0.0)
  2115. det = (M3D_FLOAT)1.0;
  2116. else
  2117. det = (M3D_FLOAT)1.0 / det;
  2118. r[0] = det * (m[5] * (m[10] * m[15] - m[11] * m[14]) + m[6] * (m[11] * m[13] - m[9] * m[15]) + m[7] * (m[9] * m[14] - m[10] * m[13]));
  2119. r[1] = -det * (m[1] * (m[10] * m[15] - m[11] * m[14]) + m[2] * (m[11] * m[13] - m[9] * m[15]) + m[3] * (m[9] * m[14] - m[10] * m[13]));
  2120. r[2] = det * (m[1] * (m[6] * m[15] - m[7] * m[14]) + m[2] * (m[7] * m[13] - m[5] * m[15]) + m[3] * (m[5] * m[14] - m[6] * m[13]));
  2121. r[3] = -det * (m[1] * (m[6] * m[11] - m[7] * m[10]) + m[2] * (m[7] * m[9] - m[5] * m[11]) + m[3] * (m[5] * m[10] - m[6] * m[9]));
  2122. r[4] = -det * (m[4] * (m[10] * m[15] - m[11] * m[14]) + m[6] * (m[11] * m[12] - m[8] * m[15]) + m[7] * (m[8] * m[14] - m[10] * m[12]));
  2123. r[5] = det * (m[0] * (m[10] * m[15] - m[11] * m[14]) + m[2] * (m[11] * m[12] - m[8] * m[15]) + m[3] * (m[8] * m[14] - m[10] * m[12]));
  2124. r[6] = -det * (m[0] * (m[6] * m[15] - m[7] * m[14]) + m[2] * (m[7] * m[12] - m[4] * m[15]) + m[3] * (m[4] * m[14] - m[6] * m[12]));
  2125. r[7] = det * (m[0] * (m[6] * m[11] - m[7] * m[10]) + m[2] * (m[7] * m[8] - m[4] * m[11]) + m[3] * (m[4] * m[10] - m[6] * m[8]));
  2126. r[8] = det * (m[4] * (m[9] * m[15] - m[11] * m[13]) + m[5] * (m[11] * m[12] - m[8] * m[15]) + m[7] * (m[8] * m[13] - m[9] * m[12]));
  2127. r[9] = -det * (m[0] * (m[9] * m[15] - m[11] * m[13]) + m[1] * (m[11] * m[12] - m[8] * m[15]) + m[3] * (m[8] * m[13] - m[9] * m[12]));
  2128. r[10] = det * (m[0] * (m[5] * m[15] - m[7] * m[13]) + m[1] * (m[7] * m[12] - m[4] * m[15]) + m[3] * (m[4] * m[13] - m[5] * m[12]));
  2129. r[11] = -det * (m[0] * (m[5] * m[11] - m[7] * m[9]) + m[1] * (m[7] * m[8] - m[4] * m[11]) + m[3] * (m[4] * m[9] - m[5] * m[8]));
  2130. r[12] = -det * (m[4] * (m[9] * m[14] - m[10] * m[13]) + m[5] * (m[10] * m[12] - m[8] * m[14]) + m[6] * (m[8] * m[13] - m[9] * m[12]));
  2131. r[13] = det * (m[0] * (m[9] * m[14] - m[10] * m[13]) + m[1] * (m[10] * m[12] - m[8] * m[14]) + m[2] * (m[8] * m[13] - m[9] * m[12]));
  2132. r[14] = -det * (m[0] * (m[5] * m[14] - m[6] * m[13]) + m[1] * (m[6] * m[12] - m[4] * m[14]) + m[2] * (m[4] * m[13] - m[5] * m[12]));
  2133. r[15] = det * (m[0] * (m[5] * m[10] - m[6] * m[9]) + m[1] * (m[6] * m[8] - m[4] * m[10]) + m[2] * (m[4] * m[9] - m[5] * m[8]));
  2134. memcpy(m, &r, sizeof(r));
  2135. }
  2136. /* compose a coloumn major 4 x 4 matrix from vec3 position and vec4 orientation/rotation quaternion */
  2137. void _m3d_mat(M3D_FLOAT *r, m3dv_t *p, m3dv_t *q) {
  2138. if (q->x == (M3D_FLOAT)0.0 && q->y == (M3D_FLOAT)0.0 && q->z >= (M3D_FLOAT)0.7071065 && q->z <= (M3D_FLOAT)0.7071075 &&
  2139. q->w == (M3D_FLOAT)0.0) {
  2140. r[1] = r[2] = r[4] = r[6] = r[8] = r[9] = (M3D_FLOAT)0.0;
  2141. r[0] = r[5] = r[10] = (M3D_FLOAT)-1.0;
  2142. } else {
  2143. r[0] = 1 - 2 * (q->y * q->y + q->z * q->z);
  2144. if (r[0] > -M3D_EPSILON && r[0] < M3D_EPSILON) r[0] = (M3D_FLOAT)0.0;
  2145. r[1] = 2 * (q->x * q->y - q->z * q->w);
  2146. if (r[1] > -M3D_EPSILON && r[1] < M3D_EPSILON) r[1] = (M3D_FLOAT)0.0;
  2147. r[2] = 2 * (q->x * q->z + q->y * q->w);
  2148. if (r[2] > -M3D_EPSILON && r[2] < M3D_EPSILON) r[2] = (M3D_FLOAT)0.0;
  2149. r[4] = 2 * (q->x * q->y + q->z * q->w);
  2150. if (r[4] > -M3D_EPSILON && r[4] < M3D_EPSILON) r[4] = (M3D_FLOAT)0.0;
  2151. r[5] = 1 - 2 * (q->x * q->x + q->z * q->z);
  2152. if (r[5] > -M3D_EPSILON && r[5] < M3D_EPSILON) r[5] = (M3D_FLOAT)0.0;
  2153. r[6] = 2 * (q->y * q->z - q->x * q->w);
  2154. if (r[6] > -M3D_EPSILON && r[6] < M3D_EPSILON) r[6] = (M3D_FLOAT)0.0;
  2155. r[8] = 2 * (q->x * q->z - q->y * q->w);
  2156. if (r[8] > -M3D_EPSILON && r[8] < M3D_EPSILON) r[8] = (M3D_FLOAT)0.0;
  2157. r[9] = 2 * (q->y * q->z + q->x * q->w);
  2158. if (r[9] > -M3D_EPSILON && r[9] < M3D_EPSILON) r[9] = (M3D_FLOAT)0.0;
  2159. r[10] = 1 - 2 * (q->x * q->x + q->y * q->y);
  2160. if (r[10] > -M3D_EPSILON && r[10] < M3D_EPSILON) r[10] = (M3D_FLOAT)0.0;
  2161. }
  2162. r[3] = p->x;
  2163. r[7] = p->y;
  2164. r[11] = p->z;
  2165. r[12] = 0;
  2166. r[13] = 0;
  2167. r[14] = 0;
  2168. r[15] = 1;
  2169. }
  2170. #endif
  2171. #if !defined(M3D_NOANIMATION) || !defined(M3D_NONORMALS)
  2172. /* portable fast inverse square root calculation. returns 1/sqrt(x) */
  2173. static M3D_FLOAT _m3d_rsq(M3D_FLOAT x) {
  2174. #ifdef M3D_DOUBLE
  2175. return ((M3D_FLOAT)15.0 / (M3D_FLOAT)8.0) + ((M3D_FLOAT)-5.0 / (M3D_FLOAT)4.0) * x + ((M3D_FLOAT)3.0 / (M3D_FLOAT)8.0) * x * x;
  2176. #else
  2177. /* John Carmack's */
  2178. float x2 = x * 0.5f;
  2179. *((uint32_t *)&x) = (0x5f3759df - (*((uint32_t *)&x) >> 1));
  2180. return x * (1.5f - (x2 * x * x));
  2181. #endif
  2182. }
  2183. #endif
  2184. /**
  2185. * Function to decode a Model 3D into in-memory format
  2186. */
  2187. m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d_t *mtllib) {
  2188. unsigned char *end, *chunk, *buff, weights[8];
  2189. unsigned int i, j, k, l, n, am, len = 0, reclen, offs;
  2190. char *name, *lang;
  2191. float f;
  2192. m3d_t *model;
  2193. M3D_INDEX mi;
  2194. M3D_FLOAT w;
  2195. m3dcd_t *cd;
  2196. m3dtx_t *tx;
  2197. m3dh_t *h;
  2198. m3dm_t *m;
  2199. m3da_t *a;
  2200. m3di_t *t;
  2201. #ifndef M3D_NONORMALS
  2202. char neednorm = 0;
  2203. m3dv_t *norm = NULL, *v0, *v1, *v2, va, vb;
  2204. #endif
  2205. #ifndef M3D_NOANIMATION
  2206. M3D_FLOAT r[16];
  2207. #endif
  2208. #if !defined(M3D_NOWEIGHTS) || !defined(M3D_NOANIMATION)
  2209. m3db_t *b;
  2210. #endif
  2211. #ifndef M3D_NOWEIGHTS
  2212. m3ds_t *sk;
  2213. #endif
  2214. m3ds_t s;
  2215. M3D_INDEX bi[M3D_BONEMAXLEVEL + 1], level;
  2216. const char *ol;
  2217. char *ptr, *pe, *fn;
  2218. #ifdef M3D_PROFILING
  2219. struct timeval tv0, tv1, tvd;
  2220. gettimeofday(&tv0, NULL);
  2221. #endif
  2222. if (!data || (!M3D_CHUNKMAGIC(data, '3', 'D', 'M', 'O')
  2223. && !M3D_CHUNKMAGIC(data, '3', 'd', 'm', 'o')
  2224. ))
  2225. return NULL;
  2226. model = (m3d_t *)M3D_MALLOC(sizeof(m3d_t));
  2227. if (!model) {
  2228. M3D_LOG("Out of memory");
  2229. return NULL;
  2230. }
  2231. memset(model, 0, sizeof(m3d_t));
  2232. if (mtllib) {
  2233. model->nummaterial = mtllib->nummaterial;
  2234. model->material = mtllib->material;
  2235. model->numtexture = mtllib->numtexture;
  2236. model->texture = mtllib->texture;
  2237. model->flags |= M3D_FLG_MTLLIB;
  2238. }
  2239. /* ASCII variant? */
  2240. if (M3D_CHUNKMAGIC(data, '3', 'd', 'm', 'o')) {
  2241. model->errcode = M3D_ERR_BADFILE;
  2242. model->flags |= M3D_FLG_FREESTR;
  2243. model->raw = (m3dhdr_t *)data;
  2244. ptr = (char *)data;
  2245. ol = setlocale(LC_NUMERIC, NULL);
  2246. setlocale(LC_NUMERIC, "C");
  2247. /* parse header. Don't use sscanf, that's incredibly slow */
  2248. ptr = _m3d_findarg(ptr);
  2249. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2250. pe = _m3d_findnl(ptr);
  2251. model->scale = (float)strtod(ptr, NULL);
  2252. ptr = pe;
  2253. if (model->scale <= (M3D_FLOAT)0.0) model->scale = (M3D_FLOAT)1.0;
  2254. model->name = _m3d_safestr(ptr, 2);
  2255. ptr = _m3d_findnl(ptr);
  2256. if (!*ptr) goto asciiend;
  2257. model->license = _m3d_safestr(ptr, 2);
  2258. ptr = _m3d_findnl(ptr);
  2259. if (!*ptr) goto asciiend;
  2260. model->author = _m3d_safestr(ptr, 2);
  2261. ptr = _m3d_findnl(ptr);
  2262. if (!*ptr) goto asciiend;
  2263. if (*ptr != '\r' && *ptr != '\n')
  2264. model->desc = _m3d_safestr(ptr, 3);
  2265. while (*ptr) {
  2266. while (*ptr && *ptr != '\n')
  2267. ptr++;
  2268. ptr++;
  2269. if (*ptr == '\r') ptr++;
  2270. if (*ptr == '\n') break;
  2271. }
  2272. /* the main chunk reader loop */
  2273. while (*ptr) {
  2274. while (*ptr && (*ptr == '\r' || *ptr == '\n'))
  2275. ptr++;
  2276. if (!*ptr || (ptr[0] == 'E' && ptr[1] == 'n' && ptr[2] == 'd')) break;
  2277. /* make sure there's at least one data row */
  2278. pe = ptr;
  2279. ptr = _m3d_findnl(ptr);
  2280. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2281. /* Preview chunk */
  2282. if (!memcmp(pe, "Preview", 7)) {
  2283. if (readfilecb) {
  2284. pe = _m3d_safestr(ptr, 0);
  2285. if (!pe || !*pe) goto asciiend;
  2286. model->preview.data = (*readfilecb)(pe, &model->preview.length);
  2287. M3D_FREE(pe);
  2288. }
  2289. while (*ptr && *ptr != '\r' && *ptr != '\n')
  2290. ptr = _m3d_findnl(ptr);
  2291. } else
  2292. /* texture map chunk */
  2293. if (!memcmp(pe, "Textmap", 7)) {
  2294. if (model->tmap) {
  2295. M3D_LOG("More texture map chunks, should be unique");
  2296. goto asciiend;
  2297. }
  2298. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2299. i = model->numtmap++;
  2300. model->tmap = (m3dti_t *)M3D_REALLOC(model->tmap, model->numtmap * sizeof(m3dti_t));
  2301. if (!model->tmap) goto memerr;
  2302. ptr = _m3d_getfloat(ptr, &model->tmap[i].u);
  2303. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2304. _m3d_getfloat(ptr, &model->tmap[i].v);
  2305. ptr = _m3d_findnl(ptr);
  2306. }
  2307. } else
  2308. /* vertex chunk */
  2309. if (!memcmp(pe, "Vertex", 6)) {
  2310. if (model->vertex) {
  2311. M3D_LOG("More vertex chunks, should be unique");
  2312. goto asciiend;
  2313. }
  2314. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2315. i = model->numvertex++;
  2316. model->vertex = (m3dv_t *)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t));
  2317. if (!model->vertex) goto memerr;
  2318. memset(&model->vertex[i], 0, sizeof(m3dv_t));
  2319. model->vertex[i].skinid = M3D_UNDEF;
  2320. model->vertex[i].color = 0;
  2321. model->vertex[i].w = (M3D_FLOAT)1.0;
  2322. ptr = _m3d_getfloat(ptr, &model->vertex[i].x);
  2323. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2324. ptr = _m3d_getfloat(ptr, &model->vertex[i].y);
  2325. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2326. ptr = _m3d_getfloat(ptr, &model->vertex[i].z);
  2327. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2328. ptr = _m3d_getfloat(ptr, &model->vertex[i].w);
  2329. if (!*ptr) goto asciiend;
  2330. if (*ptr == '#') {
  2331. ptr = _m3d_gethex(ptr, &model->vertex[i].color);
  2332. if (!*ptr) goto asciiend;
  2333. }
  2334. /* parse skin */
  2335. memset(&s, 0, sizeof(m3ds_t));
  2336. for (j = 0, w = (M3D_FLOAT)0.0; j < M3D_NUMBONE && *ptr && *ptr != '\r' && *ptr != '\n'; j++) {
  2337. ptr = _m3d_findarg(ptr);
  2338. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2339. ptr = _m3d_getint(ptr, &k);
  2340. s.boneid[j] = (M3D_INDEX)k;
  2341. if (*ptr == ':') {
  2342. ptr++;
  2343. ptr = _m3d_getfloat(ptr, &s.weight[j]);
  2344. w += s.weight[j];
  2345. } else if (!j)
  2346. s.weight[j] = (M3D_FLOAT)1.0;
  2347. if (!*ptr) goto asciiend;
  2348. }
  2349. if (s.boneid[0] != M3D_UNDEF && s.weight[0] > (M3D_FLOAT)0.0) {
  2350. if (w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0)
  2351. for (j = 0; j < M3D_NUMBONE && s.weight[j] > (M3D_FLOAT)0.0; j++)
  2352. s.weight[j] /= w;
  2353. k = M3D_NOTDEFINED;
  2354. if (model->skin) {
  2355. for (j = 0; j < model->numskin; j++)
  2356. if (!memcmp(&model->skin[j], &s, sizeof(m3ds_t))) {
  2357. k = j;
  2358. break;
  2359. }
  2360. }
  2361. if (k == M3D_NOTDEFINED) {
  2362. k = model->numskin++;
  2363. model->skin = (m3ds_t *)M3D_REALLOC(model->skin, model->numskin * sizeof(m3ds_t));
  2364. memcpy(&model->skin[k], &s, sizeof(m3ds_t));
  2365. }
  2366. model->vertex[i].skinid = (M3D_INDEX)k;
  2367. }
  2368. ptr = _m3d_findnl(ptr);
  2369. }
  2370. } else
  2371. /* Skeleton, bone hierarchy */
  2372. if (!memcmp(pe, "Bones", 5)) {
  2373. if (model->bone) {
  2374. M3D_LOG("More bones chunks, should be unique");
  2375. goto asciiend;
  2376. }
  2377. bi[0] = M3D_UNDEF;
  2378. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2379. i = model->numbone++;
  2380. model->bone = (m3db_t *)M3D_REALLOC(model->bone, model->numbone * sizeof(m3db_t));
  2381. if (!model->bone) goto memerr;
  2382. for (level = 0; *ptr == '/'; ptr++, level++)
  2383. ;
  2384. if (level > M3D_BONEMAXLEVEL || !*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2385. bi[level + 1] = i;
  2386. model->bone[i].numweight = 0;
  2387. model->bone[i].weight = NULL;
  2388. model->bone[i].parent = bi[level];
  2389. ptr = _m3d_getint(ptr, &k);
  2390. ptr = _m3d_findarg(ptr);
  2391. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2392. model->bone[i].pos = (M3D_INDEX)k;
  2393. ptr = _m3d_getint(ptr, &k);
  2394. ptr = _m3d_findarg(ptr);
  2395. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2396. model->bone[i].ori = (M3D_INDEX)k;
  2397. model->vertex[k].skinid = M3D_INDEXMAX;
  2398. pe = _m3d_safestr(ptr, 0);
  2399. if (!pe || !*pe) goto asciiend;
  2400. model->bone[i].name = pe;
  2401. ptr = _m3d_findnl(ptr);
  2402. }
  2403. } else
  2404. /* material chunk */
  2405. if (!memcmp(pe, "Material", 8)) {
  2406. pe = _m3d_findarg(pe);
  2407. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  2408. pe = _m3d_safestr(pe, 0);
  2409. if (!pe || !*pe) goto asciiend;
  2410. for (i = 0; i < model->nummaterial; i++)
  2411. if (!strcmp(pe, model->material[i].name)) {
  2412. M3D_LOG("Multiple definitions for material");
  2413. M3D_LOG(pe);
  2414. M3D_FREE(pe);
  2415. pe = NULL;
  2416. while (*ptr && *ptr != '\r' && *ptr != '\n')
  2417. ptr = _m3d_findnl(ptr);
  2418. break;
  2419. }
  2420. if (!pe) continue;
  2421. i = model->nummaterial++;
  2422. if (model->flags & M3D_FLG_MTLLIB) {
  2423. m = model->material;
  2424. model->material = (m3dm_t *)M3D_MALLOC(model->nummaterial * sizeof(m3dm_t));
  2425. if (!model->material) goto memerr;
  2426. memcpy(model->material, m, (model->nummaterial - 1) * sizeof(m3dm_t));
  2427. if (model->texture) {
  2428. tx = model->texture;
  2429. model->texture = (m3dtx_t *)M3D_MALLOC(model->numtexture * sizeof(m3dtx_t));
  2430. if (!model->texture) goto memerr;
  2431. memcpy(model->texture, tx, model->numtexture * sizeof(m3dm_t));
  2432. }
  2433. model->flags &= ~M3D_FLG_MTLLIB;
  2434. } else {
  2435. model->material = (m3dm_t *)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t));
  2436. if (!model->material) goto memerr;
  2437. }
  2438. m = &model->material[i];
  2439. m->name = pe;
  2440. m->numprop = 0;
  2441. m->prop = NULL;
  2442. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2443. k = n = 256;
  2444. if (*ptr == 'm' && *(ptr + 1) == 'a' && *(ptr + 2) == 'p' && *(ptr + 3) == '_') {
  2445. k = m3dpf_map;
  2446. ptr += 4;
  2447. }
  2448. for (j = 0; j < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); j++)
  2449. if (!memcmp(ptr, m3d_propertytypes[j].key, strlen(m3d_propertytypes[j].key))) {
  2450. n = m3d_propertytypes[j].id;
  2451. if (k != m3dpf_map) k = m3d_propertytypes[j].format;
  2452. break;
  2453. }
  2454. if (n != 256 && k != 256) {
  2455. ptr = _m3d_findarg(ptr);
  2456. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2457. j = m->numprop++;
  2458. m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t));
  2459. if (!m->prop) goto memerr;
  2460. m->prop[j].type = n + (k == m3dpf_map && n < 128 ? 128 : 0);
  2461. switch (k) {
  2462. case m3dpf_color: ptr = _m3d_gethex(ptr, &m->prop[j].value.color); break;
  2463. case m3dpf_uint8:
  2464. case m3dpf_uint16:
  2465. case m3dpf_uint32: ptr = _m3d_getint(ptr, &m->prop[j].value.num); break;
  2466. case m3dpf_float: ptr = _m3d_getfloat(ptr, &m->prop[j].value.fnum); break;
  2467. case m3dpf_map:
  2468. pe = _m3d_safestr(ptr, 0);
  2469. if (!pe || !*pe) goto asciiend;
  2470. m->prop[j].value.textureid = _m3d_gettx(model, readfilecb, freecb, pe);
  2471. if (model->errcode == M3D_ERR_ALLOC) {
  2472. M3D_FREE(pe);
  2473. goto memerr;
  2474. }
  2475. /* this error code only returned if readfilecb was specified */
  2476. if (m->prop[j].value.textureid == M3D_UNDEF) {
  2477. M3D_LOG("Texture not found");
  2478. M3D_LOG(pe);
  2479. m->numprop--;
  2480. }
  2481. M3D_FREE(pe);
  2482. break;
  2483. }
  2484. } else {
  2485. M3D_LOG("Unknown material property in");
  2486. M3D_LOG(m->name);
  2487. model->errcode = M3D_ERR_UNKPROP;
  2488. }
  2489. ptr = _m3d_findnl(ptr);
  2490. }
  2491. if (!m->numprop) model->nummaterial--;
  2492. } else
  2493. /* procedural */
  2494. if (!memcmp(pe, "Procedural", 10)) {
  2495. pe = _m3d_safestr(ptr, 0);
  2496. _m3d_getpr(model, readfilecb, freecb, pe);
  2497. M3D_FREE(pe);
  2498. while (*ptr && *ptr != '\r' && *ptr != '\n')
  2499. ptr = _m3d_findnl(ptr);
  2500. } else
  2501. /* mesh */
  2502. if (!memcmp(pe, "Mesh", 4)) {
  2503. mi = M3D_UNDEF;
  2504. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2505. if (*ptr == 'u') {
  2506. ptr = _m3d_findarg(ptr);
  2507. if (!*ptr) goto asciiend;
  2508. mi = M3D_UNDEF;
  2509. if (*ptr != '\r' && *ptr != '\n') {
  2510. pe = _m3d_safestr(ptr, 0);
  2511. if (!pe || !*pe) goto asciiend;
  2512. for (j = 0; j < model->nummaterial; j++)
  2513. if (!strcmp(pe, model->material[j].name)) {
  2514. mi = (M3D_INDEX)j;
  2515. break;
  2516. }
  2517. if (mi == M3D_UNDEF && !(model->flags & M3D_FLG_MTLLIB)) {
  2518. mi = model->nummaterial++;
  2519. model->material = (m3dm_t *)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t));
  2520. if (!model->material) goto memerr;
  2521. model->material[mi].name = pe;
  2522. model->material[mi].numprop = 1;
  2523. model->material[mi].prop = NULL;
  2524. } else
  2525. M3D_FREE(pe);
  2526. }
  2527. } else {
  2528. i = model->numface++;
  2529. model->face = (m3df_t *)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t));
  2530. if (!model->face) goto memerr;
  2531. memset(&model->face[i], 255, sizeof(m3df_t)); /* set all index to -1 by default */
  2532. model->face[i].materialid = mi;
  2533. /* hardcoded triangles. */
  2534. for (j = 0; j < 3; j++) {
  2535. /* vertex */
  2536. ptr = _m3d_getint(ptr, &k);
  2537. model->face[i].vertex[j] = (M3D_INDEX)k;
  2538. if (!*ptr) goto asciiend;
  2539. if (*ptr == '/') {
  2540. ptr++;
  2541. if (*ptr != '/') {
  2542. /* texcoord */
  2543. ptr = _m3d_getint(ptr, &k);
  2544. model->face[i].texcoord[j] = (M3D_INDEX)k;
  2545. if (!*ptr) goto asciiend;
  2546. }
  2547. if (*ptr == '/') {
  2548. ptr++;
  2549. /* normal */
  2550. ptr = _m3d_getint(ptr, &k);
  2551. model->face[i].normal[j] = (M3D_INDEX)k;
  2552. if (!*ptr) goto asciiend;
  2553. }
  2554. }
  2555. #ifndef M3D_NONORMALS
  2556. if (model->face[i].normal[j] == M3D_UNDEF) neednorm = 1;
  2557. #endif
  2558. ptr = _m3d_findarg(ptr);
  2559. }
  2560. }
  2561. ptr = _m3d_findnl(ptr);
  2562. }
  2563. } else
  2564. /* mathematical shape */
  2565. if (!memcmp(pe, "Shape", 5)) {
  2566. pe = _m3d_findarg(pe);
  2567. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  2568. pe = _m3d_safestr(pe, 0);
  2569. if (!pe || !*pe) goto asciiend;
  2570. i = model->numshape++;
  2571. model->shape = (m3dh_t *)M3D_REALLOC(model->shape, model->numshape * sizeof(m3ds_t));
  2572. if (!model->shape) goto memerr;
  2573. h = &model->shape[i];
  2574. h->name = pe;
  2575. h->group = M3D_UNDEF;
  2576. h->numcmd = 0;
  2577. h->cmd = NULL;
  2578. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2579. if (!memcmp(ptr, "group", 5)) {
  2580. ptr = _m3d_findarg(ptr);
  2581. ptr = _m3d_getint(ptr, &h->group);
  2582. ptr = _m3d_findnl(ptr);
  2583. if (h->group != M3D_UNDEF && h->group >= model->numbone) {
  2584. M3D_LOG("Unknown bone id as shape group in shape");
  2585. M3D_LOG(pe);
  2586. h->group = M3D_UNDEF;
  2587. model->errcode = M3D_ERR_SHPE;
  2588. }
  2589. continue;
  2590. }
  2591. for (cd = NULL, k = 0; k < (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0])); k++) {
  2592. j = (unsigned int)strlen(m3d_commandtypes[k].key);
  2593. if (!memcmp(ptr, m3d_commandtypes[k].key, j) && (ptr[j] == ' ' || ptr[j] == '\r' || ptr[j] == '\n')) {
  2594. cd = &m3d_commandtypes[k];
  2595. break;
  2596. }
  2597. }
  2598. if (cd) {
  2599. j = h->numcmd++;
  2600. h->cmd = (m3dc_t *)M3D_REALLOC(h->cmd, h->numcmd * sizeof(m3dc_t));
  2601. if (!h->cmd) goto memerr;
  2602. h->cmd[j].type = k;
  2603. h->cmd[j].arg = (uint32_t *)M3D_MALLOC(cd->p * sizeof(uint32_t));
  2604. if (!h->cmd[j].arg) goto memerr;
  2605. memset(h->cmd[j].arg, 0, cd->p * sizeof(uint32_t));
  2606. for (k = n = 0, l = cd->p; k < l; k++) {
  2607. ptr = _m3d_findarg(ptr);
  2608. if (!*ptr) goto asciiend;
  2609. if (*ptr == '[') {
  2610. ptr = _m3d_findarg(ptr + 1);
  2611. if (!*ptr) goto asciiend;
  2612. }
  2613. if (*ptr == ']' || *ptr == '\r' || *ptr == '\n') break;
  2614. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  2615. case m3dcp_mi_t:
  2616. mi = M3D_UNDEF;
  2617. if (*ptr != '\r' && *ptr != '\n') {
  2618. pe = _m3d_safestr(ptr, 0);
  2619. if (!pe || !*pe) goto asciiend;
  2620. for (n = 0; n < model->nummaterial; n++)
  2621. if (!strcmp(pe, model->material[n].name)) {
  2622. mi = (M3D_INDEX)n;
  2623. break;
  2624. }
  2625. if (mi == M3D_UNDEF && !(model->flags & M3D_FLG_MTLLIB)) {
  2626. mi = model->nummaterial++;
  2627. model->material = (m3dm_t *)M3D_REALLOC(model->material,
  2628. model->nummaterial * sizeof(m3dm_t));
  2629. if (!model->material) goto memerr;
  2630. model->material[mi].name = pe;
  2631. model->material[mi].numprop = 1;
  2632. model->material[mi].prop = NULL;
  2633. } else
  2634. M3D_FREE(pe);
  2635. }
  2636. h->cmd[j].arg[k] = mi;
  2637. break;
  2638. case m3dcp_vc_t:
  2639. _m3d_getfloat(ptr, &w);
  2640. h->cmd[j].arg[k] = *((uint32_t *)&w);
  2641. break;
  2642. case m3dcp_va_t:
  2643. ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]);
  2644. n = k + 1;
  2645. l += (h->cmd[j].arg[k] - 1) * (cd->p - k - 1);
  2646. h->cmd[j].arg = (uint32_t *)M3D_REALLOC(h->cmd[j].arg, l * sizeof(uint32_t));
  2647. if (!h->cmd[j].arg) goto memerr;
  2648. memset(&h->cmd[j].arg[k + 1], 0, (l - k - 1) * sizeof(uint32_t));
  2649. break;
  2650. case m3dcp_qi_t:
  2651. ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]);
  2652. model->vertex[h->cmd[i].arg[k]].skinid = M3D_INDEXMAX;
  2653. break;
  2654. default:
  2655. ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]);
  2656. break;
  2657. }
  2658. }
  2659. } else {
  2660. M3D_LOG("Unknown shape command in");
  2661. M3D_LOG(h->name);
  2662. model->errcode = M3D_ERR_UNKCMD;
  2663. }
  2664. ptr = _m3d_findnl(ptr);
  2665. }
  2666. if (!h->numcmd) model->numshape--;
  2667. } else
  2668. /* annotation labels */
  2669. if (!memcmp(pe, "Labels", 6)) {
  2670. pe = _m3d_findarg(pe);
  2671. if (!*pe) goto asciiend;
  2672. if (*pe == '\r' || *pe == '\n')
  2673. pe = NULL;
  2674. else
  2675. pe = _m3d_safestr(pe, 0);
  2676. k = 0;
  2677. fn = NULL;
  2678. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2679. if (*ptr == 'c') {
  2680. ptr = _m3d_findarg(ptr);
  2681. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  2682. ptr = _m3d_gethex(ptr, &k);
  2683. } else if (*ptr == 'l') {
  2684. ptr = _m3d_findarg(ptr);
  2685. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  2686. fn = _m3d_safestr(ptr, 2);
  2687. } else {
  2688. i = model->numlabel++;
  2689. model->label = (m3dl_t *)M3D_REALLOC(model->label, model->numlabel * sizeof(m3dl_t));
  2690. if (!model->label) goto memerr;
  2691. model->label[i].name = pe;
  2692. model->label[i].lang = fn;
  2693. model->label[i].color = k;
  2694. ptr = _m3d_getint(ptr, &j);
  2695. model->label[i].vertexid = (M3D_INDEX)j;
  2696. ptr = _m3d_findarg(ptr);
  2697. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  2698. model->label[i].text = _m3d_safestr(ptr, 2);
  2699. }
  2700. ptr = _m3d_findnl(ptr);
  2701. }
  2702. } else
  2703. /* action */
  2704. if (!memcmp(pe, "Action", 6)) {
  2705. pe = _m3d_findarg(pe);
  2706. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  2707. pe = _m3d_getint(pe, &k);
  2708. pe = _m3d_findarg(pe);
  2709. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  2710. pe = _m3d_safestr(pe, 0);
  2711. if (!pe || !*pe) goto asciiend;
  2712. i = model->numaction++;
  2713. model->action = (m3da_t *)M3D_REALLOC(model->action, model->numaction * sizeof(m3da_t));
  2714. if (!model->action) goto memerr;
  2715. a = &model->action[i];
  2716. a->name = pe;
  2717. a->durationmsec = k;
  2718. /* skip the first frame marker as there's always at least one frame */
  2719. a->numframe = 1;
  2720. a->frame = (m3dfr_t *)M3D_MALLOC(sizeof(m3dfr_t));
  2721. if (!a->frame) goto memerr;
  2722. a->frame[0].msec = 0;
  2723. a->frame[0].numtransform = 0;
  2724. a->frame[0].transform = NULL;
  2725. i = 0;
  2726. if (*ptr == 'f')
  2727. ptr = _m3d_findnl(ptr);
  2728. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2729. if (*ptr == 'f') {
  2730. i = a->numframe++;
  2731. a->frame = (m3dfr_t *)M3D_REALLOC(a->frame, a->numframe * sizeof(m3dfr_t));
  2732. if (!a->frame) goto memerr;
  2733. ptr = _m3d_findarg(ptr);
  2734. ptr = _m3d_getint(ptr, &a->frame[i].msec);
  2735. a->frame[i].numtransform = 0;
  2736. a->frame[i].transform = NULL;
  2737. } else {
  2738. j = a->frame[i].numtransform++;
  2739. a->frame[i].transform = (m3dtr_t *)M3D_REALLOC(a->frame[i].transform,
  2740. a->frame[i].numtransform * sizeof(m3dtr_t));
  2741. if (!a->frame[i].transform) goto memerr;
  2742. ptr = _m3d_getint(ptr, &k);
  2743. ptr = _m3d_findarg(ptr);
  2744. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2745. a->frame[i].transform[j].boneid = (M3D_INDEX)k;
  2746. ptr = _m3d_getint(ptr, &k);
  2747. ptr = _m3d_findarg(ptr);
  2748. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2749. a->frame[i].transform[j].pos = (M3D_INDEX)k;
  2750. ptr = _m3d_getint(ptr, &k);
  2751. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  2752. a->frame[i].transform[j].ori = (M3D_INDEX)k;
  2753. model->vertex[k].skinid = M3D_INDEXMAX;
  2754. }
  2755. ptr = _m3d_findnl(ptr);
  2756. }
  2757. } else
  2758. /* inlined assets chunk */
  2759. if (!memcmp(pe, "Assets", 6)) {
  2760. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2761. if (readfilecb) {
  2762. pe = _m3d_safestr(ptr, 2);
  2763. if (!pe || !*pe) goto asciiend;
  2764. i = model->numinlined++;
  2765. model->inlined = (m3di_t *)M3D_REALLOC(model->inlined, model->numinlined * sizeof(m3di_t));
  2766. if (!model->inlined) goto memerr;
  2767. t = &model->inlined[i];
  2768. model->inlined[i].data = (*readfilecb)(pe, &model->inlined[i].length);
  2769. if (model->inlined[i].data) {
  2770. fn = strrchr(pe, '.');
  2771. if (fn && (fn[1] == 'p' || fn[1] == 'P') && (fn[2] == 'n' || fn[2] == 'N') &&
  2772. (fn[3] == 'g' || fn[3] == 'G')) *fn = 0;
  2773. fn = strrchr(pe, '/');
  2774. if (!fn) fn = strrchr(pe, '\\');
  2775. if (!fn)
  2776. fn = pe;
  2777. else
  2778. fn++;
  2779. model->inlined[i].name = _m3d_safestr(fn, 0);
  2780. } else
  2781. model->numinlined--;
  2782. M3D_FREE(pe);
  2783. }
  2784. ptr = _m3d_findnl(ptr);
  2785. }
  2786. } else
  2787. /* extra chunks */
  2788. if (!memcmp(pe, "Extra", 5)) {
  2789. pe = _m3d_findarg(pe);
  2790. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  2791. buff = (unsigned char *)_m3d_findnl(ptr);
  2792. k = ((uint32_t)((uintptr_t)buff - (uintptr_t)ptr) / 3) + 1;
  2793. i = model->numextra++;
  2794. model->extra = (m3dchunk_t **)M3D_REALLOC(model->extra, model->numextra * sizeof(m3dchunk_t *));
  2795. if (!model->extra) goto memerr;
  2796. model->extra[i] = (m3dchunk_t *)M3D_MALLOC(k + sizeof(m3dchunk_t));
  2797. if (!model->extra[i]) goto memerr;
  2798. memcpy(&model->extra[i]->magic, pe, 4);
  2799. model->extra[i]->length = sizeof(m3dchunk_t);
  2800. pe = (char *)model->extra[i] + sizeof(m3dchunk_t);
  2801. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  2802. ptr = _m3d_gethex(ptr, &k);
  2803. *pe++ = (uint8_t)k;
  2804. model->extra[i]->length++;
  2805. }
  2806. } else
  2807. goto asciiend;
  2808. }
  2809. model->errcode = M3D_SUCCESS;
  2810. asciiend:
  2811. setlocale(LC_NUMERIC, ol);
  2812. goto postprocess;
  2813. }
  2814. /* Binary variant */
  2815. if (!M3D_CHUNKMAGIC(data + 8, 'H', 'E', 'A', 'D')) {
  2816. buff = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char *)data + 8, ((m3dchunk_t *)data)->length - 8,
  2817. 4096, (int *)&len, 1);
  2818. if (!buff || !len || !M3D_CHUNKMAGIC(buff, 'H', 'E', 'A', 'D')) {
  2819. if (buff) M3D_FREE(buff);
  2820. M3D_FREE(model);
  2821. return NULL;
  2822. }
  2823. buff = (unsigned char *)M3D_REALLOC(buff, len);
  2824. model->flags |= M3D_FLG_FREERAW; /* mark that we have to free the raw buffer */
  2825. data = buff;
  2826. #ifdef M3D_PROFILING
  2827. gettimeofday(&tv1, NULL);
  2828. tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;
  2829. tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
  2830. if (tvd.tv_usec < 0) {
  2831. tvd.tv_sec--;
  2832. tvd.tv_usec += 1000000L;
  2833. }
  2834. printf(" Deflate model %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec);
  2835. memcpy(&tv0, &tv1, sizeof(struct timeval));
  2836. #endif
  2837. } else {
  2838. len = ((m3dhdr_t *)data)->length;
  2839. data += 8;
  2840. }
  2841. model->raw = (m3dhdr_t *)data;
  2842. end = data + len;
  2843. /* parse header */
  2844. data += sizeof(m3dhdr_t);
  2845. M3D_LOG(data);
  2846. model->name = (char *)data;
  2847. for (; data < end && *data; data++) {
  2848. };
  2849. data++;
  2850. model->license = (char *)data;
  2851. for (; data < end && *data; data++) {
  2852. };
  2853. data++;
  2854. model->author = (char *)data;
  2855. for (; data < end && *data; data++) {
  2856. };
  2857. data++;
  2858. model->desc = (char *)data;
  2859. chunk = (unsigned char *)model->raw + model->raw->length;
  2860. model->scale = (M3D_FLOAT)model->raw->scale;
  2861. if (model->scale <= (M3D_FLOAT)0.0) model->scale = (M3D_FLOAT)1.0;
  2862. model->vc_s = 1 << ((model->raw->types >> 0) & 3); /* vertex coordinate size */
  2863. model->vi_s = 1 << ((model->raw->types >> 2) & 3); /* vertex index size */
  2864. model->si_s = 1 << ((model->raw->types >> 4) & 3); /* string offset size */
  2865. model->ci_s = 1 << ((model->raw->types >> 6) & 3); /* color index size */
  2866. model->ti_s = 1 << ((model->raw->types >> 8) & 3); /* tmap index size */
  2867. model->bi_s = 1 << ((model->raw->types >> 10) & 3); /* bone index size */
  2868. model->nb_s = 1 << ((model->raw->types >> 12) & 3); /* number of bones per vertex */
  2869. model->sk_s = 1 << ((model->raw->types >> 14) & 3); /* skin index size */
  2870. model->fc_s = 1 << ((model->raw->types >> 16) & 3); /* frame counter size */
  2871. model->hi_s = 1 << ((model->raw->types >> 18) & 3); /* shape index size */
  2872. model->fi_s = 1 << ((model->raw->types >> 20) & 3); /* face index size */
  2873. if (model->ci_s == 8) model->ci_s = 0; /* optional indices */
  2874. if (model->ti_s == 8) model->ti_s = 0;
  2875. if (model->bi_s == 8) model->bi_s = 0;
  2876. if (model->sk_s == 8) model->sk_s = 0;
  2877. if (model->fc_s == 8) model->fc_s = 0;
  2878. if (model->hi_s == 8) model->hi_s = 0;
  2879. if (model->fi_s == 8) model->fi_s = 0;
  2880. /* variable limit checks */
  2881. if (sizeof(M3D_FLOAT) == 4 && model->vc_s > 4) {
  2882. M3D_LOG("Double precision coordinates not supported, truncating to float...");
  2883. model->errcode = M3D_ERR_TRUNC;
  2884. }
  2885. if (sizeof(M3D_INDEX) == 2 && (model->vi_s > 2 || model->si_s > 2 || model->ci_s > 2 || model->ti_s > 2 ||
  2886. model->bi_s > 2 || model->sk_s > 2 || model->fc_s > 2 || model->hi_s > 2 || model->fi_s > 2)) {
  2887. M3D_LOG("32 bit indices not supported, unable to load model");
  2888. M3D_FREE(model);
  2889. return NULL;
  2890. }
  2891. if (model->vi_s > 4 || model->si_s > 4) {
  2892. M3D_LOG("Invalid index size, unable to load model");
  2893. M3D_FREE(model);
  2894. return NULL;
  2895. }
  2896. if (model->nb_s > M3D_NUMBONE) {
  2897. M3D_LOG("Model has more bones per vertex than what importer was configured to support");
  2898. model->errcode = M3D_ERR_TRUNC;
  2899. }
  2900. /* look for inlined assets in advance, material and procedural chunks may need them */
  2901. buff = chunk;
  2902. while (buff < end && !M3D_CHUNKMAGIC(buff, 'O', 'M', 'D', '3')) {
  2903. data = buff;
  2904. len = ((m3dchunk_t *)data)->length;
  2905. buff += len;
  2906. if (len < sizeof(m3dchunk_t) || buff >= end) {
  2907. M3D_LOG("Invalid chunk size");
  2908. break;
  2909. }
  2910. len -= sizeof(m3dchunk_t) + model->si_s;
  2911. /* inlined assets */
  2912. if (M3D_CHUNKMAGIC(data, 'A', 'S', 'E', 'T') && len > 0) {
  2913. M3D_LOG("Inlined asset");
  2914. i = model->numinlined++;
  2915. model->inlined = (m3di_t *)M3D_REALLOC(model->inlined, model->numinlined * sizeof(m3di_t));
  2916. if (!model->inlined) {
  2917. memerr:
  2918. M3D_LOG("Out of memory");
  2919. model->errcode = M3D_ERR_ALLOC;
  2920. return model;
  2921. }
  2922. data += sizeof(m3dchunk_t);
  2923. t = &model->inlined[i];
  2924. M3D_GETSTR(t->name);
  2925. M3D_LOG(t->name);
  2926. t->data = (uint8_t *)data;
  2927. t->length = len;
  2928. }
  2929. }
  2930. /* parse chunks */
  2931. while (chunk < end && !M3D_CHUNKMAGIC(chunk, 'O', 'M', 'D', '3')) {
  2932. data = chunk;
  2933. len = ((m3dchunk_t *)chunk)->length;
  2934. chunk += len;
  2935. if (len < sizeof(m3dchunk_t) || chunk >= end) {
  2936. M3D_LOG("Invalid chunk size");
  2937. break;
  2938. }
  2939. len -= sizeof(m3dchunk_t);
  2940. /* preview chunk */
  2941. if (M3D_CHUNKMAGIC(data, 'P', 'R', 'V', 'W') && len > 0) {
  2942. model->preview.length = len;
  2943. model->preview.data = data + sizeof(m3dchunk_t);
  2944. } else
  2945. /* color map */
  2946. if (M3D_CHUNKMAGIC(data, 'C', 'M', 'A', 'P')) {
  2947. M3D_LOG("Color map");
  2948. if (model->cmap) {
  2949. M3D_LOG("More color map chunks, should be unique");
  2950. model->errcode = M3D_ERR_CMAP;
  2951. continue;
  2952. }
  2953. if (!model->ci_s) {
  2954. M3D_LOG("Color map chunk, shouldn't be any");
  2955. model->errcode = M3D_ERR_CMAP;
  2956. continue;
  2957. }
  2958. model->numcmap = len / sizeof(uint32_t);
  2959. model->cmap = (uint32_t *)(data + sizeof(m3dchunk_t));
  2960. } else
  2961. /* texture map */
  2962. if (M3D_CHUNKMAGIC(data, 'T', 'M', 'A', 'P')) {
  2963. M3D_LOG("Texture map");
  2964. if (model->tmap) {
  2965. M3D_LOG("More texture map chunks, should be unique");
  2966. model->errcode = M3D_ERR_TMAP;
  2967. continue;
  2968. }
  2969. if (!model->ti_s) {
  2970. M3D_LOG("Texture map chunk, shouldn't be any");
  2971. model->errcode = M3D_ERR_TMAP;
  2972. continue;
  2973. }
  2974. reclen = model->vc_s + model->vc_s;
  2975. model->numtmap = len / reclen;
  2976. model->tmap = (m3dti_t *)M3D_MALLOC(model->numtmap * sizeof(m3dti_t));
  2977. if (!model->tmap) goto memerr;
  2978. for (i = 0, data += sizeof(m3dchunk_t); data < chunk; i++) {
  2979. switch (model->vc_s) {
  2980. case 1:
  2981. model->tmap[i].u = (M3D_FLOAT)(data[0]) / (M3D_FLOAT)255.0;
  2982. model->tmap[i].v = (M3D_FLOAT)(data[1]) / (M3D_FLOAT)255.0;
  2983. break;
  2984. case 2:
  2985. model->tmap[i].u = (M3D_FLOAT)(*((int16_t *)(data + 0))) / (M3D_FLOAT)65535.0;
  2986. model->tmap[i].v = (M3D_FLOAT)(*((int16_t *)(data + 2))) / (M3D_FLOAT)65535.0;
  2987. break;
  2988. case 4:
  2989. model->tmap[i].u = (M3D_FLOAT)(*((float *)(data + 0)));
  2990. model->tmap[i].v = (M3D_FLOAT)(*((float *)(data + 4)));
  2991. break;
  2992. case 8:
  2993. model->tmap[i].u = (M3D_FLOAT)(*((double *)(data + 0)));
  2994. model->tmap[i].v = (M3D_FLOAT)(*((double *)(data + 8)));
  2995. break;
  2996. }
  2997. data += reclen;
  2998. }
  2999. } else
  3000. /* vertex list */
  3001. if (M3D_CHUNKMAGIC(data, 'V', 'R', 'T', 'S')) {
  3002. M3D_LOG("Vertex list");
  3003. if (model->vertex) {
  3004. M3D_LOG("More vertex chunks, should be unique");
  3005. model->errcode = M3D_ERR_VRTS;
  3006. continue;
  3007. }
  3008. if (model->ci_s && model->ci_s < 4 && !model->cmap) model->errcode = M3D_ERR_CMAP;
  3009. reclen = model->ci_s + model->sk_s + 4 * model->vc_s;
  3010. model->numvertex = len / reclen;
  3011. model->vertex = (m3dv_t *)M3D_MALLOC(model->numvertex * sizeof(m3dv_t));
  3012. if (!model->vertex) goto memerr;
  3013. memset(model->vertex, 0, model->numvertex * sizeof(m3dv_t));
  3014. for (i = 0, data += sizeof(m3dchunk_t); data < chunk && i < model->numvertex; i++) {
  3015. switch (model->vc_s) {
  3016. case 1:
  3017. model->vertex[i].x = (M3D_FLOAT)((int8_t)data[0]) / (M3D_FLOAT)127.0;
  3018. model->vertex[i].y = (M3D_FLOAT)((int8_t)data[1]) / (M3D_FLOAT)127.0;
  3019. model->vertex[i].z = (M3D_FLOAT)((int8_t)data[2]) / (M3D_FLOAT)127.0;
  3020. model->vertex[i].w = (M3D_FLOAT)((int8_t)data[3]) / (M3D_FLOAT)127.0;
  3021. data += 4;
  3022. break;
  3023. case 2:
  3024. model->vertex[i].x = (M3D_FLOAT)(*((int16_t *)(data + 0))) / (M3D_FLOAT)32767.0;
  3025. model->vertex[i].y = (M3D_FLOAT)(*((int16_t *)(data + 2))) / (M3D_FLOAT)32767.0;
  3026. model->vertex[i].z = (M3D_FLOAT)(*((int16_t *)(data + 4))) / (M3D_FLOAT)32767.0;
  3027. model->vertex[i].w = (M3D_FLOAT)(*((int16_t *)(data + 6))) / (M3D_FLOAT)32767.0;
  3028. data += 8;
  3029. break;
  3030. case 4:
  3031. model->vertex[i].x = (M3D_FLOAT)(*((float *)(data + 0)));
  3032. model->vertex[i].y = (M3D_FLOAT)(*((float *)(data + 4)));
  3033. model->vertex[i].z = (M3D_FLOAT)(*((float *)(data + 8)));
  3034. model->vertex[i].w = (M3D_FLOAT)(*((float *)(data + 12)));
  3035. data += 16;
  3036. break;
  3037. case 8:
  3038. model->vertex[i].x = (M3D_FLOAT)(*((double *)(data + 0)));
  3039. model->vertex[i].y = (M3D_FLOAT)(*((double *)(data + 8)));
  3040. model->vertex[i].z = (M3D_FLOAT)(*((double *)(data + 16)));
  3041. model->vertex[i].w = (M3D_FLOAT)(*((double *)(data + 24)));
  3042. data += 32;
  3043. break;
  3044. }
  3045. switch (model->ci_s) {
  3046. case 1:
  3047. model->vertex[i].color = model->cmap ? model->cmap[data[0]] : 0;
  3048. data++;
  3049. break;
  3050. case 2:
  3051. model->vertex[i].color = model->cmap ? model->cmap[*((uint16_t *)data)] : 0;
  3052. data += 2;
  3053. break;
  3054. case 4:
  3055. model->vertex[i].color = *((uint32_t *)data);
  3056. data += 4;
  3057. break;
  3058. /* case 8: break; */
  3059. }
  3060. model->vertex[i].skinid = M3D_UNDEF;
  3061. data = _m3d_getidx(data, model->sk_s, &model->vertex[i].skinid);
  3062. }
  3063. } else
  3064. /* skeleton: bone hierarchy and skin */
  3065. if (M3D_CHUNKMAGIC(data, 'B', 'O', 'N', 'E')) {
  3066. M3D_LOG("Skeleton");
  3067. if (model->bone) {
  3068. M3D_LOG("More bone chunks, should be unique");
  3069. model->errcode = M3D_ERR_BONE;
  3070. continue;
  3071. }
  3072. if (!model->bi_s) {
  3073. M3D_LOG("Bone chunk, shouldn't be any");
  3074. model->errcode = M3D_ERR_BONE;
  3075. continue;
  3076. }
  3077. if (!model->vertex) {
  3078. M3D_LOG("No vertex chunk before bones");
  3079. model->errcode = M3D_ERR_VRTS;
  3080. break;
  3081. }
  3082. data += sizeof(m3dchunk_t);
  3083. model->numbone = 0;
  3084. data = _m3d_getidx(data, model->bi_s, &model->numbone);
  3085. if (model->numbone) {
  3086. model->bone = (m3db_t *)M3D_MALLOC(model->numbone * sizeof(m3db_t));
  3087. if (!model->bone) goto memerr;
  3088. }
  3089. model->numskin = 0;
  3090. data = _m3d_getidx(data, model->sk_s, &model->numskin);
  3091. /* read bone hierarchy */
  3092. for (i = 0; i < model->numbone; i++) {
  3093. data = _m3d_getidx(data, model->bi_s, &model->bone[i].parent);
  3094. M3D_GETSTR(model->bone[i].name);
  3095. data = _m3d_getidx(data, model->vi_s, &model->bone[i].pos);
  3096. data = _m3d_getidx(data, model->vi_s, &model->bone[i].ori);
  3097. model->bone[i].numweight = 0;
  3098. model->bone[i].weight = NULL;
  3099. }
  3100. /* read skin definitions */
  3101. if (model->numskin) {
  3102. model->skin = (m3ds_t *)M3D_MALLOC(model->numskin * sizeof(m3ds_t));
  3103. if (!model->skin) goto memerr;
  3104. for (i = 0; data < chunk && i < model->numskin; i++) {
  3105. for (j = 0; j < M3D_NUMBONE; j++) {
  3106. model->skin[i].boneid[j] = M3D_UNDEF;
  3107. model->skin[i].weight[j] = (M3D_FLOAT)0.0;
  3108. }
  3109. memset(&weights, 0, sizeof(weights));
  3110. if (model->nb_s == 1)
  3111. weights[0] = 255;
  3112. else {
  3113. memcpy(&weights, data, model->nb_s);
  3114. data += model->nb_s;
  3115. }
  3116. for (j = 0, w = (M3D_FLOAT)0.0; j < (unsigned int)model->nb_s; j++) {
  3117. if (weights[j]) {
  3118. if (j >= M3D_NUMBONE)
  3119. data += model->bi_s;
  3120. else {
  3121. model->skin[i].weight[j] = (M3D_FLOAT)(weights[j]) / (M3D_FLOAT)255.0;
  3122. w += model->skin[i].weight[j];
  3123. data = _m3d_getidx(data, model->bi_s, &model->skin[i].boneid[j]);
  3124. }
  3125. }
  3126. }
  3127. /* this can occur if model has more bones than what the importer is configured to handle */
  3128. if (w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0) {
  3129. for (j = 0; j < M3D_NUMBONE; j++)
  3130. model->skin[i].weight[j] /= w;
  3131. }
  3132. }
  3133. }
  3134. } else
  3135. /* material */
  3136. if (M3D_CHUNKMAGIC(data, 'M', 'T', 'R', 'L')) {
  3137. data += sizeof(m3dchunk_t);
  3138. M3D_GETSTR(name);
  3139. M3D_LOG("Material");
  3140. M3D_LOG(name);
  3141. if (model->ci_s < 4 && !model->numcmap) model->errcode = M3D_ERR_CMAP;
  3142. for (i = 0; i < model->nummaterial; i++)
  3143. if (!strcmp(name, model->material[i].name)) {
  3144. model->errcode = M3D_ERR_MTRL;
  3145. M3D_LOG("Multiple definitions for material");
  3146. M3D_LOG(name);
  3147. name = NULL;
  3148. break;
  3149. }
  3150. if (name) {
  3151. i = model->nummaterial++;
  3152. if (model->flags & M3D_FLG_MTLLIB) {
  3153. m = model->material;
  3154. model->material = (m3dm_t *)M3D_MALLOC(model->nummaterial * sizeof(m3dm_t));
  3155. if (!model->material) goto memerr;
  3156. memcpy(model->material, m, (model->nummaterial - 1) * sizeof(m3dm_t));
  3157. if (model->texture) {
  3158. tx = model->texture;
  3159. model->texture = (m3dtx_t *)M3D_MALLOC(model->numtexture * sizeof(m3dtx_t));
  3160. if (!model->texture) goto memerr;
  3161. memcpy(model->texture, tx, model->numtexture * sizeof(m3dm_t));
  3162. }
  3163. model->flags &= ~M3D_FLG_MTLLIB;
  3164. } else {
  3165. model->material = (m3dm_t *)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t));
  3166. if (!model->material) goto memerr;
  3167. }
  3168. m = &model->material[i];
  3169. m->numprop = 0;
  3170. m->name = name;
  3171. m->prop = (m3dp_t *)M3D_MALLOC((len / 2) * sizeof(m3dp_t));
  3172. if (!m->prop) goto memerr;
  3173. while (data < chunk) {
  3174. i = m->numprop++;
  3175. m->prop[i].type = *data++;
  3176. m->prop[i].value.num = 0;
  3177. if (m->prop[i].type >= 128)
  3178. k = m3dpf_map;
  3179. else {
  3180. for (k = 256, j = 0; j < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); j++)
  3181. if (m->prop[i].type == m3d_propertytypes[j].id) {
  3182. k = m3d_propertytypes[j].format;
  3183. break;
  3184. }
  3185. }
  3186. switch (k) {
  3187. case m3dpf_color:
  3188. switch (model->ci_s) {
  3189. case 1:
  3190. m->prop[i].value.color = model->cmap ? model->cmap[data[0]] : 0;
  3191. data++;
  3192. break;
  3193. case 2:
  3194. m->prop[i].value.color = model->cmap ? model->cmap[*((uint16_t *)data)] : 0;
  3195. data += 2;
  3196. break;
  3197. case 4:
  3198. m->prop[i].value.color = *((uint32_t *)data);
  3199. data += 4;
  3200. break;
  3201. }
  3202. break;
  3203. case m3dpf_uint8: m->prop[i].value.num = *data++; break;
  3204. case m3dpf_uint16:
  3205. m->prop[i].value.num = *((uint16_t *)data);
  3206. data += 2;
  3207. break;
  3208. case m3dpf_uint32:
  3209. m->prop[i].value.num = *((uint32_t *)data);
  3210. data += 4;
  3211. break;
  3212. case m3dpf_float:
  3213. m->prop[i].value.fnum = *((float *)data);
  3214. data += 4;
  3215. break;
  3216. case m3dpf_map:
  3217. M3D_GETSTR(name);
  3218. m->prop[i].value.textureid = _m3d_gettx(model, readfilecb, freecb, name);
  3219. if (model->errcode == M3D_ERR_ALLOC) goto memerr;
  3220. /* this error code only returned if readfilecb was specified */
  3221. if (m->prop[i].value.textureid == M3D_UNDEF) {
  3222. M3D_LOG("Texture not found");
  3223. M3D_LOG(m->name);
  3224. m->numprop--;
  3225. }
  3226. break;
  3227. default:
  3228. M3D_LOG("Unknown material property in");
  3229. M3D_LOG(m->name);
  3230. model->errcode = M3D_ERR_UNKPROP;
  3231. data = chunk;
  3232. break;
  3233. }
  3234. }
  3235. m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t));
  3236. if (!m->prop) goto memerr;
  3237. }
  3238. } else
  3239. /* face */
  3240. if (M3D_CHUNKMAGIC(data, 'P', 'R', 'O', 'C')) {
  3241. /* procedural surface */
  3242. M3D_GETSTR(name);
  3243. M3D_LOG("Procedural surface");
  3244. M3D_LOG(name);
  3245. _m3d_getpr(model, readfilecb, freecb, name);
  3246. } else if (M3D_CHUNKMAGIC(data, 'M', 'E', 'S', 'H')) {
  3247. M3D_LOG("Mesh data");
  3248. /* mesh */
  3249. data += sizeof(m3dchunk_t);
  3250. mi = M3D_UNDEF;
  3251. am = model->numface;
  3252. while (data < chunk) {
  3253. k = *data++;
  3254. n = k >> 4;
  3255. k &= 15;
  3256. if (!n) {
  3257. /* use material */
  3258. mi = M3D_UNDEF;
  3259. M3D_GETSTR(name);
  3260. if (name) {
  3261. for (j = 0; j < model->nummaterial; j++)
  3262. if (!strcmp(name, model->material[j].name)) {
  3263. mi = (M3D_INDEX)j;
  3264. break;
  3265. }
  3266. if (mi == M3D_UNDEF) model->errcode = M3D_ERR_MTRL;
  3267. }
  3268. continue;
  3269. }
  3270. if (n != 3) {
  3271. M3D_LOG("Only triangle mesh supported for now");
  3272. model->errcode = M3D_ERR_UNKMESH;
  3273. return model;
  3274. }
  3275. i = model->numface++;
  3276. if (model->numface > am) {
  3277. am = model->numface + 4095;
  3278. model->face = (m3df_t *)M3D_REALLOC(model->face, am * sizeof(m3df_t));
  3279. if (!model->face) goto memerr;
  3280. }
  3281. memset(&model->face[i], 255, sizeof(m3df_t)); /* set all index to -1 by default */
  3282. model->face[i].materialid = mi;
  3283. for (j = 0; j < n; j++) {
  3284. /* vertex */
  3285. data = _m3d_getidx(data, model->vi_s, &model->face[i].vertex[j]);
  3286. /* texcoord */
  3287. if (k & 1)
  3288. data = _m3d_getidx(data, model->ti_s, &model->face[i].texcoord[j]);
  3289. /* normal */
  3290. if (k & 2)
  3291. data = _m3d_getidx(data, model->vi_s, &model->face[i].normal[j]);
  3292. #ifndef M3D_NONORMALS
  3293. if (model->face[i].normal[j] == M3D_UNDEF) neednorm = 1;
  3294. #endif
  3295. }
  3296. }
  3297. model->face = (m3df_t *)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t));
  3298. } else if (M3D_CHUNKMAGIC(data, 'S', 'H', 'P', 'E')) {
  3299. /* mathematical shape */
  3300. data += sizeof(m3dchunk_t);
  3301. M3D_GETSTR(name);
  3302. M3D_LOG("Mathematical Shape");
  3303. M3D_LOG(name);
  3304. i = model->numshape++;
  3305. model->shape = (m3dh_t *)M3D_REALLOC(model->shape, model->numshape * sizeof(m3dh_t));
  3306. if (!model->shape) goto memerr;
  3307. h = &model->shape[i];
  3308. h->numcmd = 0;
  3309. h->cmd = NULL;
  3310. h->name = name;
  3311. h->group = M3D_UNDEF;
  3312. data = _m3d_getidx(data, model->bi_s, &h->group);
  3313. if (h->group != M3D_UNDEF && h->group >= model->numbone) {
  3314. M3D_LOG("Unknown bone id as shape group in shape");
  3315. M3D_LOG(name);
  3316. h->group = M3D_UNDEF;
  3317. model->errcode = M3D_ERR_SHPE;
  3318. }
  3319. while (data < chunk) {
  3320. i = h->numcmd++;
  3321. h->cmd = (m3dc_t *)M3D_REALLOC(h->cmd, h->numcmd * sizeof(m3dc_t));
  3322. if (!h->cmd) goto memerr;
  3323. h->cmd[i].type = *data++;
  3324. if (h->cmd[i].type & 0x80) {
  3325. h->cmd[i].type &= 0x7F;
  3326. h->cmd[i].type |= (*data++ << 7);
  3327. }
  3328. if (h->cmd[i].type >= (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0]))) {
  3329. M3D_LOG("Unknown shape command in");
  3330. M3D_LOG(h->name);
  3331. model->errcode = M3D_ERR_UNKCMD;
  3332. break;
  3333. }
  3334. cd = &m3d_commandtypes[h->cmd[i].type];
  3335. h->cmd[i].arg = (uint32_t *)M3D_MALLOC(cd->p * sizeof(uint32_t));
  3336. if (!h->cmd[i].arg) goto memerr;
  3337. memset(h->cmd[i].arg, 0, cd->p * sizeof(uint32_t));
  3338. for (k = n = 0, l = cd->p; k < l; k++)
  3339. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  3340. case m3dcp_mi_t:
  3341. h->cmd[i].arg[k] = M3D_NOTDEFINED;
  3342. M3D_GETSTR(name);
  3343. if (name) {
  3344. for (n = 0; n < model->nummaterial; n++)
  3345. if (!strcmp(name, model->material[n].name)) {
  3346. h->cmd[i].arg[k] = n;
  3347. break;
  3348. }
  3349. if (h->cmd[i].arg[k] == M3D_NOTDEFINED) model->errcode = M3D_ERR_MTRL;
  3350. }
  3351. break;
  3352. case m3dcp_vc_t:
  3353. f = 0.0f;
  3354. switch (model->vc_s) {
  3355. case 1: f = (float)((int8_t)data[0]) / 127; break;
  3356. case 2: f = (float)(*((int16_t *)(data + 0))) / 32767; break;
  3357. case 4: f = (float)(*((float *)(data + 0))); break;
  3358. case 8: f = (float)(*((double *)(data + 0))); break;
  3359. }
  3360. memcpy(&(h->cmd[i].arg[k]), &f, sizeof(uint32_t));
  3361. data += model->vc_s;
  3362. break;
  3363. case m3dcp_hi_t: data = _m3d_getidx(data, model->hi_s, &h->cmd[i].arg[k]); break;
  3364. case m3dcp_fi_t: data = _m3d_getidx(data, model->fi_s, &h->cmd[i].arg[k]); break;
  3365. case m3dcp_ti_t: data = _m3d_getidx(data, model->ti_s, &h->cmd[i].arg[k]); break;
  3366. case m3dcp_qi_t:
  3367. case m3dcp_vi_t: data = _m3d_getidx(data, model->vi_s, &h->cmd[i].arg[k]); break;
  3368. case m3dcp_i1_t: data = _m3d_getidx(data, 1, &h->cmd[i].arg[k]); break;
  3369. case m3dcp_i2_t: data = _m3d_getidx(data, 2, &h->cmd[i].arg[k]); break;
  3370. case m3dcp_i4_t: data = _m3d_getidx(data, 4, &h->cmd[i].arg[k]); break;
  3371. case m3dcp_va_t:
  3372. data = _m3d_getidx(data, 4, &h->cmd[i].arg[k]);
  3373. n = k + 1;
  3374. l += (h->cmd[i].arg[k] - 1) * (cd->p - k - 1);
  3375. h->cmd[i].arg = (uint32_t *)M3D_REALLOC(h->cmd[i].arg, l * sizeof(uint32_t));
  3376. if (!h->cmd[i].arg) goto memerr;
  3377. memset(&h->cmd[i].arg[k + 1], 0, (l - k - 1) * sizeof(uint32_t));
  3378. break;
  3379. }
  3380. }
  3381. } else
  3382. /* annotation label list */
  3383. if (M3D_CHUNKMAGIC(data, 'L', 'B', 'L', 'S')) {
  3384. data += sizeof(m3dchunk_t);
  3385. M3D_GETSTR(name);
  3386. M3D_GETSTR(lang);
  3387. M3D_LOG("Label list");
  3388. if (name) {
  3389. M3D_LOG(name);
  3390. }
  3391. if (lang) {
  3392. M3D_LOG(lang);
  3393. }
  3394. if (model->ci_s && model->ci_s < 4 && !model->cmap) model->errcode = M3D_ERR_CMAP;
  3395. k = 0;
  3396. switch (model->ci_s) {
  3397. case 1:
  3398. k = model->cmap ? model->cmap[data[0]] : 0;
  3399. data++;
  3400. break;
  3401. case 2:
  3402. k = model->cmap ? model->cmap[*((uint16_t *)data)] : 0;
  3403. data += 2;
  3404. break;
  3405. case 4:
  3406. k = *((uint32_t *)data);
  3407. data += 4;
  3408. break;
  3409. /* case 8: break; */
  3410. }
  3411. reclen = model->vi_s + model->si_s;
  3412. i = model->numlabel;
  3413. model->numlabel += len / reclen;
  3414. model->label = (m3dl_t *)M3D_REALLOC(model->label, model->numlabel * sizeof(m3dl_t));
  3415. if (!model->label) goto memerr;
  3416. memset(&model->label[i], 0, (model->numlabel - i) * sizeof(m3dl_t));
  3417. for (; data < chunk && i < model->numlabel; i++) {
  3418. model->label[i].name = name;
  3419. model->label[i].lang = lang;
  3420. model->label[i].color = k;
  3421. data = _m3d_getidx(data, model->vi_s, &model->label[i].vertexid);
  3422. M3D_GETSTR(model->label[i].text);
  3423. }
  3424. } else
  3425. /* action */
  3426. if (M3D_CHUNKMAGIC(data, 'A', 'C', 'T', 'N')) {
  3427. M3D_LOG("Action");
  3428. i = model->numaction++;
  3429. model->action = (m3da_t *)M3D_REALLOC(model->action, model->numaction * sizeof(m3da_t));
  3430. if (!model->action) goto memerr;
  3431. a = &model->action[i];
  3432. data += sizeof(m3dchunk_t);
  3433. M3D_GETSTR(a->name);
  3434. M3D_LOG(a->name);
  3435. a->numframe = *((uint16_t *)data);
  3436. data += 2;
  3437. if (a->numframe < 1) {
  3438. model->numaction--;
  3439. } else {
  3440. a->durationmsec = *((uint32_t *)data);
  3441. data += 4;
  3442. a->frame = (m3dfr_t *)M3D_MALLOC(a->numframe * sizeof(m3dfr_t));
  3443. if (!a->frame) goto memerr;
  3444. for (i = 0; data < chunk && i < a->numframe; i++) {
  3445. a->frame[i].msec = *((uint32_t *)data);
  3446. data += 4;
  3447. a->frame[i].numtransform = 0;
  3448. a->frame[i].transform = NULL;
  3449. data = _m3d_getidx(data, model->fc_s, &a->frame[i].numtransform);
  3450. if (a->frame[i].numtransform > 0) {
  3451. a->frame[i].transform = (m3dtr_t *)M3D_MALLOC(a->frame[i].numtransform * sizeof(m3dtr_t));
  3452. for (j = 0; j < a->frame[i].numtransform; j++) {
  3453. data = _m3d_getidx(data, model->bi_s, &a->frame[i].transform[j].boneid);
  3454. data = _m3d_getidx(data, model->vi_s, &a->frame[i].transform[j].pos);
  3455. data = _m3d_getidx(data, model->vi_s, &a->frame[i].transform[j].ori);
  3456. }
  3457. }
  3458. }
  3459. }
  3460. } else {
  3461. i = model->numextra++;
  3462. model->extra = (m3dchunk_t **)M3D_REALLOC(model->extra, model->numextra * sizeof(m3dchunk_t *));
  3463. if (!model->extra) goto memerr;
  3464. model->extra[i] = (m3dchunk_t *)data;
  3465. }
  3466. }
  3467. /* calculate normals, normalize skin weights, create bone/vertex cross-references and calculate transform matrices */
  3468. postprocess:
  3469. if (model) {
  3470. M3D_LOG("Post-process");
  3471. #ifdef M3D_PROFILING
  3472. gettimeofday(&tv1, NULL);
  3473. tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;
  3474. tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
  3475. if (tvd.tv_usec < 0) {
  3476. tvd.tv_sec--;
  3477. tvd.tv_usec += 1000000L;
  3478. }
  3479. printf(" Parsing chunks %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec);
  3480. #endif
  3481. #ifndef M3D_NONORMALS
  3482. if (model->numface && model->face && neednorm) {
  3483. /* if they are missing, calculate triangle normals into a temporary buffer */
  3484. norm = (m3dv_t *)M3D_MALLOC(model->numface * sizeof(m3dv_t));
  3485. if (!norm) goto memerr;
  3486. for (i = 0, n = model->numvertex; i < model->numface; i++)
  3487. if (model->face[i].normal[0] == M3D_UNDEF) {
  3488. v0 = &model->vertex[model->face[i].vertex[0]];
  3489. v1 = &model->vertex[model->face[i].vertex[1]];
  3490. v2 = &model->vertex[model->face[i].vertex[2]];
  3491. va.x = v1->x - v0->x;
  3492. va.y = v1->y - v0->y;
  3493. va.z = v1->z - v0->z;
  3494. vb.x = v2->x - v0->x;
  3495. vb.y = v2->y - v0->y;
  3496. vb.z = v2->z - v0->z;
  3497. v0 = &norm[i];
  3498. v0->x = (va.y * vb.z) - (va.z * vb.y);
  3499. v0->y = (va.z * vb.x) - (va.x * vb.z);
  3500. v0->z = (va.x * vb.y) - (va.y * vb.x);
  3501. w = _m3d_rsq((v0->x * v0->x) + (v0->y * v0->y) + (v0->z * v0->z));
  3502. v0->x *= w;
  3503. v0->y *= w;
  3504. v0->z *= w;
  3505. model->face[i].normal[0] = model->face[i].vertex[0] + n;
  3506. model->face[i].normal[1] = model->face[i].vertex[1] + n;
  3507. model->face[i].normal[2] = model->face[i].vertex[2] + n;
  3508. }
  3509. /* this is the fast way, we don't care if a normal is repeated in model->vertex */
  3510. M3D_LOG("Generating normals");
  3511. model->flags |= M3D_FLG_GENNORM;
  3512. model->numvertex <<= 1;
  3513. model->vertex = (m3dv_t *)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t));
  3514. if (!model->vertex) goto memerr;
  3515. memset(&model->vertex[n], 0, n * sizeof(m3dv_t));
  3516. for (i = 0; i < model->numface; i++)
  3517. for (j = 0; j < 3; j++) {
  3518. v0 = &model->vertex[model->face[i].vertex[j] + n];
  3519. v0->x += norm[i].x;
  3520. v0->y += norm[i].y;
  3521. v0->z += norm[i].z;
  3522. }
  3523. /* for each vertex, take the average of the temporary normals and use that */
  3524. for (i = 0, v0 = &model->vertex[n]; i < n; i++, v0++) {
  3525. w = _m3d_rsq((v0->x * v0->x) + (v0->y * v0->y) + (v0->z * v0->z));
  3526. v0->x *= w;
  3527. v0->y *= w;
  3528. v0->z *= w;
  3529. v0->skinid = M3D_UNDEF;
  3530. }
  3531. M3D_FREE(norm);
  3532. }
  3533. #endif
  3534. if (model->numbone && model->bone && model->numskin && model->skin && model->numvertex && model->vertex) {
  3535. #ifndef M3D_NOWEIGHTS
  3536. M3D_LOG("Generating weight cross-reference");
  3537. for (i = 0; i < model->numvertex; i++) {
  3538. if (model->vertex[i].skinid < model->numskin) {
  3539. sk = &model->skin[model->vertex[i].skinid];
  3540. w = (M3D_FLOAT)0.0;
  3541. for (j = 0; j < M3D_NUMBONE && sk->boneid[j] != M3D_UNDEF && sk->weight[j] > (M3D_FLOAT)0.0; j++)
  3542. w += sk->weight[j];
  3543. for (j = 0; j < M3D_NUMBONE && sk->boneid[j] != M3D_UNDEF && sk->weight[j] > (M3D_FLOAT)0.0; j++) {
  3544. sk->weight[j] /= w;
  3545. b = &model->bone[sk->boneid[j]];
  3546. k = b->numweight++;
  3547. b->weight = (m3dw_t *)M3D_REALLOC(b->weight, b->numweight * sizeof(m3da_t));
  3548. if (!b->weight) goto memerr;
  3549. b->weight[k].vertexid = i;
  3550. b->weight[k].weight = sk->weight[j];
  3551. }
  3552. }
  3553. }
  3554. #endif
  3555. #ifndef M3D_NOANIMATION
  3556. M3D_LOG("Calculating bone transformation matrices");
  3557. for (i = 0; i < model->numbone; i++) {
  3558. b = &model->bone[i];
  3559. if (model->bone[i].parent == M3D_UNDEF) {
  3560. _m3d_mat((M3D_FLOAT *)&b->mat4, &model->vertex[b->pos], &model->vertex[b->ori]);
  3561. } else {
  3562. _m3d_mat((M3D_FLOAT *)&r, &model->vertex[b->pos], &model->vertex[b->ori]);
  3563. _m3d_mul((M3D_FLOAT *)&b->mat4, (M3D_FLOAT *)&model->bone[b->parent].mat4, (M3D_FLOAT *)&r);
  3564. }
  3565. }
  3566. for (i = 0; i < model->numbone; i++)
  3567. _m3d_inv((M3D_FLOAT *)&model->bone[i].mat4);
  3568. #endif
  3569. }
  3570. #ifdef M3D_PROFILING
  3571. gettimeofday(&tv0, NULL);
  3572. tvd.tv_sec = tv0.tv_sec - tv1.tv_sec;
  3573. tvd.tv_usec = tv0.tv_usec - tv1.tv_usec;
  3574. if (tvd.tv_usec < 0) {
  3575. tvd.tv_sec--;
  3576. tvd.tv_usec += 1000000L;
  3577. }
  3578. printf(" Post-process %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec);
  3579. #endif
  3580. }
  3581. return model;
  3582. }
  3583. /**
  3584. * Calculates skeletons for animation frames, returns a working copy (should be freed after use)
  3585. */
  3586. m3dtr_t *m3d_frame(m3d_t *model, M3D_INDEX actionid, M3D_INDEX frameid, m3dtr_t *skeleton) {
  3587. unsigned int i;
  3588. M3D_INDEX s = frameid;
  3589. m3dfr_t *fr;
  3590. if (!model || !model->numbone || !model->bone || (actionid != M3D_UNDEF && (!model->action || actionid >= model->numaction || frameid >= model->action[actionid].numframe))) {
  3591. model->errcode = M3D_ERR_UNKFRAME;
  3592. return skeleton;
  3593. }
  3594. model->errcode = M3D_SUCCESS;
  3595. if (!skeleton) {
  3596. skeleton = (m3dtr_t *)M3D_MALLOC(model->numbone * sizeof(m3dtr_t));
  3597. if (!skeleton) {
  3598. model->errcode = M3D_ERR_ALLOC;
  3599. return NULL;
  3600. }
  3601. goto gen;
  3602. }
  3603. if (actionid == M3D_UNDEF || !frameid) {
  3604. gen:
  3605. s = 0;
  3606. for (i = 0; i < model->numbone; i++) {
  3607. skeleton[i].boneid = i;
  3608. skeleton[i].pos = model->bone[i].pos;
  3609. skeleton[i].ori = model->bone[i].ori;
  3610. }
  3611. }
  3612. if (actionid < model->numaction && (frameid || !model->action[actionid].frame[0].msec)) {
  3613. for (; s <= frameid; s++) {
  3614. fr = &model->action[actionid].frame[s];
  3615. for (i = 0; i < fr->numtransform; i++) {
  3616. skeleton[fr->transform[i].boneid].pos = fr->transform[i].pos;
  3617. skeleton[fr->transform[i].boneid].ori = fr->transform[i].ori;
  3618. }
  3619. }
  3620. }
  3621. return skeleton;
  3622. }
  3623. #ifndef M3D_NOANIMATION
  3624. /**
  3625. * Returns interpolated animation-pose, a working copy (should be freed after use)
  3626. */
  3627. m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec) {
  3628. unsigned int i, j, l;
  3629. M3D_FLOAT r[16], t, c, d, s;
  3630. m3db_t *ret;
  3631. m3dv_t *v, *p, *f;
  3632. m3dtr_t *tmp;
  3633. m3dfr_t *fr;
  3634. if (!model || !model->numbone || !model->bone) {
  3635. model->errcode = M3D_ERR_UNKFRAME;
  3636. return NULL;
  3637. }
  3638. ret = (m3db_t *)M3D_MALLOC(model->numbone * sizeof(m3db_t));
  3639. if (!ret) {
  3640. model->errcode = M3D_ERR_ALLOC;
  3641. return NULL;
  3642. }
  3643. memcpy(ret, model->bone, model->numbone * sizeof(m3db_t));
  3644. for (i = 0; i < model->numbone; i++)
  3645. _m3d_inv((M3D_FLOAT *)&ret[i].mat4);
  3646. if (!model->action || actionid >= model->numaction) {
  3647. model->errcode = M3D_ERR_UNKFRAME;
  3648. return ret;
  3649. }
  3650. msec %= model->action[actionid].durationmsec;
  3651. model->errcode = M3D_SUCCESS;
  3652. fr = &model->action[actionid].frame[0];
  3653. for (j = l = 0; j < model->action[actionid].numframe && model->action[actionid].frame[j].msec <= msec; j++) {
  3654. fr = &model->action[actionid].frame[j];
  3655. l = fr->msec;
  3656. for (i = 0; i < fr->numtransform; i++) {
  3657. ret[fr->transform[i].boneid].pos = fr->transform[i].pos;
  3658. ret[fr->transform[i].boneid].ori = fr->transform[i].ori;
  3659. }
  3660. }
  3661. if (l != msec) {
  3662. model->vertex = (m3dv_t *)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t));
  3663. if (!model->vertex) {
  3664. free(ret);
  3665. model->errcode = M3D_ERR_ALLOC;
  3666. return NULL;
  3667. }
  3668. tmp = (m3dtr_t *)M3D_MALLOC(model->numbone * sizeof(m3dtr_t));
  3669. if (tmp) {
  3670. for (i = 0; i < model->numbone; i++) {
  3671. tmp[i].pos = ret[i].pos;
  3672. tmp[i].ori = ret[i].ori;
  3673. }
  3674. fr = &model->action[actionid].frame[j % model->action[actionid].numframe];
  3675. t = l >= fr->msec ? (M3D_FLOAT)1.0 : (M3D_FLOAT)(msec - l) / (M3D_FLOAT)(fr->msec - l);
  3676. for (i = 0; i < fr->numtransform; i++) {
  3677. tmp[fr->transform[i].boneid].pos = fr->transform[i].pos;
  3678. tmp[fr->transform[i].boneid].ori = fr->transform[i].ori;
  3679. }
  3680. for (i = 0, j = model->numvertex; i < model->numbone; i++) {
  3681. /* interpolation of position */
  3682. if (ret[i].pos != tmp[i].pos) {
  3683. p = &model->vertex[ret[i].pos];
  3684. f = &model->vertex[tmp[i].pos];
  3685. v = &model->vertex[j];
  3686. v->x = p->x + t * (f->x - p->x);
  3687. v->y = p->y + t * (f->y - p->y);
  3688. v->z = p->z + t * (f->z - p->z);
  3689. ret[i].pos = j++;
  3690. }
  3691. /* interpolation of orientation */
  3692. if (ret[i].ori != tmp[i].ori) {
  3693. p = &model->vertex[ret[i].ori];
  3694. f = &model->vertex[tmp[i].ori];
  3695. v = &model->vertex[j];
  3696. d = p->w * f->w + p->x * f->x + p->y * f->y + p->z * f->z;
  3697. if (d < 0) {
  3698. d = -d;
  3699. s = (M3D_FLOAT)-1.0;
  3700. } else
  3701. s = (M3D_FLOAT)1.0;
  3702. #if 0
  3703. /* don't use SLERP, requires two more variables, libm linkage and it is slow (but nice) */
  3704. a = (M3D_FLOAT)1.0 - t; b = t;
  3705. if(d < (M3D_FLOAT)0.999999) { c = acosf(d); b = 1 / sinf(c); a = sinf(a * c) * b; b *= sinf(t * c) * s; }
  3706. v->x = p->x * a + f->x * b;
  3707. v->y = p->y * a + f->y * b;
  3708. v->z = p->z * a + f->z * b;
  3709. v->w = p->w * a + f->w * b;
  3710. #else
  3711. /* approximated NLERP, original approximation by Arseny Kapoulkine, heavily optimized by me */
  3712. c = t - (M3D_FLOAT)0.5;
  3713. t += t * c * (t - (M3D_FLOAT)1.0) * (((M3D_FLOAT)1.0904 + d * ((M3D_FLOAT)-3.2452 + d * ((M3D_FLOAT)3.55645 - d * (M3D_FLOAT)1.43519))) * c * c + ((M3D_FLOAT)0.848013 + d * ((M3D_FLOAT)-1.06021 + d * (M3D_FLOAT)0.215638)));
  3714. v->x = p->x + t * (s * f->x - p->x);
  3715. v->y = p->y + t * (s * f->y - p->y);
  3716. v->z = p->z + t * (s * f->z - p->z);
  3717. v->w = p->w + t * (s * f->w - p->w);
  3718. d = _m3d_rsq(v->w * v->w + v->x * v->x + v->y * v->y + v->z * v->z);
  3719. v->x *= d;
  3720. v->y *= d;
  3721. v->z *= d;
  3722. v->w *= d;
  3723. #endif
  3724. ret[i].ori = j++;
  3725. }
  3726. }
  3727. M3D_FREE(tmp);
  3728. }
  3729. }
  3730. for (i = 0; i < model->numbone; i++) {
  3731. if (ret[i].parent == M3D_UNDEF) {
  3732. _m3d_mat((M3D_FLOAT *)&ret[i].mat4, &model->vertex[ret[i].pos], &model->vertex[ret[i].ori]);
  3733. } else {
  3734. _m3d_mat((M3D_FLOAT *)&r, &model->vertex[ret[i].pos], &model->vertex[ret[i].ori]);
  3735. _m3d_mul((M3D_FLOAT *)&ret[i].mat4, (M3D_FLOAT *)&ret[ret[i].parent].mat4, (M3D_FLOAT *)&r);
  3736. }
  3737. }
  3738. return ret;
  3739. }
  3740. #endif /* M3D_NOANIMATION */
  3741. #endif /* M3D_IMPLEMENTATION */
  3742. #if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER))
  3743. /**
  3744. * Free the in-memory model
  3745. */
  3746. void m3d_free(m3d_t *model) {
  3747. unsigned int i, j;
  3748. if (!model) return;
  3749. /* if model imported from ASCII, we have to free all strings as well */
  3750. if (model->flags & M3D_FLG_FREESTR) {
  3751. if (model->name) M3D_FREE(model->name);
  3752. if (model->license) M3D_FREE(model->license);
  3753. if (model->author) M3D_FREE(model->author);
  3754. if (model->desc) M3D_FREE(model->desc);
  3755. if (model->bone)
  3756. for (i = 0; i < model->numbone; i++)
  3757. if (model->bone[i].name)
  3758. M3D_FREE(model->bone[i].name);
  3759. if (model->shape)
  3760. for (i = 0; i < model->numshape; i++)
  3761. if (model->shape[i].name)
  3762. M3D_FREE(model->shape[i].name);
  3763. if (model->material)
  3764. for (i = 0; i < model->nummaterial; i++)
  3765. if (model->material[i].name)
  3766. M3D_FREE(model->material[i].name);
  3767. if (model->action)
  3768. for (i = 0; i < model->numaction; i++)
  3769. if (model->action[i].name)
  3770. M3D_FREE(model->action[i].name);
  3771. if (model->texture)
  3772. for (i = 0; i < model->numtexture; i++)
  3773. if (model->texture[i].name)
  3774. M3D_FREE(model->texture[i].name);
  3775. if (model->inlined)
  3776. for (i = 0; i < model->numinlined; i++) {
  3777. if (model->inlined[i].name)
  3778. M3D_FREE(model->inlined[i].name);
  3779. if (model->inlined[i].data)
  3780. M3D_FREE(model->inlined[i].data);
  3781. }
  3782. if (model->extra)
  3783. for (i = 0; i < model->numextra; i++)
  3784. if (model->extra[i])
  3785. M3D_FREE(model->extra[i]);
  3786. if (model->label)
  3787. for (i = 0; i < model->numlabel; i++) {
  3788. if (model->label[i].name) {
  3789. for (j = i + 1; j < model->numlabel; j++)
  3790. if (model->label[j].name == model->label[i].name)
  3791. model->label[j].name = NULL;
  3792. M3D_FREE(model->label[i].name);
  3793. }
  3794. if (model->label[i].lang) {
  3795. for (j = i + 1; j < model->numlabel; j++)
  3796. if (model->label[j].lang == model->label[i].lang)
  3797. model->label[j].lang = NULL;
  3798. M3D_FREE(model->label[i].lang);
  3799. }
  3800. if (model->label[i].text)
  3801. M3D_FREE(model->label[i].text);
  3802. }
  3803. if (model->preview.data)
  3804. M3D_FREE(model->preview.data);
  3805. }
  3806. if (model->flags & M3D_FLG_FREERAW) M3D_FREE(model->raw);
  3807. if (model->tmap) M3D_FREE(model->tmap);
  3808. if (model->bone) {
  3809. for (i = 0; i < model->numbone; i++)
  3810. if (model->bone[i].weight)
  3811. M3D_FREE(model->bone[i].weight);
  3812. M3D_FREE(model->bone);
  3813. }
  3814. if (model->skin) M3D_FREE(model->skin);
  3815. if (model->vertex) M3D_FREE(model->vertex);
  3816. if (model->face) M3D_FREE(model->face);
  3817. if (model->shape) {
  3818. for (i = 0; i < model->numshape; i++) {
  3819. if (model->shape[i].cmd) {
  3820. for (j = 0; j < model->shape[i].numcmd; j++)
  3821. if (model->shape[i].cmd[j].arg) M3D_FREE(model->shape[i].cmd[j].arg);
  3822. M3D_FREE(model->shape[i].cmd);
  3823. }
  3824. }
  3825. M3D_FREE(model->shape);
  3826. }
  3827. if (model->material && !(model->flags & M3D_FLG_MTLLIB)) {
  3828. for (i = 0; i < model->nummaterial; i++)
  3829. if (model->material[i].prop) M3D_FREE(model->material[i].prop);
  3830. M3D_FREE(model->material);
  3831. }
  3832. if (model->texture) {
  3833. for (i = 0; i < model->numtexture; i++)
  3834. if (model->texture[i].d) M3D_FREE(model->texture[i].d);
  3835. M3D_FREE(model->texture);
  3836. }
  3837. if (model->action) {
  3838. for (i = 0; i < model->numaction; i++) {
  3839. if (model->action[i].frame) {
  3840. for (j = 0; j < model->action[i].numframe; j++)
  3841. if (model->action[i].frame[j].transform) M3D_FREE(model->action[i].frame[j].transform);
  3842. M3D_FREE(model->action[i].frame);
  3843. }
  3844. }
  3845. M3D_FREE(model->action);
  3846. }
  3847. if (model->label) M3D_FREE(model->label);
  3848. if (model->inlined) M3D_FREE(model->inlined);
  3849. if (model->extra) M3D_FREE(model->extra);
  3850. free(model);
  3851. }
  3852. #endif
  3853. #ifdef M3D_EXPORTER
  3854. typedef struct {
  3855. char *str;
  3856. uint32_t offs;
  3857. } m3dstr_t;
  3858. typedef struct {
  3859. m3dti_t data;
  3860. M3D_INDEX oldidx;
  3861. M3D_INDEX newidx;
  3862. } m3dtisave_t;
  3863. typedef struct {
  3864. m3dv_t data;
  3865. M3D_INDEX oldidx;
  3866. M3D_INDEX newidx;
  3867. unsigned char norm;
  3868. } m3dvsave_t;
  3869. typedef struct {
  3870. m3ds_t data;
  3871. M3D_INDEX oldidx;
  3872. M3D_INDEX newidx;
  3873. } m3dssave_t;
  3874. typedef struct {
  3875. m3df_t data;
  3876. int group;
  3877. uint8_t opacity;
  3878. } m3dfsave_t;
  3879. /* create unique list of strings */
  3880. static m3dstr_t *_m3d_addstr(m3dstr_t *str, uint32_t *numstr, char *s) {
  3881. uint32_t i;
  3882. if (!s || !*s) return str;
  3883. if (str) {
  3884. for (i = 0; i < *numstr; i++)
  3885. if (str[i].str == s || !strcmp(str[i].str, s)) return str;
  3886. }
  3887. str = (m3dstr_t *)M3D_REALLOC(str, ((*numstr) + 1) * sizeof(m3dstr_t));
  3888. str[*numstr].str = s;
  3889. str[*numstr].offs = 0;
  3890. (*numstr)++;
  3891. return str;
  3892. }
  3893. /* add strings to header */
  3894. m3dhdr_t *_m3d_addhdr(m3dhdr_t *h, m3dstr_t *s) {
  3895. int i;
  3896. char *safe = _m3d_safestr(s->str, 0);
  3897. i = (int)strlen(safe);
  3898. h = (m3dhdr_t *)M3D_REALLOC(h, h->length + i + 1);
  3899. if (!h) {
  3900. M3D_FREE(safe);
  3901. return NULL;
  3902. }
  3903. memcpy((uint8_t *)h + h->length, safe, i + 1);
  3904. s->offs = h->length - 16;
  3905. h->length += i + 1;
  3906. M3D_FREE(safe);
  3907. return h;
  3908. }
  3909. /* return offset of string */
  3910. static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s) {
  3911. uint32_t i;
  3912. char *safe;
  3913. if (!s || !*s) return 0;
  3914. if (str) {
  3915. safe = _m3d_safestr(s, 0);
  3916. if (!safe) return 0;
  3917. if (!*safe) {
  3918. free(safe);
  3919. return 0;
  3920. }
  3921. for (i = 0; i < numstr; i++)
  3922. if (!strcmp(str[i].str, s)) {
  3923. free(safe);
  3924. return str[i].offs;
  3925. }
  3926. free(safe);
  3927. }
  3928. return 0;
  3929. }
  3930. /* compare to faces by their material */
  3931. static int _m3d_facecmp(const void *a, const void *b) {
  3932. const m3dfsave_t *A = (const m3dfsave_t *)a, *B = (const m3dfsave_t *)b;
  3933. return A->group != B->group ? A->group - B->group : (A->opacity != B->opacity ? (int)B->opacity - (int)A->opacity : (int)A->data.materialid - (int)B->data.materialid);
  3934. }
  3935. /* compare face groups */
  3936. static int _m3d_grpcmp(const void *a, const void *b) {
  3937. return *((uint32_t *)a) - *((uint32_t *)b);
  3938. }
  3939. /* compare UVs */
  3940. static int _m3d_ticmp(const void *a, const void *b) {
  3941. return memcmp(a, b, sizeof(m3dti_t));
  3942. }
  3943. /* compare skin groups */
  3944. static int _m3d_skincmp(const void *a, const void *b) {
  3945. return memcmp(a, b, sizeof(m3ds_t));
  3946. }
  3947. /* compare vertices */
  3948. static int _m3d_vrtxcmp(const void *a, const void *b) {
  3949. int c = memcmp(a, b, 3 * sizeof(M3D_FLOAT));
  3950. if (c) return c;
  3951. c = ((m3dvsave_t *)a)->norm - ((m3dvsave_t *)b)->norm;
  3952. if (c) return c;
  3953. return memcmp(a, b, sizeof(m3dv_t));
  3954. }
  3955. /* compare labels */
  3956. static _inline int _m3d_strcmp(char *a, char *b) {
  3957. if (a == NULL && b != NULL) return -1;
  3958. if (a != NULL && b == NULL) return 1;
  3959. if (a == NULL && b == NULL) return 0;
  3960. return strcmp(a, b);
  3961. }
  3962. static int _m3d_lblcmp(const void *a, const void *b) {
  3963. const m3dl_t *A = (const m3dl_t *)a, *B = (const m3dl_t *)b;
  3964. int c = _m3d_strcmp(A->lang, B->lang);
  3965. if (!c) c = _m3d_strcmp(A->name, B->name);
  3966. if (!c) c = _m3d_strcmp(A->text, B->text);
  3967. return c;
  3968. }
  3969. /* compare two colors by HSV value */
  3970. _inline static int _m3d_cmapcmp(const void *a, const void *b) {
  3971. uint8_t *A = (uint8_t *)a, *B = (uint8_t *)b;
  3972. _register int m, vA, vB;
  3973. /* get HSV value for A */
  3974. m = A[2] < A[1] ? A[2] : A[1];
  3975. if (A[0] < m) m = A[0];
  3976. vA = A[2] > A[1] ? A[2] : A[1];
  3977. if (A[0] > vA) vA = A[0];
  3978. /* get HSV value for B */
  3979. m = B[2] < B[1] ? B[2] : B[1];
  3980. if (B[0] < m) m = B[0];
  3981. vB = B[2] > B[1] ? B[2] : B[1];
  3982. if (B[0] > vB) vB = B[0];
  3983. return vA - vB;
  3984. }
  3985. /* create sorted list of colors */
  3986. static uint32_t *_m3d_addcmap(uint32_t *cmap, uint32_t *numcmap, uint32_t color) {
  3987. uint32_t i;
  3988. if (cmap) {
  3989. for (i = 0; i < *numcmap; i++)
  3990. if (cmap[i] == color) return cmap;
  3991. }
  3992. cmap = (uint32_t *)M3D_REALLOC(cmap, ((*numcmap) + 1) * sizeof(uint32_t));
  3993. for (i = 0; i < *numcmap && _m3d_cmapcmp(&color, &cmap[i]) > 0; i++)
  3994. ;
  3995. if (i < *numcmap) memmove(&cmap[i + 1], &cmap[i], ((*numcmap) - i) * sizeof(uint32_t));
  3996. cmap[i] = color;
  3997. (*numcmap)++;
  3998. return cmap;
  3999. }
  4000. /* look up a color and return its index */
  4001. static uint32_t _m3d_cmapidx(uint32_t *cmap, uint32_t numcmap, uint32_t color) {
  4002. uint32_t i;
  4003. if (numcmap >= 65536)
  4004. return color;
  4005. for (i = 0; i < numcmap; i++)
  4006. if (cmap[i] == color) return i;
  4007. return 0;
  4008. }
  4009. /* add index to output */
  4010. static unsigned char *_m3d_addidx(unsigned char *out, char type, uint32_t idx) {
  4011. switch (type) {
  4012. case 1: *out++ = (uint8_t)(idx); break;
  4013. case 2:
  4014. *((uint16_t *)out) = (uint16_t)(idx);
  4015. out += 2;
  4016. break;
  4017. case 4:
  4018. *((uint32_t *)out) = (uint32_t)(idx);
  4019. out += 4;
  4020. break;
  4021. /* case 0: case 8: break; */
  4022. }
  4023. return out;
  4024. }
  4025. /* round a vertex position */
  4026. static void _m3d_round(int quality, m3dv_t *src, m3dv_t *dst) {
  4027. _register int t;
  4028. /* copy additional attributes */
  4029. if (src != dst) memcpy(dst, src, sizeof(m3dv_t));
  4030. /* round according to quality */
  4031. switch (quality) {
  4032. case M3D_EXP_INT8:
  4033. t = (int)(src->x * 127 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  4034. dst->x = (M3D_FLOAT)t / (M3D_FLOAT)127.0;
  4035. t = (int)(src->y * 127 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  4036. dst->y = (M3D_FLOAT)t / (M3D_FLOAT)127.0;
  4037. t = (int)(src->z * 127 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  4038. dst->z = (M3D_FLOAT)t / (M3D_FLOAT)127.0;
  4039. t = (int)(src->w * 127 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  4040. dst->w = (M3D_FLOAT)t / (M3D_FLOAT)127.0;
  4041. break;
  4042. case M3D_EXP_INT16:
  4043. t = (int)(src->x * 32767 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  4044. dst->x = (M3D_FLOAT)t / (M3D_FLOAT)32767.0;
  4045. t = (int)(src->y * 32767 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  4046. dst->y = (M3D_FLOAT)t / (M3D_FLOAT)32767.0;
  4047. t = (int)(src->z * 32767 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  4048. dst->z = (M3D_FLOAT)t / (M3D_FLOAT)32767.0;
  4049. t = (int)(src->w * 32767 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  4050. dst->w = (M3D_FLOAT)t / (M3D_FLOAT)32767.0;
  4051. break;
  4052. }
  4053. if (dst->x == (M3D_FLOAT)-0.0) dst->x = (M3D_FLOAT)0.0;
  4054. if (dst->y == (M3D_FLOAT)-0.0) dst->y = (M3D_FLOAT)0.0;
  4055. if (dst->z == (M3D_FLOAT)-0.0) dst->z = (M3D_FLOAT)0.0;
  4056. if (dst->w == (M3D_FLOAT)-0.0) dst->w = (M3D_FLOAT)0.0;
  4057. }
  4058. /* add a bone to ascii output */
  4059. static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX parent, uint32_t level, M3D_INDEX *vrtxidx) {
  4060. uint32_t i, j;
  4061. char *sn;
  4062. if (level > M3D_BONEMAXLEVEL || !bone) return ptr;
  4063. for (i = 0; i < numbone; i++) {
  4064. if (bone[i].parent == parent) {
  4065. for (j = 0; j < level; j++)
  4066. *ptr++ = '/';
  4067. sn = _m3d_safestr(bone[i].name, 0);
  4068. ptr += sprintf(ptr, "%d %d %s\r\n", vrtxidx[bone[i].pos], vrtxidx[bone[i].ori], sn);
  4069. M3D_FREE(sn);
  4070. ptr = _m3d_prtbone(ptr, bone, numbone, i, level + 1, vrtxidx);
  4071. }
  4072. }
  4073. return ptr;
  4074. }
  4075. /**
  4076. * Function to encode an in-memory model into on storage Model 3D format
  4077. */
  4078. unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size) {
  4079. const char *ol;
  4080. char *ptr;
  4081. char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s, fi_s;
  4082. char *sn = NULL, *sl = NULL, *sa = NULL, *sd = NULL;
  4083. unsigned char *out = NULL, *z = NULL, weights[M3D_NUMBONE], *norm = NULL;
  4084. unsigned int i = 0, j = 0, k = 0, l = 0, n = 0, len = 0, chunklen = 0, *length = NULL;
  4085. M3D_FLOAT scale = (M3D_FLOAT)0.0, min_x, max_x, min_y, max_y, min_z, max_z;
  4086. M3D_INDEX last, *vrtxidx = NULL, *mtrlidx = NULL, *tmapidx = NULL, *skinidx = NULL;
  4087. uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, maxvrtx = 0, numtmap = 0, maxtmap = 0, numproc = 0;
  4088. uint32_t numskin = 0, maxskin = 0, numstr = 0, maxt = 0, maxbone = 0, numgrp = 0, maxgrp = 0, *grpidx = NULL;
  4089. uint8_t *opa = nullptr;
  4090. m3dcd_t *cd;
  4091. m3dc_t *cmd;
  4092. m3dstr_t *str = NULL;
  4093. m3dvsave_t *vrtx = NULL, vertex;
  4094. m3dtisave_t *tmap = NULL, tcoord;
  4095. m3dssave_t *skin = NULL, sk;
  4096. m3dfsave_t *face = NULL;
  4097. m3dhdr_t *h = NULL;
  4098. m3dm_t *m;
  4099. m3da_t *a;
  4100. if (!model) {
  4101. if (size) *size = 0;
  4102. return NULL;
  4103. }
  4104. model->errcode = M3D_SUCCESS;
  4105. if (flags & M3D_EXP_ASCII) quality = M3D_EXP_DOUBLE;
  4106. vrtxidx = (M3D_INDEX *)M3D_MALLOC(model->numvertex * sizeof(M3D_INDEX));
  4107. if (!vrtxidx) goto memerr;
  4108. memset(vrtxidx, 255, model->numvertex * sizeof(M3D_INDEX));
  4109. if (model->numvertex && !(flags & M3D_EXP_NONORMAL)) {
  4110. norm = (unsigned char *)M3D_MALLOC(model->numvertex * sizeof(unsigned char));
  4111. if (!norm) goto memerr;
  4112. memset(norm, 0, model->numvertex * sizeof(unsigned char));
  4113. }
  4114. if (model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) {
  4115. mtrlidx = (M3D_INDEX *)M3D_MALLOC(model->nummaterial * sizeof(M3D_INDEX));
  4116. if (!mtrlidx) goto memerr;
  4117. memset(mtrlidx, 255, model->nummaterial * sizeof(M3D_INDEX));
  4118. opa = (uint8_t *)M3D_MALLOC(model->nummaterial * 2 * sizeof(M3D_INDEX));
  4119. if (!opa) goto memerr;
  4120. memset(opa, 255, model->nummaterial * 2 * sizeof(M3D_INDEX));
  4121. }
  4122. if (model->numtmap && !(flags & M3D_EXP_NOTXTCRD)) {
  4123. tmapidx = (M3D_INDEX *)M3D_MALLOC(model->numtmap * sizeof(M3D_INDEX));
  4124. if (!tmapidx) goto memerr;
  4125. memset(tmapidx, 255, model->numtmap * sizeof(M3D_INDEX));
  4126. }
  4127. /** collect array elements that are actually referenced **/
  4128. if (!(flags & M3D_EXP_NOFACE)) {
  4129. /* face */
  4130. if (model->numface && model->face) {
  4131. M3D_LOG("Processing mesh face");
  4132. face = (m3dfsave_t *)M3D_MALLOC(model->numface * sizeof(m3dfsave_t));
  4133. if (!face) goto memerr;
  4134. for (i = 0; i < model->numface; i++) {
  4135. memcpy(&face[i].data, &model->face[i], sizeof(m3df_t));
  4136. face[i].group = 0;
  4137. face[i].opacity = 255;
  4138. if (!(flags & M3D_EXP_NOMATERIAL) && model->face[i].materialid < model->nummaterial) {
  4139. if (model->material[model->face[i].materialid].numprop) {
  4140. mtrlidx[model->face[i].materialid] = 0;
  4141. if (opa[model->face[i].materialid * 2]) {
  4142. m = &model->material[model->face[i].materialid];
  4143. for (j = 0; j < m->numprop; j++)
  4144. if (m->prop[j].type == m3dp_Kd) {
  4145. opa[model->face[i].materialid * 2 + 1] = ((uint8_t *)&m->prop[j].value.color)[3];
  4146. break;
  4147. }
  4148. for (j = 0; j < m->numprop; j++)
  4149. if (m->prop[j].type == m3dp_d) {
  4150. opa[model->face[i].materialid * 2 + 1] = (uint8_t)(m->prop[j].value.fnum * 255);
  4151. break;
  4152. }
  4153. opa[model->face[i].materialid * 2] = 0;
  4154. }
  4155. face[i].opacity = opa[model->face[i].materialid * 2 + 1];
  4156. } else
  4157. face[i].data.materialid = M3D_UNDEF;
  4158. }
  4159. for (j = 0; j < 3; j++) {
  4160. k = model->face[i].vertex[j];
  4161. if (k < model->numvertex)
  4162. vrtxidx[k] = 0;
  4163. if (!(flags & M3D_EXP_NOCMAP)) {
  4164. cmap = _m3d_addcmap(cmap, &numcmap, model->vertex[k].color);
  4165. if (!cmap) goto memerr;
  4166. }
  4167. k = model->face[i].normal[j];
  4168. if (k < model->numvertex && !(flags & M3D_EXP_NONORMAL)) {
  4169. vrtxidx[k] = 0;
  4170. norm[k] = 1;
  4171. }
  4172. k = model->face[i].texcoord[j];
  4173. if (k < model->numtmap && !(flags & M3D_EXP_NOTXTCRD))
  4174. tmapidx[k] = 0;
  4175. }
  4176. /* convert from CW to CCW */
  4177. if (flags & M3D_EXP_IDOSUCK) {
  4178. j = face[i].data.vertex[1];
  4179. face[i].data.vertex[1] = face[i].data.vertex[2];
  4180. face[i].data.vertex[2] = face[i].data.vertex[1];
  4181. j = face[i].data.normal[1];
  4182. face[i].data.normal[1] = face[i].data.normal[2];
  4183. face[i].data.normal[2] = face[i].data.normal[1];
  4184. j = face[i].data.texcoord[1];
  4185. face[i].data.texcoord[1] = face[i].data.texcoord[2];
  4186. face[i].data.texcoord[2] = face[i].data.texcoord[1];
  4187. }
  4188. }
  4189. }
  4190. if (model->numshape && model->shape) {
  4191. M3D_LOG("Processing shape face");
  4192. for (i = 0; i < model->numshape; i++) {
  4193. if (!model->shape[i].numcmd) continue;
  4194. str = _m3d_addstr(str, &numstr, model->shape[i].name);
  4195. if (!str) goto memerr;
  4196. for (j = 0; j < model->shape[i].numcmd; j++) {
  4197. cmd = &model->shape[i].cmd[j];
  4198. if (cmd->type >= (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0])) || !cmd->arg)
  4199. continue;
  4200. if (cmd->type == m3dc_mesh) {
  4201. if (numgrp + 2 < maxgrp) {
  4202. maxgrp += 1024;
  4203. grpidx = (uint32_t *)realloc(grpidx, maxgrp * sizeof(uint32_t));
  4204. if (!grpidx) goto memerr;
  4205. if (!numgrp) {
  4206. grpidx[0] = 0;
  4207. grpidx[1] = model->numface;
  4208. numgrp += 2;
  4209. }
  4210. }
  4211. grpidx[numgrp + 0] = cmd->arg[0];
  4212. grpidx[numgrp + 1] = cmd->arg[0] + cmd->arg[1];
  4213. numgrp += 2;
  4214. }
  4215. cd = &m3d_commandtypes[cmd->type];
  4216. for (k = n = 0, l = cd->p; k < l; k++)
  4217. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  4218. case m3dcp_mi_t:
  4219. if (!(flags & M3D_EXP_NOMATERIAL) && cmd->arg[k] < model->nummaterial)
  4220. mtrlidx[cmd->arg[k]] = 0;
  4221. break;
  4222. case m3dcp_ti_t:
  4223. if (!(flags & M3D_EXP_NOTXTCRD) && cmd->arg[k] < model->numtmap)
  4224. tmapidx[cmd->arg[k]] = 0;
  4225. break;
  4226. case m3dcp_qi_t:
  4227. case m3dcp_vi_t:
  4228. if (cmd->arg[k] < model->numvertex)
  4229. vrtxidx[cmd->arg[k]] = 0;
  4230. break;
  4231. case m3dcp_va_t:
  4232. n = k + 1;
  4233. l += (cmd->arg[k] - 1) * (cd->p - k - 1);
  4234. break;
  4235. }
  4236. }
  4237. }
  4238. }
  4239. if (model->numface && face) {
  4240. if (numgrp && grpidx) {
  4241. qsort(grpidx, numgrp, sizeof(uint32_t), _m3d_grpcmp);
  4242. for (i = j = 0; i < model->numface && j < numgrp; i++) {
  4243. while (j < numgrp && grpidx[j] < i)
  4244. j++;
  4245. face[i].group = j;
  4246. }
  4247. }
  4248. qsort(face, model->numface, sizeof(m3dfsave_t), _m3d_facecmp);
  4249. }
  4250. if (grpidx) {
  4251. M3D_FREE(grpidx);
  4252. grpidx = NULL;
  4253. }
  4254. if (model->numlabel && model->label) {
  4255. M3D_LOG("Processing annotation labels");
  4256. for (i = 0; i < model->numlabel; i++) {
  4257. str = _m3d_addstr(str, &numstr, model->label[i].name);
  4258. str = _m3d_addstr(str, &numstr, model->label[i].lang);
  4259. str = _m3d_addstr(str, &numstr, model->label[i].text);
  4260. if (!(flags & M3D_EXP_NOCMAP)) {
  4261. cmap = _m3d_addcmap(cmap, &numcmap, model->label[i].color);
  4262. if (!cmap) goto memerr;
  4263. }
  4264. if (model->label[i].vertexid < model->numvertex)
  4265. vrtxidx[model->label[i].vertexid] = 0;
  4266. }
  4267. qsort(model->label, model->numlabel, sizeof(m3dl_t), _m3d_lblcmp);
  4268. }
  4269. } else if (!(flags & M3D_EXP_NOMATERIAL)) {
  4270. /* without a face, simply add all materials, because it can be an mtllib */
  4271. for (i = 0; i < model->nummaterial; i++)
  4272. mtrlidx[i] = i;
  4273. }
  4274. /* bind-pose skeleton */
  4275. if (model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
  4276. M3D_LOG("Processing bones");
  4277. for (i = 0; i < model->numbone; i++) {
  4278. str = _m3d_addstr(str, &numstr, model->bone[i].name);
  4279. if (!str) goto memerr;
  4280. k = model->bone[i].pos;
  4281. if (k < model->numvertex)
  4282. vrtxidx[k] = 0;
  4283. k = model->bone[i].ori;
  4284. if (k < model->numvertex)
  4285. vrtxidx[k] = 0;
  4286. }
  4287. }
  4288. /* actions, animated skeleton poses */
  4289. if (model->numaction && model->action && !(flags & M3D_EXP_NOACTION)) {
  4290. M3D_LOG("Processing action list");
  4291. for (j = 0; j < model->numaction; j++) {
  4292. a = &model->action[j];
  4293. str = _m3d_addstr(str, &numstr, a->name);
  4294. if (!str) goto memerr;
  4295. if (a->numframe > 65535) a->numframe = 65535;
  4296. for (i = 0; i < a->numframe; i++) {
  4297. for (l = 0; l < a->frame[i].numtransform; l++) {
  4298. k = a->frame[i].transform[l].pos;
  4299. if (k < model->numvertex)
  4300. vrtxidx[k] = 0;
  4301. k = a->frame[i].transform[l].ori;
  4302. if (k < model->numvertex)
  4303. vrtxidx[k] = 0;
  4304. }
  4305. if (l > maxt) maxt = l;
  4306. }
  4307. }
  4308. }
  4309. /* add colors to color map and texture names to string table */
  4310. if (!(flags & M3D_EXP_NOMATERIAL)) {
  4311. M3D_LOG("Processing materials");
  4312. for (i = k = 0; i < model->nummaterial; i++) {
  4313. if (mtrlidx[i] == M3D_UNDEF || !model->material[i].numprop) continue;
  4314. mtrlidx[i] = k++;
  4315. m = &model->material[i];
  4316. str = _m3d_addstr(str, &numstr, m->name);
  4317. if (!str) goto memerr;
  4318. if (m->prop)
  4319. for (j = 0; j < m->numprop; j++) {
  4320. if (!(flags & M3D_EXP_NOCMAP) && m->prop[j].type < 128) {
  4321. for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++) {
  4322. if (m->prop[j].type == m3d_propertytypes[l].id && m3d_propertytypes[l].format == m3dpf_color) {
  4323. ((uint8_t *)&m->prop[j].value.color)[3] = opa[i * 2 + 1];
  4324. cmap = _m3d_addcmap(cmap, &numcmap, m->prop[j].value.color);
  4325. if (!cmap) goto memerr;
  4326. break;
  4327. }
  4328. }
  4329. }
  4330. if (m->prop[j].type >= 128 && m->prop[j].value.textureid < model->numtexture &&
  4331. model->texture[m->prop[j].value.textureid].name) {
  4332. str = _m3d_addstr(str, &numstr, model->texture[m->prop[j].value.textureid].name);
  4333. if (!str) goto memerr;
  4334. }
  4335. }
  4336. }
  4337. }
  4338. /* if there's only one black color, don't store it */
  4339. if (numcmap == 1 && cmap && !cmap[0]) numcmap = 0;
  4340. /** compress lists **/
  4341. if (model->numtmap && !(flags & M3D_EXP_NOTXTCRD)) {
  4342. M3D_LOG("Compressing tmap");
  4343. tmap = (m3dtisave_t *)M3D_MALLOC(model->numtmap * sizeof(m3dtisave_t));
  4344. if (!tmap) goto memerr;
  4345. for (i = 0; i < model->numtmap; i++) {
  4346. if (tmapidx[i] == M3D_UNDEF) continue;
  4347. switch (quality) {
  4348. case M3D_EXP_INT8:
  4349. l = (unsigned int)(model->tmap[i].u * 255);
  4350. tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)255.0;
  4351. l = (unsigned int)(model->tmap[i].v * 255);
  4352. tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)255.0;
  4353. break;
  4354. case M3D_EXP_INT16:
  4355. l = (unsigned int)(model->tmap[i].u * 65535);
  4356. tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)65535.0;
  4357. l = (unsigned int)(model->tmap[i].v * 65535);
  4358. tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)65535.0;
  4359. break;
  4360. default:
  4361. tcoord.data.u = model->tmap[i].u;
  4362. tcoord.data.v = model->tmap[i].v;
  4363. break;
  4364. }
  4365. if (flags & M3D_EXP_FLIPTXTCRD)
  4366. tcoord.data.v = (M3D_FLOAT)1.0 - tcoord.data.v;
  4367. tcoord.oldidx = i;
  4368. memcpy(&tmap[numtmap++], &tcoord, sizeof(m3dtisave_t));
  4369. }
  4370. if (numtmap) {
  4371. qsort(tmap, numtmap, sizeof(m3dtisave_t), _m3d_ticmp);
  4372. memcpy(&tcoord.data, &tmap[0], sizeof(m3dti_t));
  4373. for (i = 0; i < numtmap; i++) {
  4374. if (memcmp(&tcoord.data, &tmap[i].data, sizeof(m3dti_t))) {
  4375. memcpy(&tcoord.data, &tmap[i].data, sizeof(m3dti_t));
  4376. maxtmap++;
  4377. }
  4378. tmap[i].newidx = maxtmap;
  4379. tmapidx[tmap[i].oldidx] = maxtmap;
  4380. }
  4381. maxtmap++;
  4382. }
  4383. }
  4384. if (model->numskin && model->skin && !(flags & M3D_EXP_NOBONE)) {
  4385. M3D_LOG("Compressing skin");
  4386. skinidx = (M3D_INDEX *)M3D_MALLOC(model->numskin * sizeof(M3D_INDEX));
  4387. if (!skinidx) goto memerr;
  4388. skin = (m3dssave_t *)M3D_MALLOC(model->numskin * sizeof(m3dssave_t));
  4389. if (!skin) goto memerr;
  4390. memset(skinidx, 255, model->numskin * sizeof(M3D_INDEX));
  4391. for (i = 0; i < model->numvertex; i++) {
  4392. if (vrtxidx[i] != M3D_UNDEF && model->vertex[i].skinid < model->numskin)
  4393. skinidx[model->vertex[i].skinid] = 0;
  4394. }
  4395. for (i = 0; i < model->numskin; i++) {
  4396. if (skinidx[i] == M3D_UNDEF) continue;
  4397. memset(&sk, 0, sizeof(m3dssave_t));
  4398. for (j = 0, min_x = (M3D_FLOAT)0.0; j < M3D_NUMBONE && model->skin[i].boneid[j] != M3D_UNDEF &&
  4399. model->skin[i].weight[j] > (M3D_FLOAT)0.0;
  4400. j++) {
  4401. sk.data.boneid[j] = model->skin[i].boneid[j];
  4402. sk.data.weight[j] = model->skin[i].weight[j];
  4403. min_x += sk.data.weight[j];
  4404. }
  4405. if (j > maxbone) maxbone = j;
  4406. if (min_x != (M3D_FLOAT)1.0 && min_x != (M3D_FLOAT)0.0)
  4407. for (j = 0; j < M3D_NUMBONE && sk.data.weight[j] > (M3D_FLOAT)0.0; j++)
  4408. sk.data.weight[j] /= min_x;
  4409. sk.oldidx = i;
  4410. memcpy(&skin[numskin++], &sk, sizeof(m3dssave_t));
  4411. }
  4412. if (numskin) {
  4413. qsort(skin, numskin, sizeof(m3dssave_t), _m3d_skincmp);
  4414. memcpy(&sk.data, &skin[0].data, sizeof(m3ds_t));
  4415. for (i = 0; i < numskin; i++) {
  4416. if (memcmp(&sk.data, &skin[i].data, sizeof(m3ds_t))) {
  4417. memcpy(&sk.data, &skin[i].data, sizeof(m3ds_t));
  4418. maxskin++;
  4419. }
  4420. skin[i].newidx = maxskin;
  4421. skinidx[skin[i].oldidx] = maxskin;
  4422. }
  4423. maxskin++;
  4424. }
  4425. }
  4426. M3D_LOG("Compressing vertex list");
  4427. min_x = min_y = min_z = (M3D_FLOAT)1e10;
  4428. max_x = max_y = max_z = (M3D_FLOAT)-1e10;
  4429. if (vrtxidx) {
  4430. vrtx = (m3dvsave_t *)M3D_MALLOC(model->numvertex * sizeof(m3dvsave_t));
  4431. if (!vrtx) goto memerr;
  4432. for (i = numvrtx = 0; i < model->numvertex; i++) {
  4433. if (vrtxidx[i] == M3D_UNDEF) continue;
  4434. _m3d_round(quality, &model->vertex[i], &vertex.data);
  4435. vertex.norm = norm ? norm[i] : 0;
  4436. if (vertex.data.skinid != M3D_INDEXMAX && !vertex.norm) {
  4437. vertex.data.skinid = vertex.data.skinid != M3D_UNDEF && skinidx ? skinidx[vertex.data.skinid] : M3D_UNDEF;
  4438. if (vertex.data.x > max_x) max_x = vertex.data.x;
  4439. if (vertex.data.x < min_x) min_x = vertex.data.x;
  4440. if (vertex.data.y > max_y) max_y = vertex.data.y;
  4441. if (vertex.data.y < min_y) min_y = vertex.data.y;
  4442. if (vertex.data.z > max_z) max_z = vertex.data.z;
  4443. if (vertex.data.z < min_z) min_z = vertex.data.z;
  4444. }
  4445. #ifdef M3D_VERTEXTYPE
  4446. vertex.data.type = 0;
  4447. #endif
  4448. vertex.oldidx = i;
  4449. memcpy(&vrtx[numvrtx++], &vertex, sizeof(m3dvsave_t));
  4450. }
  4451. if (numvrtx) {
  4452. qsort(vrtx, numvrtx, sizeof(m3dvsave_t), _m3d_vrtxcmp);
  4453. memcpy(&vertex.data, &vrtx[0].data, sizeof(m3dv_t));
  4454. for (i = 0; i < numvrtx; i++) {
  4455. if (memcmp(&vertex.data, &vrtx[i].data, vrtx[i].norm ? 3 * sizeof(M3D_FLOAT) : sizeof(m3dv_t))) {
  4456. memcpy(&vertex.data, &vrtx[i].data, sizeof(m3dv_t));
  4457. maxvrtx++;
  4458. }
  4459. vrtx[i].newidx = maxvrtx;
  4460. vrtxidx[vrtx[i].oldidx] = maxvrtx;
  4461. }
  4462. maxvrtx++;
  4463. }
  4464. }
  4465. if (skinidx) {
  4466. M3D_FREE(skinidx);
  4467. skinidx = NULL;
  4468. }
  4469. if (norm) {
  4470. M3D_FREE(norm);
  4471. norm = NULL;
  4472. }
  4473. /* normalize to bounding cube */
  4474. if (numvrtx && !(flags & M3D_EXP_NORECALC)) {
  4475. M3D_LOG("Normalizing coordinates");
  4476. if (min_x < (M3D_FLOAT)0.0) min_x = -min_x;
  4477. if (max_x < (M3D_FLOAT)0.0) max_x = -max_x;
  4478. if (min_y < (M3D_FLOAT)0.0) min_y = -min_y;
  4479. if (max_y < (M3D_FLOAT)0.0) max_y = -max_y;
  4480. if (min_z < (M3D_FLOAT)0.0) min_z = -min_z;
  4481. if (max_z < (M3D_FLOAT)0.0) max_z = -max_z;
  4482. scale = min_x;
  4483. if (max_x > scale) scale = max_x;
  4484. if (min_y > scale) scale = min_y;
  4485. if (max_y > scale) scale = max_y;
  4486. if (min_z > scale) scale = min_z;
  4487. if (max_z > scale) scale = max_z;
  4488. if (scale == (M3D_FLOAT)0.0) scale = (M3D_FLOAT)1.0;
  4489. if (scale != (M3D_FLOAT)1.0) {
  4490. for (i = 0; i < numvrtx; i++) {
  4491. if (vrtx[i].data.skinid == M3D_INDEXMAX) continue;
  4492. vrtx[i].data.x /= scale;
  4493. vrtx[i].data.y /= scale;
  4494. vrtx[i].data.z /= scale;
  4495. }
  4496. }
  4497. }
  4498. if (model->scale > (M3D_FLOAT)0.0) scale = model->scale;
  4499. if (scale <= (M3D_FLOAT)0.0) scale = (M3D_FLOAT)1.0;
  4500. /* meta info */
  4501. sn = _m3d_safestr(model->name && *model->name ? model->name : (char *)"(noname)", 2);
  4502. sl = _m3d_safestr(model->license ? model->license : (char *)"MIT", 2);
  4503. sa = _m3d_safestr(model->author ? model->author : getenv("LOGNAME"), 2);
  4504. if (!sn || !sl || !sa) {
  4505. memerr:
  4506. if (vrtxidx) M3D_FREE(vrtxidx);
  4507. if (mtrlidx) M3D_FREE(mtrlidx);
  4508. if (tmapidx) M3D_FREE(tmapidx);
  4509. if (skinidx) M3D_FREE(skinidx);
  4510. if (grpidx) M3D_FREE(grpidx);
  4511. if (norm) M3D_FREE(norm);
  4512. if (face) M3D_FREE(face);
  4513. if (cmap) M3D_FREE(cmap);
  4514. if (tmap) M3D_FREE(tmap);
  4515. if (skin) M3D_FREE(skin);
  4516. if (str) M3D_FREE(str);
  4517. if (vrtx) M3D_FREE(vrtx);
  4518. if (sn) M3D_FREE(sn);
  4519. if (sl) M3D_FREE(sl);
  4520. if (sa) M3D_FREE(sa);
  4521. if (sd) M3D_FREE(sd);
  4522. if (out) M3D_FREE(out);
  4523. if (h) M3D_FREE(h);
  4524. M3D_LOG("Out of memory");
  4525. model->errcode = M3D_ERR_ALLOC;
  4526. return NULL;
  4527. }
  4528. M3D_LOG("Serializing model");
  4529. if (flags & M3D_EXP_ASCII) {
  4530. /* use CRLF to make model creators on Win happy... */
  4531. sd = _m3d_safestr(model->desc, 1);
  4532. if (!sd) goto memerr;
  4533. ol = setlocale(LC_NUMERIC, NULL);
  4534. setlocale(LC_NUMERIC, "C");
  4535. /* header */
  4536. len = 64 + (unsigned int)(strlen(sn) + strlen(sl) + strlen(sa) + strlen(sd));
  4537. out = (unsigned char *)M3D_MALLOC(len);
  4538. if (!out) {
  4539. setlocale(LC_NUMERIC, ol);
  4540. goto memerr;
  4541. }
  4542. ptr = (char *)out;
  4543. ptr += sprintf(ptr, "3dmodel %g\r\n%s\r\n%s\r\n%s\r\n%s\r\n\r\n", scale,
  4544. sn, sl, sa, sd);
  4545. M3D_FREE(sl);
  4546. M3D_FREE(sa);
  4547. M3D_FREE(sd);
  4548. sl = sa = sd = NULL;
  4549. /* preview chunk */
  4550. if (model->preview.data && model->preview.length) {
  4551. sl = _m3d_safestr(sn, 0);
  4552. if (sl) {
  4553. ptr -= (uintptr_t)out;
  4554. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)20);
  4555. out = (unsigned char *)M3D_REALLOC(out, len);
  4556. ptr += (uintptr_t)out;
  4557. if (!out) {
  4558. setlocale(LC_NUMERIC, ol);
  4559. goto memerr;
  4560. }
  4561. ptr += sprintf(ptr, "Preview\r\n%s.png\r\n\r\n", sl);
  4562. M3D_FREE(sl);
  4563. sl = NULL;
  4564. }
  4565. }
  4566. M3D_FREE(sn);
  4567. sn = NULL;
  4568. /* texture map */
  4569. if (numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) {
  4570. ptr -= (uintptr_t)out;
  4571. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(maxtmap * 32) + (uintptr_t)12);
  4572. out = (unsigned char *)M3D_REALLOC(out, len);
  4573. ptr += (uintptr_t)out;
  4574. if (!out) {
  4575. setlocale(LC_NUMERIC, ol);
  4576. goto memerr;
  4577. }
  4578. ptr += sprintf(ptr, "Textmap\r\n");
  4579. last = M3D_UNDEF;
  4580. for (i = 0; i < numtmap; i++) {
  4581. if (tmap[i].newidx == last) continue;
  4582. last = tmap[i].newidx;
  4583. ptr += sprintf(ptr, "%g %g\r\n", tmap[i].data.u, tmap[i].data.v);
  4584. }
  4585. ptr += sprintf(ptr, "\r\n");
  4586. }
  4587. /* vertex chunk */
  4588. if (numvrtx && vrtx && !(flags & M3D_EXP_NOFACE)) {
  4589. ptr -= (uintptr_t)out;
  4590. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(maxvrtx * 128) + (uintptr_t)10);
  4591. out = (unsigned char *)M3D_REALLOC(out, len);
  4592. ptr += (uintptr_t)out;
  4593. if (!out) {
  4594. setlocale(LC_NUMERIC, ol);
  4595. goto memerr;
  4596. }
  4597. ptr += sprintf(ptr, "Vertex\r\n");
  4598. last = M3D_UNDEF;
  4599. for (i = 0; i < numvrtx; i++) {
  4600. if (vrtx[i].newidx == last) continue;
  4601. last = vrtx[i].newidx;
  4602. ptr += sprintf(ptr, "%g %g %g %g", vrtx[i].data.x, vrtx[i].data.y, vrtx[i].data.z, vrtx[i].data.w);
  4603. if (!(flags & M3D_EXP_NOCMAP) && vrtx[i].data.color)
  4604. ptr += sprintf(ptr, " #%08x", vrtx[i].data.color);
  4605. if (!(flags & M3D_EXP_NOBONE) && model->numbone && maxskin && vrtx[i].data.skinid < M3D_INDEXMAX) {
  4606. if (skin[vrtx[i].data.skinid].data.weight[0] == (M3D_FLOAT)1.0)
  4607. ptr += sprintf(ptr, " %d", skin[vrtx[i].data.skinid].data.boneid[0]);
  4608. else
  4609. for (j = 0; j < M3D_NUMBONE && skin[vrtx[i].data.skinid].data.boneid[j] != M3D_UNDEF &&
  4610. skin[vrtx[i].data.skinid].data.weight[j] > (M3D_FLOAT)0.0;
  4611. j++)
  4612. ptr += sprintf(ptr, " %d:%g", skin[vrtx[i].data.skinid].data.boneid[j],
  4613. skin[vrtx[i].data.skinid].data.weight[j]);
  4614. }
  4615. ptr += sprintf(ptr, "\r\n");
  4616. }
  4617. ptr += sprintf(ptr, "\r\n");
  4618. }
  4619. /* bones chunk */
  4620. if (model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
  4621. ptr -= (uintptr_t)out;
  4622. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)9);
  4623. for (i = 0; i < model->numbone; i++) {
  4624. len += (unsigned int)strlen(model->bone[i].name) + 128;
  4625. }
  4626. out = (unsigned char *)M3D_REALLOC(out, len);
  4627. ptr += (uintptr_t)out;
  4628. if (!out) {
  4629. setlocale(LC_NUMERIC, ol);
  4630. goto memerr;
  4631. }
  4632. ptr += sprintf(ptr, "Bones\r\n");
  4633. ptr = _m3d_prtbone(ptr, model->bone, model->numbone, M3D_UNDEF, 0, vrtxidx);
  4634. ptr += sprintf(ptr, "\r\n");
  4635. }
  4636. /* materials */
  4637. if (model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) {
  4638. for (j = 0; j < model->nummaterial; j++) {
  4639. if (mtrlidx[j] == M3D_UNDEF || !model->material[j].numprop || !model->material[j].prop) continue;
  4640. m = &model->material[j];
  4641. sn = _m3d_safestr(m->name, 0);
  4642. if (!sn) {
  4643. setlocale(LC_NUMERIC, ol);
  4644. goto memerr;
  4645. }
  4646. ptr -= (uintptr_t)out;
  4647. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)12);
  4648. for (i = 0; i < m->numprop; i++) {
  4649. if (m->prop[i].type < 128)
  4650. len += 32;
  4651. else if (m->prop[i].value.textureid < model->numtexture && model->texture[m->prop[i].value.textureid].name)
  4652. len += (unsigned int)strlen(model->texture[m->prop[i].value.textureid].name) + 16;
  4653. }
  4654. out = (unsigned char *)M3D_REALLOC(out, len);
  4655. ptr += (uintptr_t)out;
  4656. if (!out) {
  4657. setlocale(LC_NUMERIC, ol);
  4658. goto memerr;
  4659. }
  4660. ptr += sprintf(ptr, "Material %s\r\n", sn);
  4661. M3D_FREE(sn);
  4662. sn = NULL;
  4663. for (i = 0; i < m->numprop; i++) {
  4664. k = 256;
  4665. if (m->prop[i].type >= 128) {
  4666. for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++)
  4667. if (m->prop[i].type == m3d_propertytypes[l].id) {
  4668. sn = m3d_propertytypes[l].key;
  4669. break;
  4670. }
  4671. if (!sn)
  4672. for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++)
  4673. if (m->prop[i].type - 128 == m3d_propertytypes[l].id) {
  4674. sn = m3d_propertytypes[l].key;
  4675. break;
  4676. }
  4677. k = sn ? m3dpf_map : 256;
  4678. } else {
  4679. for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++)
  4680. if (m->prop[i].type == m3d_propertytypes[l].id) {
  4681. sn = m3d_propertytypes[l].key;
  4682. k = m3d_propertytypes[l].format;
  4683. break;
  4684. }
  4685. }
  4686. switch (k) {
  4687. case m3dpf_color: ptr += sprintf(ptr, "%s #%08x\r\n", sn, m->prop[i].value.color); break;
  4688. case m3dpf_uint8:
  4689. case m3dpf_uint16:
  4690. case m3dpf_uint32: ptr += sprintf(ptr, "%s %d\r\n", sn, m->prop[i].value.num); break;
  4691. case m3dpf_float: ptr += sprintf(ptr, "%s %g\r\n", sn, m->prop[i].value.fnum); break;
  4692. case m3dpf_map:
  4693. if (m->prop[i].value.textureid < model->numtexture &&
  4694. model->texture[m->prop[i].value.textureid].name) {
  4695. sl = _m3d_safestr(model->texture[m->prop[i].value.textureid].name, 0);
  4696. if (!sl) {
  4697. setlocale(LC_NUMERIC, ol);
  4698. goto memerr;
  4699. }
  4700. if (*sl)
  4701. ptr += sprintf(ptr, "map_%s %s\r\n", sn, sl);
  4702. M3D_FREE(sn);
  4703. M3D_FREE(sl);
  4704. sl = NULL;
  4705. }
  4706. break;
  4707. }
  4708. sn = NULL;
  4709. }
  4710. ptr += sprintf(ptr, "\r\n");
  4711. }
  4712. }
  4713. /* procedural face */
  4714. if (model->numinlined && model->inlined && !(flags & M3D_EXP_NOFACE)) {
  4715. /* all inlined assets which are not textures should be procedural surfaces */
  4716. for (j = 0; j < model->numinlined; j++) {
  4717. if (!model->inlined[j].name || !*model->inlined[j].name || !model->inlined[j].length || !model->inlined[j].data ||
  4718. (model->inlined[j].data[1] == 'P' && model->inlined[j].data[2] == 'N' && model->inlined[j].data[3] == 'G'))
  4719. continue;
  4720. for (i = k = 0; i < model->numtexture; i++) {
  4721. if (!strcmp(model->inlined[j].name, model->texture[i].name)) {
  4722. k = 1;
  4723. break;
  4724. }
  4725. }
  4726. if (k) continue;
  4727. sn = _m3d_safestr(model->inlined[j].name, 0);
  4728. if (!sn) {
  4729. setlocale(LC_NUMERIC, ol);
  4730. goto memerr;
  4731. }
  4732. ptr -= (uintptr_t)out;
  4733. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)18);
  4734. out = (unsigned char *)M3D_REALLOC(out, len);
  4735. ptr += (uintptr_t)out;
  4736. if (!out) {
  4737. setlocale(LC_NUMERIC, ol);
  4738. goto memerr;
  4739. }
  4740. ptr += sprintf(ptr, "Procedural\r\n%s\r\n\r\n", sn);
  4741. M3D_FREE(sn);
  4742. sn = NULL;
  4743. }
  4744. }
  4745. /* mesh face */
  4746. if (model->numface && face && !(flags & M3D_EXP_NOFACE)) {
  4747. ptr -= (uintptr_t)out;
  4748. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(model->numface * 128) + (uintptr_t)6);
  4749. last = M3D_UNDEF;
  4750. if (!(flags & M3D_EXP_NOMATERIAL))
  4751. for (i = 0; i < model->numface; i++) {
  4752. j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : M3D_UNDEF;
  4753. if (j != last) {
  4754. last = j;
  4755. if (last < model->nummaterial)
  4756. len += (unsigned int)strlen(model->material[last].name);
  4757. len += 6;
  4758. }
  4759. }
  4760. out = (unsigned char *)M3D_REALLOC(out, len);
  4761. ptr += (uintptr_t)out;
  4762. if (!out) {
  4763. setlocale(LC_NUMERIC, ol);
  4764. goto memerr;
  4765. }
  4766. ptr += sprintf(ptr, "Mesh\r\n");
  4767. last = M3D_UNDEF;
  4768. for (i = 0; i < model->numface; i++) {
  4769. j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : M3D_UNDEF;
  4770. if (!(flags & M3D_EXP_NOMATERIAL) && j != last) {
  4771. last = j;
  4772. if (last < model->nummaterial) {
  4773. sn = _m3d_safestr(model->material[last].name, 0);
  4774. if (!sn) {
  4775. setlocale(LC_NUMERIC, ol);
  4776. goto memerr;
  4777. }
  4778. ptr += sprintf(ptr, "use %s\r\n", sn);
  4779. M3D_FREE(sn);
  4780. sn = NULL;
  4781. } else
  4782. ptr += sprintf(ptr, "use\r\n");
  4783. }
  4784. /* hardcoded triangles. Should be repeated as many times as the number of edges in polygon */
  4785. for (j = 0; j < 3; j++) {
  4786. ptr += sprintf(ptr, "%s%d", j ? " " : "", vrtxidx[face[i].data.vertex[j]]);
  4787. k = M3D_NOTDEFINED;
  4788. if (!(flags & M3D_EXP_NOTXTCRD) && (face[i].data.texcoord[j] != M3D_UNDEF) &&
  4789. (tmapidx[face[i].data.texcoord[j]] != M3D_UNDEF)) {
  4790. k = tmapidx[face[i].data.texcoord[j]];
  4791. ptr += sprintf(ptr, "/%d", k);
  4792. }
  4793. if (!(flags & M3D_EXP_NONORMAL) && (face[i].data.normal[j] != M3D_UNDEF))
  4794. ptr += sprintf(ptr, "%s/%d", k == M3D_NOTDEFINED ? "/" : "", vrtxidx[face[i].data.normal[j]]);
  4795. }
  4796. ptr += sprintf(ptr, "\r\n");
  4797. }
  4798. ptr += sprintf(ptr, "\r\n");
  4799. }
  4800. /* mathematical shapes face */
  4801. if (model->numshape && (!(flags & M3D_EXP_NOFACE))) {
  4802. for (j = 0; j < model->numshape; j++) {
  4803. sn = _m3d_safestr(model->shape[j].name, 0);
  4804. if (!sn) {
  4805. setlocale(LC_NUMERIC, ol);
  4806. goto memerr;
  4807. }
  4808. ptr -= (uintptr_t)out;
  4809. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)33);
  4810. out = (unsigned char *)M3D_REALLOC(out, len);
  4811. ptr += (uintptr_t)out;
  4812. if (!out) {
  4813. setlocale(LC_NUMERIC, ol);
  4814. goto memerr;
  4815. }
  4816. ptr += sprintf(ptr, "Shape %s\r\n", sn);
  4817. M3D_FREE(sn);
  4818. sn = NULL;
  4819. if (model->shape[j].group != M3D_UNDEF && !(flags & M3D_EXP_NOBONE))
  4820. ptr += sprintf(ptr, "group %d\r\n", model->shape[j].group);
  4821. for (i = 0; i < model->shape[j].numcmd; i++) {
  4822. cmd = &model->shape[j].cmd[i];
  4823. if (cmd->type >= (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0])) || !cmd->arg)
  4824. continue;
  4825. cd = &m3d_commandtypes[cmd->type];
  4826. ptr -= (uintptr_t)out;
  4827. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(cd->key) + (uintptr_t)3);
  4828. for (k = 0; k < cd->p; k++)
  4829. switch (cd->a[k]) {
  4830. case m3dcp_mi_t:
  4831. if (cmd->arg[k] != M3D_NOTDEFINED) {
  4832. len += (unsigned int)strlen(model->material[cmd->arg[k]].name) + 1;
  4833. }
  4834. break;
  4835. case m3dcp_va_t:
  4836. len += cmd->arg[k] * (cd->p - k - 1) * 16;
  4837. k = cd->p;
  4838. break;
  4839. default: len += 16; break;
  4840. }
  4841. out = (unsigned char *)M3D_REALLOC(out, len);
  4842. ptr += (uintptr_t)out;
  4843. if (!out) {
  4844. setlocale(LC_NUMERIC, ol);
  4845. goto memerr;
  4846. }
  4847. ptr += sprintf(ptr, "%s", cd->key);
  4848. for (k = n = 0, l = cd->p; k < l; k++) {
  4849. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  4850. case m3dcp_mi_t:
  4851. if (cmd->arg[k] != M3D_NOTDEFINED) {
  4852. sn = _m3d_safestr(model->material[cmd->arg[k]].name, 0);
  4853. if (!sn) {
  4854. setlocale(LC_NUMERIC, ol);
  4855. goto memerr;
  4856. }
  4857. ptr += sprintf(ptr, " %s", sn);
  4858. M3D_FREE(sn);
  4859. sn = NULL;
  4860. }
  4861. break;
  4862. case m3dcp_vc_t: ptr += sprintf(ptr, " %g", *((float *)&cmd->arg[k])); break;
  4863. case m3dcp_va_t:
  4864. ptr += sprintf(ptr, " %d[", cmd->arg[k]);
  4865. n = k + 1;
  4866. l += (cmd->arg[k] - 1) * (cd->p - k - 1);
  4867. break;
  4868. default: ptr += sprintf(ptr, " %d", cmd->arg[k]); break;
  4869. }
  4870. }
  4871. ptr += sprintf(ptr, "%s\r\n", l > cd->p ? " ]" : "");
  4872. }
  4873. ptr += sprintf(ptr, "\r\n");
  4874. }
  4875. }
  4876. /* annotation labels */
  4877. if (model->numlabel && model->label && !(flags & M3D_EXP_NOFACE)) {
  4878. for (i = 0, j = 3, length = NULL; i < model->numlabel; i++) {
  4879. if (model->label[i].name) j += (unsigned int)strlen(model->label[i].name);
  4880. if (model->label[i].lang) j += (unsigned int)strlen(model->label[i].lang);
  4881. if (model->label[i].text) j += (unsigned int)strlen(model->label[i].text);
  4882. j += 40;
  4883. }
  4884. ptr -= (uintptr_t)out;
  4885. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)j);
  4886. out = (unsigned char *)M3D_REALLOC(out, len);
  4887. ptr += (uintptr_t)out;
  4888. if (!out) {
  4889. setlocale(LC_NUMERIC, ol);
  4890. goto memerr;
  4891. }
  4892. for (i = 0; i < model->numlabel; i++) {
  4893. if (!i || _m3d_strcmp(sl, model->label[i].lang) || _m3d_strcmp(sn, model->label[i].name)) {
  4894. sl = model->label[i].lang;
  4895. sn = model->label[i].name;
  4896. sd = _m3d_safestr(sn, 0);
  4897. if (!sd) {
  4898. setlocale(LC_NUMERIC, ol);
  4899. sn = sl = NULL;
  4900. goto memerr;
  4901. }
  4902. if (i) ptr += sprintf(ptr, "\r\n");
  4903. ptr += sprintf(ptr, "Labels %s\r\n", sd);
  4904. M3D_FREE(sd);
  4905. sd = NULL;
  4906. if (model->label[i].color)
  4907. ptr += sprintf(ptr, "color #0x%08x\r\n", model->label[i].color);
  4908. if (sl && *sl) {
  4909. sd = _m3d_safestr(sl, 0);
  4910. if (!sd) {
  4911. setlocale(LC_NUMERIC, ol);
  4912. sn = sl = NULL;
  4913. goto memerr;
  4914. }
  4915. ptr += sprintf(ptr, "lang %s\r\n", sd);
  4916. M3D_FREE(sd);
  4917. sd = NULL;
  4918. }
  4919. }
  4920. sd = _m3d_safestr(model->label[i].text, 2);
  4921. if (!sd) {
  4922. setlocale(LC_NUMERIC, ol);
  4923. sn = sl = NULL;
  4924. goto memerr;
  4925. }
  4926. ptr += sprintf(ptr, "%d %s\r\n", model->label[i].vertexid, sd);
  4927. M3D_FREE(sd);
  4928. sd = NULL;
  4929. }
  4930. ptr += sprintf(ptr, "\r\n");
  4931. sn = sl = NULL;
  4932. }
  4933. /* actions */
  4934. if (model->numaction && model->action && !(flags & M3D_EXP_NOACTION)) {
  4935. for (j = 0; j < model->numaction; j++) {
  4936. a = &model->action[j];
  4937. sn = _m3d_safestr(a->name, 0);
  4938. if (!sn) {
  4939. setlocale(LC_NUMERIC, ol);
  4940. goto memerr;
  4941. }
  4942. ptr -= (uintptr_t)out;
  4943. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)48);
  4944. for (i = 0; i < a->numframe; i++)
  4945. len += a->frame[i].numtransform * 128 + 8;
  4946. out = (unsigned char *)M3D_REALLOC(out, len);
  4947. ptr += (uintptr_t)out;
  4948. if (!out) {
  4949. setlocale(LC_NUMERIC, ol);
  4950. goto memerr;
  4951. }
  4952. ptr += sprintf(ptr, "Action %d %s\r\n", a->durationmsec, sn);
  4953. M3D_FREE(sn);
  4954. sn = NULL;
  4955. for (i = 0; i < a->numframe; i++) {
  4956. ptr += sprintf(ptr, "frame %d\r\n", a->frame[i].msec);
  4957. for (k = 0; k < a->frame[i].numtransform; k++) {
  4958. ptr += sprintf(ptr, "%d %d %d\r\n", a->frame[i].transform[k].boneid,
  4959. vrtxidx[a->frame[i].transform[k].pos], vrtxidx[a->frame[i].transform[k].ori]);
  4960. }
  4961. }
  4962. ptr += sprintf(ptr, "\r\n");
  4963. }
  4964. }
  4965. /* inlined assets */
  4966. if (model->numinlined && model->inlined) {
  4967. for (i = j = 0; i < model->numinlined; i++)
  4968. if (model->inlined[i].name)
  4969. j += (unsigned int)strlen(model->inlined[i].name) + 6;
  4970. if (j > 0) {
  4971. ptr -= (uintptr_t)out;
  4972. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)j + (uintptr_t)16);
  4973. out = (unsigned char *)M3D_REALLOC(out, len);
  4974. ptr += (uintptr_t)out;
  4975. if (!out) {
  4976. setlocale(LC_NUMERIC, ol);
  4977. goto memerr;
  4978. }
  4979. ptr += sprintf(ptr, "Assets\r\n");
  4980. for (i = 0; i < model->numinlined; i++)
  4981. if (model->inlined[i].name)
  4982. ptr += sprintf(ptr, "%s%s\r\n", model->inlined[i].name, strrchr(model->inlined[i].name, '.') ? "" : ".png");
  4983. ptr += sprintf(ptr, "\r\n");
  4984. }
  4985. }
  4986. /* extra info */
  4987. if (model->numextra && (flags & M3D_EXP_EXTRA)) {
  4988. for (i = 0; i < model->numextra; i++) {
  4989. if (model->extra[i]->length < 9) continue;
  4990. ptr -= (uintptr_t)out;
  4991. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)17 + (uintptr_t)(model->extra[i]->length * 3));
  4992. out = (unsigned char *)M3D_REALLOC(out, len);
  4993. ptr += (uintptr_t)out;
  4994. if (!out) {
  4995. setlocale(LC_NUMERIC, ol);
  4996. goto memerr;
  4997. }
  4998. ptr += sprintf(ptr, "Extra %c%c%c%c\r\n",
  4999. model->extra[i]->magic[0] > ' ' ? model->extra[i]->magic[0] : '_',
  5000. model->extra[i]->magic[1] > ' ' ? model->extra[i]->magic[1] : '_',
  5001. model->extra[i]->magic[2] > ' ' ? model->extra[i]->magic[2] : '_',
  5002. model->extra[i]->magic[3] > ' ' ? model->extra[i]->magic[3] : '_');
  5003. for (j = 0; j < model->extra[i]->length; j++)
  5004. ptr += sprintf(ptr, "%02x ", *((unsigned char *)model->extra + sizeof(m3dchunk_t) + j));
  5005. ptr--;
  5006. ptr += sprintf(ptr, "\r\n\r\n");
  5007. }
  5008. }
  5009. setlocale(LC_NUMERIC, ol);
  5010. len = (unsigned int)((uintptr_t)ptr - (uintptr_t)out);
  5011. out = (unsigned char *)M3D_REALLOC(out, len + 1);
  5012. if (!out) goto memerr;
  5013. out[len] = 0;
  5014. } else
  5015. {
  5016. /* stricly only use LF (newline) in binary */
  5017. sd = _m3d_safestr(model->desc, 3);
  5018. if (!sd) goto memerr;
  5019. /* header */
  5020. h = (m3dhdr_t *)M3D_MALLOC(sizeof(m3dhdr_t) + strlen(sn) + strlen(sl) + strlen(sa) + strlen(sd) + 4);
  5021. if (!h) goto memerr;
  5022. memcpy((uint8_t *)h, "HEAD", 4);
  5023. h->length = sizeof(m3dhdr_t);
  5024. h->scale = scale;
  5025. i = (unsigned int)strlen(sn);
  5026. memcpy((uint8_t *)h + h->length, sn, i + 1);
  5027. h->length += i + 1;
  5028. M3D_FREE(sn);
  5029. i = (unsigned int)strlen(sl);
  5030. memcpy((uint8_t *)h + h->length, sl, i + 1);
  5031. h->length += i + 1;
  5032. M3D_FREE(sl);
  5033. i = (unsigned int)strlen(sa);
  5034. memcpy((uint8_t *)h + h->length, sa, i + 1);
  5035. h->length += i + 1;
  5036. M3D_FREE(sa);
  5037. i = (unsigned int)strlen(sd);
  5038. memcpy((uint8_t *)h + h->length, sd, i + 1);
  5039. h->length += i + 1;
  5040. M3D_FREE(sd);
  5041. sn = sl = sa = sd = NULL;
  5042. if (model->inlined)
  5043. for (i = 0; i < model->numinlined; i++) {
  5044. if (model->inlined[i].name && *model->inlined[i].name && model->inlined[i].length > 0) {
  5045. str = _m3d_addstr(str, &numstr, model->inlined[i].name);
  5046. if (!str) goto memerr;
  5047. }
  5048. }
  5049. if (str)
  5050. for (i = 0; i < numstr; i++) {
  5051. h = _m3d_addhdr(h, &str[i]);
  5052. if (!h) goto memerr;
  5053. }
  5054. vc_s = quality == M3D_EXP_INT8 ? 1 : (quality == M3D_EXP_INT16 ? 2 : (quality == M3D_EXP_DOUBLE ? 8 : 4));
  5055. vi_s = maxvrtx < 254 ? 1 : (maxvrtx < 65534 ? 2 : 4);
  5056. si_s = h->length - 16 < 254 ? 1 : (h->length - 16 < 65534 ? 2 : 4);
  5057. ci_s = !numcmap || !cmap ? 0 : (numcmap < 254 ? 1 : (numcmap < 65534 ? 2 : 4));
  5058. ti_s = !maxtmap || !tmap ? 0 : (maxtmap < 254 ? 1 : (maxtmap < 65534 ? 2 : 4));
  5059. bi_s = !model->numbone || !model->bone || (flags & M3D_EXP_NOBONE) ? 0 : (model->numbone < 254 ? 1 : (model->numbone < 65534 ? 2 : 4));
  5060. nb_s = maxbone < 2 ? 1 : (maxbone == 2 ? 2 : (maxbone <= 4 ? 4 : 8));
  5061. sk_s = !bi_s || !maxskin || !skin ? 0 : (maxskin < 254 ? 1 : (maxskin < 65534 ? 2 : 4));
  5062. fc_s = maxt < 254 ? 1 : (maxt < 65534 ? 2 : 4);
  5063. hi_s = !model->numshape || !model->shape || (flags & M3D_EXP_NOFACE) ? 0 : (model->numshape < 254 ? 1 : (model->numshape < 65534 ? 2 : 4));
  5064. fi_s = !model->numface || !model->face || (flags & M3D_EXP_NOFACE) ? 0 : (model->numface < 254 ? 1 : (model->numface < 65534 ? 2 : 4));
  5065. h->types = (vc_s == 8 ? (3 << 0) : (vc_s == 2 ? (1 << 0) : (vc_s == 1 ? (0 << 0) : (2 << 0)))) |
  5066. (vi_s == 2 ? (1 << 2) : (vi_s == 1 ? (0 << 2) : (2 << 2))) |
  5067. (si_s == 2 ? (1 << 4) : (si_s == 1 ? (0 << 4) : (2 << 4))) |
  5068. (ci_s == 2 ? (1 << 6) : (ci_s == 1 ? (0 << 6) : (ci_s == 4 ? (2 << 6) : (3 << 6)))) |
  5069. (ti_s == 2 ? (1 << 8) : (ti_s == 1 ? (0 << 8) : (ti_s == 4 ? (2 << 8) : (3 << 8)))) |
  5070. (bi_s == 2 ? (1 << 10) : (bi_s == 1 ? (0 << 10) : (bi_s == 4 ? (2 << 10) : (3 << 10)))) |
  5071. (nb_s == 2 ? (1 << 12) : (nb_s == 1 ? (0 << 12) : (2 << 12))) |
  5072. (sk_s == 2 ? (1 << 14) : (sk_s == 1 ? (0 << 14) : (sk_s == 4 ? (2 << 14) : (3 << 14)))) |
  5073. (fc_s == 2 ? (1 << 16) : (fc_s == 1 ? (0 << 16) : (2 << 16))) |
  5074. (hi_s == 2 ? (1 << 18) : (hi_s == 1 ? (0 << 18) : (hi_s == 4 ? (2 << 18) : (3 << 18)))) |
  5075. (fi_s == 2 ? (1 << 20) : (fi_s == 1 ? (0 << 20) : (fi_s == 4 ? (2 << 20) : (3 << 20))));
  5076. len = h->length;
  5077. /* preview image chunk, must be the first if exists */
  5078. if (model->preview.data && model->preview.length) {
  5079. chunklen = 8 + model->preview.length;
  5080. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5081. if (!h) goto memerr;
  5082. memcpy((uint8_t *)h + len, "PRVW", 4);
  5083. *((uint32_t *)((uint8_t *)h + len + 4)) = chunklen;
  5084. memcpy((uint8_t *)h + len + 8, model->preview.data, model->preview.length);
  5085. len += chunklen;
  5086. }
  5087. /* color map */
  5088. if (numcmap && cmap && ci_s < 4 && !(flags & M3D_EXP_NOCMAP)) {
  5089. chunklen = 8 + numcmap * sizeof(uint32_t);
  5090. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5091. if (!h) goto memerr;
  5092. memcpy((uint8_t *)h + len, "CMAP", 4);
  5093. *((uint32_t *)((uint8_t *)h + len + 4)) = chunklen;
  5094. memcpy((uint8_t *)h + len + 8, cmap, chunklen - 8);
  5095. len += chunklen;
  5096. } else
  5097. numcmap = 0;
  5098. /* texture map */
  5099. if (numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) {
  5100. chunklen = 8 + maxtmap * vc_s * 2;
  5101. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5102. if (!h) goto memerr;
  5103. memcpy((uint8_t *)h + len, "TMAP", 4);
  5104. length = (uint32_t *)((uint8_t *)h + len + 4);
  5105. out = (uint8_t *)h + len + 8;
  5106. last = M3D_UNDEF;
  5107. for (i = 0; i < numtmap; i++) {
  5108. if (tmap[i].newidx == last) continue;
  5109. last = tmap[i].newidx;
  5110. switch (vc_s) {
  5111. case 1:
  5112. *out++ = (uint8_t)(tmap[i].data.u * 255);
  5113. *out++ = (uint8_t)(tmap[i].data.v * 255);
  5114. break;
  5115. case 2:
  5116. *((uint16_t *)out) = (uint16_t)(tmap[i].data.u * 65535);
  5117. out += 2;
  5118. *((uint16_t *)out) = (uint16_t)(tmap[i].data.v * 65535);
  5119. out += 2;
  5120. break;
  5121. case 4:
  5122. *((float *)out) = tmap[i].data.u;
  5123. out += 4;
  5124. *((float *)out) = tmap[i].data.v;
  5125. out += 4;
  5126. break;
  5127. case 8:
  5128. *((double *)out) = tmap[i].data.u;
  5129. out += 8;
  5130. *((double *)out) = tmap[i].data.v;
  5131. out += 8;
  5132. break;
  5133. }
  5134. }
  5135. *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5136. out = NULL;
  5137. len += *length;
  5138. }
  5139. /* vertex */
  5140. if (numvrtx && vrtx) {
  5141. chunklen = 8 + maxvrtx * (ci_s + sk_s + 4 * vc_s);
  5142. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5143. if (!h) goto memerr;
  5144. memcpy((uint8_t *)h + len, "VRTS", 4);
  5145. length = (uint32_t *)((uint8_t *)h + len + 4);
  5146. out = (uint8_t *)h + len + 8;
  5147. last = M3D_UNDEF;
  5148. for (i = 0; i < numvrtx; i++) {
  5149. if (vrtx[i].newidx == last) continue;
  5150. last = vrtx[i].newidx;
  5151. switch (vc_s) {
  5152. case 1:
  5153. *out++ = (int8_t)(vrtx[i].data.x * 127);
  5154. *out++ = (int8_t)(vrtx[i].data.y * 127);
  5155. *out++ = (int8_t)(vrtx[i].data.z * 127);
  5156. *out++ = (int8_t)(vrtx[i].data.w * 127);
  5157. break;
  5158. case 2:
  5159. *((int16_t *)out) = (int16_t)(vrtx[i].data.x * 32767);
  5160. out += 2;
  5161. *((int16_t *)out) = (int16_t)(vrtx[i].data.y * 32767);
  5162. out += 2;
  5163. *((int16_t *)out) = (int16_t)(vrtx[i].data.z * 32767);
  5164. out += 2;
  5165. *((int16_t *)out) = (int16_t)(vrtx[i].data.w * 32767);
  5166. out += 2;
  5167. break;
  5168. case 4:
  5169. memcpy(out, &vrtx[i].data.x, sizeof(float));
  5170. out += 4;
  5171. memcpy(out, &vrtx[i].data.y, sizeof(float));
  5172. out += 4;
  5173. memcpy(out, &vrtx[i].data.z, sizeof(float));
  5174. out += 4;
  5175. memcpy(out, &vrtx[i].data.w, sizeof(float));
  5176. out += 4;
  5177. break;
  5178. case 8:
  5179. *((double *)out) = vrtx[i].data.x;
  5180. out += 8;
  5181. *((double *)out) = vrtx[i].data.y;
  5182. out += 8;
  5183. *((double *)out) = vrtx[i].data.z;
  5184. out += 8;
  5185. *((double *)out) = vrtx[i].data.w;
  5186. out += 8;
  5187. break;
  5188. }
  5189. idx = _m3d_cmapidx(cmap, numcmap, vrtx[i].data.color);
  5190. switch (ci_s) {
  5191. case 1: *out++ = (uint8_t)(idx); break;
  5192. case 2:
  5193. *((uint16_t *)out) = (uint16_t)(idx);
  5194. out += 2;
  5195. break;
  5196. case 4:
  5197. *((uint32_t *)out) = vrtx[i].data.color;
  5198. out += 4;
  5199. break;
  5200. }
  5201. out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid);
  5202. }
  5203. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5204. memcpy(length, &v, sizeof(uint32_t));
  5205. //*length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5206. out = NULL;
  5207. len += v;
  5208. }
  5209. /* bones chunk */
  5210. if (model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
  5211. i = 8 + bi_s + sk_s + model->numbone * (bi_s + si_s + 2 * vi_s);
  5212. chunklen = i + numskin * nb_s * (bi_s + 1);
  5213. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5214. if (!h) goto memerr;
  5215. memcpy((uint8_t *)h + len, "BONE", 4);
  5216. length = (uint32_t *)((uint8_t *)h + len + 4);
  5217. out = (uint8_t *)h + len + 8;
  5218. out = _m3d_addidx(out, bi_s, model->numbone);
  5219. out = _m3d_addidx(out, sk_s, maxskin);
  5220. for (i = 0; i < model->numbone; i++) {
  5221. out = _m3d_addidx(out, bi_s, model->bone[i].parent);
  5222. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->bone[i].name));
  5223. out = _m3d_addidx(out, vi_s, vrtxidx[model->bone[i].pos]);
  5224. out = _m3d_addidx(out, vi_s, vrtxidx[model->bone[i].ori]);
  5225. }
  5226. if (numskin && skin && sk_s) {
  5227. last = M3D_UNDEF;
  5228. for (i = 0; i < numskin; i++) {
  5229. if (skin[i].newidx == last) continue;
  5230. last = skin[i].newidx;
  5231. memset(&weights, 0, nb_s);
  5232. for (j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != M3D_UNDEF &&
  5233. skin[i].data.weight[j] > (M3D_FLOAT)0.0;
  5234. j++)
  5235. weights[j] = (uint8_t)(skin[i].data.weight[j] * 255);
  5236. switch (nb_s) {
  5237. case 1: weights[0] = 255; break;
  5238. case 2:
  5239. *((uint16_t *)out) = *((uint16_t *)&weights[0]);
  5240. out += 2;
  5241. break;
  5242. case 4:
  5243. *((uint32_t *)out) = *((uint32_t *)&weights[0]);
  5244. out += 4;
  5245. break;
  5246. case 8:
  5247. *((uint64_t *)out) = *((uint64_t *)&weights[0]);
  5248. out += 8;
  5249. break;
  5250. }
  5251. for (j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != M3D_UNDEF && weights[j]; j++) {
  5252. out = _m3d_addidx(out, bi_s, skin[i].data.boneid[j]);
  5253. *length += bi_s;
  5254. }
  5255. }
  5256. }
  5257. *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5258. out = NULL;
  5259. len += *length;
  5260. }
  5261. /* materials */
  5262. if (model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) {
  5263. for (j = 0; j < model->nummaterial; j++) {
  5264. if (mtrlidx[j] == M3D_UNDEF || !model->material[j].numprop || !model->material[j].prop) continue;
  5265. m = &model->material[j];
  5266. chunklen = 12 + si_s + m->numprop * 5;
  5267. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5268. if (!h) goto memerr;
  5269. memcpy((uint8_t *)h + len, "MTRL", 4);
  5270. length = (uint32_t *)((uint8_t *)h + len + 4);
  5271. out = (uint8_t *)h + len + 8;
  5272. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, m->name));
  5273. for (i = 0; i < m->numprop; i++) {
  5274. if (m->prop[i].type >= 128) {
  5275. if (m->prop[i].value.textureid >= model->numtexture ||
  5276. !model->texture[m->prop[i].value.textureid].name) continue;
  5277. k = m3dpf_map;
  5278. } else {
  5279. for (k = 256, l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++)
  5280. if (m->prop[i].type == m3d_propertytypes[l].id) {
  5281. k = m3d_propertytypes[l].format;
  5282. break;
  5283. }
  5284. }
  5285. if (k == 256) continue;
  5286. *out++ = m->prop[i].type;
  5287. switch (k) {
  5288. case m3dpf_color:
  5289. if (!(flags & M3D_EXP_NOCMAP)) {
  5290. idx = _m3d_cmapidx(cmap, numcmap, m->prop[i].value.color);
  5291. switch (ci_s) {
  5292. case 1: *out++ = (uint8_t)(idx); break;
  5293. case 2:
  5294. *((uint16_t *)out) = (uint16_t)(idx);
  5295. out += 2;
  5296. break;
  5297. case 4:
  5298. *((uint32_t *)out) = (uint32_t)(m->prop[i].value.color);
  5299. out += 4;
  5300. break;
  5301. }
  5302. } else
  5303. out--;
  5304. break;
  5305. case m3dpf_uint8: *out++ = (uint8_t)m->prop[i].value.num; break;
  5306. case m3dpf_uint16:
  5307. *((uint16_t *)out) = (uint16_t)m->prop[i].value.num;
  5308. out += 2;
  5309. break;
  5310. case m3dpf_uint32:
  5311. *((uint32_t *)out) = m->prop[i].value.num;
  5312. out += 4;
  5313. break;
  5314. case m3dpf_float:
  5315. *((float *)out) = m->prop[i].value.fnum;
  5316. out += 4;
  5317. break;
  5318. case m3dpf_map:
  5319. idx = _m3d_stridx(str, numstr, model->texture[m->prop[i].value.textureid].name);
  5320. out = _m3d_addidx(out, si_s, idx);
  5321. break;
  5322. }
  5323. }
  5324. *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5325. len += *length;
  5326. out = NULL;
  5327. }
  5328. }
  5329. /* procedural face */
  5330. if (model->numinlined && model->inlined && !(flags & M3D_EXP_NOFACE)) {
  5331. /* all inlined assets which are not textures should be procedural surfaces */
  5332. for (j = 0; j < model->numinlined; j++) {
  5333. if (!model->inlined[j].name || !model->inlined[j].name[0] || model->inlined[j].length < 4 ||
  5334. !model->inlined[j].data || (model->inlined[j].data[1] == 'P' && model->inlined[j].data[2] == 'N' && model->inlined[j].data[3] == 'G'))
  5335. continue;
  5336. for (i = k = 0; i < model->numtexture; i++) {
  5337. if (!strcmp(model->inlined[j].name, model->texture[i].name)) {
  5338. k = 1;
  5339. break;
  5340. }
  5341. }
  5342. if (k) continue;
  5343. numproc++;
  5344. chunklen = 8 + si_s;
  5345. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5346. if (!h) goto memerr;
  5347. memcpy((uint8_t *)h + len, "PROC", 4);
  5348. *((uint32_t *)((uint8_t *)h + len + 4)) = chunklen;
  5349. out = (uint8_t *)h + len + 8;
  5350. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->inlined[j].name));
  5351. out = NULL;
  5352. len += chunklen;
  5353. }
  5354. }
  5355. /* mesh face */
  5356. if (model->numface && face && !(flags & M3D_EXP_NOFACE)) {
  5357. chunklen = 8 + si_s + model->numface * (6 * vi_s + 3 * ti_s + si_s + 1);
  5358. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5359. if (!h) goto memerr;
  5360. memcpy((uint8_t *)h + len, "MESH", 4);
  5361. length = (uint32_t *)((uint8_t *)h + len + 4);
  5362. out = (uint8_t *)h + len + 8;
  5363. last = M3D_UNDEF;
  5364. for (i = 0; i < model->numface; i++) {
  5365. if (!(flags & M3D_EXP_NOMATERIAL) && face[i].data.materialid != last) {
  5366. last = face[i].data.materialid;
  5367. idx = last < model->nummaterial ? _m3d_stridx(str, numstr, model->material[last].name) : 0;
  5368. *out++ = 0;
  5369. out = _m3d_addidx(out, si_s, idx);
  5370. }
  5371. /* hardcoded triangles. */
  5372. k = (3 << 4) |
  5373. (((flags & M3D_EXP_NOTXTCRD) || !ti_s || face[i].data.texcoord[0] == M3D_UNDEF ||
  5374. face[i].data.texcoord[1] == M3D_UNDEF || face[i].data.texcoord[2] == M3D_UNDEF) ?
  5375. 0 :
  5376. 1) |
  5377. (((flags & M3D_EXP_NONORMAL) || face[i].data.normal[0] == M3D_UNDEF ||
  5378. face[i].data.normal[1] == M3D_UNDEF || face[i].data.normal[2] == M3D_UNDEF) ?
  5379. 0 :
  5380. 2);
  5381. *out++ = (uint8_t)k;
  5382. for (j = 0; j < 3; j++) {
  5383. out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.vertex[j]]);
  5384. if (k & 1)
  5385. out = _m3d_addidx(out, ti_s, tmapidx[face[i].data.texcoord[j]]);
  5386. if (k & 2)
  5387. out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]);
  5388. }
  5389. }
  5390. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5391. memcpy(length, &v, sizeof(uint32_t));
  5392. len += v;
  5393. out = NULL;
  5394. }
  5395. /* mathematical shapes face */
  5396. if (model->numshape && model->shape && !(flags & M3D_EXP_NOFACE)) {
  5397. for (j = 0; j < model->numshape; j++) {
  5398. chunklen = 12 + si_s + model->shape[j].numcmd * (M3D_CMDMAXARG + 1) * 4;
  5399. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5400. if (!h) goto memerr;
  5401. memcpy((uint8_t *)h + len, "SHPE", 4);
  5402. length = (uint32_t *)((uint8_t *)h + len + 4);
  5403. out = (uint8_t *)h + len + 8;
  5404. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->shape[j].name));
  5405. out = _m3d_addidx(out, bi_s, model->shape[j].group);
  5406. for (i = 0; i < model->shape[j].numcmd; i++) {
  5407. cmd = &model->shape[j].cmd[i];
  5408. if (cmd->type >= (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0])) || !cmd->arg)
  5409. continue;
  5410. cd = &m3d_commandtypes[cmd->type];
  5411. *out++ = (cmd->type & 0x7F) | (cmd->type > 127 ? 0x80 : 0);
  5412. if (cmd->type > 127) *out++ = (cmd->type >> 7) & 0xff;
  5413. for (k = n = 0, l = cd->p; k < l; k++) {
  5414. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  5415. case m3dcp_mi_t:
  5416. out = _m3d_addidx(out, si_s, cmd->arg[k] < model->nummaterial ? _m3d_stridx(str, numstr, model->material[cmd->arg[k]].name) : 0);
  5417. break;
  5418. case m3dcp_vc_t:
  5419. min_x = *((float *)&cmd->arg[k]);
  5420. switch (vc_s) {
  5421. case 1: *out++ = (int8_t)(min_x * 127); break;
  5422. case 2:
  5423. *((int16_t *)out) = (int16_t)(min_x * 32767);
  5424. out += 2;
  5425. break;
  5426. case 4:
  5427. *((float *)out) = min_x;
  5428. out += 4;
  5429. break;
  5430. case 8:
  5431. *((double *)out) = min_x;
  5432. out += 8;
  5433. break;
  5434. }
  5435. break;
  5436. case m3dcp_hi_t: out = _m3d_addidx(out, hi_s, cmd->arg[k]); break;
  5437. case m3dcp_fi_t: out = _m3d_addidx(out, fi_s, cmd->arg[k]); break;
  5438. case m3dcp_ti_t: out = _m3d_addidx(out, ti_s, cmd->arg[k]); break;
  5439. case m3dcp_qi_t:
  5440. case m3dcp_vi_t: out = _m3d_addidx(out, vi_s, cmd->arg[k]); break;
  5441. case m3dcp_i1_t: out = _m3d_addidx(out, 1, cmd->arg[k]); break;
  5442. case m3dcp_i2_t: out = _m3d_addidx(out, 2, cmd->arg[k]); break;
  5443. case m3dcp_i4_t: out = _m3d_addidx(out, 4, cmd->arg[k]); break;
  5444. case m3dcp_va_t:
  5445. out = _m3d_addidx(out, 4, cmd->arg[k]);
  5446. n = k + 1;
  5447. l += (cmd->arg[k] - 1) * (cd->p - k - 1);
  5448. break;
  5449. }
  5450. }
  5451. }
  5452. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5453. memcpy( length, &v, sizeof(uint32_t));
  5454. len += v;
  5455. out = NULL;
  5456. }
  5457. }
  5458. /* annotation labels */
  5459. if (model->numlabel && model->label) {
  5460. for (i = 0, length = NULL; i < model->numlabel; i++) {
  5461. if (!i || _m3d_strcmp(sl, model->label[i].lang) || _m3d_strcmp(sn, model->label[i].name)) {
  5462. sl = model->label[i].lang;
  5463. sn = model->label[i].name;
  5464. if (length) {
  5465. *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5466. len += *length;
  5467. }
  5468. chunklen = 8 + 2 * si_s + ci_s + model->numlabel * (vi_s + si_s);
  5469. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5470. if (!h) {
  5471. sn = NULL;
  5472. sl = NULL;
  5473. goto memerr;
  5474. }
  5475. memcpy((uint8_t *)h + len, "LBLS", 4);
  5476. length = (uint32_t *)((uint8_t *)h + len + 4);
  5477. out = (uint8_t *)h + len + 8;
  5478. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].name));
  5479. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].lang));
  5480. idx = _m3d_cmapidx(cmap, numcmap, model->label[i].color);
  5481. switch (ci_s) {
  5482. case 1: *out++ = (uint8_t)(idx); break;
  5483. case 2:
  5484. *((uint16_t *)out) = (uint16_t)(idx);
  5485. out += 2;
  5486. break;
  5487. case 4:
  5488. *((uint32_t *)out) = model->label[i].color;
  5489. out += 4;
  5490. break;
  5491. }
  5492. }
  5493. out = _m3d_addidx(out, vi_s, vrtxidx[model->label[i].vertexid]);
  5494. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text));
  5495. }
  5496. if (length) {
  5497. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5498. memcpy( length, &v, sizeof(uint32_t));
  5499. len += v;
  5500. }
  5501. out = NULL;
  5502. sn = sl = NULL;
  5503. }
  5504. /* actions */
  5505. if (model->numaction && model->action && model->numbone && model->bone && !(flags & M3D_EXP_NOACTION)) {
  5506. for (j = 0; j < model->numaction; j++) {
  5507. a = &model->action[j];
  5508. chunklen = 14 + si_s + a->numframe * (4 + fc_s + maxt * (bi_s + 2 * vi_s));
  5509. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5510. if (!h) goto memerr;
  5511. memcpy((uint8_t *)h + len, "ACTN", 4);
  5512. length = (uint32_t *)((uint8_t *)h + len + 4);
  5513. out = (uint8_t *)h + len + 8;
  5514. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, a->name));
  5515. *((uint16_t *)out) = (uint16_t)(a->numframe);
  5516. out += 2;
  5517. *((uint32_t *)out) = (uint32_t)(a->durationmsec);
  5518. out += 4;
  5519. for (i = 0; i < a->numframe; i++) {
  5520. *((uint32_t *)out) = (uint32_t)(a->frame[i].msec);
  5521. out += 4;
  5522. out = _m3d_addidx(out, fc_s, a->frame[i].numtransform);
  5523. for (k = 0; k < a->frame[i].numtransform; k++) {
  5524. out = _m3d_addidx(out, bi_s, a->frame[i].transform[k].boneid);
  5525. out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].pos]);
  5526. out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]);
  5527. }
  5528. }
  5529. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  5530. memcpy( length, &v, sizeof(uint32_t));
  5531. len += v;
  5532. out = NULL;
  5533. }
  5534. }
  5535. /* inlined assets */
  5536. if (model->numinlined && model->inlined && (numproc || (flags & M3D_EXP_INLINE))) {
  5537. for (j = 0; j < model->numinlined; j++) {
  5538. if (!model->inlined[j].name || !model->inlined[j].name[0] || model->inlined[j].length < 4 || !model->inlined[j].data)
  5539. continue;
  5540. if (!(flags & M3D_EXP_INLINE)) {
  5541. if (model->inlined[j].data[1] == 'P' && model->inlined[j].data[2] == 'N' && model->inlined[j].data[3] == 'G')
  5542. continue;
  5543. for (i = k = 0; i < model->numtexture; i++) {
  5544. if (!strcmp(model->inlined[j].name, model->texture[i].name)) {
  5545. k = 1;
  5546. break;
  5547. }
  5548. }
  5549. if (k) continue;
  5550. }
  5551. chunklen = 8 + si_s + model->inlined[j].length;
  5552. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5553. if (!h) goto memerr;
  5554. memcpy((uint8_t *)h + len, "ASET", 4);
  5555. *((uint32_t *)((uint8_t *)h + len + 4)) = chunklen;
  5556. out = (uint8_t *)h + len + 8;
  5557. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->inlined[j].name));
  5558. memcpy(out, model->inlined[j].data, model->inlined[j].length);
  5559. out = NULL;
  5560. len += chunklen;
  5561. }
  5562. }
  5563. /* extra chunks */
  5564. if (model->numextra && model->extra && (flags & M3D_EXP_EXTRA)) {
  5565. for (j = 0; j < model->numextra; j++) {
  5566. if (!model->extra[j] || model->extra[j]->length < 8)
  5567. continue;
  5568. chunklen = model->extra[j]->length;
  5569. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  5570. if (!h) goto memerr;
  5571. memcpy((uint8_t *)h + len, model->extra[j], chunklen);
  5572. len += chunklen;
  5573. }
  5574. }
  5575. /* add end chunk */
  5576. h = (m3dhdr_t *)M3D_REALLOC(h, len + 4);
  5577. if (!h) goto memerr;
  5578. memcpy((uint8_t *)h + len, "OMD3", 4);
  5579. len += 4;
  5580. /* zlib compress */
  5581. if (!(flags & M3D_EXP_NOZLIB)) {
  5582. M3D_LOG("Deflating chunks");
  5583. z = stbi_zlib_compress((unsigned char *)h, len, (int *)&l, 9);
  5584. if (z && l > 0 && l < len) {
  5585. len = l;
  5586. M3D_FREE(h);
  5587. h = (m3dhdr_t *)z;
  5588. }
  5589. }
  5590. /* add file header at the begining */
  5591. len += 8;
  5592. out = (unsigned char *)M3D_MALLOC(len);
  5593. if (!out) goto memerr;
  5594. memcpy(out, "3DMO", 4);
  5595. *((uint32_t *)(out + 4)) = len;
  5596. memcpy(out + 8, h, len - 8);
  5597. }
  5598. if (size) *size = out ? len : 0;
  5599. if (vrtxidx) M3D_FREE(vrtxidx);
  5600. if (mtrlidx) M3D_FREE(mtrlidx);
  5601. if (tmapidx) M3D_FREE(tmapidx);
  5602. if (skinidx) M3D_FREE(skinidx);
  5603. if (norm) M3D_FREE(norm);
  5604. if (face) M3D_FREE(face);
  5605. if (cmap) M3D_FREE(cmap);
  5606. if (tmap) M3D_FREE(tmap);
  5607. if (skin) M3D_FREE(skin);
  5608. if (str) M3D_FREE(str);
  5609. if (vrtx) M3D_FREE(vrtx);
  5610. if (h) M3D_FREE(h);
  5611. return out;
  5612. }
  5613. #endif
  5614. #endif /* M3D_IMPLEMENTATION */
  5615. #ifdef __cplusplus
  5616. }
  5617. #ifdef M3D_CPPWRAPPER
  5618. #include <memory>
  5619. #include <string>
  5620. #include <vector>
  5621. /*** C++ wrapper class ***/
  5622. namespace M3D {
  5623. #ifdef M3D_IMPLEMENTATION
  5624. class Model {
  5625. public:
  5626. m3d_t *model;
  5627. public:
  5628. Model() {
  5629. this->model = (m3d_t *)malloc(sizeof(m3d_t));
  5630. memset(this->model, 0, sizeof(m3d_t));
  5631. }
  5632. Model(_unused const std::string &data, _unused m3dread_t ReadFileCB,
  5633. _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
  5634. #ifndef M3D_NOIMPORTER
  5635. this->model = m3d_load((unsigned char *)data.data(), ReadFileCB, FreeCB, mtllib.model);
  5636. #else
  5637. Model();
  5638. #endif
  5639. }
  5640. Model(_unused const std::vector<unsigned char> data, _unused m3dread_t ReadFileCB,
  5641. _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
  5642. #ifndef M3D_NOIMPORTER
  5643. this->model = m3d_load((unsigned char *)&data[0], ReadFileCB, FreeCB, mtllib.model);
  5644. #else
  5645. Model();
  5646. #endif
  5647. }
  5648. Model(_unused const unsigned char *data, _unused m3dread_t ReadFileCB,
  5649. _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
  5650. #ifndef M3D_NOIMPORTER
  5651. this->model = m3d_load((unsigned char *)data, ReadFileCB, FreeCB, mtllib.model);
  5652. #else
  5653. Model();
  5654. #endif
  5655. }
  5656. ~Model() { m3d_free(this->model); }
  5657. public:
  5658. m3d_t *getCStruct() { return this->model; }
  5659. std::string getName() { return std::string(this->model->name); }
  5660. void setName(std::string name) { this->model->name = (char *)name.c_str(); }
  5661. std::string getLicense() { return std::string(this->model->license); }
  5662. void setLicense(std::string license) { this->model->license = (char *)license.c_str(); }
  5663. std::string getAuthor() { return std::string(this->model->author); }
  5664. void setAuthor(std::string author) { this->model->author = (char *)author.c_str(); }
  5665. std::string getDescription() { return std::string(this->model->desc); }
  5666. void setDescription(std::string desc) { this->model->desc = (char *)desc.c_str(); }
  5667. float getScale() { return this->model->scale; }
  5668. void setScale(float scale) { this->model->scale = scale; }
  5669. std::vector<unsigned char> getPreview() { return this->model->preview.data ?
  5670. std::vector<unsigned char>(this->model->preview.data, this->model->preview.data + this->model->preview.length) :
  5671. std::vector<unsigned char>(); }
  5672. std::vector<uint32_t> getColorMap() { return this->model->cmap ? std::vector<uint32_t>(this->model->cmap,
  5673. this->model->cmap + this->model->numcmap) :
  5674. std::vector<uint32_t>(); }
  5675. std::vector<m3dti_t> getTextureMap() { return this->model->tmap ? std::vector<m3dti_t>(this->model->tmap,
  5676. this->model->tmap + this->model->numtmap) :
  5677. std::vector<m3dti_t>(); }
  5678. std::vector<m3dtx_t> getTextures() { return this->model->texture ? std::vector<m3dtx_t>(this->model->texture,
  5679. this->model->texture + this->model->numtexture) :
  5680. std::vector<m3dtx_t>(); }
  5681. std::string getTextureName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numtexture ?
  5682. std::string(this->model->texture[idx].name) :
  5683. nullptr; }
  5684. std::vector<m3db_t> getBones() { return this->model->bone ? std::vector<m3db_t>(this->model->bone, this->model->bone +
  5685. this->model->numbone) :
  5686. std::vector<m3db_t>(); }
  5687. std::string getBoneName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numbone ?
  5688. std::string(this->model->bone[idx].name) :
  5689. nullptr; }
  5690. std::vector<m3dm_t> getMaterials() { return this->model->material ? std::vector<m3dm_t>(this->model->material,
  5691. this->model->material + this->model->nummaterial) :
  5692. std::vector<m3dm_t>(); }
  5693. std::string getMaterialName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->nummaterial ?
  5694. std::string(this->model->material[idx].name) :
  5695. nullptr; }
  5696. int getMaterialPropertyInt(int idx, int type) {
  5697. if (idx < 0 || (unsigned int)idx >= this->model->nummaterial || type < 0 || type >= 127 ||
  5698. !this->model->material[idx].prop) return -1;
  5699. for (int i = 0; i < this->model->material[idx].numprop; i++) {
  5700. if (this->model->material[idx].prop[i].type == type)
  5701. return this->model->material[idx].prop[i].value.num;
  5702. }
  5703. return -1;
  5704. }
  5705. uint32_t getMaterialPropertyColor(int idx, int type) { return this->getMaterialPropertyInt(idx, type); }
  5706. float getMaterialPropertyFloat(int idx, int type) {
  5707. if (idx < 0 || (unsigned int)idx >= this->model->nummaterial || type < 0 || type >= 127 ||
  5708. !this->model->material[idx].prop) return -1.0f;
  5709. for (int i = 0; i < this->model->material[idx].numprop; i++) {
  5710. if (this->model->material[idx].prop[i].type == type)
  5711. return this->model->material[idx].prop[i].value.fnum;
  5712. }
  5713. return -1.0f;
  5714. }
  5715. m3dtx_t *getMaterialPropertyMap(int idx, int type) {
  5716. if (idx < 0 || (unsigned int)idx >= this->model->nummaterial || type < 128 || type > 255 ||
  5717. !this->model->material[idx].prop) return nullptr;
  5718. for (int i = 0; i < this->model->material[idx].numprop; i++) {
  5719. if (this->model->material[idx].prop[i].type == type)
  5720. return this->model->material[idx].prop[i].value.textureid < this->model->numtexture ?
  5721. &this->model->texture[this->model->material[idx].prop[i].value.textureid] :
  5722. nullptr;
  5723. }
  5724. return nullptr;
  5725. }
  5726. std::vector<m3dv_t> getVertices() { return this->model->vertex ? std::vector<m3dv_t>(this->model->vertex,
  5727. this->model->vertex + this->model->numvertex) :
  5728. std::vector<m3dv_t>(); }
  5729. std::vector<m3df_t> getFace() { return this->model->face ? std::vector<m3df_t>(this->model->face, this->model->face +
  5730. this->model->numface) :
  5731. std::vector<m3df_t>(); }
  5732. std::vector<m3dh_t> getShape() { return this->model->shape ? std::vector<m3dh_t>(this->model->shape,
  5733. this->model->shape + this->model->numshape) :
  5734. std::vector<m3dh_t>(); }
  5735. std::string getShapeName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numshape &&
  5736. this->model->shape[idx].name && this->model->shape[idx].name[0] ?
  5737. std::string(this->model->shape[idx].name) :
  5738. nullptr; }
  5739. unsigned int getShapeGroup(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numshape ?
  5740. this->model->shape[idx].group :
  5741. 0xFFFFFFFF; }
  5742. std::vector<m3dc_t> getShapeCommands(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numshape &&
  5743. this->model->shape[idx].cmd ?
  5744. std::vector<m3dc_t>(this->model->shape[idx].cmd, this->model->shape[idx].cmd +
  5745. this->model->shape[idx].numcmd) :
  5746. std::vector<m3dc_t>(); }
  5747. std::vector<m3dl_t> getAnnotationLabels() { return this->model->label ? std::vector<m3dl_t>(this->model->label,
  5748. this->model->label + this->model->numlabel) :
  5749. std::vector<m3dl_t>(); }
  5750. std::vector<m3ds_t> getSkin() { return this->model->skin ? std::vector<m3ds_t>(this->model->skin, this->model->skin +
  5751. this->model->numskin) :
  5752. std::vector<m3ds_t>(); }
  5753. std::vector<m3da_t> getActions() { return this->model->action ? std::vector<m3da_t>(this->model->action,
  5754. this->model->action + this->model->numaction) :
  5755. std::vector<m3da_t>(); }
  5756. std::string getActionName(int aidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ?
  5757. std::string(this->model->action[aidx].name) :
  5758. nullptr; }
  5759. unsigned int getActionDuration(int aidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ?
  5760. this->model->action[aidx].durationmsec :
  5761. 0; }
  5762. std::vector<m3dfr_t> getActionFrames(int aidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ?
  5763. std::vector<m3dfr_t>(this->model->action[aidx].frame, this->model->action[aidx].frame +
  5764. this->model->action[aidx].numframe) :
  5765. std::vector<m3dfr_t>(); }
  5766. unsigned int getActionFrameTimestamp(int aidx, int fidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ?
  5767. (fidx >= 0 && (unsigned int)fidx < this->model->action[aidx].numframe ?
  5768. this->model->action[aidx].frame[fidx].msec :
  5769. 0) :
  5770. 0; }
  5771. std::vector<m3dtr_t> getActionFrameTransforms(int aidx, int fidx) {
  5772. return aidx >= 0 && (unsigned int)aidx < this->model->numaction ? (
  5773. fidx >= 0 && (unsigned int)fidx < this->model->action[aidx].numframe ?
  5774. std::vector<m3dtr_t>(this->model->action[aidx].frame[fidx].transform,
  5775. this->model->action[aidx].frame[fidx].transform + this->model->action[aidx].frame[fidx].numtransform) :
  5776. std::vector<m3dtr_t>()) :
  5777. std::vector<m3dtr_t>();
  5778. }
  5779. std::vector<m3dtr_t> getActionFrame(int aidx, int fidx, std::vector<m3dtr_t> skeleton) {
  5780. m3dtr_t *pose = m3d_frame(this->model, (unsigned int)aidx, (unsigned int)fidx,
  5781. skeleton.size() ? &skeleton[0] : nullptr);
  5782. return std::vector<m3dtr_t>(pose, pose + this->model->numbone);
  5783. }
  5784. std::vector<m3db_t> getActionPose(int aidx, unsigned int msec) {
  5785. m3db_t *pose = m3d_pose(this->model, (unsigned int)aidx, (unsigned int)msec);
  5786. return std::vector<m3db_t>(pose, pose + this->model->numbone);
  5787. }
  5788. std::vector<m3di_t> getInlinedAssets() { return this->model->inlined ? std::vector<m3di_t>(this->model->inlined,
  5789. this->model->inlined + this->model->numinlined) :
  5790. std::vector<m3di_t>(); }
  5791. std::vector<std::unique_ptr<m3dchunk_t>> getExtras() { return this->model->extra ?
  5792. std::vector<std::unique_ptr<m3dchunk_t>>(this->model->extra,
  5793. this->model->extra + this->model->numextra) :
  5794. std::vector<std::unique_ptr<m3dchunk_t>>(); }
  5795. std::vector<unsigned char> Save(_unused int quality, _unused int flags) {
  5796. #ifdef M3D_EXPORTER
  5797. unsigned int size;
  5798. unsigned char *ptr = m3d_save(this->model, quality, flags, &size);
  5799. return ptr && size ? std::vector<unsigned char>(ptr, ptr + size) : std::vector<unsigned char>();
  5800. #else
  5801. return std::vector<unsigned char>();
  5802. #endif
  5803. }
  5804. };
  5805. #else
  5806. class Model {
  5807. public:
  5808. m3d_t *model;
  5809. public:
  5810. Model(const std::string &data, m3dread_t ReadFileCB, m3dfree_t FreeCB);
  5811. Model(const std::vector<unsigned char> data, m3dread_t ReadFileCB, m3dfree_t FreeCB);
  5812. Model(const unsigned char *data, m3dread_t ReadFileCB, m3dfree_t FreeCB);
  5813. Model();
  5814. ~Model();
  5815. public:
  5816. m3d_t *getCStruct();
  5817. std::string getName();
  5818. void setName(std::string name);
  5819. std::string getLicense();
  5820. void setLicense(std::string license);
  5821. std::string getAuthor();
  5822. void setAuthor(std::string author);
  5823. std::string getDescription();
  5824. void setDescription(std::string desc);
  5825. float getScale();
  5826. void setScale(float scale);
  5827. std::vector<unsigned char> getPreview();
  5828. std::vector<uint32_t> getColorMap();
  5829. std::vector<m3dti_t> getTextureMap();
  5830. std::vector<m3dtx_t> getTextures();
  5831. std::string getTextureName(int idx);
  5832. std::vector<m3db_t> getBones();
  5833. std::string getBoneName(int idx);
  5834. std::vector<m3dm_t> getMaterials();
  5835. std::string getMaterialName(int idx);
  5836. int getMaterialPropertyInt(int idx, int type);
  5837. uint32_t getMaterialPropertyColor(int idx, int type);
  5838. float getMaterialPropertyFloat(int idx, int type);
  5839. m3dtx_t *getMaterialPropertyMap(int idx, int type);
  5840. std::vector<m3dv_t> getVertices();
  5841. std::vector<m3df_t> getFace();
  5842. std::vector<m3dh_t> getShape();
  5843. std::string getShapeName(int idx);
  5844. unsigned int getShapeGroup(int idx);
  5845. std::vector<m3dc_t> getShapeCommands(int idx);
  5846. std::vector<m3dl_t> getAnnotationLabels();
  5847. std::vector<m3ds_t> getSkin();
  5848. std::vector<m3da_t> getActions();
  5849. std::string getActionName(int aidx);
  5850. unsigned int getActionDuration(int aidx);
  5851. std::vector<m3dfr_t> getActionFrames(int aidx);
  5852. unsigned int getActionFrameTimestamp(int aidx, int fidx);
  5853. std::vector<m3dtr_t> getActionFrameTransforms(int aidx, int fidx);
  5854. std::vector<m3dtr_t> getActionFrame(int aidx, int fidx, std::vector<m3dtr_t> skeleton);
  5855. std::vector<m3db_t> getActionPose(int aidx, unsigned int msec);
  5856. std::vector<m3di_t> getInlinedAssets();
  5857. std::vector<std::unique_ptr<m3dchunk_t>> getExtras();
  5858. std::vector<unsigned char> Save(int quality, int flags);
  5859. };
  5860. #endif /* impl */
  5861. } // namespace M3D
  5862. #endif /* M3D_CPPWRAPPER */
  5863. #if _MSC_VER > 1920 && !defined(__clang__)
  5864. # pragma warning(pop)
  5865. #endif /* _MSC_VER */
  5866. #endif /* __cplusplus */
  5867. #endif