m3d.h 299 KB

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