m3d.h 216 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902
  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 chosen 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 probably 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_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H)
  577. /* zlib_compressor from
  578. stb_image_write - v1.13 - public domain - http://nothings.org/stb/stb_image_write.h
  579. */
  580. typedef unsigned char _m3dstbiw__uc;
  581. typedef unsigned short _m3dstbiw__us;
  582. typedef uint16_t _m3dstbiw__uint16;
  583. typedef int16_t _m3dstbiw__int16;
  584. typedef uint32_t _m3dstbiw__uint32;
  585. typedef int32_t _m3dstbiw__int32;
  586. #define STBIW_MALLOC(s) M3D_MALLOC(s)
  587. #define STBIW_REALLOC(p, ns) M3D_REALLOC(p, ns)
  588. #define STBIW_REALLOC_SIZED(p, oldsz, newsz) STBIW_REALLOC(p, newsz)
  589. #define STBIW_FREE M3D_FREE
  590. #define STBIW_MEMMOVE memmove
  591. #define STBIW_UCHAR (uint8_t)
  592. #define STBIW_ASSERT(x)
  593. #define _m3dstbiw___sbraw(a) ((int *)(a)-2)
  594. #define _m3dstbiw___sbm(a) _m3dstbiw___sbraw(a)[0]
  595. #define _m3dstbiw___sbn(a) _m3dstbiw___sbraw(a)[1]
  596. #define _m3dstbiw___sbneedgrow(a, n) ((a) == 0 || _m3dstbiw___sbn(a) + n >= _m3dstbiw___sbm(a))
  597. #define _m3dstbiw___sbmaybegrow(a, n) (_m3dstbiw___sbneedgrow(a, (n)) ? _m3dstbiw___sbgrow(a, n) : 0)
  598. #define _m3dstbiw___sbgrow(a, n) _m3dstbiw___sbgrowf((void **)&(a), (n), sizeof(*(a)))
  599. #define _m3dstbiw___sbpush(a, v) (_m3dstbiw___sbmaybegrow(a, 1), (a)[_m3dstbiw___sbn(a)++] = (v))
  600. #define _m3dstbiw___sbcount(a) ((a) ? _m3dstbiw___sbn(a) : 0)
  601. #define _m3dstbiw___sbfree(a) ((a) ? STBIW_FREE(_m3dstbiw___sbraw(a)), 0 : 0)
  602. static void *_m3dstbiw___sbgrowf(void **arr, int increment, int itemsize) {
  603. int m = *arr ? 2 * _m3dstbiw___sbm(*arr) + increment : increment + 1;
  604. void *p = STBIW_REALLOC_SIZED(*arr ? _m3dstbiw___sbraw(*arr) : 0, *arr ? (_m3dstbiw___sbm(*arr) * itemsize + sizeof(int) * 2) : 0, itemsize * m + sizeof(int) * 2);
  605. STBIW_ASSERT(p);
  606. if (p) {
  607. if (!*arr) ((int *)p)[1] = 0;
  608. *arr = (void *)((int *)p + 2);
  609. _m3dstbiw___sbm(*arr) = m;
  610. }
  611. return *arr;
  612. }
  613. static unsigned char *_m3dstbiw___zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) {
  614. while (*bitcount >= 8) {
  615. _m3dstbiw___sbpush(data, STBIW_UCHAR(*bitbuffer));
  616. *bitbuffer >>= 8;
  617. *bitcount -= 8;
  618. }
  619. return data;
  620. }
  621. static int _m3dstbiw___zlib_bitrev(int code, int codebits) {
  622. int res = 0;
  623. while (codebits--) {
  624. res = (res << 1) | (code & 1);
  625. code >>= 1;
  626. }
  627. return res;
  628. }
  629. static unsigned int _m3dstbiw___zlib_countm(unsigned char *a, unsigned char *b, int limit) {
  630. int i;
  631. for (i = 0; i < limit && i < 258; ++i)
  632. if (a[i] != b[i]) break;
  633. return i;
  634. }
  635. static unsigned int _m3dstbiw___zhash(unsigned char *data) {
  636. _m3dstbiw__uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
  637. hash ^= hash << 3;
  638. hash += hash >> 5;
  639. hash ^= hash << 4;
  640. hash += hash >> 17;
  641. hash ^= hash << 25;
  642. hash += hash >> 6;
  643. return hash;
  644. }
  645. #define _m3dstbiw___zlib_flush() (out = _m3dstbiw___zlib_flushf(out, &bitbuf, &bitcount))
  646. #define _m3dstbiw___zlib_add(code, codebits) \
  647. (bitbuf |= (code) << bitcount, bitcount += (codebits), _m3dstbiw___zlib_flush())
  648. #define _m3dstbiw___zlib_huffa(b, c) _m3dstbiw___zlib_add(_m3dstbiw___zlib_bitrev(b, c), c)
  649. #define _m3dstbiw___zlib_huff1(n) _m3dstbiw___zlib_huffa(0x30 + (n), 8)
  650. #define _m3dstbiw___zlib_huff2(n) _m3dstbiw___zlib_huffa(0x190 + (n)-144, 9)
  651. #define _m3dstbiw___zlib_huff3(n) _m3dstbiw___zlib_huffa(0 + (n)-256, 7)
  652. #define _m3dstbiw___zlib_huff4(n) _m3dstbiw___zlib_huffa(0xc0 + (n)-280, 8)
  653. #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))
  654. #define _m3dstbiw___zlib_huffb(n) ((n) <= 143 ? _m3dstbiw___zlib_huff1(n) : _m3dstbiw___zlib_huff2(n))
  655. #define _m3dstbiw___ZHASH 16384
  656. unsigned char *_m3dstbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) {
  657. 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 };
  658. 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 };
  659. 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 };
  660. 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 };
  661. unsigned int bitbuf = 0;
  662. int i, j, bitcount = 0;
  663. unsigned char *out = NULL;
  664. unsigned char ***hash_table = (unsigned char ***)STBIW_MALLOC(_m3dstbiw___ZHASH * sizeof(char **));
  665. if (hash_table == NULL)
  666. return NULL;
  667. if (quality < 5) quality = 5;
  668. _m3dstbiw___sbpush(out, 0x78);
  669. _m3dstbiw___sbpush(out, 0x5e);
  670. _m3dstbiw___zlib_add(1, 1);
  671. _m3dstbiw___zlib_add(1, 2);
  672. for (i = 0; i < _m3dstbiw___ZHASH; ++i)
  673. hash_table[i] = NULL;
  674. i = 0;
  675. while (i < data_len - 3) {
  676. int h = _m3dstbiw___zhash(data + i) & (_m3dstbiw___ZHASH - 1), best = 3;
  677. unsigned char *bestloc = 0;
  678. unsigned char **hlist = hash_table[h];
  679. int n = _m3dstbiw___sbcount(hlist);
  680. for (j = 0; j < n; ++j) {
  681. if (hlist[j] - data > i - 32768) {
  682. int d = _m3dstbiw___zlib_countm(hlist[j], data + i, data_len - i);
  683. if (d >= best) best = d, bestloc = hlist[j];
  684. }
  685. }
  686. if (hash_table[h] && _m3dstbiw___sbn(hash_table[h]) == 2 * quality) {
  687. STBIW_MEMMOVE(hash_table[h], hash_table[h] + quality, sizeof(hash_table[h][0]) * quality);
  688. _m3dstbiw___sbn(hash_table[h]) = quality;
  689. }
  690. _m3dstbiw___sbpush(hash_table[h], data + i);
  691. if (bestloc) {
  692. h = _m3dstbiw___zhash(data + i + 1) & (_m3dstbiw___ZHASH - 1);
  693. hlist = hash_table[h];
  694. n = _m3dstbiw___sbcount(hlist);
  695. for (j = 0; j < n; ++j) {
  696. if (hlist[j] - data > i - 32767) {
  697. int e = _m3dstbiw___zlib_countm(hlist[j], data + i + 1, data_len - i - 1);
  698. if (e > best) {
  699. bestloc = NULL;
  700. break;
  701. }
  702. }
  703. }
  704. }
  705. if (bestloc) {
  706. int d = (int)(data + i - bestloc);
  707. STBIW_ASSERT(d <= 32767 && best <= 258);
  708. for (j = 0; best > lengthc[j + 1] - 1; ++j)
  709. ;
  710. _m3dstbiw___zlib_huff(j + 257);
  711. if (lengtheb[j]) _m3dstbiw___zlib_add(best - lengthc[j], lengtheb[j]);
  712. for (j = 0; d > distc[j + 1] - 1; ++j)
  713. ;
  714. _m3dstbiw___zlib_add(_m3dstbiw___zlib_bitrev(j, 5), 5);
  715. if (disteb[j]) _m3dstbiw___zlib_add(d - distc[j], disteb[j]);
  716. i += best;
  717. } else {
  718. _m3dstbiw___zlib_huffb(data[i]);
  719. ++i;
  720. }
  721. }
  722. for (; i < data_len; ++i)
  723. _m3dstbiw___zlib_huffb(data[i]);
  724. _m3dstbiw___zlib_huff(256);
  725. while (bitcount)
  726. _m3dstbiw___zlib_add(0, 1);
  727. for (i = 0; i < _m3dstbiw___ZHASH; ++i)
  728. (void)_m3dstbiw___sbfree(hash_table[i]);
  729. STBIW_FREE(hash_table);
  730. {
  731. unsigned int s1 = 1, s2 = 0;
  732. int blocklen = (int)(data_len % 5552);
  733. j = 0;
  734. while (j < data_len) {
  735. for (i = 0; i < blocklen; ++i)
  736. s1 += data[j + i], s2 += s1;
  737. s1 %= 65521, s2 %= 65521;
  738. j += blocklen;
  739. blocklen = 5552;
  740. }
  741. _m3dstbiw___sbpush(out, STBIW_UCHAR(s2 >> 8));
  742. _m3dstbiw___sbpush(out, STBIW_UCHAR(s2));
  743. _m3dstbiw___sbpush(out, STBIW_UCHAR(s1 >> 8));
  744. _m3dstbiw___sbpush(out, STBIW_UCHAR(s1));
  745. }
  746. *out_len = _m3dstbiw___sbn(out);
  747. STBIW_MEMMOVE(_m3dstbiw___sbraw(out), out, *out_len);
  748. return (unsigned char *)_m3dstbiw___sbraw(out);
  749. }
  750. #define stbi_zlib_compress _m3dstbi_zlib_compress
  751. #else
  752. unsigned char *_m3dstbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality);
  753. #endif
  754. #define M3D_CHUNKMAGIC(m, a, b, c, d) ((m)[0] == (a) && (m)[1] == (b) && (m)[2] == (c) && (m)[3] == (d))
  755. #include <locale.h> /* sprintf and strtod cares about number locale */
  756. #include <stdio.h> /* get sprintf */
  757. #ifdef M3D_PROFILING
  758. #include <sys/time.h>
  759. #endif
  760. #if !defined(M3D_NOIMPORTER)
  761. /* helper functions for the ASCII parser */
  762. static char *_m3d_findarg(char *s) {
  763. while (s && *s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n')
  764. s++;
  765. while (s && *s && (*s == ' ' || *s == '\t'))
  766. s++;
  767. return s;
  768. }
  769. static char *_m3d_findnl(char *s) {
  770. while (s && *s && *s != '\r' && *s != '\n')
  771. s++;
  772. if (*s == '\r') s++;
  773. if (*s == '\n') s++;
  774. return s;
  775. }
  776. static char *_m3d_gethex(char *s, uint32_t *ret) {
  777. if (*s == '#') s++;
  778. *ret = 0;
  779. for (; *s; s++) {
  780. if (*s >= '0' && *s <= '9') {
  781. *ret <<= 4;
  782. *ret += (uint32_t)(*s - '0');
  783. } else if (*s >= 'a' && *s <= 'f') {
  784. *ret <<= 4;
  785. *ret += (uint32_t)(*s - 'a' + 10);
  786. } else if (*s >= 'A' && *s <= 'F') {
  787. *ret <<= 4;
  788. *ret += (uint32_t)(*s - 'A' + 10);
  789. } else
  790. break;
  791. }
  792. return _m3d_findarg(s);
  793. }
  794. static char *_m3d_getint(char *s, uint32_t *ret) {
  795. char *e = s;
  796. if (!s || !*s || *s == '\r' || *s == '\n') return s;
  797. for (; *e >= '0' && *e <= '9'; e++)
  798. ;
  799. *ret = atoi(s);
  800. return e;
  801. }
  802. static char *_m3d_getfloat(char *s, M3D_FLOAT *ret) {
  803. char *e = s;
  804. if (!s || !*s || *s == '\r' || *s == '\n') return s;
  805. for (; *e == '-' || *e == '+' || *e == '.' || (*e >= '0' && *e <= '9') || *e == 'e' || *e == 'E'; e++)
  806. ;
  807. *ret = (M3D_FLOAT)strtod(s, NULL);
  808. return _m3d_findarg(e);
  809. }
  810. #endif
  811. #if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER))
  812. /* helper function to create safe strings */
  813. char *_m3d_safestr(char *in, int morelines) {
  814. char *out, *o, *i = in;
  815. int l;
  816. if (!in || !*in) {
  817. out = (char *)M3D_MALLOC(1);
  818. if (!out) return NULL;
  819. out[0] = 0;
  820. } else {
  821. for (o = in, l = 0; *o && ((morelines & 1) || (*o != '\r' && *o != '\n')) && l < 256; o++, l++)
  822. ;
  823. out = o = (char *)M3D_MALLOC(l + 1);
  824. if (!out) return NULL;
  825. while (*i == ' ' || *i == '\t' || *i == '\r' || (morelines && *i == '\n'))
  826. i++;
  827. for (; *i && (morelines || (*i != '\r' && *i != '\n')) && o - out < l; i++) {
  828. if (*i == '\r') continue;
  829. if (*i == '\n') {
  830. if (morelines >= 3 && o > out && *(o - 1) == '\n') break;
  831. if (i > in && *(i - 1) == '\n') continue;
  832. if (morelines & 1) {
  833. if (morelines == 1) *o++ = '\r';
  834. *o++ = '\n';
  835. } else
  836. break;
  837. } else if (*i == ' ' || *i == '\t') {
  838. *o++ = morelines ? ' ' : '_';
  839. } else
  840. *o++ = !morelines && (*i == '/' || *i == '\\') ? '_' : *i;
  841. }
  842. for (; o > out && (*(o - 1) == ' ' || *(o - 1) == '\t' || *(o - 1) == '\r' || *(o - 1) == '\n'); o--)
  843. ;
  844. *o = 0;
  845. out = (char *)M3D_REALLOC(out, (uintptr_t)o - (uintptr_t)out + 1);
  846. }
  847. return out;
  848. }
  849. #endif
  850. #ifndef M3D_NOIMPORTER
  851. /* helper function to load and decode/generate a texture */
  852. M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char *fn) {
  853. unsigned int i, len = 0;
  854. unsigned char *buff = NULL;
  855. char *fn2;
  856. #ifdef STBI__PNG_TYPE
  857. unsigned int w, h;
  858. stbi__context s;
  859. stbi__result_info ri;
  860. #endif
  861. /* do we have loaded this texture already? */
  862. for (i = 0; i < model->numtexture; i++)
  863. if (!strcmp(fn, model->texture[i].name)) return i;
  864. /* see if it's inlined in the model */
  865. if (model->inlined) {
  866. for (i = 0; i < model->numinlined; i++)
  867. if (!strcmp(fn, model->inlined[i].name)) {
  868. buff = model->inlined[i].data;
  869. len = model->inlined[i].length;
  870. freecb = NULL;
  871. break;
  872. }
  873. }
  874. /* try to load from external source */
  875. if (!buff && readfilecb) {
  876. i = (unsigned int)strlen(fn);
  877. if (i < 5 || fn[i - 4] != '.') {
  878. fn2 = (char *)M3D_MALLOC(i + 5);
  879. if (!fn2) {
  880. model->errcode = M3D_ERR_ALLOC;
  881. return M3D_UNDEF;
  882. }
  883. memcpy(fn2, fn, i);
  884. memcpy(fn2 + i, ".png", 5);
  885. buff = (*readfilecb)(fn2, &len);
  886. M3D_FREE(fn2);
  887. }
  888. if (!buff) {
  889. buff = (*readfilecb)(fn, &len);
  890. if (!buff) return M3D_UNDEF;
  891. }
  892. }
  893. /* add to textures array */
  894. i = model->numtexture++;
  895. model->texture = (m3dtx_t *)M3D_REALLOC(model->texture, model->numtexture * sizeof(m3dtx_t));
  896. if (!model->texture) {
  897. if (buff && freecb) (*freecb)(buff);
  898. model->errcode = M3D_ERR_ALLOC;
  899. return M3D_UNDEF;
  900. }
  901. model->texture[i].name = fn;
  902. model->texture[i].w = model->texture[i].h = 0;
  903. model->texture[i].d = NULL;
  904. if (buff) {
  905. if (buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
  906. #ifdef STBI__PNG_TYPE
  907. s.read_from_callbacks = 0;
  908. s.img_buffer = s.img_buffer_original = (unsigned char *)buff;
  909. s.img_buffer_end = s.img_buffer_original_end = (unsigned char *)buff + len;
  910. /* don't use model->texture[i].w directly, it's a uint16_t */
  911. w = h = len = 0;
  912. ri.bits_per_channel = 8;
  913. model->texture[i].d = (uint8_t *)stbi__png_load(&s, (int *)&w, (int *)&h, (int *)&len, 0, &ri);
  914. model->texture[i].w = (uint16_t)w;
  915. model->texture[i].h = (uint16_t)h;
  916. model->texture[i].f = (uint8_t)len;
  917. #endif
  918. } else {
  919. #ifdef M3D_TX_INTERP
  920. if ((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
  921. M3D_LOG("Unable to generate texture");
  922. M3D_LOG(fn);
  923. }
  924. #else
  925. M3D_LOG("Unimplemented interpreter");
  926. M3D_LOG(fn);
  927. #endif
  928. }
  929. if (freecb) (*freecb)(buff);
  930. }
  931. if (!model->texture[i].d)
  932. model->errcode = M3D_ERR_UNKIMG;
  933. return i;
  934. }
  935. /* helper function to load and generate a procedural surface */
  936. void _m3d_getpr(m3d_t *model, _unused m3dread_t readfilecb, _unused m3dfree_t freecb, _unused char *fn) {
  937. #ifdef M3D_PR_INTERP
  938. unsigned int i, len = 0;
  939. unsigned char *buff = readfilecb ? (*readfilecb)(fn, &len) : NULL;
  940. if (!buff && model->inlined) {
  941. for (i = 0; i < model->numinlined; i++)
  942. if (!strcmp(fn, model->inlined[i].name)) {
  943. buff = model->inlined[i].data;
  944. len = model->inlined[i].length;
  945. freecb = NULL;
  946. break;
  947. }
  948. }
  949. if (!buff || !len || (model->errcode = M3D_PR_INTERP(fn, buff, len, model)) != M3D_SUCCESS) {
  950. M3D_LOG("Unable to generate procedural surface");
  951. M3D_LOG(fn);
  952. model->errcode = M3D_ERR_UNKIMG;
  953. }
  954. if (freecb && buff) (*freecb)(buff);
  955. #else
  956. (void)readfilecb;
  957. (void)freecb;
  958. (void)fn;
  959. M3D_LOG("Unimplemented interpreter");
  960. M3D_LOG(fn);
  961. model->errcode = M3D_ERR_UNIMPL;
  962. #endif
  963. }
  964. /* helpers to read indices from data stream */
  965. #define M3D_GETSTR(x) \
  966. do { \
  967. offs = 0; \
  968. data = _m3d_getidx(data, model->si_s, &offs); \
  969. x = offs ? ((char *)model->raw + 16 + offs) : NULL; \
  970. } while (0)
  971. _inline static unsigned char *_m3d_getidx(unsigned char *data, char type, M3D_INDEX *idx) {
  972. switch (type) {
  973. case 1:
  974. *idx = data[0] > 253 ? (int8_t)data[0] : data[0];
  975. data++;
  976. break;
  977. case 2:
  978. *idx = *((uint16_t *)data) > 65533 ? *((int16_t *)data) : *((uint16_t *)data);
  979. data += 2;
  980. break;
  981. case 4:
  982. *idx = *((int32_t *)data);
  983. data += 4;
  984. break;
  985. }
  986. return data;
  987. }
  988. #ifndef M3D_NOANIMATION
  989. /* multiply 4 x 4 matrices. Do not use float *r[16] as argument, because some compilers misinterpret that as
  990. * 16 pointers each pointing to a float, but we need a single pointer to 16 floats. */
  991. void _m3d_mul(M3D_FLOAT *r, M3D_FLOAT *a, M3D_FLOAT *b) {
  992. r[0] = b[0] * a[0] + b[4] * a[1] + b[8] * a[2] + b[12] * a[3];
  993. r[1] = b[1] * a[0] + b[5] * a[1] + b[9] * a[2] + b[13] * a[3];
  994. r[2] = b[2] * a[0] + b[6] * a[1] + b[10] * a[2] + b[14] * a[3];
  995. r[3] = b[3] * a[0] + b[7] * a[1] + b[11] * a[2] + b[15] * a[3];
  996. r[4] = b[0] * a[4] + b[4] * a[5] + b[8] * a[6] + b[12] * a[7];
  997. r[5] = b[1] * a[4] + b[5] * a[5] + b[9] * a[6] + b[13] * a[7];
  998. r[6] = b[2] * a[4] + b[6] * a[5] + b[10] * a[6] + b[14] * a[7];
  999. r[7] = b[3] * a[4] + b[7] * a[5] + b[11] * a[6] + b[15] * a[7];
  1000. r[8] = b[0] * a[8] + b[4] * a[9] + b[8] * a[10] + b[12] * a[11];
  1001. r[9] = b[1] * a[8] + b[5] * a[9] + b[9] * a[10] + b[13] * a[11];
  1002. r[10] = b[2] * a[8] + b[6] * a[9] + b[10] * a[10] + b[14] * a[11];
  1003. r[11] = b[3] * a[8] + b[7] * a[9] + b[11] * a[10] + b[15] * a[11];
  1004. r[12] = b[0] * a[12] + b[4] * a[13] + b[8] * a[14] + b[12] * a[15];
  1005. r[13] = b[1] * a[12] + b[5] * a[13] + b[9] * a[14] + b[13] * a[15];
  1006. r[14] = b[2] * a[12] + b[6] * a[13] + b[10] * a[14] + b[14] * a[15];
  1007. r[15] = b[3] * a[12] + b[7] * a[13] + b[11] * a[14] + b[15] * a[15];
  1008. }
  1009. /* calculate 4 x 4 matrix inverse */
  1010. void _m3d_inv(M3D_FLOAT *m) {
  1011. M3D_FLOAT r[16];
  1012. M3D_FLOAT det =
  1013. 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];
  1014. if (det == (M3D_FLOAT)0.0 || det == (M3D_FLOAT)-0.0)
  1015. det = (M3D_FLOAT)1.0;
  1016. else
  1017. det = (M3D_FLOAT)1.0 / det;
  1018. 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]));
  1019. 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]));
  1020. 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]));
  1021. 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]));
  1022. 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]));
  1023. 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]));
  1024. 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]));
  1025. 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]));
  1026. 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]));
  1027. 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]));
  1028. 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]));
  1029. 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]));
  1030. 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]));
  1031. 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]));
  1032. 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]));
  1033. 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]));
  1034. memcpy(m, &r, sizeof(r));
  1035. }
  1036. /* compose a column major 4 x 4 matrix from vec3 position and vec4 orientation/rotation quaternion */
  1037. void _m3d_mat(M3D_FLOAT *r, m3dv_t *p, m3dv_t *q) {
  1038. 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 &&
  1039. q->w == (M3D_FLOAT)0.0) {
  1040. r[1] = r[2] = r[4] = r[6] = r[8] = r[9] = (M3D_FLOAT)0.0;
  1041. r[0] = r[5] = r[10] = (M3D_FLOAT)-1.0;
  1042. } else {
  1043. r[0] = 1 - 2 * (q->y * q->y + q->z * q->z);
  1044. if (r[0] > -M3D_EPSILON && r[0] < M3D_EPSILON) r[0] = (M3D_FLOAT)0.0;
  1045. r[1] = 2 * (q->x * q->y - q->z * q->w);
  1046. if (r[1] > -M3D_EPSILON && r[1] < M3D_EPSILON) r[1] = (M3D_FLOAT)0.0;
  1047. r[2] = 2 * (q->x * q->z + q->y * q->w);
  1048. if (r[2] > -M3D_EPSILON && r[2] < M3D_EPSILON) r[2] = (M3D_FLOAT)0.0;
  1049. r[4] = 2 * (q->x * q->y + q->z * q->w);
  1050. if (r[4] > -M3D_EPSILON && r[4] < M3D_EPSILON) r[4] = (M3D_FLOAT)0.0;
  1051. r[5] = 1 - 2 * (q->x * q->x + q->z * q->z);
  1052. if (r[5] > -M3D_EPSILON && r[5] < M3D_EPSILON) r[5] = (M3D_FLOAT)0.0;
  1053. r[6] = 2 * (q->y * q->z - q->x * q->w);
  1054. if (r[6] > -M3D_EPSILON && r[6] < M3D_EPSILON) r[6] = (M3D_FLOAT)0.0;
  1055. r[8] = 2 * (q->x * q->z - q->y * q->w);
  1056. if (r[8] > -M3D_EPSILON && r[8] < M3D_EPSILON) r[8] = (M3D_FLOAT)0.0;
  1057. r[9] = 2 * (q->y * q->z + q->x * q->w);
  1058. if (r[9] > -M3D_EPSILON && r[9] < M3D_EPSILON) r[9] = (M3D_FLOAT)0.0;
  1059. r[10] = 1 - 2 * (q->x * q->x + q->y * q->y);
  1060. if (r[10] > -M3D_EPSILON && r[10] < M3D_EPSILON) r[10] = (M3D_FLOAT)0.0;
  1061. }
  1062. r[3] = p->x;
  1063. r[7] = p->y;
  1064. r[11] = p->z;
  1065. r[12] = 0;
  1066. r[13] = 0;
  1067. r[14] = 0;
  1068. r[15] = 1;
  1069. }
  1070. #endif
  1071. #if !defined(M3D_NOANIMATION) || !defined(M3D_NONORMALS)
  1072. /* portable fast inverse square root calculation. returns 1/sqrt(x) */
  1073. static M3D_FLOAT _m3d_rsq(M3D_FLOAT x) {
  1074. #ifdef M3D_DOUBLE
  1075. 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;
  1076. #else
  1077. /* John Carmack's */
  1078. float x2 = x * 0.5f;
  1079. *((uint32_t *)&x) = (0x5f3759df - (*((uint32_t *)&x) >> 1));
  1080. return x * (1.5f - (x2 * x * x));
  1081. #endif
  1082. }
  1083. #endif
  1084. /**
  1085. * Function to decode a Model 3D into in-memory format
  1086. */
  1087. m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d_t *mtllib) {
  1088. unsigned char *end, *chunk, *buff, weights[8];
  1089. unsigned int i, j, k, l, n, am, len = 0, reclen, offs;
  1090. char *name, *lang;
  1091. float f;
  1092. m3d_t *model;
  1093. M3D_INDEX mi;
  1094. M3D_FLOAT w;
  1095. m3dcd_t *cd;
  1096. m3dtx_t *tx;
  1097. m3dh_t *h;
  1098. m3dm_t *m;
  1099. m3da_t *a;
  1100. m3di_t *t;
  1101. #ifndef M3D_NONORMALS
  1102. char neednorm = 0;
  1103. m3dv_t *norm = NULL, *v0, *v1, *v2, va, vb;
  1104. #endif
  1105. #ifndef M3D_NOANIMATION
  1106. M3D_FLOAT r[16];
  1107. #endif
  1108. #if !defined(M3D_NOWEIGHTS) || !defined(M3D_NOANIMATION)
  1109. m3db_t *b;
  1110. #endif
  1111. #ifndef M3D_NOWEIGHTS
  1112. m3ds_t *sk;
  1113. #endif
  1114. m3ds_t s;
  1115. M3D_INDEX bi[M3D_BONEMAXLEVEL + 1], level;
  1116. const char *ol;
  1117. char *ptr, *pe, *fn;
  1118. #ifdef M3D_PROFILING
  1119. struct timeval tv0, tv1, tvd;
  1120. gettimeofday(&tv0, NULL);
  1121. #endif
  1122. if (!data || (!M3D_CHUNKMAGIC(data, '3', 'D', 'M', 'O')
  1123. && !M3D_CHUNKMAGIC(data, '3', 'd', 'm', 'o')
  1124. ))
  1125. return NULL;
  1126. model = (m3d_t *)M3D_MALLOC(sizeof(m3d_t));
  1127. if (!model) {
  1128. M3D_LOG("Out of memory");
  1129. return NULL;
  1130. }
  1131. memset(model, 0, sizeof(m3d_t));
  1132. if (mtllib) {
  1133. model->nummaterial = mtllib->nummaterial;
  1134. model->material = mtllib->material;
  1135. model->numtexture = mtllib->numtexture;
  1136. model->texture = mtllib->texture;
  1137. model->flags |= M3D_FLG_MTLLIB;
  1138. }
  1139. /* ASCII variant? */
  1140. if (M3D_CHUNKMAGIC(data, '3', 'd', 'm', 'o')) {
  1141. model->errcode = M3D_ERR_BADFILE;
  1142. model->flags |= M3D_FLG_FREESTR;
  1143. model->raw = (m3dhdr_t *)data;
  1144. ptr = (char *)data;
  1145. ol = setlocale(LC_NUMERIC, NULL);
  1146. setlocale(LC_NUMERIC, "C");
  1147. /* parse header. Don't use sscanf, that's incredibly slow */
  1148. ptr = _m3d_findarg(ptr);
  1149. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1150. pe = _m3d_findnl(ptr);
  1151. model->scale = (float)strtod(ptr, NULL);
  1152. ptr = pe;
  1153. if (model->scale <= (M3D_FLOAT)0.0) model->scale = (M3D_FLOAT)1.0;
  1154. model->name = _m3d_safestr(ptr, 2);
  1155. ptr = _m3d_findnl(ptr);
  1156. if (!*ptr) goto asciiend;
  1157. model->license = _m3d_safestr(ptr, 2);
  1158. ptr = _m3d_findnl(ptr);
  1159. if (!*ptr) goto asciiend;
  1160. model->author = _m3d_safestr(ptr, 2);
  1161. ptr = _m3d_findnl(ptr);
  1162. if (!*ptr) goto asciiend;
  1163. if (*ptr != '\r' && *ptr != '\n')
  1164. model->desc = _m3d_safestr(ptr, 3);
  1165. while (*ptr) {
  1166. while (*ptr && *ptr != '\n')
  1167. ptr++;
  1168. ptr++;
  1169. if (*ptr == '\r') ptr++;
  1170. if (*ptr == '\n') break;
  1171. }
  1172. /* the main chunk reader loop */
  1173. while (*ptr) {
  1174. while (*ptr && (*ptr == '\r' || *ptr == '\n'))
  1175. ptr++;
  1176. if (!*ptr || (ptr[0] == 'E' && ptr[1] == 'n' && ptr[2] == 'd')) break;
  1177. /* make sure there's at least one data row */
  1178. pe = ptr;
  1179. ptr = _m3d_findnl(ptr);
  1180. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1181. /* Preview chunk */
  1182. if (!memcmp(pe, "Preview", 7)) {
  1183. if (readfilecb) {
  1184. pe = _m3d_safestr(ptr, 0);
  1185. if (!pe || !*pe) goto asciiend;
  1186. model->preview.data = (*readfilecb)(pe, &model->preview.length);
  1187. M3D_FREE(pe);
  1188. }
  1189. while (*ptr && *ptr != '\r' && *ptr != '\n')
  1190. ptr = _m3d_findnl(ptr);
  1191. } else
  1192. /* texture map chunk */
  1193. if (!memcmp(pe, "Textmap", 7)) {
  1194. if (model->tmap) {
  1195. M3D_LOG("More texture map chunks, should be unique");
  1196. goto asciiend;
  1197. }
  1198. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1199. i = model->numtmap++;
  1200. model->tmap = (m3dti_t *)M3D_REALLOC(model->tmap, model->numtmap * sizeof(m3dti_t));
  1201. if (!model->tmap) goto memerr;
  1202. ptr = _m3d_getfloat(ptr, &model->tmap[i].u);
  1203. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1204. _m3d_getfloat(ptr, &model->tmap[i].v);
  1205. ptr = _m3d_findnl(ptr);
  1206. }
  1207. } else
  1208. /* vertex chunk */
  1209. if (!memcmp(pe, "Vertex", 6)) {
  1210. if (model->vertex) {
  1211. M3D_LOG("More vertex chunks, should be unique");
  1212. goto asciiend;
  1213. }
  1214. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1215. i = model->numvertex++;
  1216. model->vertex = (m3dv_t *)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t));
  1217. if (!model->vertex) goto memerr;
  1218. memset(&model->vertex[i], 0, sizeof(m3dv_t));
  1219. model->vertex[i].skinid = M3D_UNDEF;
  1220. model->vertex[i].color = 0;
  1221. model->vertex[i].w = (M3D_FLOAT)1.0;
  1222. ptr = _m3d_getfloat(ptr, &model->vertex[i].x);
  1223. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1224. ptr = _m3d_getfloat(ptr, &model->vertex[i].y);
  1225. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1226. ptr = _m3d_getfloat(ptr, &model->vertex[i].z);
  1227. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1228. ptr = _m3d_getfloat(ptr, &model->vertex[i].w);
  1229. if (!*ptr) goto asciiend;
  1230. if (*ptr == '#') {
  1231. ptr = _m3d_gethex(ptr, &model->vertex[i].color);
  1232. if (!*ptr) goto asciiend;
  1233. }
  1234. /* parse skin */
  1235. memset(&s, 0, sizeof(m3ds_t));
  1236. for (j = 0, w = (M3D_FLOAT)0.0; j < M3D_NUMBONE && *ptr && *ptr != '\r' && *ptr != '\n'; j++) {
  1237. ptr = _m3d_findarg(ptr);
  1238. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1239. ptr = _m3d_getint(ptr, &k);
  1240. s.boneid[j] = (M3D_INDEX)k;
  1241. if (*ptr == ':') {
  1242. ptr++;
  1243. ptr = _m3d_getfloat(ptr, &s.weight[j]);
  1244. w += s.weight[j];
  1245. } else if (!j)
  1246. s.weight[j] = (M3D_FLOAT)1.0;
  1247. if (!*ptr) goto asciiend;
  1248. }
  1249. if (s.boneid[0] != M3D_UNDEF && s.weight[0] > (M3D_FLOAT)0.0) {
  1250. if (w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0)
  1251. for (j = 0; j < M3D_NUMBONE && s.weight[j] > (M3D_FLOAT)0.0; j++)
  1252. s.weight[j] /= w;
  1253. k = M3D_NOTDEFINED;
  1254. if (model->skin) {
  1255. for (j = 0; j < model->numskin; j++)
  1256. if (!memcmp(&model->skin[j], &s, sizeof(m3ds_t))) {
  1257. k = j;
  1258. break;
  1259. }
  1260. }
  1261. if (k == M3D_NOTDEFINED) {
  1262. k = model->numskin++;
  1263. model->skin = (m3ds_t *)M3D_REALLOC(model->skin, model->numskin * sizeof(m3ds_t));
  1264. memcpy(&model->skin[k], &s, sizeof(m3ds_t));
  1265. }
  1266. model->vertex[i].skinid = (M3D_INDEX)k;
  1267. }
  1268. ptr = _m3d_findnl(ptr);
  1269. }
  1270. } else
  1271. /* Skeleton, bone hierarchy */
  1272. if (!memcmp(pe, "Bones", 5)) {
  1273. if (model->bone) {
  1274. M3D_LOG("More bones chunks, should be unique");
  1275. goto asciiend;
  1276. }
  1277. bi[0] = M3D_UNDEF;
  1278. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1279. i = model->numbone++;
  1280. model->bone = (m3db_t *)M3D_REALLOC(model->bone, model->numbone * sizeof(m3db_t));
  1281. if (!model->bone) goto memerr;
  1282. for (level = 0; *ptr == '/'; ptr++, level++)
  1283. ;
  1284. if (level > M3D_BONEMAXLEVEL || !*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1285. bi[level + 1] = i;
  1286. model->bone[i].numweight = 0;
  1287. model->bone[i].weight = NULL;
  1288. model->bone[i].parent = bi[level];
  1289. ptr = _m3d_getint(ptr, &k);
  1290. ptr = _m3d_findarg(ptr);
  1291. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1292. model->bone[i].pos = (M3D_INDEX)k;
  1293. ptr = _m3d_getint(ptr, &k);
  1294. ptr = _m3d_findarg(ptr);
  1295. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1296. model->bone[i].ori = (M3D_INDEX)k;
  1297. model->vertex[k].skinid = M3D_INDEXMAX;
  1298. pe = _m3d_safestr(ptr, 0);
  1299. if (!pe || !*pe) goto asciiend;
  1300. model->bone[i].name = pe;
  1301. ptr = _m3d_findnl(ptr);
  1302. }
  1303. } else
  1304. /* material chunk */
  1305. if (!memcmp(pe, "Material", 8)) {
  1306. pe = _m3d_findarg(pe);
  1307. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  1308. pe = _m3d_safestr(pe, 0);
  1309. if (!pe || !*pe) goto asciiend;
  1310. for (i = 0; i < model->nummaterial; i++)
  1311. if (!strcmp(pe, model->material[i].name)) {
  1312. M3D_LOG("Multiple definitions for material");
  1313. M3D_LOG(pe);
  1314. M3D_FREE(pe);
  1315. pe = NULL;
  1316. while (*ptr && *ptr != '\r' && *ptr != '\n')
  1317. ptr = _m3d_findnl(ptr);
  1318. break;
  1319. }
  1320. if (!pe) continue;
  1321. i = model->nummaterial++;
  1322. if (model->flags & M3D_FLG_MTLLIB) {
  1323. m = model->material;
  1324. model->material = (m3dm_t *)M3D_MALLOC(model->nummaterial * sizeof(m3dm_t));
  1325. if (!model->material) goto memerr;
  1326. memcpy(model->material, m, (model->nummaterial - 1) * sizeof(m3dm_t));
  1327. if (model->texture) {
  1328. tx = model->texture;
  1329. model->texture = (m3dtx_t *)M3D_MALLOC(model->numtexture * sizeof(m3dtx_t));
  1330. if (!model->texture) goto memerr;
  1331. memcpy(model->texture, tx, model->numtexture * sizeof(m3dm_t));
  1332. }
  1333. model->flags &= ~M3D_FLG_MTLLIB;
  1334. } else {
  1335. model->material = (m3dm_t *)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t));
  1336. if (!model->material) goto memerr;
  1337. }
  1338. m = &model->material[i];
  1339. m->name = pe;
  1340. m->numprop = 0;
  1341. m->prop = NULL;
  1342. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1343. k = n = 256;
  1344. if (*ptr == 'm' && *(ptr + 1) == 'a' && *(ptr + 2) == 'p' && *(ptr + 3) == '_') {
  1345. k = m3dpf_map;
  1346. ptr += 4;
  1347. }
  1348. for (j = 0; j < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); j++)
  1349. if (!memcmp(ptr, m3d_propertytypes[j].key, strlen(m3d_propertytypes[j].key))) {
  1350. n = m3d_propertytypes[j].id;
  1351. if (k != m3dpf_map) k = m3d_propertytypes[j].format;
  1352. break;
  1353. }
  1354. if (n != 256 && k != 256) {
  1355. ptr = _m3d_findarg(ptr);
  1356. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1357. j = m->numprop++;
  1358. m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t));
  1359. if (!m->prop) goto memerr;
  1360. m->prop[j].type = n + (k == m3dpf_map && n < 128 ? 128 : 0);
  1361. switch (k) {
  1362. case m3dpf_color: ptr = _m3d_gethex(ptr, &m->prop[j].value.color); break;
  1363. case m3dpf_uint8:
  1364. case m3dpf_uint16:
  1365. case m3dpf_uint32: ptr = _m3d_getint(ptr, &m->prop[j].value.num); break;
  1366. case m3dpf_float: ptr = _m3d_getfloat(ptr, &m->prop[j].value.fnum); break;
  1367. case m3dpf_map:
  1368. pe = _m3d_safestr(ptr, 0);
  1369. if (!pe || !*pe) goto asciiend;
  1370. m->prop[j].value.textureid = _m3d_gettx(model, readfilecb, freecb, pe);
  1371. if (model->errcode == M3D_ERR_ALLOC) {
  1372. M3D_FREE(pe);
  1373. goto memerr;
  1374. }
  1375. /* this error code only returned if readfilecb was specified */
  1376. if (m->prop[j].value.textureid == M3D_UNDEF) {
  1377. M3D_LOG("Texture not found");
  1378. M3D_LOG(pe);
  1379. m->numprop--;
  1380. }
  1381. M3D_FREE(pe);
  1382. break;
  1383. }
  1384. } else {
  1385. M3D_LOG("Unknown material property in");
  1386. M3D_LOG(m->name);
  1387. model->errcode = M3D_ERR_UNKPROP;
  1388. }
  1389. ptr = _m3d_findnl(ptr);
  1390. }
  1391. if (!m->numprop) model->nummaterial--;
  1392. } else
  1393. /* procedural */
  1394. if (!memcmp(pe, "Procedural", 10)) {
  1395. pe = _m3d_safestr(ptr, 0);
  1396. _m3d_getpr(model, readfilecb, freecb, pe);
  1397. M3D_FREE(pe);
  1398. while (*ptr && *ptr != '\r' && *ptr != '\n')
  1399. ptr = _m3d_findnl(ptr);
  1400. } else
  1401. /* mesh */
  1402. if (!memcmp(pe, "Mesh", 4)) {
  1403. mi = M3D_UNDEF;
  1404. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1405. if (*ptr == 'u') {
  1406. ptr = _m3d_findarg(ptr);
  1407. if (!*ptr) goto asciiend;
  1408. mi = M3D_UNDEF;
  1409. if (*ptr != '\r' && *ptr != '\n') {
  1410. pe = _m3d_safestr(ptr, 0);
  1411. if (!pe || !*pe) goto asciiend;
  1412. for (j = 0; j < model->nummaterial; j++)
  1413. if (!strcmp(pe, model->material[j].name)) {
  1414. mi = (M3D_INDEX)j;
  1415. break;
  1416. }
  1417. if (mi == M3D_UNDEF && !(model->flags & M3D_FLG_MTLLIB)) {
  1418. mi = model->nummaterial++;
  1419. model->material = (m3dm_t *)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t));
  1420. if (!model->material) goto memerr;
  1421. model->material[mi].name = pe;
  1422. model->material[mi].numprop = 1;
  1423. model->material[mi].prop = NULL;
  1424. } else
  1425. M3D_FREE(pe);
  1426. }
  1427. } else {
  1428. i = model->numface++;
  1429. model->face = (m3df_t *)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t));
  1430. if (!model->face) goto memerr;
  1431. memset(&model->face[i], 255, sizeof(m3df_t)); /* set all index to -1 by default */
  1432. model->face[i].materialid = mi;
  1433. /* hardcoded triangles. */
  1434. for (j = 0; j < 3; j++) {
  1435. /* vertex */
  1436. ptr = _m3d_getint(ptr, &k);
  1437. model->face[i].vertex[j] = (M3D_INDEX)k;
  1438. if (!*ptr) goto asciiend;
  1439. if (*ptr == '/') {
  1440. ptr++;
  1441. if (*ptr != '/') {
  1442. /* texcoord */
  1443. ptr = _m3d_getint(ptr, &k);
  1444. model->face[i].texcoord[j] = (M3D_INDEX)k;
  1445. if (!*ptr) goto asciiend;
  1446. }
  1447. if (*ptr == '/') {
  1448. ptr++;
  1449. /* normal */
  1450. ptr = _m3d_getint(ptr, &k);
  1451. model->face[i].normal[j] = (M3D_INDEX)k;
  1452. if (!*ptr) goto asciiend;
  1453. }
  1454. }
  1455. #ifndef M3D_NONORMALS
  1456. if (model->face[i].normal[j] == M3D_UNDEF) neednorm = 1;
  1457. #endif
  1458. ptr = _m3d_findarg(ptr);
  1459. }
  1460. }
  1461. ptr = _m3d_findnl(ptr);
  1462. }
  1463. } else
  1464. /* mathematical shape */
  1465. if (!memcmp(pe, "Shape", 5)) {
  1466. pe = _m3d_findarg(pe);
  1467. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  1468. pe = _m3d_safestr(pe, 0);
  1469. if (!pe || !*pe) goto asciiend;
  1470. i = model->numshape++;
  1471. model->shape = (m3dh_t *)M3D_REALLOC(model->shape, model->numshape * sizeof(m3ds_t));
  1472. if (!model->shape) goto memerr;
  1473. h = &model->shape[i];
  1474. h->name = pe;
  1475. h->group = M3D_UNDEF;
  1476. h->numcmd = 0;
  1477. h->cmd = NULL;
  1478. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1479. if (!memcmp(ptr, "group", 5)) {
  1480. ptr = _m3d_findarg(ptr);
  1481. ptr = _m3d_getint(ptr, &h->group);
  1482. ptr = _m3d_findnl(ptr);
  1483. if (h->group != M3D_UNDEF && h->group >= model->numbone) {
  1484. M3D_LOG("Unknown bone id as shape group in shape");
  1485. M3D_LOG(pe);
  1486. h->group = M3D_UNDEF;
  1487. model->errcode = M3D_ERR_SHPE;
  1488. }
  1489. continue;
  1490. }
  1491. for (cd = NULL, k = 0; k < (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0])); k++) {
  1492. j = (unsigned int)strlen(m3d_commandtypes[k].key);
  1493. if (!memcmp(ptr, m3d_commandtypes[k].key, j) && (ptr[j] == ' ' || ptr[j] == '\r' || ptr[j] == '\n')) {
  1494. cd = &m3d_commandtypes[k];
  1495. break;
  1496. }
  1497. }
  1498. if (cd) {
  1499. j = h->numcmd++;
  1500. h->cmd = (m3dc_t *)M3D_REALLOC(h->cmd, h->numcmd * sizeof(m3dc_t));
  1501. if (!h->cmd) goto memerr;
  1502. h->cmd[j].type = k;
  1503. h->cmd[j].arg = (uint32_t *)M3D_MALLOC(cd->p * sizeof(uint32_t));
  1504. if (!h->cmd[j].arg) goto memerr;
  1505. memset(h->cmd[j].arg, 0, cd->p * sizeof(uint32_t));
  1506. for (k = n = 0, l = cd->p; k < l; k++) {
  1507. ptr = _m3d_findarg(ptr);
  1508. if (!*ptr) goto asciiend;
  1509. if (*ptr == '[') {
  1510. ptr = _m3d_findarg(ptr + 1);
  1511. if (!*ptr) goto asciiend;
  1512. }
  1513. if (*ptr == ']' || *ptr == '\r' || *ptr == '\n') break;
  1514. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  1515. case m3dcp_mi_t:
  1516. mi = M3D_UNDEF;
  1517. if (*ptr != '\r' && *ptr != '\n') {
  1518. pe = _m3d_safestr(ptr, 0);
  1519. if (!pe || !*pe) goto asciiend;
  1520. for (n = 0; n < model->nummaterial; n++)
  1521. if (!strcmp(pe, model->material[n].name)) {
  1522. mi = (M3D_INDEX)n;
  1523. break;
  1524. }
  1525. if (mi == M3D_UNDEF && !(model->flags & M3D_FLG_MTLLIB)) {
  1526. mi = model->nummaterial++;
  1527. model->material = (m3dm_t *)M3D_REALLOC(model->material,
  1528. model->nummaterial * sizeof(m3dm_t));
  1529. if (!model->material) goto memerr;
  1530. model->material[mi].name = pe;
  1531. model->material[mi].numprop = 1;
  1532. model->material[mi].prop = NULL;
  1533. } else
  1534. M3D_FREE(pe);
  1535. }
  1536. h->cmd[j].arg[k] = mi;
  1537. break;
  1538. case m3dcp_vc_t:
  1539. _m3d_getfloat(ptr, &w);
  1540. h->cmd[j].arg[k] = *((uint32_t *)&w);
  1541. break;
  1542. case m3dcp_va_t:
  1543. ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]);
  1544. n = k + 1;
  1545. l += (h->cmd[j].arg[k] - 1) * (cd->p - k - 1);
  1546. h->cmd[j].arg = (uint32_t *)M3D_REALLOC(h->cmd[j].arg, l * sizeof(uint32_t));
  1547. if (!h->cmd[j].arg) goto memerr;
  1548. memset(&h->cmd[j].arg[k + 1], 0, (l - k - 1) * sizeof(uint32_t));
  1549. break;
  1550. case m3dcp_qi_t:
  1551. ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]);
  1552. model->vertex[h->cmd[i].arg[k]].skinid = M3D_INDEXMAX;
  1553. break;
  1554. default:
  1555. ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]);
  1556. break;
  1557. }
  1558. }
  1559. } else {
  1560. M3D_LOG("Unknown shape command in");
  1561. M3D_LOG(h->name);
  1562. model->errcode = M3D_ERR_UNKCMD;
  1563. }
  1564. ptr = _m3d_findnl(ptr);
  1565. }
  1566. if (!h->numcmd) model->numshape--;
  1567. } else
  1568. /* annotation labels */
  1569. if (!memcmp(pe, "Labels", 6)) {
  1570. pe = _m3d_findarg(pe);
  1571. if (!*pe) goto asciiend;
  1572. if (*pe == '\r' || *pe == '\n')
  1573. pe = NULL;
  1574. else
  1575. pe = _m3d_safestr(pe, 0);
  1576. k = 0;
  1577. fn = NULL;
  1578. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1579. if (*ptr == 'c') {
  1580. ptr = _m3d_findarg(ptr);
  1581. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  1582. ptr = _m3d_gethex(ptr, &k);
  1583. } else if (*ptr == 'l') {
  1584. ptr = _m3d_findarg(ptr);
  1585. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  1586. fn = _m3d_safestr(ptr, 2);
  1587. } else {
  1588. i = model->numlabel++;
  1589. model->label = (m3dl_t *)M3D_REALLOC(model->label, model->numlabel * sizeof(m3dl_t));
  1590. if (!model->label) goto memerr;
  1591. model->label[i].name = pe;
  1592. model->label[i].lang = fn;
  1593. model->label[i].color = k;
  1594. ptr = _m3d_getint(ptr, &j);
  1595. model->label[i].vertexid = (M3D_INDEX)j;
  1596. ptr = _m3d_findarg(ptr);
  1597. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  1598. model->label[i].text = _m3d_safestr(ptr, 2);
  1599. }
  1600. ptr = _m3d_findnl(ptr);
  1601. }
  1602. } else
  1603. /* action */
  1604. if (!memcmp(pe, "Action", 6)) {
  1605. pe = _m3d_findarg(pe);
  1606. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  1607. pe = _m3d_getint(pe, &k);
  1608. pe = _m3d_findarg(pe);
  1609. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  1610. pe = _m3d_safestr(pe, 0);
  1611. if (!pe || !*pe) goto asciiend;
  1612. i = model->numaction++;
  1613. model->action = (m3da_t *)M3D_REALLOC(model->action, model->numaction * sizeof(m3da_t));
  1614. if (!model->action) goto memerr;
  1615. a = &model->action[i];
  1616. a->name = pe;
  1617. a->durationmsec = k;
  1618. /* skip the first frame marker as there's always at least one frame */
  1619. a->numframe = 1;
  1620. a->frame = (m3dfr_t *)M3D_MALLOC(sizeof(m3dfr_t));
  1621. if (!a->frame) goto memerr;
  1622. a->frame[0].msec = 0;
  1623. a->frame[0].numtransform = 0;
  1624. a->frame[0].transform = NULL;
  1625. i = 0;
  1626. if (*ptr == 'f')
  1627. ptr = _m3d_findnl(ptr);
  1628. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1629. if (*ptr == 'f') {
  1630. i = a->numframe++;
  1631. a->frame = (m3dfr_t *)M3D_REALLOC(a->frame, a->numframe * sizeof(m3dfr_t));
  1632. if (!a->frame) goto memerr;
  1633. ptr = _m3d_findarg(ptr);
  1634. ptr = _m3d_getint(ptr, &a->frame[i].msec);
  1635. a->frame[i].numtransform = 0;
  1636. a->frame[i].transform = NULL;
  1637. } else {
  1638. j = a->frame[i].numtransform++;
  1639. a->frame[i].transform = (m3dtr_t *)M3D_REALLOC(a->frame[i].transform,
  1640. a->frame[i].numtransform * sizeof(m3dtr_t));
  1641. if (!a->frame[i].transform) goto memerr;
  1642. ptr = _m3d_getint(ptr, &k);
  1643. ptr = _m3d_findarg(ptr);
  1644. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1645. a->frame[i].transform[j].boneid = (M3D_INDEX)k;
  1646. ptr = _m3d_getint(ptr, &k);
  1647. ptr = _m3d_findarg(ptr);
  1648. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1649. a->frame[i].transform[j].pos = (M3D_INDEX)k;
  1650. ptr = _m3d_getint(ptr, &k);
  1651. if (!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend;
  1652. a->frame[i].transform[j].ori = (M3D_INDEX)k;
  1653. model->vertex[k].skinid = M3D_INDEXMAX;
  1654. }
  1655. ptr = _m3d_findnl(ptr);
  1656. }
  1657. } else
  1658. /* inlined assets chunk */
  1659. if (!memcmp(pe, "Assets", 6)) {
  1660. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1661. if (readfilecb) {
  1662. pe = _m3d_safestr(ptr, 2);
  1663. if (!pe || !*pe) goto asciiend;
  1664. i = model->numinlined++;
  1665. model->inlined = (m3di_t *)M3D_REALLOC(model->inlined, model->numinlined * sizeof(m3di_t));
  1666. if (!model->inlined) goto memerr;
  1667. t = &model->inlined[i];
  1668. model->inlined[i].data = (*readfilecb)(pe, &model->inlined[i].length);
  1669. if (model->inlined[i].data) {
  1670. fn = strrchr(pe, '.');
  1671. if (fn && (fn[1] == 'p' || fn[1] == 'P') && (fn[2] == 'n' || fn[2] == 'N') &&
  1672. (fn[3] == 'g' || fn[3] == 'G')) *fn = 0;
  1673. fn = strrchr(pe, '/');
  1674. if (!fn) fn = strrchr(pe, '\\');
  1675. if (!fn)
  1676. fn = pe;
  1677. else
  1678. fn++;
  1679. model->inlined[i].name = _m3d_safestr(fn, 0);
  1680. } else
  1681. model->numinlined--;
  1682. M3D_FREE(pe);
  1683. }
  1684. ptr = _m3d_findnl(ptr);
  1685. }
  1686. } else
  1687. /* extra chunks */
  1688. if (!memcmp(pe, "Extra", 5)) {
  1689. pe = _m3d_findarg(pe);
  1690. if (!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
  1691. buff = (unsigned char *)_m3d_findnl(ptr);
  1692. k = ((uint32_t)((uintptr_t)buff - (uintptr_t)ptr) / 3) + 1;
  1693. i = model->numextra++;
  1694. model->extra = (m3dchunk_t **)M3D_REALLOC(model->extra, model->numextra * sizeof(m3dchunk_t *));
  1695. if (!model->extra) goto memerr;
  1696. model->extra[i] = (m3dchunk_t *)M3D_MALLOC(k + sizeof(m3dchunk_t));
  1697. if (!model->extra[i]) goto memerr;
  1698. memcpy(&model->extra[i]->magic, pe, 4);
  1699. model->extra[i]->length = sizeof(m3dchunk_t);
  1700. pe = (char *)model->extra[i] + sizeof(m3dchunk_t);
  1701. while (*ptr && *ptr != '\r' && *ptr != '\n') {
  1702. ptr = _m3d_gethex(ptr, &k);
  1703. *pe++ = (uint8_t)k;
  1704. model->extra[i]->length++;
  1705. }
  1706. } else
  1707. goto asciiend;
  1708. }
  1709. model->errcode = M3D_SUCCESS;
  1710. asciiend:
  1711. setlocale(LC_NUMERIC, ol);
  1712. goto postprocess;
  1713. }
  1714. /* Binary variant */
  1715. if (!M3D_CHUNKMAGIC(data + 8, 'H', 'E', 'A', 'D')) {
  1716. buff = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char *)data + 8, ((m3dchunk_t *)data)->length - 8,
  1717. 4096, (int *)&len, 1);
  1718. if (!buff || !len || !M3D_CHUNKMAGIC(buff, 'H', 'E', 'A', 'D')) {
  1719. if (buff) M3D_FREE(buff);
  1720. M3D_FREE(model);
  1721. return NULL;
  1722. }
  1723. buff = (unsigned char *)M3D_REALLOC(buff, len);
  1724. model->flags |= M3D_FLG_FREERAW; /* mark that we have to free the raw buffer */
  1725. data = buff;
  1726. #ifdef M3D_PROFILING
  1727. gettimeofday(&tv1, NULL);
  1728. tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;
  1729. tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
  1730. if (tvd.tv_usec < 0) {
  1731. tvd.tv_sec--;
  1732. tvd.tv_usec += 1000000L;
  1733. }
  1734. printf(" Deflate model %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec);
  1735. memcpy(&tv0, &tv1, sizeof(struct timeval));
  1736. #endif
  1737. } else {
  1738. len = ((m3dhdr_t *)data)->length;
  1739. data += 8;
  1740. }
  1741. model->raw = (m3dhdr_t *)data;
  1742. end = data + len;
  1743. /* parse header */
  1744. data += sizeof(m3dhdr_t);
  1745. M3D_LOG(data);
  1746. model->name = (char *)data;
  1747. for (; data < end && *data; data++) {
  1748. };
  1749. data++;
  1750. model->license = (char *)data;
  1751. for (; data < end && *data; data++) {
  1752. };
  1753. data++;
  1754. model->author = (char *)data;
  1755. for (; data < end && *data; data++) {
  1756. };
  1757. data++;
  1758. model->desc = (char *)data;
  1759. chunk = (unsigned char *)model->raw + model->raw->length;
  1760. model->scale = (M3D_FLOAT)model->raw->scale;
  1761. if (model->scale <= (M3D_FLOAT)0.0) model->scale = (M3D_FLOAT)1.0;
  1762. model->vc_s = 1 << ((model->raw->types >> 0) & 3); /* vertex coordinate size */
  1763. model->vi_s = 1 << ((model->raw->types >> 2) & 3); /* vertex index size */
  1764. model->si_s = 1 << ((model->raw->types >> 4) & 3); /* string offset size */
  1765. model->ci_s = 1 << ((model->raw->types >> 6) & 3); /* color index size */
  1766. model->ti_s = 1 << ((model->raw->types >> 8) & 3); /* tmap index size */
  1767. model->bi_s = 1 << ((model->raw->types >> 10) & 3); /* bone index size */
  1768. model->nb_s = 1 << ((model->raw->types >> 12) & 3); /* number of bones per vertex */
  1769. model->sk_s = 1 << ((model->raw->types >> 14) & 3); /* skin index size */
  1770. model->fc_s = 1 << ((model->raw->types >> 16) & 3); /* frame counter size */
  1771. model->hi_s = 1 << ((model->raw->types >> 18) & 3); /* shape index size */
  1772. model->fi_s = 1 << ((model->raw->types >> 20) & 3); /* face index size */
  1773. if (model->ci_s == 8) model->ci_s = 0; /* optional indices */
  1774. if (model->ti_s == 8) model->ti_s = 0;
  1775. if (model->bi_s == 8) model->bi_s = 0;
  1776. if (model->sk_s == 8) model->sk_s = 0;
  1777. if (model->fc_s == 8) model->fc_s = 0;
  1778. if (model->hi_s == 8) model->hi_s = 0;
  1779. if (model->fi_s == 8) model->fi_s = 0;
  1780. /* variable limit checks */
  1781. if (sizeof(M3D_FLOAT) == 4 && model->vc_s > 4) {
  1782. M3D_LOG("Double precision coordinates not supported, truncating to float...");
  1783. model->errcode = M3D_ERR_TRUNC;
  1784. }
  1785. if (sizeof(M3D_INDEX) == 2 && (model->vi_s > 2 || model->si_s > 2 || model->ci_s > 2 || model->ti_s > 2 ||
  1786. model->bi_s > 2 || model->sk_s > 2 || model->fc_s > 2 || model->hi_s > 2 || model->fi_s > 2)) {
  1787. M3D_LOG("32 bit indices not supported, unable to load model");
  1788. M3D_FREE(model);
  1789. return NULL;
  1790. }
  1791. if (model->vi_s > 4 || model->si_s > 4) {
  1792. M3D_LOG("Invalid index size, unable to load model");
  1793. M3D_FREE(model);
  1794. return NULL;
  1795. }
  1796. if (model->nb_s > M3D_NUMBONE) {
  1797. M3D_LOG("Model has more bones per vertex than what importer was configured to support");
  1798. model->errcode = M3D_ERR_TRUNC;
  1799. }
  1800. /* look for inlined assets in advance, material and procedural chunks may need them */
  1801. buff = chunk;
  1802. while (buff < end && !M3D_CHUNKMAGIC(buff, 'O', 'M', 'D', '3')) {
  1803. data = buff;
  1804. len = ((m3dchunk_t *)data)->length;
  1805. buff += len;
  1806. if (len < sizeof(m3dchunk_t) || buff >= end) {
  1807. M3D_LOG("Invalid chunk size");
  1808. break;
  1809. }
  1810. len -= sizeof(m3dchunk_t) + model->si_s;
  1811. /* inlined assets */
  1812. if (M3D_CHUNKMAGIC(data, 'A', 'S', 'E', 'T') && len > 0) {
  1813. M3D_LOG("Inlined asset");
  1814. i = model->numinlined++;
  1815. model->inlined = (m3di_t *)M3D_REALLOC(model->inlined, model->numinlined * sizeof(m3di_t));
  1816. if (!model->inlined) {
  1817. memerr:
  1818. M3D_LOG("Out of memory");
  1819. model->errcode = M3D_ERR_ALLOC;
  1820. return model;
  1821. }
  1822. data += sizeof(m3dchunk_t);
  1823. t = &model->inlined[i];
  1824. M3D_GETSTR(t->name);
  1825. M3D_LOG(t->name);
  1826. t->data = (uint8_t *)data;
  1827. t->length = len;
  1828. }
  1829. }
  1830. /* parse chunks */
  1831. while (chunk < end && !M3D_CHUNKMAGIC(chunk, 'O', 'M', 'D', '3')) {
  1832. data = chunk;
  1833. len = ((m3dchunk_t *)chunk)->length;
  1834. chunk += len;
  1835. if (len < sizeof(m3dchunk_t) || chunk >= end) {
  1836. M3D_LOG("Invalid chunk size");
  1837. break;
  1838. }
  1839. len -= sizeof(m3dchunk_t);
  1840. /* preview chunk */
  1841. if (M3D_CHUNKMAGIC(data, 'P', 'R', 'V', 'W') && len > 0) {
  1842. model->preview.length = len;
  1843. model->preview.data = data + sizeof(m3dchunk_t);
  1844. } else
  1845. /* color map */
  1846. if (M3D_CHUNKMAGIC(data, 'C', 'M', 'A', 'P')) {
  1847. M3D_LOG("Color map");
  1848. if (model->cmap) {
  1849. M3D_LOG("More color map chunks, should be unique");
  1850. model->errcode = M3D_ERR_CMAP;
  1851. continue;
  1852. }
  1853. if (!model->ci_s) {
  1854. M3D_LOG("Color map chunk, shouldn't be any");
  1855. model->errcode = M3D_ERR_CMAP;
  1856. continue;
  1857. }
  1858. model->numcmap = len / sizeof(uint32_t);
  1859. model->cmap = (uint32_t *)(data + sizeof(m3dchunk_t));
  1860. } else
  1861. /* texture map */
  1862. if (M3D_CHUNKMAGIC(data, 'T', 'M', 'A', 'P')) {
  1863. M3D_LOG("Texture map");
  1864. if (model->tmap) {
  1865. M3D_LOG("More texture map chunks, should be unique");
  1866. model->errcode = M3D_ERR_TMAP;
  1867. continue;
  1868. }
  1869. if (!model->ti_s) {
  1870. M3D_LOG("Texture map chunk, shouldn't be any");
  1871. model->errcode = M3D_ERR_TMAP;
  1872. continue;
  1873. }
  1874. reclen = model->vc_s + model->vc_s;
  1875. model->numtmap = len / reclen;
  1876. model->tmap = (m3dti_t *)M3D_MALLOC(model->numtmap * sizeof(m3dti_t));
  1877. if (!model->tmap) goto memerr;
  1878. for (i = 0, data += sizeof(m3dchunk_t); data < chunk; i++) {
  1879. switch (model->vc_s) {
  1880. case 1:
  1881. model->tmap[i].u = (M3D_FLOAT)(data[0]) / (M3D_FLOAT)255.0;
  1882. model->tmap[i].v = (M3D_FLOAT)(data[1]) / (M3D_FLOAT)255.0;
  1883. break;
  1884. case 2:
  1885. model->tmap[i].u = (M3D_FLOAT)(*((int16_t *)(data + 0))) / (M3D_FLOAT)65535.0;
  1886. model->tmap[i].v = (M3D_FLOAT)(*((int16_t *)(data + 2))) / (M3D_FLOAT)65535.0;
  1887. break;
  1888. case 4:
  1889. model->tmap[i].u = (M3D_FLOAT)(*((float *)(data + 0)));
  1890. model->tmap[i].v = (M3D_FLOAT)(*((float *)(data + 4)));
  1891. break;
  1892. case 8:
  1893. model->tmap[i].u = (M3D_FLOAT)(*((double *)(data + 0)));
  1894. model->tmap[i].v = (M3D_FLOAT)(*((double *)(data + 8)));
  1895. break;
  1896. }
  1897. data += reclen;
  1898. }
  1899. } else
  1900. /* vertex list */
  1901. if (M3D_CHUNKMAGIC(data, 'V', 'R', 'T', 'S')) {
  1902. M3D_LOG("Vertex list");
  1903. if (model->vertex) {
  1904. M3D_LOG("More vertex chunks, should be unique");
  1905. model->errcode = M3D_ERR_VRTS;
  1906. continue;
  1907. }
  1908. if (model->ci_s && model->ci_s < 4 && !model->cmap) model->errcode = M3D_ERR_CMAP;
  1909. reclen = model->ci_s + model->sk_s + 4 * model->vc_s;
  1910. model->numvertex = len / reclen;
  1911. model->vertex = (m3dv_t *)M3D_MALLOC(model->numvertex * sizeof(m3dv_t));
  1912. if (!model->vertex) goto memerr;
  1913. memset(model->vertex, 0, model->numvertex * sizeof(m3dv_t));
  1914. for (i = 0, data += sizeof(m3dchunk_t); data < chunk && i < model->numvertex; i++) {
  1915. switch (model->vc_s) {
  1916. case 1:
  1917. model->vertex[i].x = (M3D_FLOAT)((int8_t)data[0]) / (M3D_FLOAT)127.0;
  1918. model->vertex[i].y = (M3D_FLOAT)((int8_t)data[1]) / (M3D_FLOAT)127.0;
  1919. model->vertex[i].z = (M3D_FLOAT)((int8_t)data[2]) / (M3D_FLOAT)127.0;
  1920. model->vertex[i].w = (M3D_FLOAT)((int8_t)data[3]) / (M3D_FLOAT)127.0;
  1921. data += 4;
  1922. break;
  1923. case 2:
  1924. model->vertex[i].x = (M3D_FLOAT)(*((int16_t *)(data + 0))) / (M3D_FLOAT)32767.0;
  1925. model->vertex[i].y = (M3D_FLOAT)(*((int16_t *)(data + 2))) / (M3D_FLOAT)32767.0;
  1926. model->vertex[i].z = (M3D_FLOAT)(*((int16_t *)(data + 4))) / (M3D_FLOAT)32767.0;
  1927. model->vertex[i].w = (M3D_FLOAT)(*((int16_t *)(data + 6))) / (M3D_FLOAT)32767.0;
  1928. data += 8;
  1929. break;
  1930. case 4:
  1931. model->vertex[i].x = (M3D_FLOAT)(*((float *)(data + 0)));
  1932. model->vertex[i].y = (M3D_FLOAT)(*((float *)(data + 4)));
  1933. model->vertex[i].z = (M3D_FLOAT)(*((float *)(data + 8)));
  1934. model->vertex[i].w = (M3D_FLOAT)(*((float *)(data + 12)));
  1935. data += 16;
  1936. break;
  1937. case 8:
  1938. model->vertex[i].x = (M3D_FLOAT)(*((double *)(data + 0)));
  1939. model->vertex[i].y = (M3D_FLOAT)(*((double *)(data + 8)));
  1940. model->vertex[i].z = (M3D_FLOAT)(*((double *)(data + 16)));
  1941. model->vertex[i].w = (M3D_FLOAT)(*((double *)(data + 24)));
  1942. data += 32;
  1943. break;
  1944. }
  1945. switch (model->ci_s) {
  1946. case 1:
  1947. model->vertex[i].color = model->cmap ? model->cmap[data[0]] : 0;
  1948. data++;
  1949. break;
  1950. case 2:
  1951. model->vertex[i].color = model->cmap ? model->cmap[*((uint16_t *)data)] : 0;
  1952. data += 2;
  1953. break;
  1954. case 4:
  1955. model->vertex[i].color = *((uint32_t *)data);
  1956. data += 4;
  1957. break;
  1958. /* case 8: break; */
  1959. }
  1960. model->vertex[i].skinid = M3D_UNDEF;
  1961. data = _m3d_getidx(data, model->sk_s, &model->vertex[i].skinid);
  1962. }
  1963. } else
  1964. /* skeleton: bone hierarchy and skin */
  1965. if (M3D_CHUNKMAGIC(data, 'B', 'O', 'N', 'E')) {
  1966. M3D_LOG("Skeleton");
  1967. if (model->bone) {
  1968. M3D_LOG("More bone chunks, should be unique");
  1969. model->errcode = M3D_ERR_BONE;
  1970. continue;
  1971. }
  1972. if (!model->bi_s) {
  1973. M3D_LOG("Bone chunk, shouldn't be any");
  1974. model->errcode = M3D_ERR_BONE;
  1975. continue;
  1976. }
  1977. if (!model->vertex) {
  1978. M3D_LOG("No vertex chunk before bones");
  1979. model->errcode = M3D_ERR_VRTS;
  1980. break;
  1981. }
  1982. data += sizeof(m3dchunk_t);
  1983. model->numbone = 0;
  1984. data = _m3d_getidx(data, model->bi_s, &model->numbone);
  1985. if (model->numbone) {
  1986. model->bone = (m3db_t *)M3D_MALLOC(model->numbone * sizeof(m3db_t));
  1987. if (!model->bone) goto memerr;
  1988. }
  1989. model->numskin = 0;
  1990. data = _m3d_getidx(data, model->sk_s, &model->numskin);
  1991. /* read bone hierarchy */
  1992. for (i = 0; i < model->numbone; i++) {
  1993. data = _m3d_getidx(data, model->bi_s, &model->bone[i].parent);
  1994. M3D_GETSTR(model->bone[i].name);
  1995. data = _m3d_getidx(data, model->vi_s, &model->bone[i].pos);
  1996. data = _m3d_getidx(data, model->vi_s, &model->bone[i].ori);
  1997. model->bone[i].numweight = 0;
  1998. model->bone[i].weight = NULL;
  1999. }
  2000. /* read skin definitions */
  2001. if (model->numskin) {
  2002. model->skin = (m3ds_t *)M3D_MALLOC(model->numskin * sizeof(m3ds_t));
  2003. if (!model->skin) goto memerr;
  2004. for (i = 0; data < chunk && i < model->numskin; i++) {
  2005. for (j = 0; j < M3D_NUMBONE; j++) {
  2006. model->skin[i].boneid[j] = M3D_UNDEF;
  2007. model->skin[i].weight[j] = (M3D_FLOAT)0.0;
  2008. }
  2009. memset(&weights, 0, sizeof(weights));
  2010. if (model->nb_s == 1)
  2011. weights[0] = 255;
  2012. else {
  2013. memcpy(&weights, data, model->nb_s);
  2014. data += model->nb_s;
  2015. }
  2016. for (j = 0, w = (M3D_FLOAT)0.0; j < (unsigned int)model->nb_s; j++) {
  2017. if (weights[j]) {
  2018. if (j >= M3D_NUMBONE)
  2019. data += model->bi_s;
  2020. else {
  2021. model->skin[i].weight[j] = (M3D_FLOAT)(weights[j]) / (M3D_FLOAT)255.0;
  2022. w += model->skin[i].weight[j];
  2023. data = _m3d_getidx(data, model->bi_s, &model->skin[i].boneid[j]);
  2024. }
  2025. }
  2026. }
  2027. /* this can occur if model has more bones than what the importer is configured to handle */
  2028. if (w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0) {
  2029. for (j = 0; j < M3D_NUMBONE; j++)
  2030. model->skin[i].weight[j] /= w;
  2031. }
  2032. }
  2033. }
  2034. } else
  2035. /* material */
  2036. if (M3D_CHUNKMAGIC(data, 'M', 'T', 'R', 'L')) {
  2037. data += sizeof(m3dchunk_t);
  2038. M3D_GETSTR(name);
  2039. M3D_LOG("Material");
  2040. M3D_LOG(name);
  2041. if (model->ci_s < 4 && !model->numcmap) model->errcode = M3D_ERR_CMAP;
  2042. for (i = 0; i < model->nummaterial; i++)
  2043. if (!strcmp(name, model->material[i].name)) {
  2044. model->errcode = M3D_ERR_MTRL;
  2045. M3D_LOG("Multiple definitions for material");
  2046. M3D_LOG(name);
  2047. name = NULL;
  2048. break;
  2049. }
  2050. if (name) {
  2051. i = model->nummaterial++;
  2052. if (model->flags & M3D_FLG_MTLLIB) {
  2053. m = model->material;
  2054. model->material = (m3dm_t *)M3D_MALLOC(model->nummaterial * sizeof(m3dm_t));
  2055. if (!model->material) goto memerr;
  2056. memcpy(model->material, m, (model->nummaterial - 1) * sizeof(m3dm_t));
  2057. if (model->texture) {
  2058. tx = model->texture;
  2059. model->texture = (m3dtx_t *)M3D_MALLOC(model->numtexture * sizeof(m3dtx_t));
  2060. if (!model->texture) goto memerr;
  2061. memcpy(model->texture, tx, model->numtexture * sizeof(m3dm_t));
  2062. }
  2063. model->flags &= ~M3D_FLG_MTLLIB;
  2064. } else {
  2065. model->material = (m3dm_t *)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t));
  2066. if (!model->material) goto memerr;
  2067. }
  2068. m = &model->material[i];
  2069. m->numprop = 0;
  2070. m->name = name;
  2071. m->prop = (m3dp_t *)M3D_MALLOC((len / 2) * sizeof(m3dp_t));
  2072. if (!m->prop) goto memerr;
  2073. while (data < chunk) {
  2074. i = m->numprop++;
  2075. m->prop[i].type = *data++;
  2076. m->prop[i].value.num = 0;
  2077. if (m->prop[i].type >= 128)
  2078. k = m3dpf_map;
  2079. else {
  2080. for (k = 256, j = 0; j < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); j++)
  2081. if (m->prop[i].type == m3d_propertytypes[j].id) {
  2082. k = m3d_propertytypes[j].format;
  2083. break;
  2084. }
  2085. }
  2086. switch (k) {
  2087. case m3dpf_color:
  2088. switch (model->ci_s) {
  2089. case 1:
  2090. m->prop[i].value.color = model->cmap ? model->cmap[data[0]] : 0;
  2091. data++;
  2092. break;
  2093. case 2:
  2094. m->prop[i].value.color = model->cmap ? model->cmap[*((uint16_t *)data)] : 0;
  2095. data += 2;
  2096. break;
  2097. case 4:
  2098. m->prop[i].value.color = *((uint32_t *)data);
  2099. data += 4;
  2100. break;
  2101. }
  2102. break;
  2103. case m3dpf_uint8: m->prop[i].value.num = *data++; break;
  2104. case m3dpf_uint16:
  2105. m->prop[i].value.num = *((uint16_t *)data);
  2106. data += 2;
  2107. break;
  2108. case m3dpf_uint32:
  2109. m->prop[i].value.num = *((uint32_t *)data);
  2110. data += 4;
  2111. break;
  2112. case m3dpf_float:
  2113. m->prop[i].value.fnum = *((float *)data);
  2114. data += 4;
  2115. break;
  2116. case m3dpf_map:
  2117. M3D_GETSTR(name);
  2118. m->prop[i].value.textureid = _m3d_gettx(model, readfilecb, freecb, name);
  2119. if (model->errcode == M3D_ERR_ALLOC) goto memerr;
  2120. /* this error code only returned if readfilecb was specified */
  2121. if (m->prop[i].value.textureid == M3D_UNDEF) {
  2122. M3D_LOG("Texture not found");
  2123. M3D_LOG(m->name);
  2124. m->numprop--;
  2125. }
  2126. break;
  2127. default:
  2128. M3D_LOG("Unknown material property in");
  2129. M3D_LOG(m->name);
  2130. model->errcode = M3D_ERR_UNKPROP;
  2131. data = chunk;
  2132. break;
  2133. }
  2134. }
  2135. m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t));
  2136. if (!m->prop) goto memerr;
  2137. }
  2138. } else
  2139. /* face */
  2140. if (M3D_CHUNKMAGIC(data, 'P', 'R', 'O', 'C')) {
  2141. /* procedural surface */
  2142. M3D_GETSTR(name);
  2143. M3D_LOG("Procedural surface");
  2144. M3D_LOG(name);
  2145. _m3d_getpr(model, readfilecb, freecb, name);
  2146. } else if (M3D_CHUNKMAGIC(data, 'M', 'E', 'S', 'H')) {
  2147. M3D_LOG("Mesh data");
  2148. /* mesh */
  2149. data += sizeof(m3dchunk_t);
  2150. mi = M3D_UNDEF;
  2151. am = model->numface;
  2152. while (data < chunk) {
  2153. k = *data++;
  2154. n = k >> 4;
  2155. k &= 15;
  2156. if (!n) {
  2157. /* use material */
  2158. mi = M3D_UNDEF;
  2159. M3D_GETSTR(name);
  2160. if (name) {
  2161. for (j = 0; j < model->nummaterial; j++)
  2162. if (!strcmp(name, model->material[j].name)) {
  2163. mi = (M3D_INDEX)j;
  2164. break;
  2165. }
  2166. if (mi == M3D_UNDEF) model->errcode = M3D_ERR_MTRL;
  2167. }
  2168. continue;
  2169. }
  2170. if (n != 3) {
  2171. M3D_LOG("Only triangle mesh supported for now");
  2172. model->errcode = M3D_ERR_UNKMESH;
  2173. return model;
  2174. }
  2175. i = model->numface++;
  2176. if (model->numface > am) {
  2177. am = model->numface + 4095;
  2178. model->face = (m3df_t *)M3D_REALLOC(model->face, am * sizeof(m3df_t));
  2179. if (!model->face) goto memerr;
  2180. }
  2181. memset(&model->face[i], 255, sizeof(m3df_t)); /* set all index to -1 by default */
  2182. model->face[i].materialid = mi;
  2183. for (j = 0; j < n; j++) {
  2184. /* vertex */
  2185. data = _m3d_getidx(data, model->vi_s, &model->face[i].vertex[j]);
  2186. /* texcoord */
  2187. if (k & 1)
  2188. data = _m3d_getidx(data, model->ti_s, &model->face[i].texcoord[j]);
  2189. /* normal */
  2190. if (k & 2)
  2191. data = _m3d_getidx(data, model->vi_s, &model->face[i].normal[j]);
  2192. #ifndef M3D_NONORMALS
  2193. if (model->face[i].normal[j] == M3D_UNDEF) neednorm = 1;
  2194. #endif
  2195. }
  2196. }
  2197. model->face = (m3df_t *)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t));
  2198. } else if (M3D_CHUNKMAGIC(data, 'S', 'H', 'P', 'E')) {
  2199. /* mathematical shape */
  2200. data += sizeof(m3dchunk_t);
  2201. M3D_GETSTR(name);
  2202. M3D_LOG("Mathematical Shape");
  2203. M3D_LOG(name);
  2204. i = model->numshape++;
  2205. model->shape = (m3dh_t *)M3D_REALLOC(model->shape, model->numshape * sizeof(m3dh_t));
  2206. if (!model->shape) goto memerr;
  2207. h = &model->shape[i];
  2208. h->numcmd = 0;
  2209. h->cmd = NULL;
  2210. h->name = name;
  2211. h->group = M3D_UNDEF;
  2212. data = _m3d_getidx(data, model->bi_s, &h->group);
  2213. if (h->group != M3D_UNDEF && h->group >= model->numbone) {
  2214. M3D_LOG("Unknown bone id as shape group in shape");
  2215. M3D_LOG(name);
  2216. h->group = M3D_UNDEF;
  2217. model->errcode = M3D_ERR_SHPE;
  2218. }
  2219. while (data < chunk) {
  2220. i = h->numcmd++;
  2221. h->cmd = (m3dc_t *)M3D_REALLOC(h->cmd, h->numcmd * sizeof(m3dc_t));
  2222. if (!h->cmd) goto memerr;
  2223. h->cmd[i].type = *data++;
  2224. if (h->cmd[i].type & 0x80) {
  2225. h->cmd[i].type &= 0x7F;
  2226. h->cmd[i].type |= (*data++ << 7);
  2227. }
  2228. if (h->cmd[i].type >= (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0]))) {
  2229. M3D_LOG("Unknown shape command in");
  2230. M3D_LOG(h->name);
  2231. model->errcode = M3D_ERR_UNKCMD;
  2232. break;
  2233. }
  2234. cd = &m3d_commandtypes[h->cmd[i].type];
  2235. h->cmd[i].arg = (uint32_t *)M3D_MALLOC(cd->p * sizeof(uint32_t));
  2236. if (!h->cmd[i].arg) goto memerr;
  2237. memset(h->cmd[i].arg, 0, cd->p * sizeof(uint32_t));
  2238. for (k = n = 0, l = cd->p; k < l; k++)
  2239. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  2240. case m3dcp_mi_t:
  2241. h->cmd[i].arg[k] = M3D_NOTDEFINED;
  2242. M3D_GETSTR(name);
  2243. if (name) {
  2244. for (n = 0; n < model->nummaterial; n++)
  2245. if (!strcmp(name, model->material[n].name)) {
  2246. h->cmd[i].arg[k] = n;
  2247. break;
  2248. }
  2249. if (h->cmd[i].arg[k] == M3D_NOTDEFINED) model->errcode = M3D_ERR_MTRL;
  2250. }
  2251. break;
  2252. case m3dcp_vc_t:
  2253. f = 0.0f;
  2254. switch (model->vc_s) {
  2255. case 1: f = (float)((int8_t)data[0]) / 127; break;
  2256. case 2: f = (float)(*((int16_t *)(data + 0))) / 32767; break;
  2257. case 4: f = (float)(*((float *)(data + 0))); break;
  2258. case 8: f = (float)(*((double *)(data + 0))); break;
  2259. }
  2260. memcpy(&(h->cmd[i].arg[k]), &f, sizeof(uint32_t));
  2261. data += model->vc_s;
  2262. break;
  2263. case m3dcp_hi_t: data = _m3d_getidx(data, model->hi_s, &h->cmd[i].arg[k]); break;
  2264. case m3dcp_fi_t: data = _m3d_getidx(data, model->fi_s, &h->cmd[i].arg[k]); break;
  2265. case m3dcp_ti_t: data = _m3d_getidx(data, model->ti_s, &h->cmd[i].arg[k]); break;
  2266. case m3dcp_qi_t:
  2267. case m3dcp_vi_t: data = _m3d_getidx(data, model->vi_s, &h->cmd[i].arg[k]); break;
  2268. case m3dcp_i1_t: data = _m3d_getidx(data, 1, &h->cmd[i].arg[k]); break;
  2269. case m3dcp_i2_t: data = _m3d_getidx(data, 2, &h->cmd[i].arg[k]); break;
  2270. case m3dcp_i4_t: data = _m3d_getidx(data, 4, &h->cmd[i].arg[k]); break;
  2271. case m3dcp_va_t:
  2272. data = _m3d_getidx(data, 4, &h->cmd[i].arg[k]);
  2273. n = k + 1;
  2274. l += (h->cmd[i].arg[k] - 1) * (cd->p - k - 1);
  2275. h->cmd[i].arg = (uint32_t *)M3D_REALLOC(h->cmd[i].arg, l * sizeof(uint32_t));
  2276. if (!h->cmd[i].arg) goto memerr;
  2277. memset(&h->cmd[i].arg[k + 1], 0, (l - k - 1) * sizeof(uint32_t));
  2278. break;
  2279. }
  2280. }
  2281. } else
  2282. /* annotation label list */
  2283. if (M3D_CHUNKMAGIC(data, 'L', 'B', 'L', 'S')) {
  2284. data += sizeof(m3dchunk_t);
  2285. M3D_GETSTR(name);
  2286. M3D_GETSTR(lang);
  2287. M3D_LOG("Label list");
  2288. if (name) {
  2289. M3D_LOG(name);
  2290. }
  2291. if (lang) {
  2292. M3D_LOG(lang);
  2293. }
  2294. if (model->ci_s && model->ci_s < 4 && !model->cmap) model->errcode = M3D_ERR_CMAP;
  2295. k = 0;
  2296. switch (model->ci_s) {
  2297. case 1:
  2298. k = model->cmap ? model->cmap[data[0]] : 0;
  2299. data++;
  2300. break;
  2301. case 2:
  2302. k = model->cmap ? model->cmap[*((uint16_t *)data)] : 0;
  2303. data += 2;
  2304. break;
  2305. case 4:
  2306. k = *((uint32_t *)data);
  2307. data += 4;
  2308. break;
  2309. /* case 8: break; */
  2310. }
  2311. reclen = model->vi_s + model->si_s;
  2312. i = model->numlabel;
  2313. model->numlabel += len / reclen;
  2314. model->label = (m3dl_t *)M3D_REALLOC(model->label, model->numlabel * sizeof(m3dl_t));
  2315. if (!model->label) goto memerr;
  2316. memset(&model->label[i], 0, (model->numlabel - i) * sizeof(m3dl_t));
  2317. for (; data < chunk && i < model->numlabel; i++) {
  2318. model->label[i].name = name;
  2319. model->label[i].lang = lang;
  2320. model->label[i].color = k;
  2321. data = _m3d_getidx(data, model->vi_s, &model->label[i].vertexid);
  2322. M3D_GETSTR(model->label[i].text);
  2323. }
  2324. } else
  2325. /* action */
  2326. if (M3D_CHUNKMAGIC(data, 'A', 'C', 'T', 'N')) {
  2327. M3D_LOG("Action");
  2328. i = model->numaction++;
  2329. model->action = (m3da_t *)M3D_REALLOC(model->action, model->numaction * sizeof(m3da_t));
  2330. if (!model->action) goto memerr;
  2331. a = &model->action[i];
  2332. data += sizeof(m3dchunk_t);
  2333. M3D_GETSTR(a->name);
  2334. M3D_LOG(a->name);
  2335. a->numframe = *((uint16_t *)data);
  2336. data += 2;
  2337. if (a->numframe < 1) {
  2338. model->numaction--;
  2339. } else {
  2340. a->durationmsec = *((uint32_t *)data);
  2341. data += 4;
  2342. a->frame = (m3dfr_t *)M3D_MALLOC(a->numframe * sizeof(m3dfr_t));
  2343. if (!a->frame) goto memerr;
  2344. for (i = 0; data < chunk && i < a->numframe; i++) {
  2345. a->frame[i].msec = *((uint32_t *)data);
  2346. data += 4;
  2347. a->frame[i].numtransform = 0;
  2348. a->frame[i].transform = NULL;
  2349. data = _m3d_getidx(data, model->fc_s, &a->frame[i].numtransform);
  2350. if (a->frame[i].numtransform > 0) {
  2351. a->frame[i].transform = (m3dtr_t *)M3D_MALLOC(a->frame[i].numtransform * sizeof(m3dtr_t));
  2352. for (j = 0; j < a->frame[i].numtransform; j++) {
  2353. data = _m3d_getidx(data, model->bi_s, &a->frame[i].transform[j].boneid);
  2354. data = _m3d_getidx(data, model->vi_s, &a->frame[i].transform[j].pos);
  2355. data = _m3d_getidx(data, model->vi_s, &a->frame[i].transform[j].ori);
  2356. }
  2357. }
  2358. }
  2359. }
  2360. } else {
  2361. i = model->numextra++;
  2362. model->extra = (m3dchunk_t **)M3D_REALLOC(model->extra, model->numextra * sizeof(m3dchunk_t *));
  2363. if (!model->extra) goto memerr;
  2364. model->extra[i] = (m3dchunk_t *)data;
  2365. }
  2366. }
  2367. /* calculate normals, normalize skin weights, create bone/vertex cross-references and calculate transform matrices */
  2368. postprocess:
  2369. if (model) {
  2370. M3D_LOG("Post-process");
  2371. #ifdef M3D_PROFILING
  2372. gettimeofday(&tv1, NULL);
  2373. tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;
  2374. tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
  2375. if (tvd.tv_usec < 0) {
  2376. tvd.tv_sec--;
  2377. tvd.tv_usec += 1000000L;
  2378. }
  2379. printf(" Parsing chunks %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec);
  2380. #endif
  2381. #ifndef M3D_NONORMALS
  2382. if (model->numface && model->face && neednorm) {
  2383. /* if they are missing, calculate triangle normals into a temporary buffer */
  2384. norm = (m3dv_t *)M3D_MALLOC(model->numface * sizeof(m3dv_t));
  2385. if (!norm) goto memerr;
  2386. for (i = 0, n = model->numvertex; i < model->numface; i++)
  2387. if (model->face[i].normal[0] == M3D_UNDEF) {
  2388. v0 = &model->vertex[model->face[i].vertex[0]];
  2389. v1 = &model->vertex[model->face[i].vertex[1]];
  2390. v2 = &model->vertex[model->face[i].vertex[2]];
  2391. va.x = v1->x - v0->x;
  2392. va.y = v1->y - v0->y;
  2393. va.z = v1->z - v0->z;
  2394. vb.x = v2->x - v0->x;
  2395. vb.y = v2->y - v0->y;
  2396. vb.z = v2->z - v0->z;
  2397. v0 = &norm[i];
  2398. v0->x = (va.y * vb.z) - (va.z * vb.y);
  2399. v0->y = (va.z * vb.x) - (va.x * vb.z);
  2400. v0->z = (va.x * vb.y) - (va.y * vb.x);
  2401. w = _m3d_rsq((v0->x * v0->x) + (v0->y * v0->y) + (v0->z * v0->z));
  2402. v0->x *= w;
  2403. v0->y *= w;
  2404. v0->z *= w;
  2405. model->face[i].normal[0] = model->face[i].vertex[0] + n;
  2406. model->face[i].normal[1] = model->face[i].vertex[1] + n;
  2407. model->face[i].normal[2] = model->face[i].vertex[2] + n;
  2408. }
  2409. /* this is the fast way, we don't care if a normal is repeated in model->vertex */
  2410. M3D_LOG("Generating normals");
  2411. model->flags |= M3D_FLG_GENNORM;
  2412. model->numvertex <<= 1;
  2413. model->vertex = (m3dv_t *)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t));
  2414. if (!model->vertex) goto memerr;
  2415. memset(&model->vertex[n], 0, n * sizeof(m3dv_t));
  2416. for (i = 0; i < model->numface; i++)
  2417. for (j = 0; j < 3; j++) {
  2418. v0 = &model->vertex[model->face[i].vertex[j] + n];
  2419. v0->x += norm[i].x;
  2420. v0->y += norm[i].y;
  2421. v0->z += norm[i].z;
  2422. }
  2423. /* for each vertex, take the average of the temporary normals and use that */
  2424. for (i = 0, v0 = &model->vertex[n]; i < n; i++, v0++) {
  2425. w = _m3d_rsq((v0->x * v0->x) + (v0->y * v0->y) + (v0->z * v0->z));
  2426. v0->x *= w;
  2427. v0->y *= w;
  2428. v0->z *= w;
  2429. v0->skinid = M3D_UNDEF;
  2430. }
  2431. M3D_FREE(norm);
  2432. }
  2433. #endif
  2434. if (model->numbone && model->bone && model->numskin && model->skin && model->numvertex && model->vertex) {
  2435. #ifndef M3D_NOWEIGHTS
  2436. M3D_LOG("Generating weight cross-reference");
  2437. for (i = 0; i < model->numvertex; i++) {
  2438. if (model->vertex[i].skinid < model->numskin) {
  2439. sk = &model->skin[model->vertex[i].skinid];
  2440. w = (M3D_FLOAT)0.0;
  2441. for (j = 0; j < M3D_NUMBONE && sk->boneid[j] != M3D_UNDEF && sk->weight[j] > (M3D_FLOAT)0.0; j++)
  2442. w += sk->weight[j];
  2443. for (j = 0; j < M3D_NUMBONE && sk->boneid[j] != M3D_UNDEF && sk->weight[j] > (M3D_FLOAT)0.0; j++) {
  2444. sk->weight[j] /= w;
  2445. b = &model->bone[sk->boneid[j]];
  2446. k = b->numweight++;
  2447. b->weight = (m3dw_t *)M3D_REALLOC(b->weight, b->numweight * sizeof(m3da_t));
  2448. if (!b->weight) goto memerr;
  2449. b->weight[k].vertexid = i;
  2450. b->weight[k].weight = sk->weight[j];
  2451. }
  2452. }
  2453. }
  2454. #endif
  2455. #ifndef M3D_NOANIMATION
  2456. M3D_LOG("Calculating bone transformation matrices");
  2457. for (i = 0; i < model->numbone; i++) {
  2458. b = &model->bone[i];
  2459. if (model->bone[i].parent == M3D_UNDEF) {
  2460. _m3d_mat((M3D_FLOAT *)&b->mat4, &model->vertex[b->pos], &model->vertex[b->ori]);
  2461. } else {
  2462. _m3d_mat((M3D_FLOAT *)&r, &model->vertex[b->pos], &model->vertex[b->ori]);
  2463. _m3d_mul((M3D_FLOAT *)&b->mat4, (M3D_FLOAT *)&model->bone[b->parent].mat4, (M3D_FLOAT *)&r);
  2464. }
  2465. }
  2466. for (i = 0; i < model->numbone; i++)
  2467. _m3d_inv((M3D_FLOAT *)&model->bone[i].mat4);
  2468. #endif
  2469. }
  2470. #ifdef M3D_PROFILING
  2471. gettimeofday(&tv0, NULL);
  2472. tvd.tv_sec = tv0.tv_sec - tv1.tv_sec;
  2473. tvd.tv_usec = tv0.tv_usec - tv1.tv_usec;
  2474. if (tvd.tv_usec < 0) {
  2475. tvd.tv_sec--;
  2476. tvd.tv_usec += 1000000L;
  2477. }
  2478. printf(" Post-process %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec);
  2479. #endif
  2480. }
  2481. return model;
  2482. }
  2483. /**
  2484. * Calculates skeletons for animation frames, returns a working copy (should be freed after use)
  2485. */
  2486. m3dtr_t *m3d_frame(m3d_t *model, M3D_INDEX actionid, M3D_INDEX frameid, m3dtr_t *skeleton) {
  2487. unsigned int i;
  2488. M3D_INDEX s = frameid;
  2489. m3dfr_t *fr;
  2490. if (!model || !model->numbone || !model->bone || (actionid != M3D_UNDEF && (!model->action || actionid >= model->numaction || frameid >= model->action[actionid].numframe))) {
  2491. model->errcode = M3D_ERR_UNKFRAME;
  2492. return skeleton;
  2493. }
  2494. model->errcode = M3D_SUCCESS;
  2495. if (!skeleton) {
  2496. skeleton = (m3dtr_t *)M3D_MALLOC(model->numbone * sizeof(m3dtr_t));
  2497. if (!skeleton) {
  2498. model->errcode = M3D_ERR_ALLOC;
  2499. return NULL;
  2500. }
  2501. goto gen;
  2502. }
  2503. if (actionid == M3D_UNDEF || !frameid) {
  2504. gen:
  2505. s = 0;
  2506. for (i = 0; i < model->numbone; i++) {
  2507. skeleton[i].boneid = i;
  2508. skeleton[i].pos = model->bone[i].pos;
  2509. skeleton[i].ori = model->bone[i].ori;
  2510. }
  2511. }
  2512. if (actionid < model->numaction && (frameid || !model->action[actionid].frame[0].msec)) {
  2513. for (; s <= frameid; s++) {
  2514. fr = &model->action[actionid].frame[s];
  2515. for (i = 0; i < fr->numtransform; i++) {
  2516. skeleton[fr->transform[i].boneid].pos = fr->transform[i].pos;
  2517. skeleton[fr->transform[i].boneid].ori = fr->transform[i].ori;
  2518. }
  2519. }
  2520. }
  2521. return skeleton;
  2522. }
  2523. #ifndef M3D_NOANIMATION
  2524. /**
  2525. * Returns interpolated animation-pose, a working copy (should be freed after use)
  2526. */
  2527. m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec) {
  2528. unsigned int i, j, l;
  2529. M3D_FLOAT r[16], t, c, d, s;
  2530. m3db_t *ret;
  2531. m3dv_t *v, *p, *f;
  2532. m3dtr_t *tmp;
  2533. m3dfr_t *fr;
  2534. if (!model || !model->numbone || !model->bone) {
  2535. model->errcode = M3D_ERR_UNKFRAME;
  2536. return NULL;
  2537. }
  2538. ret = (m3db_t *)M3D_MALLOC(model->numbone * sizeof(m3db_t));
  2539. if (!ret) {
  2540. model->errcode = M3D_ERR_ALLOC;
  2541. return NULL;
  2542. }
  2543. memcpy(ret, model->bone, model->numbone * sizeof(m3db_t));
  2544. for (i = 0; i < model->numbone; i++)
  2545. _m3d_inv((M3D_FLOAT *)&ret[i].mat4);
  2546. if (!model->action || actionid >= model->numaction) {
  2547. model->errcode = M3D_ERR_UNKFRAME;
  2548. return ret;
  2549. }
  2550. msec %= model->action[actionid].durationmsec;
  2551. model->errcode = M3D_SUCCESS;
  2552. fr = &model->action[actionid].frame[0];
  2553. for (j = l = 0; j < model->action[actionid].numframe && model->action[actionid].frame[j].msec <= msec; j++) {
  2554. fr = &model->action[actionid].frame[j];
  2555. l = fr->msec;
  2556. for (i = 0; i < fr->numtransform; i++) {
  2557. ret[fr->transform[i].boneid].pos = fr->transform[i].pos;
  2558. ret[fr->transform[i].boneid].ori = fr->transform[i].ori;
  2559. }
  2560. }
  2561. if (l != msec) {
  2562. model->vertex = (m3dv_t *)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t));
  2563. if (!model->vertex) {
  2564. free(ret);
  2565. model->errcode = M3D_ERR_ALLOC;
  2566. return NULL;
  2567. }
  2568. tmp = (m3dtr_t *)M3D_MALLOC(model->numbone * sizeof(m3dtr_t));
  2569. if (tmp) {
  2570. for (i = 0; i < model->numbone; i++) {
  2571. tmp[i].pos = ret[i].pos;
  2572. tmp[i].ori = ret[i].ori;
  2573. }
  2574. fr = &model->action[actionid].frame[j % model->action[actionid].numframe];
  2575. t = l >= fr->msec ? (M3D_FLOAT)1.0 : (M3D_FLOAT)(msec - l) / (M3D_FLOAT)(fr->msec - l);
  2576. for (i = 0; i < fr->numtransform; i++) {
  2577. tmp[fr->transform[i].boneid].pos = fr->transform[i].pos;
  2578. tmp[fr->transform[i].boneid].ori = fr->transform[i].ori;
  2579. }
  2580. for (i = 0, j = model->numvertex; i < model->numbone; i++) {
  2581. /* interpolation of position */
  2582. if (ret[i].pos != tmp[i].pos) {
  2583. p = &model->vertex[ret[i].pos];
  2584. f = &model->vertex[tmp[i].pos];
  2585. v = &model->vertex[j];
  2586. v->x = p->x + t * (f->x - p->x);
  2587. v->y = p->y + t * (f->y - p->y);
  2588. v->z = p->z + t * (f->z - p->z);
  2589. ret[i].pos = j++;
  2590. }
  2591. /* interpolation of orientation */
  2592. if (ret[i].ori != tmp[i].ori) {
  2593. p = &model->vertex[ret[i].ori];
  2594. f = &model->vertex[tmp[i].ori];
  2595. v = &model->vertex[j];
  2596. d = p->w * f->w + p->x * f->x + p->y * f->y + p->z * f->z;
  2597. if (d < 0) {
  2598. d = -d;
  2599. s = (M3D_FLOAT)-1.0;
  2600. } else
  2601. s = (M3D_FLOAT)1.0;
  2602. #if 0
  2603. /* don't use SLERP, requires two more variables, libm linkage and it is slow (but nice) */
  2604. a = (M3D_FLOAT)1.0 - t; b = t;
  2605. if(d < (M3D_FLOAT)0.999999) { c = acosf(d); b = 1 / sinf(c); a = sinf(a * c) * b; b *= sinf(t * c) * s; }
  2606. v->x = p->x * a + f->x * b;
  2607. v->y = p->y * a + f->y * b;
  2608. v->z = p->z * a + f->z * b;
  2609. v->w = p->w * a + f->w * b;
  2610. #else
  2611. /* approximated NLERP, original approximation by Arseny Kapoulkine, heavily optimized by me */
  2612. c = t - (M3D_FLOAT)0.5;
  2613. 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)));
  2614. v->x = p->x + t * (s * f->x - p->x);
  2615. v->y = p->y + t * (s * f->y - p->y);
  2616. v->z = p->z + t * (s * f->z - p->z);
  2617. v->w = p->w + t * (s * f->w - p->w);
  2618. d = _m3d_rsq(v->w * v->w + v->x * v->x + v->y * v->y + v->z * v->z);
  2619. v->x *= d;
  2620. v->y *= d;
  2621. v->z *= d;
  2622. v->w *= d;
  2623. #endif
  2624. ret[i].ori = j++;
  2625. }
  2626. }
  2627. M3D_FREE(tmp);
  2628. }
  2629. }
  2630. for (i = 0; i < model->numbone; i++) {
  2631. if (ret[i].parent == M3D_UNDEF) {
  2632. _m3d_mat((M3D_FLOAT *)&ret[i].mat4, &model->vertex[ret[i].pos], &model->vertex[ret[i].ori]);
  2633. } else {
  2634. _m3d_mat((M3D_FLOAT *)&r, &model->vertex[ret[i].pos], &model->vertex[ret[i].ori]);
  2635. _m3d_mul((M3D_FLOAT *)&ret[i].mat4, (M3D_FLOAT *)&ret[ret[i].parent].mat4, (M3D_FLOAT *)&r);
  2636. }
  2637. }
  2638. return ret;
  2639. }
  2640. #endif /* M3D_NOANIMATION */
  2641. #endif /* M3D_IMPLEMENTATION */
  2642. #if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER))
  2643. /**
  2644. * Free the in-memory model
  2645. */
  2646. void m3d_free(m3d_t *model) {
  2647. unsigned int i, j;
  2648. if (!model) return;
  2649. /* if model imported from ASCII, we have to free all strings as well */
  2650. if (model->flags & M3D_FLG_FREESTR) {
  2651. if (model->name) M3D_FREE(model->name);
  2652. if (model->license) M3D_FREE(model->license);
  2653. if (model->author) M3D_FREE(model->author);
  2654. if (model->desc) M3D_FREE(model->desc);
  2655. if (model->bone)
  2656. for (i = 0; i < model->numbone; i++)
  2657. if (model->bone[i].name)
  2658. M3D_FREE(model->bone[i].name);
  2659. if (model->shape)
  2660. for (i = 0; i < model->numshape; i++)
  2661. if (model->shape[i].name)
  2662. M3D_FREE(model->shape[i].name);
  2663. if (model->material)
  2664. for (i = 0; i < model->nummaterial; i++)
  2665. if (model->material[i].name)
  2666. M3D_FREE(model->material[i].name);
  2667. if (model->action)
  2668. for (i = 0; i < model->numaction; i++)
  2669. if (model->action[i].name)
  2670. M3D_FREE(model->action[i].name);
  2671. if (model->texture)
  2672. for (i = 0; i < model->numtexture; i++)
  2673. if (model->texture[i].name)
  2674. M3D_FREE(model->texture[i].name);
  2675. if (model->inlined)
  2676. for (i = 0; i < model->numinlined; i++) {
  2677. if (model->inlined[i].name)
  2678. M3D_FREE(model->inlined[i].name);
  2679. if (model->inlined[i].data)
  2680. M3D_FREE(model->inlined[i].data);
  2681. }
  2682. if (model->extra)
  2683. for (i = 0; i < model->numextra; i++)
  2684. if (model->extra[i])
  2685. M3D_FREE(model->extra[i]);
  2686. if (model->label)
  2687. for (i = 0; i < model->numlabel; i++) {
  2688. if (model->label[i].name) {
  2689. for (j = i + 1; j < model->numlabel; j++)
  2690. if (model->label[j].name == model->label[i].name)
  2691. model->label[j].name = NULL;
  2692. M3D_FREE(model->label[i].name);
  2693. }
  2694. if (model->label[i].lang) {
  2695. for (j = i + 1; j < model->numlabel; j++)
  2696. if (model->label[j].lang == model->label[i].lang)
  2697. model->label[j].lang = NULL;
  2698. M3D_FREE(model->label[i].lang);
  2699. }
  2700. if (model->label[i].text)
  2701. M3D_FREE(model->label[i].text);
  2702. }
  2703. if (model->preview.data)
  2704. M3D_FREE(model->preview.data);
  2705. }
  2706. if (model->flags & M3D_FLG_FREERAW) M3D_FREE(model->raw);
  2707. if (model->tmap) M3D_FREE(model->tmap);
  2708. if (model->bone) {
  2709. for (i = 0; i < model->numbone; i++)
  2710. if (model->bone[i].weight)
  2711. M3D_FREE(model->bone[i].weight);
  2712. M3D_FREE(model->bone);
  2713. }
  2714. if (model->skin) M3D_FREE(model->skin);
  2715. if (model->vertex) M3D_FREE(model->vertex);
  2716. if (model->face) M3D_FREE(model->face);
  2717. if (model->shape) {
  2718. for (i = 0; i < model->numshape; i++) {
  2719. if (model->shape[i].cmd) {
  2720. for (j = 0; j < model->shape[i].numcmd; j++)
  2721. if (model->shape[i].cmd[j].arg) M3D_FREE(model->shape[i].cmd[j].arg);
  2722. M3D_FREE(model->shape[i].cmd);
  2723. }
  2724. }
  2725. M3D_FREE(model->shape);
  2726. }
  2727. if (model->material && !(model->flags & M3D_FLG_MTLLIB)) {
  2728. for (i = 0; i < model->nummaterial; i++)
  2729. if (model->material[i].prop) M3D_FREE(model->material[i].prop);
  2730. M3D_FREE(model->material);
  2731. }
  2732. if (model->texture) {
  2733. for (i = 0; i < model->numtexture; i++)
  2734. if (model->texture[i].d) M3D_FREE(model->texture[i].d);
  2735. M3D_FREE(model->texture);
  2736. }
  2737. if (model->action) {
  2738. for (i = 0; i < model->numaction; i++) {
  2739. if (model->action[i].frame) {
  2740. for (j = 0; j < model->action[i].numframe; j++)
  2741. if (model->action[i].frame[j].transform) M3D_FREE(model->action[i].frame[j].transform);
  2742. M3D_FREE(model->action[i].frame);
  2743. }
  2744. }
  2745. M3D_FREE(model->action);
  2746. }
  2747. if (model->label) M3D_FREE(model->label);
  2748. if (model->inlined) M3D_FREE(model->inlined);
  2749. if (model->extra) M3D_FREE(model->extra);
  2750. free(model);
  2751. }
  2752. #endif
  2753. #ifdef M3D_EXPORTER
  2754. typedef struct {
  2755. char *str;
  2756. uint32_t offs;
  2757. } m3dstr_t;
  2758. typedef struct {
  2759. m3dti_t data;
  2760. M3D_INDEX oldidx;
  2761. M3D_INDEX newidx;
  2762. } m3dtisave_t;
  2763. typedef struct {
  2764. m3dv_t data;
  2765. M3D_INDEX oldidx;
  2766. M3D_INDEX newidx;
  2767. unsigned char norm;
  2768. } m3dvsave_t;
  2769. typedef struct {
  2770. m3ds_t data;
  2771. M3D_INDEX oldidx;
  2772. M3D_INDEX newidx;
  2773. } m3dssave_t;
  2774. typedef struct {
  2775. m3df_t data;
  2776. int group;
  2777. uint8_t opacity;
  2778. } m3dfsave_t;
  2779. /* create unique list of strings */
  2780. static m3dstr_t *_m3d_addstr(m3dstr_t *str, uint32_t *numstr, char *s) {
  2781. uint32_t i;
  2782. if (!s || !*s) return str;
  2783. if (str) {
  2784. for (i = 0; i < *numstr; i++)
  2785. if (str[i].str == s || !strcmp(str[i].str, s)) return str;
  2786. }
  2787. str = (m3dstr_t *)M3D_REALLOC(str, ((*numstr) + 1) * sizeof(m3dstr_t));
  2788. str[*numstr].str = s;
  2789. str[*numstr].offs = 0;
  2790. (*numstr)++;
  2791. return str;
  2792. }
  2793. /* add strings to header */
  2794. m3dhdr_t *_m3d_addhdr(m3dhdr_t *h, m3dstr_t *s) {
  2795. int i;
  2796. char *safe = _m3d_safestr(s->str, 0);
  2797. i = (int)strlen(safe);
  2798. h = (m3dhdr_t *)M3D_REALLOC(h, h->length + i + 1);
  2799. if (!h) {
  2800. M3D_FREE(safe);
  2801. return NULL;
  2802. }
  2803. memcpy((uint8_t *)h + h->length, safe, i + 1);
  2804. s->offs = h->length - 16;
  2805. h->length += i + 1;
  2806. M3D_FREE(safe);
  2807. return h;
  2808. }
  2809. /* return offset of string */
  2810. static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s) {
  2811. uint32_t i;
  2812. char *safe;
  2813. if (!s || !*s) return 0;
  2814. if (str) {
  2815. safe = _m3d_safestr(s, 0);
  2816. if (!safe) return 0;
  2817. if (!*safe) {
  2818. free(safe);
  2819. return 0;
  2820. }
  2821. for (i = 0; i < numstr; i++)
  2822. if (!strcmp(str[i].str, s)) {
  2823. free(safe);
  2824. return str[i].offs;
  2825. }
  2826. free(safe);
  2827. }
  2828. return 0;
  2829. }
  2830. /* compare to faces by their material */
  2831. static int _m3d_facecmp(const void *a, const void *b) {
  2832. const m3dfsave_t *A = (const m3dfsave_t *)a, *B = (const m3dfsave_t *)b;
  2833. 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);
  2834. }
  2835. /* compare face groups */
  2836. static int _m3d_grpcmp(const void *a, const void *b) {
  2837. return *((uint32_t *)a) - *((uint32_t *)b);
  2838. }
  2839. /* compare UVs */
  2840. static int _m3d_ticmp(const void *a, const void *b) {
  2841. return memcmp(a, b, sizeof(m3dti_t));
  2842. }
  2843. /* compare skin groups */
  2844. static int _m3d_skincmp(const void *a, const void *b) {
  2845. return memcmp(a, b, sizeof(m3ds_t));
  2846. }
  2847. /* compare vertices */
  2848. static int _m3d_vrtxcmp(const void *a, const void *b) {
  2849. int c = memcmp(a, b, 3 * sizeof(M3D_FLOAT));
  2850. if (c) return c;
  2851. c = ((m3dvsave_t *)a)->norm - ((m3dvsave_t *)b)->norm;
  2852. if (c) return c;
  2853. return memcmp(a, b, sizeof(m3dv_t));
  2854. }
  2855. /* compare labels */
  2856. static _inline int _m3d_strcmp(char *a, char *b) {
  2857. if (a == NULL && b != NULL) return -1;
  2858. if (a != NULL && b == NULL) return 1;
  2859. if (a == NULL && b == NULL) return 0;
  2860. return strcmp(a, b);
  2861. }
  2862. static int _m3d_lblcmp(const void *a, const void *b) {
  2863. const m3dl_t *A = (const m3dl_t *)a, *B = (const m3dl_t *)b;
  2864. int c = _m3d_strcmp(A->lang, B->lang);
  2865. if (!c) c = _m3d_strcmp(A->name, B->name);
  2866. if (!c) c = _m3d_strcmp(A->text, B->text);
  2867. return c;
  2868. }
  2869. /* compare two colors by HSV value */
  2870. _inline static int _m3d_cmapcmp(const void *a, const void *b) {
  2871. uint8_t *A = (uint8_t *)a, *B = (uint8_t *)b;
  2872. _register int m, vA, vB;
  2873. /* get HSV value for A */
  2874. m = A[2] < A[1] ? A[2] : A[1];
  2875. if (A[0] < m) m = A[0];
  2876. vA = A[2] > A[1] ? A[2] : A[1];
  2877. if (A[0] > vA) vA = A[0];
  2878. /* get HSV value for B */
  2879. m = B[2] < B[1] ? B[2] : B[1];
  2880. if (B[0] < m) m = B[0];
  2881. vB = B[2] > B[1] ? B[2] : B[1];
  2882. if (B[0] > vB) vB = B[0];
  2883. return vA - vB;
  2884. }
  2885. /* create sorted list of colors */
  2886. static uint32_t *_m3d_addcmap(uint32_t *cmap, uint32_t *numcmap, uint32_t color) {
  2887. uint32_t i;
  2888. if (cmap) {
  2889. for (i = 0; i < *numcmap; i++)
  2890. if (cmap[i] == color) return cmap;
  2891. }
  2892. cmap = (uint32_t *)M3D_REALLOC(cmap, ((*numcmap) + 1) * sizeof(uint32_t));
  2893. for (i = 0; i < *numcmap && _m3d_cmapcmp(&color, &cmap[i]) > 0; i++)
  2894. ;
  2895. if (i < *numcmap) memmove(&cmap[i + 1], &cmap[i], ((*numcmap) - i) * sizeof(uint32_t));
  2896. cmap[i] = color;
  2897. (*numcmap)++;
  2898. return cmap;
  2899. }
  2900. /* look up a color and return its index */
  2901. static uint32_t _m3d_cmapidx(uint32_t *cmap, uint32_t numcmap, uint32_t color) {
  2902. uint32_t i;
  2903. if (numcmap >= 65536)
  2904. return color;
  2905. for (i = 0; i < numcmap; i++)
  2906. if (cmap[i] == color) return i;
  2907. return 0;
  2908. }
  2909. /* add index to output */
  2910. static unsigned char *_m3d_addidx(unsigned char *out, char type, uint32_t idx) {
  2911. switch (type) {
  2912. case 1: *out++ = (uint8_t)(idx); break;
  2913. case 2:
  2914. *((uint16_t *)out) = (uint16_t)(idx);
  2915. out += 2;
  2916. break;
  2917. case 4:
  2918. *((uint32_t *)out) = (uint32_t)(idx);
  2919. out += 4;
  2920. break;
  2921. /* case 0: case 8: break; */
  2922. }
  2923. return out;
  2924. }
  2925. /* round a vertex position */
  2926. static void _m3d_round(int quality, m3dv_t *src, m3dv_t *dst) {
  2927. _register int t;
  2928. /* copy additional attributes */
  2929. if (src != dst) memcpy(dst, src, sizeof(m3dv_t));
  2930. /* round according to quality */
  2931. switch (quality) {
  2932. case M3D_EXP_INT8:
  2933. t = (int)(src->x * 127 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  2934. dst->x = (M3D_FLOAT)t / (M3D_FLOAT)127.0;
  2935. t = (int)(src->y * 127 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  2936. dst->y = (M3D_FLOAT)t / (M3D_FLOAT)127.0;
  2937. t = (int)(src->z * 127 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  2938. dst->z = (M3D_FLOAT)t / (M3D_FLOAT)127.0;
  2939. t = (int)(src->w * 127 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  2940. dst->w = (M3D_FLOAT)t / (M3D_FLOAT)127.0;
  2941. break;
  2942. case M3D_EXP_INT16:
  2943. t = (int)(src->x * 32767 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  2944. dst->x = (M3D_FLOAT)t / (M3D_FLOAT)32767.0;
  2945. t = (int)(src->y * 32767 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  2946. dst->y = (M3D_FLOAT)t / (M3D_FLOAT)32767.0;
  2947. t = (int)(src->z * 32767 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  2948. dst->z = (M3D_FLOAT)t / (M3D_FLOAT)32767.0;
  2949. t = (int)(src->w * 32767 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5));
  2950. dst->w = (M3D_FLOAT)t / (M3D_FLOAT)32767.0;
  2951. break;
  2952. }
  2953. if (dst->x == (M3D_FLOAT)-0.0) dst->x = (M3D_FLOAT)0.0;
  2954. if (dst->y == (M3D_FLOAT)-0.0) dst->y = (M3D_FLOAT)0.0;
  2955. if (dst->z == (M3D_FLOAT)-0.0) dst->z = (M3D_FLOAT)0.0;
  2956. if (dst->w == (M3D_FLOAT)-0.0) dst->w = (M3D_FLOAT)0.0;
  2957. }
  2958. /* add a bone to ascii output */
  2959. static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX parent, uint32_t level, M3D_INDEX *vrtxidx) {
  2960. uint32_t i, j;
  2961. char *sn;
  2962. if (level > M3D_BONEMAXLEVEL || !bone) return ptr;
  2963. for (i = 0; i < numbone; i++) {
  2964. if (bone[i].parent == parent) {
  2965. for (j = 0; j < level; j++)
  2966. *ptr++ = '/';
  2967. sn = _m3d_safestr(bone[i].name, 0);
  2968. ptr += sprintf(ptr, "%d %d %s\r\n", vrtxidx[bone[i].pos], vrtxidx[bone[i].ori], sn);
  2969. M3D_FREE(sn);
  2970. ptr = _m3d_prtbone(ptr, bone, numbone, i, level + 1, vrtxidx);
  2971. }
  2972. }
  2973. return ptr;
  2974. }
  2975. /**
  2976. * Function to encode an in-memory model into on storage Model 3D format
  2977. */
  2978. unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size) {
  2979. const char *ol;
  2980. char *ptr;
  2981. char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s, fi_s;
  2982. char *sn = NULL, *sl = NULL, *sa = NULL, *sd = NULL;
  2983. unsigned char *out = NULL, *z = NULL, weights[M3D_NUMBONE], *norm = NULL;
  2984. unsigned int i = 0, j = 0, k = 0, l = 0, n = 0, len = 0, chunklen = 0, *length = NULL;
  2985. M3D_FLOAT scale = (M3D_FLOAT)0.0, min_x, max_x, min_y, max_y, min_z, max_z;
  2986. M3D_INDEX last, *vrtxidx = NULL, *mtrlidx = NULL, *tmapidx = NULL, *skinidx = NULL;
  2987. uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, maxvrtx = 0, numtmap = 0, maxtmap = 0, numproc = 0;
  2988. uint32_t numskin = 0, maxskin = 0, numstr = 0, maxt = 0, maxbone = 0, numgrp = 0, maxgrp = 0, *grpidx = NULL;
  2989. uint8_t *opa = nullptr;
  2990. m3dcd_t *cd;
  2991. m3dc_t *cmd;
  2992. m3dstr_t *str = NULL;
  2993. m3dvsave_t *vrtx = NULL, vertex;
  2994. m3dtisave_t *tmap = NULL, tcoord;
  2995. m3dssave_t *skin = NULL, sk;
  2996. m3dfsave_t *face = NULL;
  2997. m3dhdr_t *h = NULL;
  2998. m3dm_t *m;
  2999. m3da_t *a;
  3000. if (!model) {
  3001. if (size) *size = 0;
  3002. return NULL;
  3003. }
  3004. model->errcode = M3D_SUCCESS;
  3005. if (flags & M3D_EXP_ASCII) quality = M3D_EXP_DOUBLE;
  3006. vrtxidx = (M3D_INDEX *)M3D_MALLOC(model->numvertex * sizeof(M3D_INDEX));
  3007. if (!vrtxidx) goto memerr;
  3008. memset(vrtxidx, 255, model->numvertex * sizeof(M3D_INDEX));
  3009. if (model->numvertex && !(flags & M3D_EXP_NONORMAL)) {
  3010. norm = (unsigned char *)M3D_MALLOC(model->numvertex * sizeof(unsigned char));
  3011. if (!norm) goto memerr;
  3012. memset(norm, 0, model->numvertex * sizeof(unsigned char));
  3013. }
  3014. if (model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) {
  3015. mtrlidx = (M3D_INDEX *)M3D_MALLOC(model->nummaterial * sizeof(M3D_INDEX));
  3016. if (!mtrlidx) goto memerr;
  3017. memset(mtrlidx, 255, model->nummaterial * sizeof(M3D_INDEX));
  3018. opa = (uint8_t *)M3D_MALLOC(model->nummaterial * 2 * sizeof(M3D_INDEX));
  3019. if (!opa) goto memerr;
  3020. memset(opa, 255, model->nummaterial * 2 * sizeof(M3D_INDEX));
  3021. }
  3022. if (model->numtmap && !(flags & M3D_EXP_NOTXTCRD)) {
  3023. tmapidx = (M3D_INDEX *)M3D_MALLOC(model->numtmap * sizeof(M3D_INDEX));
  3024. if (!tmapidx) goto memerr;
  3025. memset(tmapidx, 255, model->numtmap * sizeof(M3D_INDEX));
  3026. }
  3027. /** collect array elements that are actually referenced **/
  3028. if (!(flags & M3D_EXP_NOFACE)) {
  3029. /* face */
  3030. if (model->numface && model->face) {
  3031. M3D_LOG("Processing mesh face");
  3032. face = (m3dfsave_t *)M3D_MALLOC(model->numface * sizeof(m3dfsave_t));
  3033. if (!face) goto memerr;
  3034. for (i = 0; i < model->numface; i++) {
  3035. memcpy(&face[i].data, &model->face[i], sizeof(m3df_t));
  3036. face[i].group = 0;
  3037. face[i].opacity = 255;
  3038. if (!(flags & M3D_EXP_NOMATERIAL) && model->face[i].materialid < model->nummaterial) {
  3039. if (model->material[model->face[i].materialid].numprop) {
  3040. mtrlidx[model->face[i].materialid] = 0;
  3041. if (opa[model->face[i].materialid * 2]) {
  3042. m = &model->material[model->face[i].materialid];
  3043. for (j = 0; j < m->numprop; j++)
  3044. if (m->prop[j].type == m3dp_Kd) {
  3045. opa[model->face[i].materialid * 2 + 1] = ((uint8_t *)&m->prop[j].value.color)[3];
  3046. break;
  3047. }
  3048. for (j = 0; j < m->numprop; j++)
  3049. if (m->prop[j].type == m3dp_d) {
  3050. opa[model->face[i].materialid * 2 + 1] = (uint8_t)(m->prop[j].value.fnum * 255);
  3051. break;
  3052. }
  3053. opa[model->face[i].materialid * 2] = 0;
  3054. }
  3055. face[i].opacity = opa[model->face[i].materialid * 2 + 1];
  3056. } else
  3057. face[i].data.materialid = M3D_UNDEF;
  3058. }
  3059. for (j = 0; j < 3; j++) {
  3060. k = model->face[i].vertex[j];
  3061. if (k < model->numvertex)
  3062. vrtxidx[k] = 0;
  3063. if (!(flags & M3D_EXP_NOCMAP)) {
  3064. cmap = _m3d_addcmap(cmap, &numcmap, model->vertex[k].color);
  3065. if (!cmap) goto memerr;
  3066. }
  3067. k = model->face[i].normal[j];
  3068. if (k < model->numvertex && !(flags & M3D_EXP_NONORMAL)) {
  3069. vrtxidx[k] = 0;
  3070. norm[k] = 1;
  3071. }
  3072. k = model->face[i].texcoord[j];
  3073. if (k < model->numtmap && !(flags & M3D_EXP_NOTXTCRD))
  3074. tmapidx[k] = 0;
  3075. }
  3076. /* convert from CW to CCW */
  3077. if (flags & M3D_EXP_IDOSUCK) {
  3078. j = face[i].data.vertex[1];
  3079. face[i].data.vertex[1] = face[i].data.vertex[2];
  3080. face[i].data.vertex[2] = face[i].data.vertex[1];
  3081. j = face[i].data.normal[1];
  3082. face[i].data.normal[1] = face[i].data.normal[2];
  3083. face[i].data.normal[2] = face[i].data.normal[1];
  3084. j = face[i].data.texcoord[1];
  3085. face[i].data.texcoord[1] = face[i].data.texcoord[2];
  3086. face[i].data.texcoord[2] = face[i].data.texcoord[1];
  3087. }
  3088. }
  3089. }
  3090. if (model->numshape && model->shape) {
  3091. M3D_LOG("Processing shape face");
  3092. for (i = 0; i < model->numshape; i++) {
  3093. if (!model->shape[i].numcmd) continue;
  3094. str = _m3d_addstr(str, &numstr, model->shape[i].name);
  3095. if (!str) goto memerr;
  3096. for (j = 0; j < model->shape[i].numcmd; j++) {
  3097. cmd = &model->shape[i].cmd[j];
  3098. if (cmd->type >= (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0])) || !cmd->arg)
  3099. continue;
  3100. if (cmd->type == m3dc_mesh) {
  3101. if (numgrp + 2 < maxgrp) {
  3102. maxgrp += 1024;
  3103. grpidx = (uint32_t *)realloc(grpidx, maxgrp * sizeof(uint32_t));
  3104. if (!grpidx) goto memerr;
  3105. if (!numgrp) {
  3106. grpidx[0] = 0;
  3107. grpidx[1] = model->numface;
  3108. numgrp += 2;
  3109. }
  3110. }
  3111. grpidx[numgrp + 0] = cmd->arg[0];
  3112. grpidx[numgrp + 1] = cmd->arg[0] + cmd->arg[1];
  3113. numgrp += 2;
  3114. }
  3115. cd = &m3d_commandtypes[cmd->type];
  3116. for (k = n = 0, l = cd->p; k < l; k++)
  3117. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  3118. case m3dcp_mi_t:
  3119. if (!(flags & M3D_EXP_NOMATERIAL) && cmd->arg[k] < model->nummaterial)
  3120. mtrlidx[cmd->arg[k]] = 0;
  3121. break;
  3122. case m3dcp_ti_t:
  3123. if (!(flags & M3D_EXP_NOTXTCRD) && cmd->arg[k] < model->numtmap)
  3124. tmapidx[cmd->arg[k]] = 0;
  3125. break;
  3126. case m3dcp_qi_t:
  3127. case m3dcp_vi_t:
  3128. if (cmd->arg[k] < model->numvertex)
  3129. vrtxidx[cmd->arg[k]] = 0;
  3130. break;
  3131. case m3dcp_va_t:
  3132. n = k + 1;
  3133. l += (cmd->arg[k] - 1) * (cd->p - k - 1);
  3134. break;
  3135. }
  3136. }
  3137. }
  3138. }
  3139. if (model->numface && face) {
  3140. if (numgrp && grpidx) {
  3141. qsort(grpidx, numgrp, sizeof(uint32_t), _m3d_grpcmp);
  3142. for (i = j = 0; i < model->numface && j < numgrp; i++) {
  3143. while (j < numgrp && grpidx[j] < i)
  3144. j++;
  3145. face[i].group = j;
  3146. }
  3147. }
  3148. qsort(face, model->numface, sizeof(m3dfsave_t), _m3d_facecmp);
  3149. }
  3150. if (grpidx) {
  3151. M3D_FREE(grpidx);
  3152. grpidx = NULL;
  3153. }
  3154. if (model->numlabel && model->label) {
  3155. M3D_LOG("Processing annotation labels");
  3156. for (i = 0; i < model->numlabel; i++) {
  3157. str = _m3d_addstr(str, &numstr, model->label[i].name);
  3158. str = _m3d_addstr(str, &numstr, model->label[i].lang);
  3159. str = _m3d_addstr(str, &numstr, model->label[i].text);
  3160. if (!(flags & M3D_EXP_NOCMAP)) {
  3161. cmap = _m3d_addcmap(cmap, &numcmap, model->label[i].color);
  3162. if (!cmap) goto memerr;
  3163. }
  3164. if (model->label[i].vertexid < model->numvertex)
  3165. vrtxidx[model->label[i].vertexid] = 0;
  3166. }
  3167. qsort(model->label, model->numlabel, sizeof(m3dl_t), _m3d_lblcmp);
  3168. }
  3169. } else if (!(flags & M3D_EXP_NOMATERIAL)) {
  3170. /* without a face, simply add all materials, because it can be an mtllib */
  3171. for (i = 0; i < model->nummaterial; i++)
  3172. mtrlidx[i] = i;
  3173. }
  3174. /* bind-pose skeleton */
  3175. if (model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
  3176. M3D_LOG("Processing bones");
  3177. for (i = 0; i < model->numbone; i++) {
  3178. str = _m3d_addstr(str, &numstr, model->bone[i].name);
  3179. if (!str) goto memerr;
  3180. k = model->bone[i].pos;
  3181. if (k < model->numvertex)
  3182. vrtxidx[k] = 0;
  3183. k = model->bone[i].ori;
  3184. if (k < model->numvertex)
  3185. vrtxidx[k] = 0;
  3186. }
  3187. }
  3188. /* actions, animated skeleton poses */
  3189. if (model->numaction && model->action && !(flags & M3D_EXP_NOACTION)) {
  3190. M3D_LOG("Processing action list");
  3191. for (j = 0; j < model->numaction; j++) {
  3192. a = &model->action[j];
  3193. str = _m3d_addstr(str, &numstr, a->name);
  3194. if (!str) goto memerr;
  3195. if (a->numframe > 65535) a->numframe = 65535;
  3196. for (i = 0; i < a->numframe; i++) {
  3197. for (l = 0; l < a->frame[i].numtransform; l++) {
  3198. k = a->frame[i].transform[l].pos;
  3199. if (k < model->numvertex)
  3200. vrtxidx[k] = 0;
  3201. k = a->frame[i].transform[l].ori;
  3202. if (k < model->numvertex)
  3203. vrtxidx[k] = 0;
  3204. }
  3205. if (l > maxt) maxt = l;
  3206. }
  3207. }
  3208. }
  3209. /* add colors to color map and texture names to string table */
  3210. if (!(flags & M3D_EXP_NOMATERIAL)) {
  3211. M3D_LOG("Processing materials");
  3212. for (i = k = 0; i < model->nummaterial; i++) {
  3213. if (mtrlidx[i] == M3D_UNDEF || !model->material[i].numprop) continue;
  3214. mtrlidx[i] = k++;
  3215. m = &model->material[i];
  3216. str = _m3d_addstr(str, &numstr, m->name);
  3217. if (!str) goto memerr;
  3218. if (m->prop)
  3219. for (j = 0; j < m->numprop; j++) {
  3220. if (!(flags & M3D_EXP_NOCMAP) && m->prop[j].type < 128) {
  3221. for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++) {
  3222. if (m->prop[j].type == m3d_propertytypes[l].id && m3d_propertytypes[l].format == m3dpf_color) {
  3223. ((uint8_t *)&m->prop[j].value.color)[3] = opa[i * 2 + 1];
  3224. cmap = _m3d_addcmap(cmap, &numcmap, m->prop[j].value.color);
  3225. if (!cmap) goto memerr;
  3226. break;
  3227. }
  3228. }
  3229. }
  3230. if (m->prop[j].type >= 128 && m->prop[j].value.textureid < model->numtexture &&
  3231. model->texture[m->prop[j].value.textureid].name) {
  3232. str = _m3d_addstr(str, &numstr, model->texture[m->prop[j].value.textureid].name);
  3233. if (!str) goto memerr;
  3234. }
  3235. }
  3236. }
  3237. }
  3238. /* if there's only one black color, don't store it */
  3239. if (numcmap == 1 && cmap && !cmap[0]) numcmap = 0;
  3240. /** compress lists **/
  3241. if (model->numtmap && !(flags & M3D_EXP_NOTXTCRD)) {
  3242. M3D_LOG("Compressing tmap");
  3243. tmap = (m3dtisave_t *)M3D_MALLOC(model->numtmap * sizeof(m3dtisave_t));
  3244. if (!tmap) goto memerr;
  3245. for (i = 0; i < model->numtmap; i++) {
  3246. if (tmapidx[i] == M3D_UNDEF) continue;
  3247. switch (quality) {
  3248. case M3D_EXP_INT8:
  3249. l = (unsigned int)(model->tmap[i].u * 255);
  3250. tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)255.0;
  3251. l = (unsigned int)(model->tmap[i].v * 255);
  3252. tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)255.0;
  3253. break;
  3254. case M3D_EXP_INT16:
  3255. l = (unsigned int)(model->tmap[i].u * 65535);
  3256. tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)65535.0;
  3257. l = (unsigned int)(model->tmap[i].v * 65535);
  3258. tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)65535.0;
  3259. break;
  3260. default:
  3261. tcoord.data.u = model->tmap[i].u;
  3262. tcoord.data.v = model->tmap[i].v;
  3263. break;
  3264. }
  3265. if (flags & M3D_EXP_FLIPTXTCRD)
  3266. tcoord.data.v = (M3D_FLOAT)1.0 - tcoord.data.v;
  3267. tcoord.oldidx = i;
  3268. memcpy(&tmap[numtmap++], &tcoord, sizeof(m3dtisave_t));
  3269. }
  3270. if (numtmap) {
  3271. qsort(tmap, numtmap, sizeof(m3dtisave_t), _m3d_ticmp);
  3272. memcpy(&tcoord.data, &tmap[0], sizeof(m3dti_t));
  3273. for (i = 0; i < numtmap; i++) {
  3274. if (memcmp(&tcoord.data, &tmap[i].data, sizeof(m3dti_t))) {
  3275. memcpy(&tcoord.data, &tmap[i].data, sizeof(m3dti_t));
  3276. maxtmap++;
  3277. }
  3278. tmap[i].newidx = maxtmap;
  3279. tmapidx[tmap[i].oldidx] = maxtmap;
  3280. }
  3281. maxtmap++;
  3282. }
  3283. }
  3284. if (model->numskin && model->skin && !(flags & M3D_EXP_NOBONE)) {
  3285. M3D_LOG("Compressing skin");
  3286. skinidx = (M3D_INDEX *)M3D_MALLOC(model->numskin * sizeof(M3D_INDEX));
  3287. if (!skinidx) goto memerr;
  3288. skin = (m3dssave_t *)M3D_MALLOC(model->numskin * sizeof(m3dssave_t));
  3289. if (!skin) goto memerr;
  3290. memset(skinidx, 255, model->numskin * sizeof(M3D_INDEX));
  3291. for (i = 0; i < model->numvertex; i++) {
  3292. if (vrtxidx[i] != M3D_UNDEF && model->vertex[i].skinid < model->numskin)
  3293. skinidx[model->vertex[i].skinid] = 0;
  3294. }
  3295. for (i = 0; i < model->numskin; i++) {
  3296. if (skinidx[i] == M3D_UNDEF) continue;
  3297. memset(&sk, 0, sizeof(m3dssave_t));
  3298. for (j = 0, min_x = (M3D_FLOAT)0.0; j < M3D_NUMBONE && model->skin[i].boneid[j] != M3D_UNDEF &&
  3299. model->skin[i].weight[j] > (M3D_FLOAT)0.0;
  3300. j++) {
  3301. sk.data.boneid[j] = model->skin[i].boneid[j];
  3302. sk.data.weight[j] = model->skin[i].weight[j];
  3303. min_x += sk.data.weight[j];
  3304. }
  3305. if (j > maxbone) maxbone = j;
  3306. if (min_x != (M3D_FLOAT)1.0 && min_x != (M3D_FLOAT)0.0)
  3307. for (j = 0; j < M3D_NUMBONE && sk.data.weight[j] > (M3D_FLOAT)0.0; j++)
  3308. sk.data.weight[j] /= min_x;
  3309. sk.oldidx = i;
  3310. memcpy(&skin[numskin++], &sk, sizeof(m3dssave_t));
  3311. }
  3312. if (numskin) {
  3313. qsort(skin, numskin, sizeof(m3dssave_t), _m3d_skincmp);
  3314. memcpy(&sk.data, &skin[0].data, sizeof(m3ds_t));
  3315. for (i = 0; i < numskin; i++) {
  3316. if (memcmp(&sk.data, &skin[i].data, sizeof(m3ds_t))) {
  3317. memcpy(&sk.data, &skin[i].data, sizeof(m3ds_t));
  3318. maxskin++;
  3319. }
  3320. skin[i].newidx = maxskin;
  3321. skinidx[skin[i].oldidx] = maxskin;
  3322. }
  3323. maxskin++;
  3324. }
  3325. }
  3326. M3D_LOG("Compressing vertex list");
  3327. min_x = min_y = min_z = (M3D_FLOAT)1e10;
  3328. max_x = max_y = max_z = (M3D_FLOAT)-1e10;
  3329. if (vrtxidx) {
  3330. vrtx = (m3dvsave_t *)M3D_MALLOC(model->numvertex * sizeof(m3dvsave_t));
  3331. if (!vrtx) goto memerr;
  3332. for (i = numvrtx = 0; i < model->numvertex; i++) {
  3333. if (vrtxidx[i] == M3D_UNDEF) continue;
  3334. _m3d_round(quality, &model->vertex[i], &vertex.data);
  3335. vertex.norm = norm ? norm[i] : 0;
  3336. if (vertex.data.skinid != M3D_INDEXMAX && !vertex.norm) {
  3337. vertex.data.skinid = vertex.data.skinid != M3D_UNDEF && skinidx ? skinidx[vertex.data.skinid] : M3D_UNDEF;
  3338. if (vertex.data.x > max_x) max_x = vertex.data.x;
  3339. if (vertex.data.x < min_x) min_x = vertex.data.x;
  3340. if (vertex.data.y > max_y) max_y = vertex.data.y;
  3341. if (vertex.data.y < min_y) min_y = vertex.data.y;
  3342. if (vertex.data.z > max_z) max_z = vertex.data.z;
  3343. if (vertex.data.z < min_z) min_z = vertex.data.z;
  3344. }
  3345. #ifdef M3D_VERTEXTYPE
  3346. vertex.data.type = 0;
  3347. #endif
  3348. vertex.oldidx = i;
  3349. memcpy(&vrtx[numvrtx++], &vertex, sizeof(m3dvsave_t));
  3350. }
  3351. if (numvrtx) {
  3352. qsort(vrtx, numvrtx, sizeof(m3dvsave_t), _m3d_vrtxcmp);
  3353. memcpy(&vertex.data, &vrtx[0].data, sizeof(m3dv_t));
  3354. for (i = 0; i < numvrtx; i++) {
  3355. if (memcmp(&vertex.data, &vrtx[i].data, vrtx[i].norm ? 3 * sizeof(M3D_FLOAT) : sizeof(m3dv_t))) {
  3356. memcpy(&vertex.data, &vrtx[i].data, sizeof(m3dv_t));
  3357. maxvrtx++;
  3358. }
  3359. vrtx[i].newidx = maxvrtx;
  3360. vrtxidx[vrtx[i].oldidx] = maxvrtx;
  3361. }
  3362. maxvrtx++;
  3363. }
  3364. }
  3365. if (skinidx) {
  3366. M3D_FREE(skinidx);
  3367. skinidx = NULL;
  3368. }
  3369. if (norm) {
  3370. M3D_FREE(norm);
  3371. norm = NULL;
  3372. }
  3373. /* normalize to bounding cube */
  3374. if (numvrtx && !(flags & M3D_EXP_NORECALC)) {
  3375. M3D_LOG("Normalizing coordinates");
  3376. if (min_x < (M3D_FLOAT)0.0) min_x = -min_x;
  3377. if (max_x < (M3D_FLOAT)0.0) max_x = -max_x;
  3378. if (min_y < (M3D_FLOAT)0.0) min_y = -min_y;
  3379. if (max_y < (M3D_FLOAT)0.0) max_y = -max_y;
  3380. if (min_z < (M3D_FLOAT)0.0) min_z = -min_z;
  3381. if (max_z < (M3D_FLOAT)0.0) max_z = -max_z;
  3382. scale = min_x;
  3383. if (max_x > scale) scale = max_x;
  3384. if (min_y > scale) scale = min_y;
  3385. if (max_y > scale) scale = max_y;
  3386. if (min_z > scale) scale = min_z;
  3387. if (max_z > scale) scale = max_z;
  3388. if (scale == (M3D_FLOAT)0.0) scale = (M3D_FLOAT)1.0;
  3389. if (scale != (M3D_FLOAT)1.0) {
  3390. for (i = 0; i < numvrtx; i++) {
  3391. if (vrtx[i].data.skinid == M3D_INDEXMAX) continue;
  3392. vrtx[i].data.x /= scale;
  3393. vrtx[i].data.y /= scale;
  3394. vrtx[i].data.z /= scale;
  3395. }
  3396. }
  3397. }
  3398. if (model->scale > (M3D_FLOAT)0.0) scale = model->scale;
  3399. if (scale <= (M3D_FLOAT)0.0) scale = (M3D_FLOAT)1.0;
  3400. /* meta info */
  3401. sn = _m3d_safestr(model->name && *model->name ? model->name : (char *)"(noname)", 2);
  3402. sl = _m3d_safestr(model->license ? model->license : (char *)"MIT", 2);
  3403. sa = _m3d_safestr(model->author ? model->author : getenv("LOGNAME"), 2);
  3404. if (!sn || !sl || !sa) {
  3405. memerr:
  3406. if (vrtxidx) M3D_FREE(vrtxidx);
  3407. if (mtrlidx) M3D_FREE(mtrlidx);
  3408. if (tmapidx) M3D_FREE(tmapidx);
  3409. if (skinidx) M3D_FREE(skinidx);
  3410. if (grpidx) M3D_FREE(grpidx);
  3411. if (norm) M3D_FREE(norm);
  3412. if (face) M3D_FREE(face);
  3413. if (cmap) M3D_FREE(cmap);
  3414. if (tmap) M3D_FREE(tmap);
  3415. if (skin) M3D_FREE(skin);
  3416. if (str) M3D_FREE(str);
  3417. if (vrtx) M3D_FREE(vrtx);
  3418. if (sn) M3D_FREE(sn);
  3419. if (sl) M3D_FREE(sl);
  3420. if (sa) M3D_FREE(sa);
  3421. if (sd) M3D_FREE(sd);
  3422. if (out) M3D_FREE(out);
  3423. if (h) M3D_FREE(h);
  3424. M3D_LOG("Out of memory");
  3425. model->errcode = M3D_ERR_ALLOC;
  3426. return NULL;
  3427. }
  3428. M3D_LOG("Serializing model");
  3429. if (flags & M3D_EXP_ASCII) {
  3430. /* use CRLF to make model creators on Win happy... */
  3431. sd = _m3d_safestr(model->desc, 1);
  3432. if (!sd) goto memerr;
  3433. ol = setlocale(LC_NUMERIC, NULL);
  3434. setlocale(LC_NUMERIC, "C");
  3435. /* header */
  3436. len = 64 + (unsigned int)(strlen(sn) + strlen(sl) + strlen(sa) + strlen(sd));
  3437. out = (unsigned char *)M3D_MALLOC(len);
  3438. if (!out) {
  3439. setlocale(LC_NUMERIC, ol);
  3440. goto memerr;
  3441. }
  3442. ptr = (char *)out;
  3443. ptr += sprintf(ptr, "3dmodel %g\r\n%s\r\n%s\r\n%s\r\n%s\r\n\r\n", scale,
  3444. sn, sl, sa, sd);
  3445. M3D_FREE(sl);
  3446. M3D_FREE(sa);
  3447. M3D_FREE(sd);
  3448. sl = sa = sd = NULL;
  3449. /* preview chunk */
  3450. if (model->preview.data && model->preview.length) {
  3451. sl = _m3d_safestr(sn, 0);
  3452. if (sl) {
  3453. ptr -= (uintptr_t)out;
  3454. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)20);
  3455. out = (unsigned char *)M3D_REALLOC(out, len);
  3456. ptr += (uintptr_t)out;
  3457. if (!out) {
  3458. setlocale(LC_NUMERIC, ol);
  3459. goto memerr;
  3460. }
  3461. ptr += sprintf(ptr, "Preview\r\n%s.png\r\n\r\n", sl);
  3462. M3D_FREE(sl);
  3463. sl = NULL;
  3464. }
  3465. }
  3466. M3D_FREE(sn);
  3467. sn = NULL;
  3468. /* texture map */
  3469. if (numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) {
  3470. ptr -= (uintptr_t)out;
  3471. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(maxtmap * 32) + (uintptr_t)12);
  3472. out = (unsigned char *)M3D_REALLOC(out, len);
  3473. ptr += (uintptr_t)out;
  3474. if (!out) {
  3475. setlocale(LC_NUMERIC, ol);
  3476. goto memerr;
  3477. }
  3478. ptr += sprintf(ptr, "Textmap\r\n");
  3479. last = M3D_UNDEF;
  3480. for (i = 0; i < numtmap; i++) {
  3481. if (tmap[i].newidx == last) continue;
  3482. last = tmap[i].newidx;
  3483. ptr += sprintf(ptr, "%g %g\r\n", tmap[i].data.u, tmap[i].data.v);
  3484. }
  3485. ptr += sprintf(ptr, "\r\n");
  3486. }
  3487. /* vertex chunk */
  3488. if (numvrtx && vrtx && !(flags & M3D_EXP_NOFACE)) {
  3489. ptr -= (uintptr_t)out;
  3490. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(maxvrtx * 128) + (uintptr_t)10);
  3491. out = (unsigned char *)M3D_REALLOC(out, len);
  3492. ptr += (uintptr_t)out;
  3493. if (!out) {
  3494. setlocale(LC_NUMERIC, ol);
  3495. goto memerr;
  3496. }
  3497. ptr += sprintf(ptr, "Vertex\r\n");
  3498. last = M3D_UNDEF;
  3499. for (i = 0; i < numvrtx; i++) {
  3500. if (vrtx[i].newidx == last) continue;
  3501. last = vrtx[i].newidx;
  3502. ptr += sprintf(ptr, "%g %g %g %g", vrtx[i].data.x, vrtx[i].data.y, vrtx[i].data.z, vrtx[i].data.w);
  3503. if (!(flags & M3D_EXP_NOCMAP) && vrtx[i].data.color)
  3504. ptr += sprintf(ptr, " #%08x", vrtx[i].data.color);
  3505. if (!(flags & M3D_EXP_NOBONE) && model->numbone && maxskin && vrtx[i].data.skinid < M3D_INDEXMAX) {
  3506. if (skin[vrtx[i].data.skinid].data.weight[0] == (M3D_FLOAT)1.0)
  3507. ptr += sprintf(ptr, " %d", skin[vrtx[i].data.skinid].data.boneid[0]);
  3508. else
  3509. for (j = 0; j < M3D_NUMBONE && skin[vrtx[i].data.skinid].data.boneid[j] != M3D_UNDEF &&
  3510. skin[vrtx[i].data.skinid].data.weight[j] > (M3D_FLOAT)0.0;
  3511. j++)
  3512. ptr += sprintf(ptr, " %d:%g", skin[vrtx[i].data.skinid].data.boneid[j],
  3513. skin[vrtx[i].data.skinid].data.weight[j]);
  3514. }
  3515. ptr += sprintf(ptr, "\r\n");
  3516. }
  3517. ptr += sprintf(ptr, "\r\n");
  3518. }
  3519. /* bones chunk */
  3520. if (model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
  3521. ptr -= (uintptr_t)out;
  3522. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)9);
  3523. for (i = 0; i < model->numbone; i++) {
  3524. len += (unsigned int)strlen(model->bone[i].name) + 128;
  3525. }
  3526. out = (unsigned char *)M3D_REALLOC(out, len);
  3527. ptr += (uintptr_t)out;
  3528. if (!out) {
  3529. setlocale(LC_NUMERIC, ol);
  3530. goto memerr;
  3531. }
  3532. ptr += sprintf(ptr, "Bones\r\n");
  3533. ptr = _m3d_prtbone(ptr, model->bone, model->numbone, M3D_UNDEF, 0, vrtxidx);
  3534. ptr += sprintf(ptr, "\r\n");
  3535. }
  3536. /* materials */
  3537. if (model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) {
  3538. for (j = 0; j < model->nummaterial; j++) {
  3539. if (mtrlidx[j] == M3D_UNDEF || !model->material[j].numprop || !model->material[j].prop) continue;
  3540. m = &model->material[j];
  3541. sn = _m3d_safestr(m->name, 0);
  3542. if (!sn) {
  3543. setlocale(LC_NUMERIC, ol);
  3544. goto memerr;
  3545. }
  3546. ptr -= (uintptr_t)out;
  3547. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)12);
  3548. for (i = 0; i < m->numprop; i++) {
  3549. if (m->prop[i].type < 128)
  3550. len += 32;
  3551. else if (m->prop[i].value.textureid < model->numtexture && model->texture[m->prop[i].value.textureid].name)
  3552. len += (unsigned int)strlen(model->texture[m->prop[i].value.textureid].name) + 16;
  3553. }
  3554. out = (unsigned char *)M3D_REALLOC(out, len);
  3555. ptr += (uintptr_t)out;
  3556. if (!out) {
  3557. setlocale(LC_NUMERIC, ol);
  3558. goto memerr;
  3559. }
  3560. ptr += sprintf(ptr, "Material %s\r\n", sn);
  3561. M3D_FREE(sn);
  3562. sn = NULL;
  3563. for (i = 0; i < m->numprop; i++) {
  3564. k = 256;
  3565. if (m->prop[i].type >= 128) {
  3566. for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++)
  3567. if (m->prop[i].type == m3d_propertytypes[l].id) {
  3568. sn = m3d_propertytypes[l].key;
  3569. break;
  3570. }
  3571. if (!sn)
  3572. for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++)
  3573. if (m->prop[i].type - 128 == m3d_propertytypes[l].id) {
  3574. sn = m3d_propertytypes[l].key;
  3575. break;
  3576. }
  3577. k = sn ? m3dpf_map : 256;
  3578. } else {
  3579. for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++)
  3580. if (m->prop[i].type == m3d_propertytypes[l].id) {
  3581. sn = m3d_propertytypes[l].key;
  3582. k = m3d_propertytypes[l].format;
  3583. break;
  3584. }
  3585. }
  3586. switch (k) {
  3587. case m3dpf_color: ptr += sprintf(ptr, "%s #%08x\r\n", sn, m->prop[i].value.color); break;
  3588. case m3dpf_uint8:
  3589. case m3dpf_uint16:
  3590. case m3dpf_uint32: ptr += sprintf(ptr, "%s %d\r\n", sn, m->prop[i].value.num); break;
  3591. case m3dpf_float: ptr += sprintf(ptr, "%s %g\r\n", sn, m->prop[i].value.fnum); break;
  3592. case m3dpf_map:
  3593. if (m->prop[i].value.textureid < model->numtexture &&
  3594. model->texture[m->prop[i].value.textureid].name) {
  3595. sl = _m3d_safestr(model->texture[m->prop[i].value.textureid].name, 0);
  3596. if (!sl) {
  3597. setlocale(LC_NUMERIC, ol);
  3598. goto memerr;
  3599. }
  3600. if (*sl)
  3601. ptr += sprintf(ptr, "map_%s %s\r\n", sn, sl);
  3602. M3D_FREE(sn);
  3603. M3D_FREE(sl);
  3604. sl = NULL;
  3605. }
  3606. break;
  3607. }
  3608. sn = NULL;
  3609. }
  3610. ptr += sprintf(ptr, "\r\n");
  3611. }
  3612. }
  3613. /* procedural face */
  3614. if (model->numinlined && model->inlined && !(flags & M3D_EXP_NOFACE)) {
  3615. /* all inlined assets which are not textures should be procedural surfaces */
  3616. for (j = 0; j < model->numinlined; j++) {
  3617. if (!model->inlined[j].name || !*model->inlined[j].name || !model->inlined[j].length || !model->inlined[j].data ||
  3618. (model->inlined[j].data[1] == 'P' && model->inlined[j].data[2] == 'N' && model->inlined[j].data[3] == 'G'))
  3619. continue;
  3620. for (i = k = 0; i < model->numtexture; i++) {
  3621. if (!strcmp(model->inlined[j].name, model->texture[i].name)) {
  3622. k = 1;
  3623. break;
  3624. }
  3625. }
  3626. if (k) continue;
  3627. sn = _m3d_safestr(model->inlined[j].name, 0);
  3628. if (!sn) {
  3629. setlocale(LC_NUMERIC, ol);
  3630. goto memerr;
  3631. }
  3632. ptr -= (uintptr_t)out;
  3633. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)18);
  3634. out = (unsigned char *)M3D_REALLOC(out, len);
  3635. ptr += (uintptr_t)out;
  3636. if (!out) {
  3637. setlocale(LC_NUMERIC, ol);
  3638. goto memerr;
  3639. }
  3640. ptr += sprintf(ptr, "Procedural\r\n%s\r\n\r\n", sn);
  3641. M3D_FREE(sn);
  3642. sn = NULL;
  3643. }
  3644. }
  3645. /* mesh face */
  3646. if (model->numface && face && !(flags & M3D_EXP_NOFACE)) {
  3647. ptr -= (uintptr_t)out;
  3648. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(model->numface * 128) + (uintptr_t)6);
  3649. last = M3D_UNDEF;
  3650. if (!(flags & M3D_EXP_NOMATERIAL))
  3651. for (i = 0; i < model->numface; i++) {
  3652. j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : M3D_UNDEF;
  3653. if (j != last) {
  3654. last = j;
  3655. if (last < model->nummaterial)
  3656. len += (unsigned int)strlen(model->material[last].name);
  3657. len += 6;
  3658. }
  3659. }
  3660. out = (unsigned char *)M3D_REALLOC(out, len);
  3661. ptr += (uintptr_t)out;
  3662. if (!out) {
  3663. setlocale(LC_NUMERIC, ol);
  3664. goto memerr;
  3665. }
  3666. ptr += sprintf(ptr, "Mesh\r\n");
  3667. last = M3D_UNDEF;
  3668. for (i = 0; i < model->numface; i++) {
  3669. j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : M3D_UNDEF;
  3670. if (!(flags & M3D_EXP_NOMATERIAL) && j != last) {
  3671. last = j;
  3672. if (last < model->nummaterial) {
  3673. sn = _m3d_safestr(model->material[last].name, 0);
  3674. if (!sn) {
  3675. setlocale(LC_NUMERIC, ol);
  3676. goto memerr;
  3677. }
  3678. ptr += sprintf(ptr, "use %s\r\n", sn);
  3679. M3D_FREE(sn);
  3680. sn = NULL;
  3681. } else
  3682. ptr += sprintf(ptr, "use\r\n");
  3683. }
  3684. /* hardcoded triangles. Should be repeated as many times as the number of edges in polygon */
  3685. for (j = 0; j < 3; j++) {
  3686. ptr += sprintf(ptr, "%s%d", j ? " " : "", vrtxidx[face[i].data.vertex[j]]);
  3687. k = M3D_NOTDEFINED;
  3688. if (!(flags & M3D_EXP_NOTXTCRD) && (face[i].data.texcoord[j] != M3D_UNDEF) &&
  3689. (tmapidx[face[i].data.texcoord[j]] != M3D_UNDEF)) {
  3690. k = tmapidx[face[i].data.texcoord[j]];
  3691. ptr += sprintf(ptr, "/%d", k);
  3692. }
  3693. if (!(flags & M3D_EXP_NONORMAL) && (face[i].data.normal[j] != M3D_UNDEF))
  3694. ptr += sprintf(ptr, "%s/%d", k == M3D_NOTDEFINED ? "/" : "", vrtxidx[face[i].data.normal[j]]);
  3695. }
  3696. ptr += sprintf(ptr, "\r\n");
  3697. }
  3698. ptr += sprintf(ptr, "\r\n");
  3699. }
  3700. /* mathematical shapes face */
  3701. if (model->numshape && (!(flags & M3D_EXP_NOFACE))) {
  3702. for (j = 0; j < model->numshape; j++) {
  3703. sn = _m3d_safestr(model->shape[j].name, 0);
  3704. if (!sn) {
  3705. setlocale(LC_NUMERIC, ol);
  3706. goto memerr;
  3707. }
  3708. ptr -= (uintptr_t)out;
  3709. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)33);
  3710. out = (unsigned char *)M3D_REALLOC(out, len);
  3711. ptr += (uintptr_t)out;
  3712. if (!out) {
  3713. setlocale(LC_NUMERIC, ol);
  3714. goto memerr;
  3715. }
  3716. ptr += sprintf(ptr, "Shape %s\r\n", sn);
  3717. M3D_FREE(sn);
  3718. sn = NULL;
  3719. if (model->shape[j].group != M3D_UNDEF && !(flags & M3D_EXP_NOBONE))
  3720. ptr += sprintf(ptr, "group %d\r\n", model->shape[j].group);
  3721. for (i = 0; i < model->shape[j].numcmd; i++) {
  3722. cmd = &model->shape[j].cmd[i];
  3723. if (cmd->type >= (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0])) || !cmd->arg)
  3724. continue;
  3725. cd = &m3d_commandtypes[cmd->type];
  3726. ptr -= (uintptr_t)out;
  3727. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(cd->key) + (uintptr_t)3);
  3728. for (k = 0; k < cd->p; k++)
  3729. switch (cd->a[k]) {
  3730. case m3dcp_mi_t:
  3731. if (cmd->arg[k] != M3D_NOTDEFINED) {
  3732. len += (unsigned int)strlen(model->material[cmd->arg[k]].name) + 1;
  3733. }
  3734. break;
  3735. case m3dcp_va_t:
  3736. len += cmd->arg[k] * (cd->p - k - 1) * 16;
  3737. k = cd->p;
  3738. break;
  3739. default: len += 16; break;
  3740. }
  3741. out = (unsigned char *)M3D_REALLOC(out, len);
  3742. ptr += (uintptr_t)out;
  3743. if (!out) {
  3744. setlocale(LC_NUMERIC, ol);
  3745. goto memerr;
  3746. }
  3747. ptr += sprintf(ptr, "%s", cd->key);
  3748. for (k = n = 0, l = cd->p; k < l; k++) {
  3749. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  3750. case m3dcp_mi_t:
  3751. if (cmd->arg[k] != M3D_NOTDEFINED) {
  3752. sn = _m3d_safestr(model->material[cmd->arg[k]].name, 0);
  3753. if (!sn) {
  3754. setlocale(LC_NUMERIC, ol);
  3755. goto memerr;
  3756. }
  3757. ptr += sprintf(ptr, " %s", sn);
  3758. M3D_FREE(sn);
  3759. sn = NULL;
  3760. }
  3761. break;
  3762. case m3dcp_vc_t: ptr += sprintf(ptr, " %g", *((float *)&cmd->arg[k])); break;
  3763. case m3dcp_va_t:
  3764. ptr += sprintf(ptr, " %d[", cmd->arg[k]);
  3765. n = k + 1;
  3766. l += (cmd->arg[k] - 1) * (cd->p - k - 1);
  3767. break;
  3768. default: ptr += sprintf(ptr, " %d", cmd->arg[k]); break;
  3769. }
  3770. }
  3771. ptr += sprintf(ptr, "%s\r\n", l > cd->p ? " ]" : "");
  3772. }
  3773. ptr += sprintf(ptr, "\r\n");
  3774. }
  3775. }
  3776. /* annotation labels */
  3777. if (model->numlabel && model->label && !(flags & M3D_EXP_NOFACE)) {
  3778. for (i = 0, j = 3, length = NULL; i < model->numlabel; i++) {
  3779. if (model->label[i].name) j += (unsigned int)strlen(model->label[i].name);
  3780. if (model->label[i].lang) j += (unsigned int)strlen(model->label[i].lang);
  3781. if (model->label[i].text) j += (unsigned int)strlen(model->label[i].text);
  3782. j += 40;
  3783. }
  3784. ptr -= (uintptr_t)out;
  3785. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)j);
  3786. out = (unsigned char *)M3D_REALLOC(out, len);
  3787. ptr += (uintptr_t)out;
  3788. if (!out) {
  3789. setlocale(LC_NUMERIC, ol);
  3790. goto memerr;
  3791. }
  3792. for (i = 0; i < model->numlabel; i++) {
  3793. if (!i || _m3d_strcmp(sl, model->label[i].lang) || _m3d_strcmp(sn, model->label[i].name)) {
  3794. sl = model->label[i].lang;
  3795. sn = model->label[i].name;
  3796. sd = _m3d_safestr(sn, 0);
  3797. if (!sd) {
  3798. setlocale(LC_NUMERIC, ol);
  3799. sn = sl = NULL;
  3800. goto memerr;
  3801. }
  3802. if (i) ptr += sprintf(ptr, "\r\n");
  3803. ptr += sprintf(ptr, "Labels %s\r\n", sd);
  3804. M3D_FREE(sd);
  3805. sd = NULL;
  3806. if (model->label[i].color)
  3807. ptr += sprintf(ptr, "color #0x%08x\r\n", model->label[i].color);
  3808. if (sl && *sl) {
  3809. sd = _m3d_safestr(sl, 0);
  3810. if (!sd) {
  3811. setlocale(LC_NUMERIC, ol);
  3812. sn = sl = NULL;
  3813. goto memerr;
  3814. }
  3815. ptr += sprintf(ptr, "lang %s\r\n", sd);
  3816. M3D_FREE(sd);
  3817. sd = NULL;
  3818. }
  3819. }
  3820. sd = _m3d_safestr(model->label[i].text, 2);
  3821. if (!sd) {
  3822. setlocale(LC_NUMERIC, ol);
  3823. sn = sl = NULL;
  3824. goto memerr;
  3825. }
  3826. ptr += sprintf(ptr, "%d %s\r\n", model->label[i].vertexid, sd);
  3827. M3D_FREE(sd);
  3828. sd = NULL;
  3829. }
  3830. ptr += sprintf(ptr, "\r\n");
  3831. sn = sl = NULL;
  3832. }
  3833. /* actions */
  3834. if (model->numaction && model->action && !(flags & M3D_EXP_NOACTION)) {
  3835. for (j = 0; j < model->numaction; j++) {
  3836. a = &model->action[j];
  3837. sn = _m3d_safestr(a->name, 0);
  3838. if (!sn) {
  3839. setlocale(LC_NUMERIC, ol);
  3840. goto memerr;
  3841. }
  3842. ptr -= (uintptr_t)out;
  3843. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)48);
  3844. for (i = 0; i < a->numframe; i++)
  3845. len += a->frame[i].numtransform * 128 + 8;
  3846. out = (unsigned char *)M3D_REALLOC(out, len);
  3847. ptr += (uintptr_t)out;
  3848. if (!out) {
  3849. setlocale(LC_NUMERIC, ol);
  3850. goto memerr;
  3851. }
  3852. ptr += sprintf(ptr, "Action %d %s\r\n", a->durationmsec, sn);
  3853. M3D_FREE(sn);
  3854. sn = NULL;
  3855. for (i = 0; i < a->numframe; i++) {
  3856. ptr += sprintf(ptr, "frame %d\r\n", a->frame[i].msec);
  3857. for (k = 0; k < a->frame[i].numtransform; k++) {
  3858. ptr += sprintf(ptr, "%d %d %d\r\n", a->frame[i].transform[k].boneid,
  3859. vrtxidx[a->frame[i].transform[k].pos], vrtxidx[a->frame[i].transform[k].ori]);
  3860. }
  3861. }
  3862. ptr += sprintf(ptr, "\r\n");
  3863. }
  3864. }
  3865. /* inlined assets */
  3866. if (model->numinlined && model->inlined) {
  3867. for (i = j = 0; i < model->numinlined; i++)
  3868. if (model->inlined[i].name)
  3869. j += (unsigned int)strlen(model->inlined[i].name) + 6;
  3870. if (j > 0) {
  3871. ptr -= (uintptr_t)out;
  3872. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)j + (uintptr_t)16);
  3873. out = (unsigned char *)M3D_REALLOC(out, len);
  3874. ptr += (uintptr_t)out;
  3875. if (!out) {
  3876. setlocale(LC_NUMERIC, ol);
  3877. goto memerr;
  3878. }
  3879. ptr += sprintf(ptr, "Assets\r\n");
  3880. for (i = 0; i < model->numinlined; i++)
  3881. if (model->inlined[i].name)
  3882. ptr += sprintf(ptr, "%s%s\r\n", model->inlined[i].name, strrchr(model->inlined[i].name, '.') ? "" : ".png");
  3883. ptr += sprintf(ptr, "\r\n");
  3884. }
  3885. }
  3886. /* extra info */
  3887. if (model->numextra && (flags & M3D_EXP_EXTRA)) {
  3888. for (i = 0; i < model->numextra; i++) {
  3889. if (model->extra[i]->length < 9) continue;
  3890. ptr -= (uintptr_t)out;
  3891. len = (unsigned int)((uintptr_t)ptr + (uintptr_t)17 + (uintptr_t)(model->extra[i]->length * 3));
  3892. out = (unsigned char *)M3D_REALLOC(out, len);
  3893. ptr += (uintptr_t)out;
  3894. if (!out) {
  3895. setlocale(LC_NUMERIC, ol);
  3896. goto memerr;
  3897. }
  3898. ptr += sprintf(ptr, "Extra %c%c%c%c\r\n",
  3899. model->extra[i]->magic[0] > ' ' ? model->extra[i]->magic[0] : '_',
  3900. model->extra[i]->magic[1] > ' ' ? model->extra[i]->magic[1] : '_',
  3901. model->extra[i]->magic[2] > ' ' ? model->extra[i]->magic[2] : '_',
  3902. model->extra[i]->magic[3] > ' ' ? model->extra[i]->magic[3] : '_');
  3903. for (j = 0; j < model->extra[i]->length; j++)
  3904. ptr += sprintf(ptr, "%02x ", *((unsigned char *)model->extra + sizeof(m3dchunk_t) + j));
  3905. ptr--;
  3906. ptr += sprintf(ptr, "\r\n\r\n");
  3907. }
  3908. }
  3909. setlocale(LC_NUMERIC, ol);
  3910. len = (unsigned int)((uintptr_t)ptr - (uintptr_t)out);
  3911. out = (unsigned char *)M3D_REALLOC(out, len + 1);
  3912. if (!out) goto memerr;
  3913. out[len] = 0;
  3914. } else
  3915. {
  3916. /* strictly only use LF (newline) in binary */
  3917. sd = _m3d_safestr(model->desc, 3);
  3918. if (!sd) goto memerr;
  3919. /* header */
  3920. h = (m3dhdr_t *)M3D_MALLOC(sizeof(m3dhdr_t) + strlen(sn) + strlen(sl) + strlen(sa) + strlen(sd) + 4);
  3921. if (!h) goto memerr;
  3922. memcpy((uint8_t *)h, "HEAD", 4);
  3923. h->length = sizeof(m3dhdr_t);
  3924. h->scale = scale;
  3925. i = (unsigned int)strlen(sn);
  3926. memcpy((uint8_t *)h + h->length, sn, i + 1);
  3927. h->length += i + 1;
  3928. M3D_FREE(sn);
  3929. i = (unsigned int)strlen(sl);
  3930. memcpy((uint8_t *)h + h->length, sl, i + 1);
  3931. h->length += i + 1;
  3932. M3D_FREE(sl);
  3933. i = (unsigned int)strlen(sa);
  3934. memcpy((uint8_t *)h + h->length, sa, i + 1);
  3935. h->length += i + 1;
  3936. M3D_FREE(sa);
  3937. i = (unsigned int)strlen(sd);
  3938. memcpy((uint8_t *)h + h->length, sd, i + 1);
  3939. h->length += i + 1;
  3940. M3D_FREE(sd);
  3941. sn = sl = sa = sd = NULL;
  3942. if (model->inlined)
  3943. for (i = 0; i < model->numinlined; i++) {
  3944. if (model->inlined[i].name && *model->inlined[i].name && model->inlined[i].length > 0) {
  3945. str = _m3d_addstr(str, &numstr, model->inlined[i].name);
  3946. if (!str) goto memerr;
  3947. }
  3948. }
  3949. if (str)
  3950. for (i = 0; i < numstr; i++) {
  3951. h = _m3d_addhdr(h, &str[i]);
  3952. if (!h) goto memerr;
  3953. }
  3954. vc_s = quality == M3D_EXP_INT8 ? 1 : (quality == M3D_EXP_INT16 ? 2 : (quality == M3D_EXP_DOUBLE ? 8 : 4));
  3955. vi_s = maxvrtx < 254 ? 1 : (maxvrtx < 65534 ? 2 : 4);
  3956. si_s = h->length - 16 < 254 ? 1 : (h->length - 16 < 65534 ? 2 : 4);
  3957. ci_s = !numcmap || !cmap ? 0 : (numcmap < 254 ? 1 : (numcmap < 65534 ? 2 : 4));
  3958. ti_s = !maxtmap || !tmap ? 0 : (maxtmap < 254 ? 1 : (maxtmap < 65534 ? 2 : 4));
  3959. bi_s = !model->numbone || !model->bone || (flags & M3D_EXP_NOBONE) ? 0 : (model->numbone < 254 ? 1 : (model->numbone < 65534 ? 2 : 4));
  3960. nb_s = maxbone < 2 ? 1 : (maxbone == 2 ? 2 : (maxbone <= 4 ? 4 : 8));
  3961. sk_s = !bi_s || !maxskin || !skin ? 0 : (maxskin < 254 ? 1 : (maxskin < 65534 ? 2 : 4));
  3962. fc_s = maxt < 254 ? 1 : (maxt < 65534 ? 2 : 4);
  3963. hi_s = !model->numshape || !model->shape || (flags & M3D_EXP_NOFACE) ? 0 : (model->numshape < 254 ? 1 : (model->numshape < 65534 ? 2 : 4));
  3964. fi_s = !model->numface || !model->face || (flags & M3D_EXP_NOFACE) ? 0 : (model->numface < 254 ? 1 : (model->numface < 65534 ? 2 : 4));
  3965. h->types = (vc_s == 8 ? (3 << 0) : (vc_s == 2 ? (1 << 0) : (vc_s == 1 ? (0 << 0) : (2 << 0)))) |
  3966. (vi_s == 2 ? (1 << 2) : (vi_s == 1 ? (0 << 2) : (2 << 2))) |
  3967. (si_s == 2 ? (1 << 4) : (si_s == 1 ? (0 << 4) : (2 << 4))) |
  3968. (ci_s == 2 ? (1 << 6) : (ci_s == 1 ? (0 << 6) : (ci_s == 4 ? (2 << 6) : (3 << 6)))) |
  3969. (ti_s == 2 ? (1 << 8) : (ti_s == 1 ? (0 << 8) : (ti_s == 4 ? (2 << 8) : (3 << 8)))) |
  3970. (bi_s == 2 ? (1 << 10) : (bi_s == 1 ? (0 << 10) : (bi_s == 4 ? (2 << 10) : (3 << 10)))) |
  3971. (nb_s == 2 ? (1 << 12) : (nb_s == 1 ? (0 << 12) : (2 << 12))) |
  3972. (sk_s == 2 ? (1 << 14) : (sk_s == 1 ? (0 << 14) : (sk_s == 4 ? (2 << 14) : (3 << 14)))) |
  3973. (fc_s == 2 ? (1 << 16) : (fc_s == 1 ? (0 << 16) : (2 << 16))) |
  3974. (hi_s == 2 ? (1 << 18) : (hi_s == 1 ? (0 << 18) : (hi_s == 4 ? (2 << 18) : (3 << 18)))) |
  3975. (fi_s == 2 ? (1 << 20) : (fi_s == 1 ? (0 << 20) : (fi_s == 4 ? (2 << 20) : (3 << 20))));
  3976. len = h->length;
  3977. /* preview image chunk, must be the first if exists */
  3978. if (model->preview.data && model->preview.length) {
  3979. chunklen = 8 + model->preview.length;
  3980. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  3981. if (!h) goto memerr;
  3982. memcpy((uint8_t *)h + len, "PRVW", 4);
  3983. *((uint32_t *)((uint8_t *)h + len + 4)) = chunklen;
  3984. memcpy((uint8_t *)h + len + 8, model->preview.data, model->preview.length);
  3985. len += chunklen;
  3986. }
  3987. /* color map */
  3988. if (numcmap && cmap && ci_s < 4 && !(flags & M3D_EXP_NOCMAP)) {
  3989. chunklen = 8 + numcmap * sizeof(uint32_t);
  3990. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  3991. if (!h) goto memerr;
  3992. memcpy((uint8_t *)h + len, "CMAP", 4);
  3993. *((uint32_t *)((uint8_t *)h + len + 4)) = chunklen;
  3994. memcpy((uint8_t *)h + len + 8, cmap, chunklen - 8);
  3995. len += chunklen;
  3996. } else
  3997. numcmap = 0;
  3998. /* texture map */
  3999. if (numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) {
  4000. chunklen = 8 + maxtmap * vc_s * 2;
  4001. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4002. if (!h) goto memerr;
  4003. memcpy((uint8_t *)h + len, "TMAP", 4);
  4004. length = (uint32_t *)((uint8_t *)h + len + 4);
  4005. out = (uint8_t *)h + len + 8;
  4006. last = M3D_UNDEF;
  4007. for (i = 0; i < numtmap; i++) {
  4008. if (tmap[i].newidx == last) continue;
  4009. last = tmap[i].newidx;
  4010. switch (vc_s) {
  4011. case 1:
  4012. *out++ = (uint8_t)(tmap[i].data.u * 255);
  4013. *out++ = (uint8_t)(tmap[i].data.v * 255);
  4014. break;
  4015. case 2:
  4016. *((uint16_t *)out) = (uint16_t)(tmap[i].data.u * 65535);
  4017. out += 2;
  4018. *((uint16_t *)out) = (uint16_t)(tmap[i].data.v * 65535);
  4019. out += 2;
  4020. break;
  4021. case 4:
  4022. *((float *)out) = tmap[i].data.u;
  4023. out += 4;
  4024. *((float *)out) = tmap[i].data.v;
  4025. out += 4;
  4026. break;
  4027. case 8:
  4028. *((double *)out) = tmap[i].data.u;
  4029. out += 8;
  4030. *((double *)out) = tmap[i].data.v;
  4031. out += 8;
  4032. break;
  4033. }
  4034. }
  4035. *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4036. out = NULL;
  4037. len += *length;
  4038. }
  4039. /* vertex */
  4040. if (numvrtx && vrtx) {
  4041. chunklen = 8 + maxvrtx * (ci_s + sk_s + 4 * vc_s);
  4042. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4043. if (!h) goto memerr;
  4044. memcpy((uint8_t *)h + len, "VRTS", 4);
  4045. length = (uint32_t *)((uint8_t *)h + len + 4);
  4046. out = (uint8_t *)h + len + 8;
  4047. last = M3D_UNDEF;
  4048. for (i = 0; i < numvrtx; i++) {
  4049. if (vrtx[i].newidx == last) continue;
  4050. last = vrtx[i].newidx;
  4051. switch (vc_s) {
  4052. case 1:
  4053. *out++ = (int8_t)(vrtx[i].data.x * 127);
  4054. *out++ = (int8_t)(vrtx[i].data.y * 127);
  4055. *out++ = (int8_t)(vrtx[i].data.z * 127);
  4056. *out++ = (int8_t)(vrtx[i].data.w * 127);
  4057. break;
  4058. case 2:
  4059. *((int16_t *)out) = (int16_t)(vrtx[i].data.x * 32767);
  4060. out += 2;
  4061. *((int16_t *)out) = (int16_t)(vrtx[i].data.y * 32767);
  4062. out += 2;
  4063. *((int16_t *)out) = (int16_t)(vrtx[i].data.z * 32767);
  4064. out += 2;
  4065. *((int16_t *)out) = (int16_t)(vrtx[i].data.w * 32767);
  4066. out += 2;
  4067. break;
  4068. case 4:
  4069. memcpy(out, &vrtx[i].data.x, sizeof(float));
  4070. out += 4;
  4071. memcpy(out, &vrtx[i].data.y, sizeof(float));
  4072. out += 4;
  4073. memcpy(out, &vrtx[i].data.z, sizeof(float));
  4074. out += 4;
  4075. memcpy(out, &vrtx[i].data.w, sizeof(float));
  4076. out += 4;
  4077. break;
  4078. case 8:
  4079. *((double *)out) = vrtx[i].data.x;
  4080. out += 8;
  4081. *((double *)out) = vrtx[i].data.y;
  4082. out += 8;
  4083. *((double *)out) = vrtx[i].data.z;
  4084. out += 8;
  4085. *((double *)out) = vrtx[i].data.w;
  4086. out += 8;
  4087. break;
  4088. }
  4089. idx = _m3d_cmapidx(cmap, numcmap, vrtx[i].data.color);
  4090. switch (ci_s) {
  4091. case 1: *out++ = (uint8_t)(idx); break;
  4092. case 2:
  4093. *((uint16_t *)out) = (uint16_t)(idx);
  4094. out += 2;
  4095. break;
  4096. case 4:
  4097. *((uint32_t *)out) = vrtx[i].data.color;
  4098. out += 4;
  4099. break;
  4100. }
  4101. out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid);
  4102. }
  4103. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4104. memcpy(length, &v, sizeof(uint32_t));
  4105. //*length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4106. out = NULL;
  4107. len += v;
  4108. }
  4109. /* bones chunk */
  4110. if (model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
  4111. i = 8 + bi_s + sk_s + model->numbone * (bi_s + si_s + 2 * vi_s);
  4112. chunklen = i + numskin * nb_s * (bi_s + 1);
  4113. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4114. if (!h) goto memerr;
  4115. memcpy((uint8_t *)h + len, "BONE", 4);
  4116. length = (uint32_t *)((uint8_t *)h + len + 4);
  4117. out = (uint8_t *)h + len + 8;
  4118. out = _m3d_addidx(out, bi_s, model->numbone);
  4119. out = _m3d_addidx(out, sk_s, maxskin);
  4120. for (i = 0; i < model->numbone; i++) {
  4121. out = _m3d_addidx(out, bi_s, model->bone[i].parent);
  4122. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->bone[i].name));
  4123. out = _m3d_addidx(out, vi_s, vrtxidx[model->bone[i].pos]);
  4124. out = _m3d_addidx(out, vi_s, vrtxidx[model->bone[i].ori]);
  4125. }
  4126. if (numskin && skin && sk_s) {
  4127. last = M3D_UNDEF;
  4128. for (i = 0; i < numskin; i++) {
  4129. if (skin[i].newidx == last) continue;
  4130. last = skin[i].newidx;
  4131. memset(&weights, 0, nb_s);
  4132. for (j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != M3D_UNDEF &&
  4133. skin[i].data.weight[j] > (M3D_FLOAT)0.0;
  4134. j++)
  4135. weights[j] = (uint8_t)(skin[i].data.weight[j] * 255);
  4136. switch (nb_s) {
  4137. case 1: weights[0] = 255; break;
  4138. case 2:
  4139. *((uint16_t *)out) = *((uint16_t *)&weights[0]);
  4140. out += 2;
  4141. break;
  4142. case 4:
  4143. *((uint32_t *)out) = *((uint32_t *)&weights[0]);
  4144. out += 4;
  4145. break;
  4146. case 8:
  4147. *((uint64_t *)out) = *((uint64_t *)&weights[0]);
  4148. out += 8;
  4149. break;
  4150. }
  4151. for (j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != M3D_UNDEF && weights[j]; j++) {
  4152. out = _m3d_addidx(out, bi_s, skin[i].data.boneid[j]);
  4153. *length += bi_s;
  4154. }
  4155. }
  4156. }
  4157. *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4158. out = NULL;
  4159. len += *length;
  4160. }
  4161. /* materials */
  4162. if (model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) {
  4163. for (j = 0; j < model->nummaterial; j++) {
  4164. if (mtrlidx[j] == M3D_UNDEF || !model->material[j].numprop || !model->material[j].prop) continue;
  4165. m = &model->material[j];
  4166. chunklen = 12 + si_s + m->numprop * 5;
  4167. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4168. if (!h) goto memerr;
  4169. memcpy((uint8_t *)h + len, "MTRL", 4);
  4170. length = (uint32_t *)((uint8_t *)h + len + 4);
  4171. out = (uint8_t *)h + len + 8;
  4172. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, m->name));
  4173. for (i = 0; i < m->numprop; i++) {
  4174. if (m->prop[i].type >= 128) {
  4175. if (m->prop[i].value.textureid >= model->numtexture ||
  4176. !model->texture[m->prop[i].value.textureid].name) continue;
  4177. k = m3dpf_map;
  4178. } else {
  4179. for (k = 256, l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++)
  4180. if (m->prop[i].type == m3d_propertytypes[l].id) {
  4181. k = m3d_propertytypes[l].format;
  4182. break;
  4183. }
  4184. }
  4185. if (k == 256) continue;
  4186. *out++ = m->prop[i].type;
  4187. switch (k) {
  4188. case m3dpf_color:
  4189. if (!(flags & M3D_EXP_NOCMAP)) {
  4190. idx = _m3d_cmapidx(cmap, numcmap, m->prop[i].value.color);
  4191. switch (ci_s) {
  4192. case 1: *out++ = (uint8_t)(idx); break;
  4193. case 2:
  4194. *((uint16_t *)out) = (uint16_t)(idx);
  4195. out += 2;
  4196. break;
  4197. case 4:
  4198. *((uint32_t *)out) = (uint32_t)(m->prop[i].value.color);
  4199. out += 4;
  4200. break;
  4201. }
  4202. } else
  4203. out--;
  4204. break;
  4205. case m3dpf_uint8: *out++ = (uint8_t)m->prop[i].value.num; break;
  4206. case m3dpf_uint16:
  4207. *((uint16_t *)out) = (uint16_t)m->prop[i].value.num;
  4208. out += 2;
  4209. break;
  4210. case m3dpf_uint32:
  4211. *((uint32_t *)out) = m->prop[i].value.num;
  4212. out += 4;
  4213. break;
  4214. case m3dpf_float:
  4215. *((float *)out) = m->prop[i].value.fnum;
  4216. out += 4;
  4217. break;
  4218. case m3dpf_map:
  4219. idx = _m3d_stridx(str, numstr, model->texture[m->prop[i].value.textureid].name);
  4220. out = _m3d_addidx(out, si_s, idx);
  4221. break;
  4222. }
  4223. }
  4224. *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4225. len += *length;
  4226. out = NULL;
  4227. }
  4228. }
  4229. /* procedural face */
  4230. if (model->numinlined && model->inlined && !(flags & M3D_EXP_NOFACE)) {
  4231. /* all inlined assets which are not textures should be procedural surfaces */
  4232. for (j = 0; j < model->numinlined; j++) {
  4233. if (!model->inlined[j].name || !model->inlined[j].name[0] || model->inlined[j].length < 4 ||
  4234. !model->inlined[j].data || (model->inlined[j].data[1] == 'P' && model->inlined[j].data[2] == 'N' && model->inlined[j].data[3] == 'G'))
  4235. continue;
  4236. for (i = k = 0; i < model->numtexture; i++) {
  4237. if (!strcmp(model->inlined[j].name, model->texture[i].name)) {
  4238. k = 1;
  4239. break;
  4240. }
  4241. }
  4242. if (k) continue;
  4243. numproc++;
  4244. chunklen = 8 + si_s;
  4245. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4246. if (!h) goto memerr;
  4247. memcpy((uint8_t *)h + len, "PROC", 4);
  4248. *((uint32_t *)((uint8_t *)h + len + 4)) = chunklen;
  4249. out = (uint8_t *)h + len + 8;
  4250. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->inlined[j].name));
  4251. out = NULL;
  4252. len += chunklen;
  4253. }
  4254. }
  4255. /* mesh face */
  4256. if (model->numface && face && !(flags & M3D_EXP_NOFACE)) {
  4257. chunklen = 8 + si_s + model->numface * (6 * vi_s + 3 * ti_s + si_s + 1);
  4258. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4259. if (!h) goto memerr;
  4260. memcpy((uint8_t *)h + len, "MESH", 4);
  4261. length = (uint32_t *)((uint8_t *)h + len + 4);
  4262. out = (uint8_t *)h + len + 8;
  4263. last = M3D_UNDEF;
  4264. for (i = 0; i < model->numface; i++) {
  4265. if (!(flags & M3D_EXP_NOMATERIAL) && face[i].data.materialid != last) {
  4266. last = face[i].data.materialid;
  4267. idx = last < model->nummaterial ? _m3d_stridx(str, numstr, model->material[last].name) : 0;
  4268. *out++ = 0;
  4269. out = _m3d_addidx(out, si_s, idx);
  4270. }
  4271. /* hardcoded triangles. */
  4272. k = (3 << 4) |
  4273. (((flags & M3D_EXP_NOTXTCRD) || !ti_s || face[i].data.texcoord[0] == M3D_UNDEF ||
  4274. face[i].data.texcoord[1] == M3D_UNDEF || face[i].data.texcoord[2] == M3D_UNDEF) ?
  4275. 0 :
  4276. 1) |
  4277. (((flags & M3D_EXP_NONORMAL) || face[i].data.normal[0] == M3D_UNDEF ||
  4278. face[i].data.normal[1] == M3D_UNDEF || face[i].data.normal[2] == M3D_UNDEF) ?
  4279. 0 :
  4280. 2);
  4281. *out++ = (uint8_t)k;
  4282. for (j = 0; j < 3; j++) {
  4283. out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.vertex[j]]);
  4284. if (k & 1)
  4285. out = _m3d_addidx(out, ti_s, tmapidx[face[i].data.texcoord[j]]);
  4286. if (k & 2)
  4287. out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]);
  4288. }
  4289. }
  4290. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4291. memcpy(length, &v, sizeof(uint32_t));
  4292. len += v;
  4293. out = NULL;
  4294. }
  4295. /* mathematical shapes face */
  4296. if (model->numshape && model->shape && !(flags & M3D_EXP_NOFACE)) {
  4297. for (j = 0; j < model->numshape; j++) {
  4298. chunklen = 12 + si_s + model->shape[j].numcmd * (M3D_CMDMAXARG + 1) * 4;
  4299. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4300. if (!h) goto memerr;
  4301. memcpy((uint8_t *)h + len, "SHPE", 4);
  4302. length = (uint32_t *)((uint8_t *)h + len + 4);
  4303. out = (uint8_t *)h + len + 8;
  4304. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->shape[j].name));
  4305. out = _m3d_addidx(out, bi_s, model->shape[j].group);
  4306. for (i = 0; i < model->shape[j].numcmd; i++) {
  4307. cmd = &model->shape[j].cmd[i];
  4308. if (cmd->type >= (unsigned int)(sizeof(m3d_commandtypes) / sizeof(m3d_commandtypes[0])) || !cmd->arg)
  4309. continue;
  4310. cd = &m3d_commandtypes[cmd->type];
  4311. *out++ = (cmd->type & 0x7F) | (cmd->type > 127 ? 0x80 : 0);
  4312. if (cmd->type > 127) *out++ = (cmd->type >> 7) & 0xff;
  4313. for (k = n = 0, l = cd->p; k < l; k++) {
  4314. switch (cd->a[((k - n) % (cd->p - n)) + n]) {
  4315. case m3dcp_mi_t:
  4316. out = _m3d_addidx(out, si_s, cmd->arg[k] < model->nummaterial ? _m3d_stridx(str, numstr, model->material[cmd->arg[k]].name) : 0);
  4317. break;
  4318. case m3dcp_vc_t:
  4319. min_x = *((float *)&cmd->arg[k]);
  4320. switch (vc_s) {
  4321. case 1: *out++ = (int8_t)(min_x * 127); break;
  4322. case 2:
  4323. *((int16_t *)out) = (int16_t)(min_x * 32767);
  4324. out += 2;
  4325. break;
  4326. case 4:
  4327. *((float *)out) = min_x;
  4328. out += 4;
  4329. break;
  4330. case 8:
  4331. *((double *)out) = min_x;
  4332. out += 8;
  4333. break;
  4334. }
  4335. break;
  4336. case m3dcp_hi_t: out = _m3d_addidx(out, hi_s, cmd->arg[k]); break;
  4337. case m3dcp_fi_t: out = _m3d_addidx(out, fi_s, cmd->arg[k]); break;
  4338. case m3dcp_ti_t: out = _m3d_addidx(out, ti_s, cmd->arg[k]); break;
  4339. case m3dcp_qi_t:
  4340. case m3dcp_vi_t: out = _m3d_addidx(out, vi_s, cmd->arg[k]); break;
  4341. case m3dcp_i1_t: out = _m3d_addidx(out, 1, cmd->arg[k]); break;
  4342. case m3dcp_i2_t: out = _m3d_addidx(out, 2, cmd->arg[k]); break;
  4343. case m3dcp_i4_t: out = _m3d_addidx(out, 4, cmd->arg[k]); break;
  4344. case m3dcp_va_t:
  4345. out = _m3d_addidx(out, 4, cmd->arg[k]);
  4346. n = k + 1;
  4347. l += (cmd->arg[k] - 1) * (cd->p - k - 1);
  4348. break;
  4349. }
  4350. }
  4351. }
  4352. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4353. memcpy( length, &v, sizeof(uint32_t));
  4354. len += v;
  4355. out = NULL;
  4356. }
  4357. }
  4358. /* annotation labels */
  4359. if (model->numlabel && model->label) {
  4360. for (i = 0, length = NULL; i < model->numlabel; i++) {
  4361. if (!i || _m3d_strcmp(sl, model->label[i].lang) || _m3d_strcmp(sn, model->label[i].name)) {
  4362. sl = model->label[i].lang;
  4363. sn = model->label[i].name;
  4364. if (length) {
  4365. *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4366. len += *length;
  4367. }
  4368. chunklen = 8 + 2 * si_s + ci_s + model->numlabel * (vi_s + si_s);
  4369. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4370. if (!h) {
  4371. sn = NULL;
  4372. sl = NULL;
  4373. goto memerr;
  4374. }
  4375. memcpy((uint8_t *)h + len, "LBLS", 4);
  4376. length = (uint32_t *)((uint8_t *)h + len + 4);
  4377. out = (uint8_t *)h + len + 8;
  4378. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].name));
  4379. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].lang));
  4380. idx = _m3d_cmapidx(cmap, numcmap, model->label[i].color);
  4381. switch (ci_s) {
  4382. case 1: *out++ = (uint8_t)(idx); break;
  4383. case 2:
  4384. *((uint16_t *)out) = (uint16_t)(idx);
  4385. out += 2;
  4386. break;
  4387. case 4:
  4388. *((uint32_t *)out) = model->label[i].color;
  4389. out += 4;
  4390. break;
  4391. }
  4392. }
  4393. out = _m3d_addidx(out, vi_s, vrtxidx[model->label[i].vertexid]);
  4394. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text));
  4395. }
  4396. if (length) {
  4397. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4398. memcpy( length, &v, sizeof(uint32_t));
  4399. len += v;
  4400. }
  4401. out = NULL;
  4402. sn = sl = NULL;
  4403. }
  4404. /* actions */
  4405. if (model->numaction && model->action && model->numbone && model->bone && !(flags & M3D_EXP_NOACTION)) {
  4406. for (j = 0; j < model->numaction; j++) {
  4407. a = &model->action[j];
  4408. chunklen = 14 + si_s + a->numframe * (4 + fc_s + maxt * (bi_s + 2 * vi_s));
  4409. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4410. if (!h) goto memerr;
  4411. memcpy((uint8_t *)h + len, "ACTN", 4);
  4412. length = (uint32_t *)((uint8_t *)h + len + 4);
  4413. out = (uint8_t *)h + len + 8;
  4414. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, a->name));
  4415. *((uint16_t *)out) = (uint16_t)(a->numframe);
  4416. out += 2;
  4417. *((uint32_t *)out) = (uint32_t)(a->durationmsec);
  4418. out += 4;
  4419. for (i = 0; i < a->numframe; i++) {
  4420. *((uint32_t *)out) = (uint32_t)(a->frame[i].msec);
  4421. out += 4;
  4422. out = _m3d_addidx(out, fc_s, a->frame[i].numtransform);
  4423. for (k = 0; k < a->frame[i].numtransform; k++) {
  4424. out = _m3d_addidx(out, bi_s, a->frame[i].transform[k].boneid);
  4425. out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].pos]);
  4426. out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]);
  4427. }
  4428. }
  4429. uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
  4430. memcpy( length, &v, sizeof(uint32_t));
  4431. len += v;
  4432. out = NULL;
  4433. }
  4434. }
  4435. /* inlined assets */
  4436. if (model->numinlined && model->inlined && (numproc || (flags & M3D_EXP_INLINE))) {
  4437. for (j = 0; j < model->numinlined; j++) {
  4438. if (!model->inlined[j].name || !model->inlined[j].name[0] || model->inlined[j].length < 4 || !model->inlined[j].data)
  4439. continue;
  4440. if (!(flags & M3D_EXP_INLINE)) {
  4441. if (model->inlined[j].data[1] == 'P' && model->inlined[j].data[2] == 'N' && model->inlined[j].data[3] == 'G')
  4442. continue;
  4443. for (i = k = 0; i < model->numtexture; i++) {
  4444. if (!strcmp(model->inlined[j].name, model->texture[i].name)) {
  4445. k = 1;
  4446. break;
  4447. }
  4448. }
  4449. if (k) continue;
  4450. }
  4451. chunklen = 8 + si_s + model->inlined[j].length;
  4452. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4453. if (!h) goto memerr;
  4454. memcpy((uint8_t *)h + len, "ASET", 4);
  4455. *((uint32_t *)((uint8_t *)h + len + 4)) = chunklen;
  4456. out = (uint8_t *)h + len + 8;
  4457. out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->inlined[j].name));
  4458. memcpy(out, model->inlined[j].data, model->inlined[j].length);
  4459. out = NULL;
  4460. len += chunklen;
  4461. }
  4462. }
  4463. /* extra chunks */
  4464. if (model->numextra && model->extra && (flags & M3D_EXP_EXTRA)) {
  4465. for (j = 0; j < model->numextra; j++) {
  4466. if (!model->extra[j] || model->extra[j]->length < 8)
  4467. continue;
  4468. chunklen = model->extra[j]->length;
  4469. h = (m3dhdr_t *)M3D_REALLOC(h, len + chunklen);
  4470. if (!h) goto memerr;
  4471. memcpy((uint8_t *)h + len, model->extra[j], chunklen);
  4472. len += chunklen;
  4473. }
  4474. }
  4475. /* add end chunk */
  4476. h = (m3dhdr_t *)M3D_REALLOC(h, len + 4);
  4477. if (!h) goto memerr;
  4478. memcpy((uint8_t *)h + len, "OMD3", 4);
  4479. len += 4;
  4480. /* zlib compress */
  4481. if (!(flags & M3D_EXP_NOZLIB)) {
  4482. M3D_LOG("Deflating chunks");
  4483. z = stbi_zlib_compress((unsigned char *)h, len, (int *)&l, 9);
  4484. if (z && l > 0 && l < len) {
  4485. len = l;
  4486. M3D_FREE(h);
  4487. h = (m3dhdr_t *)z;
  4488. }
  4489. }
  4490. /* add file header at the beginning */
  4491. len += 8;
  4492. out = (unsigned char *)M3D_MALLOC(len);
  4493. if (!out) goto memerr;
  4494. memcpy(out, "3DMO", 4);
  4495. *((uint32_t *)(out + 4)) = len;
  4496. memcpy(out + 8, h, len - 8);
  4497. }
  4498. if (size) *size = out ? len : 0;
  4499. if (vrtxidx) M3D_FREE(vrtxidx);
  4500. if (mtrlidx) M3D_FREE(mtrlidx);
  4501. if (tmapidx) M3D_FREE(tmapidx);
  4502. if (skinidx) M3D_FREE(skinidx);
  4503. if (norm) M3D_FREE(norm);
  4504. if (face) M3D_FREE(face);
  4505. if (cmap) M3D_FREE(cmap);
  4506. if (tmap) M3D_FREE(tmap);
  4507. if (skin) M3D_FREE(skin);
  4508. if (str) M3D_FREE(str);
  4509. if (vrtx) M3D_FREE(vrtx);
  4510. if (h) M3D_FREE(h);
  4511. return out;
  4512. }
  4513. #endif
  4514. #endif /* M3D_IMPLEMENTATION */
  4515. #ifdef __cplusplus
  4516. }
  4517. #ifdef M3D_CPPWRAPPER
  4518. #include <memory>
  4519. #include <string>
  4520. #include <vector>
  4521. /*** C++ wrapper class ***/
  4522. namespace M3D {
  4523. #ifdef M3D_IMPLEMENTATION
  4524. class Model {
  4525. public:
  4526. m3d_t *model;
  4527. public:
  4528. Model() {
  4529. this->model = (m3d_t *)malloc(sizeof(m3d_t));
  4530. memset(this->model, 0, sizeof(m3d_t));
  4531. }
  4532. Model(_unused const std::string &data, _unused m3dread_t ReadFileCB,
  4533. _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
  4534. #ifndef M3D_NOIMPORTER
  4535. this->model = m3d_load((unsigned char *)data.data(), ReadFileCB, FreeCB, mtllib.model);
  4536. #else
  4537. Model();
  4538. #endif
  4539. }
  4540. Model(_unused const std::vector<unsigned char> data, _unused m3dread_t ReadFileCB,
  4541. _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
  4542. #ifndef M3D_NOIMPORTER
  4543. this->model = m3d_load((unsigned char *)&data[0], ReadFileCB, FreeCB, mtllib.model);
  4544. #else
  4545. Model();
  4546. #endif
  4547. }
  4548. Model(_unused const unsigned char *data, _unused m3dread_t ReadFileCB,
  4549. _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
  4550. #ifndef M3D_NOIMPORTER
  4551. this->model = m3d_load((unsigned char *)data, ReadFileCB, FreeCB, mtllib.model);
  4552. #else
  4553. Model();
  4554. #endif
  4555. }
  4556. ~Model() { m3d_free(this->model); }
  4557. public:
  4558. m3d_t *getCStruct() { return this->model; }
  4559. std::string getName() { return std::string(this->model->name); }
  4560. void setName(std::string name) { this->model->name = (char *)name.c_str(); }
  4561. std::string getLicense() { return std::string(this->model->license); }
  4562. void setLicense(std::string license) { this->model->license = (char *)license.c_str(); }
  4563. std::string getAuthor() { return std::string(this->model->author); }
  4564. void setAuthor(std::string author) { this->model->author = (char *)author.c_str(); }
  4565. std::string getDescription() { return std::string(this->model->desc); }
  4566. void setDescription(std::string desc) { this->model->desc = (char *)desc.c_str(); }
  4567. float getScale() { return this->model->scale; }
  4568. void setScale(float scale) { this->model->scale = scale; }
  4569. std::vector<unsigned char> getPreview() { return this->model->preview.data ?
  4570. std::vector<unsigned char>(this->model->preview.data, this->model->preview.data + this->model->preview.length) :
  4571. std::vector<unsigned char>(); }
  4572. std::vector<uint32_t> getColorMap() { return this->model->cmap ? std::vector<uint32_t>(this->model->cmap,
  4573. this->model->cmap + this->model->numcmap) :
  4574. std::vector<uint32_t>(); }
  4575. std::vector<m3dti_t> getTextureMap() { return this->model->tmap ? std::vector<m3dti_t>(this->model->tmap,
  4576. this->model->tmap + this->model->numtmap) :
  4577. std::vector<m3dti_t>(); }
  4578. std::vector<m3dtx_t> getTextures() { return this->model->texture ? std::vector<m3dtx_t>(this->model->texture,
  4579. this->model->texture + this->model->numtexture) :
  4580. std::vector<m3dtx_t>(); }
  4581. std::string getTextureName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numtexture ?
  4582. std::string(this->model->texture[idx].name) :
  4583. nullptr; }
  4584. std::vector<m3db_t> getBones() { return this->model->bone ? std::vector<m3db_t>(this->model->bone, this->model->bone +
  4585. this->model->numbone) :
  4586. std::vector<m3db_t>(); }
  4587. std::string getBoneName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numbone ?
  4588. std::string(this->model->bone[idx].name) :
  4589. nullptr; }
  4590. std::vector<m3dm_t> getMaterials() { return this->model->material ? std::vector<m3dm_t>(this->model->material,
  4591. this->model->material + this->model->nummaterial) :
  4592. std::vector<m3dm_t>(); }
  4593. std::string getMaterialName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->nummaterial ?
  4594. std::string(this->model->material[idx].name) :
  4595. nullptr; }
  4596. int getMaterialPropertyInt(int idx, int type) {
  4597. if (idx < 0 || (unsigned int)idx >= this->model->nummaterial || type < 0 || type >= 127 ||
  4598. !this->model->material[idx].prop) return -1;
  4599. for (int i = 0; i < this->model->material[idx].numprop; i++) {
  4600. if (this->model->material[idx].prop[i].type == type)
  4601. return this->model->material[idx].prop[i].value.num;
  4602. }
  4603. return -1;
  4604. }
  4605. uint32_t getMaterialPropertyColor(int idx, int type) { return this->getMaterialPropertyInt(idx, type); }
  4606. float getMaterialPropertyFloat(int idx, int type) {
  4607. if (idx < 0 || (unsigned int)idx >= this->model->nummaterial || type < 0 || type >= 127 ||
  4608. !this->model->material[idx].prop) return -1.0f;
  4609. for (int i = 0; i < this->model->material[idx].numprop; i++) {
  4610. if (this->model->material[idx].prop[i].type == type)
  4611. return this->model->material[idx].prop[i].value.fnum;
  4612. }
  4613. return -1.0f;
  4614. }
  4615. m3dtx_t *getMaterialPropertyMap(int idx, int type) {
  4616. if (idx < 0 || (unsigned int)idx >= this->model->nummaterial || type < 128 || type > 255 ||
  4617. !this->model->material[idx].prop) return nullptr;
  4618. for (int i = 0; i < this->model->material[idx].numprop; i++) {
  4619. if (this->model->material[idx].prop[i].type == type)
  4620. return this->model->material[idx].prop[i].value.textureid < this->model->numtexture ?
  4621. &this->model->texture[this->model->material[idx].prop[i].value.textureid] :
  4622. nullptr;
  4623. }
  4624. return nullptr;
  4625. }
  4626. std::vector<m3dv_t> getVertices() { return this->model->vertex ? std::vector<m3dv_t>(this->model->vertex,
  4627. this->model->vertex + this->model->numvertex) :
  4628. std::vector<m3dv_t>(); }
  4629. std::vector<m3df_t> getFace() { return this->model->face ? std::vector<m3df_t>(this->model->face, this->model->face +
  4630. this->model->numface) :
  4631. std::vector<m3df_t>(); }
  4632. std::vector<m3dh_t> getShape() { return this->model->shape ? std::vector<m3dh_t>(this->model->shape,
  4633. this->model->shape + this->model->numshape) :
  4634. std::vector<m3dh_t>(); }
  4635. std::string getShapeName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numshape &&
  4636. this->model->shape[idx].name && this->model->shape[idx].name[0] ?
  4637. std::string(this->model->shape[idx].name) :
  4638. nullptr; }
  4639. unsigned int getShapeGroup(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numshape ?
  4640. this->model->shape[idx].group :
  4641. 0xFFFFFFFF; }
  4642. std::vector<m3dc_t> getShapeCommands(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numshape &&
  4643. this->model->shape[idx].cmd ?
  4644. std::vector<m3dc_t>(this->model->shape[idx].cmd, this->model->shape[idx].cmd +
  4645. this->model->shape[idx].numcmd) :
  4646. std::vector<m3dc_t>(); }
  4647. std::vector<m3dl_t> getAnnotationLabels() { return this->model->label ? std::vector<m3dl_t>(this->model->label,
  4648. this->model->label + this->model->numlabel) :
  4649. std::vector<m3dl_t>(); }
  4650. std::vector<m3ds_t> getSkin() { return this->model->skin ? std::vector<m3ds_t>(this->model->skin, this->model->skin +
  4651. this->model->numskin) :
  4652. std::vector<m3ds_t>(); }
  4653. std::vector<m3da_t> getActions() { return this->model->action ? std::vector<m3da_t>(this->model->action,
  4654. this->model->action + this->model->numaction) :
  4655. std::vector<m3da_t>(); }
  4656. std::string getActionName(int aidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ?
  4657. std::string(this->model->action[aidx].name) :
  4658. nullptr; }
  4659. unsigned int getActionDuration(int aidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ?
  4660. this->model->action[aidx].durationmsec :
  4661. 0; }
  4662. std::vector<m3dfr_t> getActionFrames(int aidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ?
  4663. std::vector<m3dfr_t>(this->model->action[aidx].frame, this->model->action[aidx].frame +
  4664. this->model->action[aidx].numframe) :
  4665. std::vector<m3dfr_t>(); }
  4666. unsigned int getActionFrameTimestamp(int aidx, int fidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ?
  4667. (fidx >= 0 && (unsigned int)fidx < this->model->action[aidx].numframe ?
  4668. this->model->action[aidx].frame[fidx].msec :
  4669. 0) :
  4670. 0; }
  4671. std::vector<m3dtr_t> getActionFrameTransforms(int aidx, int fidx) {
  4672. return aidx >= 0 && (unsigned int)aidx < this->model->numaction ? (
  4673. fidx >= 0 && (unsigned int)fidx < this->model->action[aidx].numframe ?
  4674. std::vector<m3dtr_t>(this->model->action[aidx].frame[fidx].transform,
  4675. this->model->action[aidx].frame[fidx].transform + this->model->action[aidx].frame[fidx].numtransform) :
  4676. std::vector<m3dtr_t>()) :
  4677. std::vector<m3dtr_t>();
  4678. }
  4679. std::vector<m3dtr_t> getActionFrame(int aidx, int fidx, std::vector<m3dtr_t> skeleton) {
  4680. m3dtr_t *pose = m3d_frame(this->model, (unsigned int)aidx, (unsigned int)fidx,
  4681. skeleton.size() ? &skeleton[0] : nullptr);
  4682. return std::vector<m3dtr_t>(pose, pose + this->model->numbone);
  4683. }
  4684. std::vector<m3db_t> getActionPose(int aidx, unsigned int msec) {
  4685. m3db_t *pose = m3d_pose(this->model, (unsigned int)aidx, (unsigned int)msec);
  4686. return std::vector<m3db_t>(pose, pose + this->model->numbone);
  4687. }
  4688. std::vector<m3di_t> getInlinedAssets() { return this->model->inlined ? std::vector<m3di_t>(this->model->inlined,
  4689. this->model->inlined + this->model->numinlined) :
  4690. std::vector<m3di_t>(); }
  4691. std::vector<std::unique_ptr<m3dchunk_t>> getExtras() { return this->model->extra ?
  4692. std::vector<std::unique_ptr<m3dchunk_t>>(this->model->extra,
  4693. this->model->extra + this->model->numextra) :
  4694. std::vector<std::unique_ptr<m3dchunk_t>>(); }
  4695. std::vector<unsigned char> Save(_unused int quality, _unused int flags) {
  4696. #ifdef M3D_EXPORTER
  4697. unsigned int size;
  4698. unsigned char *ptr = m3d_save(this->model, quality, flags, &size);
  4699. return ptr && size ? std::vector<unsigned char>(ptr, ptr + size) : std::vector<unsigned char>();
  4700. #else
  4701. return std::vector<unsigned char>();
  4702. #endif
  4703. }
  4704. };
  4705. #else
  4706. class Model {
  4707. public:
  4708. m3d_t *model;
  4709. public:
  4710. Model(const std::string &data, m3dread_t ReadFileCB, m3dfree_t FreeCB);
  4711. Model(const std::vector<unsigned char> data, m3dread_t ReadFileCB, m3dfree_t FreeCB);
  4712. Model(const unsigned char *data, m3dread_t ReadFileCB, m3dfree_t FreeCB);
  4713. Model();
  4714. ~Model();
  4715. public:
  4716. m3d_t *getCStruct();
  4717. std::string getName();
  4718. void setName(std::string name);
  4719. std::string getLicense();
  4720. void setLicense(std::string license);
  4721. std::string getAuthor();
  4722. void setAuthor(std::string author);
  4723. std::string getDescription();
  4724. void setDescription(std::string desc);
  4725. float getScale();
  4726. void setScale(float scale);
  4727. std::vector<unsigned char> getPreview();
  4728. std::vector<uint32_t> getColorMap();
  4729. std::vector<m3dti_t> getTextureMap();
  4730. std::vector<m3dtx_t> getTextures();
  4731. std::string getTextureName(int idx);
  4732. std::vector<m3db_t> getBones();
  4733. std::string getBoneName(int idx);
  4734. std::vector<m3dm_t> getMaterials();
  4735. std::string getMaterialName(int idx);
  4736. int getMaterialPropertyInt(int idx, int type);
  4737. uint32_t getMaterialPropertyColor(int idx, int type);
  4738. float getMaterialPropertyFloat(int idx, int type);
  4739. m3dtx_t *getMaterialPropertyMap(int idx, int type);
  4740. std::vector<m3dv_t> getVertices();
  4741. std::vector<m3df_t> getFace();
  4742. std::vector<m3dh_t> getShape();
  4743. std::string getShapeName(int idx);
  4744. unsigned int getShapeGroup(int idx);
  4745. std::vector<m3dc_t> getShapeCommands(int idx);
  4746. std::vector<m3dl_t> getAnnotationLabels();
  4747. std::vector<m3ds_t> getSkin();
  4748. std::vector<m3da_t> getActions();
  4749. std::string getActionName(int aidx);
  4750. unsigned int getActionDuration(int aidx);
  4751. std::vector<m3dfr_t> getActionFrames(int aidx);
  4752. unsigned int getActionFrameTimestamp(int aidx, int fidx);
  4753. std::vector<m3dtr_t> getActionFrameTransforms(int aidx, int fidx);
  4754. std::vector<m3dtr_t> getActionFrame(int aidx, int fidx, std::vector<m3dtr_t> skeleton);
  4755. std::vector<m3db_t> getActionPose(int aidx, unsigned int msec);
  4756. std::vector<m3di_t> getInlinedAssets();
  4757. std::vector<std::unique_ptr<m3dchunk_t>> getExtras();
  4758. std::vector<unsigned char> Save(int quality, int flags);
  4759. };
  4760. #endif /* impl */
  4761. } // namespace M3D
  4762. #endif /* M3D_CPPWRAPPER */
  4763. #if _MSC_VER > 1920 && !defined(__clang__)
  4764. # pragma warning(pop)
  4765. #endif /* _MSC_VER */
  4766. #endif /* __cplusplus */
  4767. #endif