Formatx.m3DSUtils.pas 210 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789
  1. //
  2. // The graphics engine GXScene
  3. //
  4. unit Formatx.m3DSUtils;
  5. (*
  6. Utility functions for the universal 3DS file reader and writer (TFile3DS).
  7. Essentially, the functions here are the heart of the import library as
  8. they deal actually with the database and chunks.
  9. *)
  10. interface
  11. {$I Stage.Defines.inc}
  12. {$R-}
  13. uses
  14. System.Classes,
  15. System.SysUtils,
  16. Formatx.m3DS,
  17. Formatx.m3DSTypes,
  18. Formatx.m3DSConst,
  19. Stage.Strings;
  20. // functions to retrieve global settings of a specific 3DS database
  21. function GetAtmosphere(const Source: TFile3DS; var DB: TDatabase3DS): TAtmosphere3DS;
  22. function GetBackground(const Source: TFile3DS; var DB: TDatabase3DS): TBackground3DS;
  23. function GetMeshSet(const Source: TFile3DS; var DB: TDatabase3DS): TMeshSet3DS;
  24. function GetViewport(const Source: TFile3DS; var DB: TDatabase3DS): TViewport3DS;
  25. // functions to retrieve/modify data related to materials, lights and objects (meshs)
  26. procedure AddChild(Parent, Child: PChunk3DS);
  27. procedure AddChildOrdered(Parent, Child: PChunk3DS);
  28. function FindChunk(Top: PChunk3DS; Tag: word): PChunk3DS;
  29. function FindNextChunk(Local: PChunk3DS; Tag: word): PChunk3DS;
  30. procedure FreeChunkData(var Chunk: PChunk3DS);
  31. function GetCameraByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  32. Index: integer): TCamera3DS;
  33. function GetCameraCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  34. function GetChunkValue(Tag: word): integer;
  35. function GetMaterialByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  36. Index: integer): TMaterial3DS;
  37. function GetMaterialCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  38. function GetMeshByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  39. Index: integer): TMesh3DS;
  40. function GetMeshCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  41. function GetOmnilightByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  42. Index: integer): TLight3DS;
  43. function GetSpotlightByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  44. Index: integer): TLight3DS;
  45. function GetOmnilightCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  46. function GetSpotlightCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  47. procedure InitChunk(var Chunk: PChunk3DS);
  48. procedure ReleaseCamera(Camera: PCamera3DS);
  49. procedure ReleaseChunk(var Chunk: PChunk3DS);
  50. procedure ReleaseChunkList(var List: PChunkList3DS);
  51. procedure ReleaseLight(Light: PLight3DS);
  52. procedure ReleaseMaterial(Mat: PMaterial3DS);
  53. procedure ReleaseMeshObj(Mesh: PMesh3DS);
  54. // functions to retrieve/modify keyframer (animation) data
  55. function GetKFSettings(const Source: TFile3DS; var DB: TDatabase3DS): TKFSets3DS;
  56. procedure ReleaseCameraMotion(Camera: PKFCamera3DS);
  57. procedure GetCameraNodeNameList(const Source: TFile3DS; var DB: TDatabase3DS;
  58. List: TStringList);
  59. function GetCameraNodeCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  60. function GetCameraMotion(const Source: TFile3DS;
  61. CamChunk, TargetChunk: PChunk3DS): TKFCamera3DS;
  62. function GetCameraMotionByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  63. Index: integer): TKFCamera3DS;
  64. procedure ReleaseAmbientLightMotion(Light: PKFAmbient3DS);
  65. function GetAmbientLightMotion(const Source: TFile3DS;
  66. var DB: TDatabase3DS): TKFAmbient3DS;
  67. procedure InitObjectMotion(var Obj: TKFMesh3DS;
  68. NewNPKeys, NewNRKeys, NewNSKeys, NewNMKeys, NewNHKeys: cardinal);
  69. procedure ReleaseObjectMotion(Obj: PKFMesh3DS);
  70. procedure GetObjectNodeNameList(const Source: TFile3DS; var DB: TDatabase3DS;
  71. List: TStringList);
  72. function GetObjectNodeCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  73. function GetObjectMotionByName(const Source: TFile3DS; var DB: TDatabase3DS;
  74. const Name: string): TKFMesh3DS;
  75. function GetObjectMotionByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  76. Index: cardinal): TKFMesh3DS;
  77. procedure ReleaseOmnilightMotion(Light: PKFOmni3DS);
  78. procedure GetOmnilightNodeNameList(const Source: TFile3DS; var DB: TDatabase3DS;
  79. List: TStringList);
  80. function GetOmnilightNodeCount(const Source: TFile3DS; var DB: TDatabase3DS): cardinal;
  81. function GetOmnilightMotionByName(const Source: TFile3DS; var DB: TDatabase3DS;
  82. const Name: string): TKFOmni3DS;
  83. function GetOmnilightMotionByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  84. Index: cardinal): TKFOmni3DS;
  85. procedure ReleaseSpotlightMotion(Spot: PKFSpot3DS);
  86. procedure GetSpotlightNodeNameList(const Source: TFile3DS; var DB: TDatabase3DS;
  87. List: TStringList);
  88. function GetSpotlightNodeCount(const Source: TFile3DS; var DB: TDatabase3DS): cardinal;
  89. function GetSpotlightMotionByName(const Source: TFile3DS; var DB: TDatabase3DS;
  90. const Name: string): TKFSpot3DS;
  91. function GetSpotlightMotionByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  92. Index: cardinal): TKFSpot3DS;
  93. // version information
  94. function GetM3dMagicRelease(const Source: TFile3DS; var DB: TDatabase3DS): TReleaseLevel;
  95. function GetMeshRelease(const Source: TFile3DS; var DB: TDatabase3DS): TReleaseLevel;
  96. function GetKfRelease(const Source: TFile3DS; var DB: TDatabase3DS): TReleaseLevel;
  97. function GetDatabaseRelease(const Source: TFile3DS; var DB: TDatabase3DS): TReleaseLevel;
  98. // support functions for text output of chunk and database contents
  99. procedure ChunkHeaderReport(var Strings: TStrings; Chunk: PChunk3DS;
  100. IndentLevel: integer);
  101. function ChunkTagToString(Tag: word): string;
  102. procedure DumpChunk(const Source: TFile3DS; var Strings: TStrings;
  103. Chunk: PChunk3DS; IndentLevel: integer; DumpLevel: TDumpLevel);
  104. procedure DumpKeyHeader(Strings: TStrings; const Key: TKeyHeader3DS; IndentLevel: integer);
  105. // support functions for chunk handling
  106. procedure DeleteChunk(var Chunk: PChunk3DS);
  107. function FindNamedObjectByIndex(Source: TFile3DS; DB: TDatabase3DS;
  108. AType: word; Index: integer): PChunk3DS;
  109. // error message routines
  110. procedure ShowError(const ErrorMessage: string);
  111. procedure ShowErrorFormatted(const ErrorMessage: string; const Args: array of const);
  112. implementation //--------------------------------------------------------------
  113. type
  114. E3DSError = class(Exception);
  115. //----------------- error handling --------------------------------------------
  116. procedure ShowError(const ErrorMessage: string);
  117. begin
  118. raise E3DSError.Create(ErrorMessage);
  119. end;
  120. //-----------------------------------------------------------------------------
  121. procedure ShowErrorFormatted(const ErrorMessage: string; const Args: array of const);
  122. begin
  123. raise E3DSError.CreateFmt(ErrorMessage, Args);
  124. end;
  125. //----------------- global settings functions ---------------------------------
  126. function InitMeshSet: TMeshSet3DS;
  127. // initializes a mesh settings structure
  128. begin
  129. FillChar(Result, SizeOf(Result), 0);
  130. with Result do
  131. begin
  132. MasterScale := 1;
  133. Shadow.Bias := 1;
  134. Shadow.RayBias := 1;
  135. Shadow.MapSize := 512;
  136. Shadow.Filter := 3;
  137. AmbientLight.R := 0.39216;
  138. AmbientLight.G := 0.39216;
  139. AmbientLight.B := 0.39216;
  140. end;
  141. end;
  142. //-----------------------------------------------------------------------------
  143. function GetMeshSet(const Source: TFile3DS; var DB: TDatabase3DS): TMeshSet3DS;
  144. // retrieves the mesh settings from the database
  145. var
  146. MDataChunk, ColorChunk, Chunk: PChunk3DS;
  147. begin
  148. FillChar(Result, SizeOf(Result), 0);
  149. // find the mesh data chunk
  150. MDataChunk := FindChunk(DB.TopChunk, MDATA);
  151. // If the mesh data section is found
  152. if Assigned(MDataChunk) then
  153. begin
  154. Result := InitMeshSet;
  155. with Result do
  156. begin
  157. // Search for a master_scale chunk
  158. Chunk := FindNextChunk(MDataChunk^.Children, MASTER_SCALE);
  159. if Assigned(Chunk) then
  160. begin
  161. Source.ReadChunkData(Chunk);
  162. MasterScale := Chunk^.Data.MasterScale^;
  163. FreeChunkData(Chunk);
  164. end;
  165. // search for Lo_Shadow_Bias chunk
  166. Chunk := FindNextChunk(MDataChunk^.Children, LO_SHADOW_BIAS);
  167. if Assigned(Chunk) then
  168. begin
  169. Source.ReadChunkData(Chunk);
  170. Shadow.Bias := Chunk^.Data.LoShadowBias^;
  171. FreeChunkData(Chunk);
  172. end;
  173. // Search for ray_Bias Chunk
  174. Chunk := FindNextChunk(MDataChunk^.Children, RAY_BIAS);
  175. if Assigned(Chunk) then
  176. begin
  177. Source.ReadChunkData(Chunk);
  178. Shadow.RayBias := Chunk^.Data.RayBias^;
  179. FreeChunkData(Chunk);
  180. end;
  181. // search for MapSize Chunk
  182. Chunk := FindNextChunk(MDataChunk^.Children, SHADOW_MAP_SIZE);
  183. if Assigned(Chunk) then
  184. begin
  185. Source.ReadChunkData(Chunk);
  186. Shadow.MapSize := Chunk^.Data.ShadowMapSize^;
  187. FreeChunkData(Chunk);
  188. end;
  189. // search for Shadow_Filter Chunk
  190. Chunk := FindNextChunk(MDataChunk^.Children, SHADOW_FILTER);
  191. if Assigned(Chunk) then
  192. begin
  193. Source.ReadChunkData(Chunk);
  194. Shadow.Filter := Chunk^.Data.ShadowFilter^;
  195. FreeChunkData(Chunk);
  196. end;
  197. // search for ambient_light Chunk
  198. Chunk := FindNextChunk(MDataChunk^.Children, AMBIENT_LIGHT);
  199. if Assigned(Chunk) then
  200. begin
  201. // search for the old style Color chunk inside the ambient Light Chunk
  202. ColorChunk := FindChunk(Chunk, COLOR_F);
  203. if Assigned(ColorChunk) then
  204. begin
  205. Source.ReadChunkData(ColorChunk);
  206. AmbientLight.R := ColorChunk^.Data.ColorF^.Red;
  207. AmbientLight.G := ColorChunk^.Data.ColorF^.Green;
  208. AmbientLight.B := ColorChunk^.Data.ColorF^.Blue;
  209. FreeChunkData(ColorChunk);
  210. end
  211. else
  212. begin
  213. // just for robust completeness, search for the COLOR_24 chunk
  214. ColorChunk := FindChunk(Chunk, COLOR_24);
  215. if Assigned(ColorChunk) then
  216. begin
  217. Source.ReadChunkData(ColorChunk);
  218. AmbientLight.R := ColorChunk^.Data.Color24^.Red / 255;
  219. AmbientLight.G := ColorChunk^.Data.Color24^.Green / 255;
  220. AmbientLight.B := ColorChunk^.Data.Color24^.Blue / 255;
  221. FreeChunkData(ColorChunk);
  222. end;
  223. end;
  224. // search for the newer linear Color Chunk inside the ambient Light chunk
  225. ColorChunk := FindChunk(Chunk, LIN_COLOR_F);
  226. if Assigned(ColorChunk) then
  227. begin
  228. Source.ReadChunkData(ColorChunk);
  229. AmbientLight.R := ColorChunk^.Data.LinColorF^.Red;
  230. AmbientLight.G := ColorChunk^.Data.LinColorF^.Green;
  231. AmbientLight.B := ColorChunk^.Data.LinColorF^.Blue;
  232. FreeChunkData(ColorChunk);
  233. end
  234. else
  235. begin
  236. // just for completeness, search for the LIN_COLOR_24 chunk
  237. ColorChunk := FindChunk(Chunk, LIN_COLOR_24);
  238. if Assigned(ColorChunk) then
  239. begin
  240. Source.ReadChunkData(ColorChunk);
  241. AmbientLight.R := ColorChunk^.Data.LinColorF^.Red / 255;
  242. AmbientLight.G := ColorChunk^.Data.LinColorF^.Green / 255;
  243. AmbientLight.B := ColorChunk^.Data.LinColorF^.Blue / 255;
  244. FreeChunkData(ColorChunk);
  245. end;
  246. end;
  247. end;
  248. // Search for the oconst chunk
  249. Chunk := FindNextChunk(MDataChunk^.Children, O_CONSTS);
  250. if Assigned(Chunk) then
  251. begin
  252. Source.ReadChunkData(Chunk);
  253. oconsts.x := Chunk^.Data.OConsts^.X;
  254. oconsts.y := Chunk^.Data.OConsts^.Y;
  255. oconsts.z := Chunk^.Data.OConsts^.Z;
  256. FreeChunkData(Chunk);
  257. end;
  258. end;
  259. end;
  260. end;
  261. //-----------------------------------------------------------------------------
  262. function InitAtmosphere: TAtmosphere3DS;
  263. // initializes a atmosphere structure
  264. begin
  265. FillChar(Result, SizeOf(Result), 0);
  266. with Result do
  267. begin
  268. Fog.FarPlane := 1000;
  269. Fog.FarDensity := 100;
  270. Fog.FogBgnd := True;
  271. LayerFog.ZMax := 100;
  272. LayerFog.Density := 50;
  273. LayerFog.Falloff := lfNoFall;
  274. LayerFog.Fogbgnd := True;
  275. DCue.FarPlane := 1000;
  276. DCue.FarDim := 100;
  277. ActiveAtmo := atNoAtmo;
  278. end;
  279. end;
  280. //-----------------------------------------------------------------------------
  281. function GetAtmosphere(const Source: TFile3DS; var DB: TDatabase3DS): TAtmosphere3DS;
  282. // retrieves the atmospheric settings from database
  283. var
  284. MDataChunk, FogChunk, BgnChunk, ColorChunk, Chunk: PChunk3DS;
  285. begin
  286. FillChar(Result, SizeOf(Result), 0);
  287. // find the MDATA chunk
  288. MDataChunk := FindChunk(DB.TopChunk, MDATA);
  289. // if the MDATA chunk was found, then search for the atmospheric chunks
  290. if Assigned(MDataChunk) then
  291. begin
  292. Result := InitAtmosphere;
  293. // Search for fog chunk
  294. FogChunk := FindChunk(MDataChunk, FOG);
  295. if Assigned(FogChunk) then
  296. with Result do
  297. begin
  298. // read the chunk information
  299. Source.ReadChunkData(FogChunk);
  300. // Copy the FogChunk data into the structure
  301. Fog.NearPlane := FogChunk^.Data.Fog^.NearPlaneDist;
  302. Fog.NearDensity := FogChunk^.Data.Fog^.NearPlaneDensity;
  303. Fog.FarPlane := FogChunk^.Data.Fog^.FarPlanedist;
  304. Fog.FarDensity := FogChunk^.Data.Fog^.FarPlaneDensity;
  305. // Search for fog Color chunk
  306. ColorChunk := FindChunk(FogChunk, COLOR_F);
  307. if Assigned(ColorChunk) then
  308. begin
  309. Source.ReadChunkData(ColorChunk);
  310. Fog.FogColor.R := ColorChunk^.Data.ColorF^.Red;
  311. Fog.Fogcolor.G := ColorChunk^.Data.ColorF^.Green;
  312. Fog.Fogcolor.B := ColorChunk^.Data.ColorF^.Blue;
  313. FreeChunkData(ColorChunk);
  314. end;
  315. // Search for FOG_BGND chunk
  316. BgnChunk := FindChunk(FogChunk, FOG_BGND);
  317. if Assigned(BgnChunk) then
  318. Fog.FogBgnd := True
  319. else
  320. Fog.FogBgnd := False;
  321. FreeChunkData(FogChunk);
  322. // search for LAYER_FOG chunk
  323. FogChunk := FindChunk(MDataChunk, LAYER_FOG);
  324. if Assigned(FogChunk) then
  325. begin
  326. Source.ReadChunkData(FogChunk);
  327. LayerFog.ZMin := FogChunk^.Data.LayerFog^.ZMin;
  328. LayerFog.ZMax := FogChunk^.Data.LayerFog^.ZMax;
  329. LayerFog.Density := FogChunk^.Data.LayerFog^.Density;
  330. if (FogChunk^.Data.LayerFog^.AType and LayerFogBgnd) <> 0 then
  331. LayerFog.FogBgnd := True
  332. else
  333. LayerFog.FogBgnd := False;
  334. if (FogChunk^.Data.LayerFog^.AType and TopFalloff) <> 0 then
  335. LayerFog.Falloff := lfTopFall
  336. else if (FogChunk^.Data.LayerFog^.AType and BottomFalloff) <> 0 then
  337. LayerFog.Falloff := lfBottomFall
  338. else
  339. LayerFog.Falloff := lfNoFall;
  340. ColorChunk := FindChunk(FogChunk, COLOR_F);
  341. if Assigned(ColorChunk) then
  342. begin
  343. Source.ReadChunkData(ColorChunk);
  344. LayerFog.FogColor.R := ColorChunk^.Data.ColorF^.Red;
  345. LayerFog.Fogcolor.G := ColorChunk^.Data.ColorF^.Green;
  346. LayerFog.Fogcolor.B := ColorChunk^.Data.ColorF^.Blue;
  347. FreeChunkData(ColorChunk);
  348. end;
  349. FreeChunkData(FogChunk);
  350. end;
  351. // search for DISTANCE_CUE chunk
  352. Chunk := FindChunk(MDataChunk, DISTANCE_CUE);
  353. if Assigned(Chunk) then
  354. begin
  355. Source.ReadChunkData(Chunk);
  356. DCue.NearPlane := Chunk^.Data.DistanceCue^.NearPlaneDist;
  357. DCue.neardim := Chunk^.Data.DistanceCue^.NearPlaneDimming;
  358. DCue.FarPlane := Chunk^.Data.DistanceCue^.FarPlaneDist;
  359. DCue.FarDim := Chunk^.Data.DistanceCue^.FarPlaneDimming;
  360. BgnChunk := FindChunk(Chunk, DCUE_BGND);
  361. if Assigned(BgnChunk) then
  362. DCue.DCueBgnd := True
  363. else
  364. DCue.DCueBgnd := False;
  365. FreeChunkData(Chunk);
  366. end;
  367. // search for USE_FOG, USE_LAYER_FOG or USE_DISTANCE_CUE chunk
  368. Chunk := FindChunk(MDataChunk, USE_FOG);
  369. if Assigned(Chunk) then
  370. ActiveAtmo := atUseFog
  371. else
  372. begin
  373. Chunk := FindChunk(MDataChunk, USE_LAYER_FOG);
  374. if Assigned(Chunk) then
  375. ActiveAtmo := atUseLayerFog
  376. else
  377. begin
  378. Chunk := FindChunk(MDataChunk, USE_DISTANCE_CUE);
  379. if Assigned(Chunk) then
  380. ActiveAtmo := atUseDistanceCue
  381. else
  382. ActiveAtmo := atNoAtmo;
  383. end;
  384. end;
  385. end; // with Result do
  386. end; // if Assigned(MDataChunk)
  387. end;
  388. //-----------------------------------------------------------------------------
  389. function InitBackground: TBackground3DS;
  390. // initializes the TBackground3DS structure
  391. begin
  392. FillChar(Result, SizeOf(Result), 0);
  393. Result.VGradient.GradPercent := 0.5;
  394. end;
  395. //-----------------------------------------------------------------------------
  396. function GetBackground(const Source: TFile3DS; var DB: TDatabase3DS): TBackground3DS;
  397. // retrieves the background settings from the database
  398. var
  399. MDataChunk, ColorChunk, TopColor, MidColor, BotColor, Chunk: PChunk3DS;
  400. begin
  401. FillChar(Result, SizeOf(Result), 0);
  402. // Find the MDATA chunk
  403. MDataChunk := FindChunk(DB.TopChunk, MDATA);
  404. // only continue with structure filling if an MDATA chunk is found
  405. if Assigned(MDataChunk) then
  406. with Result do
  407. begin
  408. Result := InitBackground;
  409. // search for bitmap chunk
  410. Chunk := FindChunk(MDataChunk, BIT_MAP);
  411. if Assigned(Chunk) then
  412. begin
  413. // read the chunk information
  414. Source.ReadChunkData(Chunk);
  415. // copy the bitmap filename to the structure
  416. if Assigned(Chunk^.Data.BitmapName) then
  417. Bitmap := Chunk^.Data.BitmapName^
  418. else
  419. Bitmap := '';
  420. FreeChunkData(Chunk);
  421. end;
  422. Chunk := FindChunk(MDataChunk, SOLID_BGND);
  423. if Assigned(Chunk) then
  424. begin
  425. ColorChunk := FindChunk(Chunk, COLOR_F);
  426. if Assigned(ColorChunk) then
  427. begin
  428. Source.ReadChunkData(ColorChunk);
  429. Solid.R := ColorChunk^.Data.ColorF^.Red;
  430. Solid.G := ColorChunk^.Data.ColorF^.Green;
  431. Solid.B := ColorChunk^.Data.ColorF^.Blue;
  432. FreeChunkData(ColorChunk);
  433. end;
  434. ColorChunk := FindChunk(Chunk, LIN_COLOR_F);
  435. if Assigned(ColorChunk) then
  436. begin
  437. Source.ReadChunkData(ColorChunk);
  438. Solid.R := ColorChunk^.Data.ColorF^.Red;
  439. Solid.G := ColorChunk^.Data.ColorF^.Green;
  440. Solid.B := ColorChunk^.Data.ColorF^.Blue;
  441. FreeChunkData(ColorChunk);
  442. end;
  443. end;
  444. Chunk := FindChunk(MDataChunk, V_GRADIENT);
  445. if Assigned(Chunk) then
  446. begin
  447. // the COLOR_F chunks are the old, non-gamma corrected colors
  448. Source.ReadChunkData(Chunk);
  449. VGradient.GradPercent := Chunk^.Data.VGradient^;
  450. TopColor := FindChunk(Chunk, COLOR_F);
  451. if Assigned(TopColor) then
  452. begin
  453. Source.ReadChunkData(TopColor);
  454. VGradient.Top.R := TopColor^.Data.ColorF^.Red;
  455. VGradient.Top.G := TopColor^.Data.ColorF^.Green;
  456. VGradient.Top.B := TopColor^.Data.ColorF^.Blue;
  457. MidColor := FindNextChunk(TopColor^.Sibling, COLOR_F);
  458. if Assigned(MidColor) then
  459. begin
  460. Source.ReadChunkData(MidColor);
  461. VGradient.Mid.R := MidColor^.Data.ColorF^.Red;
  462. VGradient.Mid.G := MidColor^.Data.ColorF^.Green;
  463. VGradient.Mid.B := MidColor^.Data.ColorF^.Blue;
  464. BotColor := FindNextChunk(MidColor^.Sibling, COLOR_F);
  465. if Assigned(BotColor) then
  466. begin
  467. Source.ReadChunkData(BotColor);
  468. VGradient.Bottom.R := MidColor^.Data.ColorF^.Red;
  469. VGradient.Bottom.G := MidColor^.Data.ColorF^.Green;
  470. VGradient.Bottom.B := MidColor^.Data.ColorF^.Blue;
  471. FreeChunkData(BotColor);
  472. end;
  473. FreeChunkData(MidColor);
  474. end;
  475. FreeChunkData(TopColor);
  476. end;
  477. // If the newer, gamma correct colors are available, then use them instead
  478. TopColor := FindChunk(Chunk, LIN_COLOR_F);
  479. if Assigned(TopColor) then
  480. begin
  481. Source.ReadChunkData(TopColor);
  482. VGradient.Top.R := TopColor^.Data.ColorF^.Red;
  483. VGradient.Top.G := TopColor^.Data.ColorF^.Green;
  484. VGradient.Top.B := TopColor^.Data.ColorF^.Blue;
  485. MidColor := FindNextChunk(TopColor^.Sibling, LIN_COLOR_F);
  486. if Assigned(MidColor) then
  487. begin
  488. Source.ReadChunkData(MidColor);
  489. VGradient.Mid.R := MidColor^.Data.ColorF^.Red;
  490. VGradient.Mid.G := MidColor^.Data.ColorF^.Green;
  491. VGradient.Mid.B := MidColor^.Data.ColorF^.Blue;
  492. BotColor := FindNextChunk(MidColor^.Sibling, LIN_COLOR_F);
  493. if Assigned(BotColor) then
  494. begin
  495. Source.ReadChunkData(BotColor);
  496. VGradient.Bottom.R := MidColor^.Data.ColorF^.Red;
  497. VGradient.Bottom.G := MidColor^.Data.ColorF^.Green;
  498. VGradient.Bottom.B := MidColor^.Data.ColorF^.Blue;
  499. FreeChunkData(BotColor);
  500. end;
  501. FreeChunkData(MidColor);
  502. end;
  503. FreeChunkData(TopColor);
  504. end;
  505. FreeChunkData(Chunk);
  506. end;
  507. // Search for use_bitmap, use_solid_bgnd and use_v_gradient chunks
  508. Chunk := FindChunk(MDataChunk, USE_BIT_MAP);
  509. if Assigned(Chunk) then
  510. BgndUsed := btUseBitmapBgnd
  511. else
  512. begin
  513. Chunk := FindChunk(MDataChunk, USE_SOLID_BGND);
  514. if Assigned(Chunk) then
  515. BgndUsed := btUseSolidBgnd
  516. else
  517. begin
  518. Chunk := FindChunk(MDataChunk, USE_V_GRADIENT);
  519. if Assigned(Chunk) then
  520. BgndUsed := btUseVGradientBgnd
  521. else
  522. BgndUsed := btNoBgnd;
  523. end;
  524. end;
  525. end;
  526. end;
  527. //-----------------------------------------------------------------------------
  528. function InitViewport: TViewport3DS;
  529. begin
  530. FillChar(Result, SizeOf(Result), 0);
  531. with Result do
  532. begin
  533. AType := vtTopView3DS;
  534. Ortho.Zoom := 0.7395;
  535. User.Zoom := 0.7395;
  536. User.HorAng := 20;
  537. User.VerAng := 30;
  538. CameraStr := '';
  539. Size.Width := 1000;
  540. Size.Height := 1000;
  541. end;
  542. end;
  543. //----------------------------------------------------------------------------
  544. function GetViewportEntry(Source: TFile3DS; Section: PChunk3DS): TViewport3DS;
  545. var
  546. Chunk, VLayout: PChunk3DS;
  547. PortIndex: integer;
  548. foundV3: boolean;
  549. begin
  550. Result := InitViewport;
  551. VLayout := FindNextChunk(Section^.Children, VIEWPORT_LAYOUT);
  552. if Assigned(VLayout) then
  553. with Result do
  554. begin
  555. Source.ReadChunkData(VLayout);
  556. Chunk := VLayout^.Children;
  557. foundV3 := False;
  558. PortIndex := 0;
  559. while Assigned(Chunk) do
  560. begin
  561. case Chunk^.Tag of
  562. VIEWPORT_SIZE:
  563. begin
  564. Source.ReadChunkData(Chunk);
  565. Size.XPos := Chunk^.Data.ViewportSize^.XPos;
  566. Size.YPos := Chunk^.Data.ViewportSize^.YPos;
  567. Size.Width := Chunk^.Data.ViewportSize^.Width;
  568. Size.Height := Chunk^.Data.ViewportSize^.Height;
  569. FreeChunkData(Chunk);
  570. end;
  571. VIEWPORT_DATA_3:
  572. begin
  573. foundV3 := True;
  574. if PortIndex = VLayout^.Data.ViewportLayout^.Top then
  575. begin
  576. Source.ReadChunkData(Chunk);
  577. case Chunk^.Data.ViewportData^.View of
  578. 1:
  579. AType := vtTopView3DS;
  580. 2:
  581. AType := vtBottomView3DS;
  582. 3:
  583. AType := vtLeftView3DS;
  584. 4:
  585. AType := vtRightView3DS;
  586. 5:
  587. AType := vtFrontView3DS;
  588. 6:
  589. AType := vtBackView3DS;
  590. 7:
  591. AType := vtUserView3DS;
  592. 18:
  593. AType := vtSpotlightView3DS;
  594. $FFFF:
  595. AType := vtCameraView3DS;
  596. else
  597. AType := vtNoView3DS;
  598. end;
  599. Ortho.Zoom := Chunk^.Data.ViewportData^.ZoomFactor;
  600. User.Zoom := Chunk^.Data.ViewportData^.ZoomFactor;
  601. Ortho.Center.X := Chunk^.Data.ViewportData^.Center.X;
  602. User.Center.X := Chunk^.Data.ViewportData^.Center.X;
  603. Ortho.Center.Y := Chunk^.Data.ViewportData^.Center.Y;
  604. User.Center.y := Chunk^.Data.ViewportData^.Center.Y;
  605. Ortho.Center.Z := Chunk^.Data.ViewportData^.Center.Z;
  606. User.Center.z := Chunk^.Data.ViewportData^.Center.Z;
  607. User.HorAng := Chunk^.Data.ViewportData^.HorizAng;
  608. User.VerAng := Chunk^.Data.ViewportData^.VertAng;
  609. CameraStr := string(Chunk^.Data.ViewportData^.CamNameStr);
  610. end;
  611. Inc(PortIndex);
  612. end;
  613. VIEWPORT_DATA:
  614. if not foundV3 then
  615. begin
  616. if PortIndex = VLayout^.Data.ViewportLayout^.Top then
  617. begin
  618. Source.ReadChunkData(Chunk);
  619. case Chunk^.Data.ViewportData^.View of
  620. 1:
  621. AType := vtTopView3DS;
  622. 2:
  623. AType := vtBottomView3DS;
  624. 3:
  625. AType := vtLeftView3DS;
  626. 4:
  627. AType := vtRightView3DS;
  628. 5:
  629. AType := vtFrontView3DS;
  630. 6:
  631. AType := vtBackView3DS;
  632. 7:
  633. AType := vtUserView3DS;
  634. 18:
  635. AType := vtSpotlightView3DS;
  636. $FFFF:
  637. AType := vtCameraView3DS;
  638. else
  639. AType := vtNoView3DS;
  640. end;
  641. Ortho.Zoom := Chunk^.Data.ViewportData^.ZoomFactor;
  642. User.Zoom := Chunk^.Data.ViewportData^.ZoomFactor;
  643. Ortho.Center.X := Chunk^.Data.ViewportData^.Center.X;
  644. User.Center.X := Chunk^.Data.ViewportData^.Center.X;
  645. Ortho.Center.Y := Chunk^.Data.ViewportData^.Center.Y;
  646. User.Center.y := Chunk^.Data.ViewportData^.Center.Y;
  647. Ortho.Center.Z := Chunk^.Data.ViewportData^.Center.Z;
  648. User.Center.z := Chunk^.Data.ViewportData^.Center.Z;
  649. User.HorAng := Chunk^.Data.ViewportData^.HorizAng;
  650. User.VerAng := Chunk^.Data.ViewportData^.VertAng;
  651. CameraStr := string(Chunk^.Data.ViewportData^.CamNameStr);
  652. end;
  653. Inc(PortIndex);
  654. end;
  655. end;
  656. Chunk := Chunk^.Sibling;
  657. end;
  658. end;
  659. end;
  660. //---------------------------------------------------------------------------
  661. function GetViewport(const Source: TFile3DS; var DB: TDatabase3DS): TViewport3DS;
  662. var
  663. Data: PChunk3DS;
  664. begin
  665. FillChar(Result, SizeOf(Result), 0);
  666. if (DB.TopChunk^.Tag = M3DMAGIC) or (DB.TopChunk^.Tag = CMAGIC) then
  667. begin
  668. Data := FindNextChunk(DB.TopChunk^.Children, KFDATA);
  669. if Assigned(Data) then
  670. Result := GetViewportEntry(Source, Data)
  671. else
  672. begin
  673. Data := FindChunk(DB.TopChunk^.Children, MDATA);
  674. if Assigned(Data) then
  675. Result := GetViewportEntry(Source, Data);
  676. end;
  677. end;
  678. end;
  679. //----------------- helper funcs for text output ------------------------------
  680. function ChunkTagToString(Tag: word): string;
  681. begin
  682. case Tag of
  683. NULL_CHUNK: Result := 'NULL_CHUNK';
  684. ChunkType: Result := 'ChunkType';
  685. ChunkUnique: Result := 'ChunkUnique';
  686. NotChunk: Result := 'NotChunk';
  687. Container: Result := 'Container';
  688. IsChunk: Result := 'IsChunk';
  689. // Dummy Chunk that sometimes appears in 3DS files created by prerelease 3D Studio R2
  690. DUMMY: Result := 'DUMMY';
  691. // Trick Chunk Types
  692. POINT_ARRAY_ENTRY: Result := 'POINT_ARRAY_ENTRY';
  693. POINT_FLAG_ARRAY_ENTRY: Result := 'POINT_FLAG_ARRAY_ENTRY';
  694. FACE_ARRAY_ENTRY: Result := 'FACE_ARRAY_ENTRY';
  695. MSH_MAT_GROUP_ENTRY: Result := 'MSH_MAT_GROUP_ENTRY';
  696. TEX_VERTS_ENTRY: Result := 'TEX_VERTS_ENTRY';
  697. SMOOTH_GROUP_ENTRY: Result := 'SMOOTH_GROUP_ENTRY';
  698. POS_TRACK_TAG_KEY: Result := 'POS_TRACK_TAG_KEY';
  699. ROT_TRACK_TAG_KEY: Result := 'ROT_TRACK_TAG_KEY';
  700. SCL_TRACK_TAG_KEY: Result := 'SCL_TRACK_TAG_KEY';
  701. FOV_TRACK_TAG_KEY: Result := 'FOV_TRACK_TAG_KEY';
  702. ROLL_TRACK_TAG_KEY: Result := 'ROLL_TRACK_TAG_KEY';
  703. COL_TRACK_TAG_KEY: Result := 'COL_TRACK_TAG_KEY';
  704. MORPH_TRACK_TAG_KEY: Result := 'MORPH_TRACK_TAG_KEY';
  705. HOT_TRACK_TAG_KEY: Result := 'HOT_TRACK_TAG_KEY';
  706. FALL_TRACK_TAG_KEY: Result := 'FALL_TRACK_TAG_KEY';
  707. // 3DS File Chunk IDs
  708. M3DMAGIC: Result := 'M3DMAGIC';
  709. SMAGIC: Result := 'SMAGIC';
  710. LMAGIC: Result := 'LMAGIC';
  711. MLIBMAGIC: Result := 'MLIBMAGIC';
  712. MATMAGIC: Result := 'MATMAGIC';
  713. M3D_VERSION: Result := 'M3D_VERSION';
  714. M3D_KFVERSION: Result := 'M3D_KFVERSION';
  715. // Mesh Chunk Ids
  716. MDATA: Result := 'MDATA';
  717. MESH_VERSION: Result := 'MESH_VERSION';
  718. COLOR_F: Result := 'COLOR_F';
  719. COLOR_24: Result := 'COLOR_24';
  720. LIN_COLOR_24: Result := 'LIN_COLOR_24';
  721. LIN_COLOR_F: Result := 'LIN_COLOR_F';
  722. INT_PERCENTAGE: Result := 'INT_PERCENTAGE';
  723. FLOAT_PERCENTAGE: Result := 'FLOAT_PERCENTAGE';
  724. MASTER_SCALE: Result := 'MASTER_SCALE';
  725. BIT_MAP: Result := 'BIT_MAP';
  726. USE_BIT_MAP: Result := 'USE_BIT_MAP';
  727. SOLID_BGND: Result := 'SOLID_BGND';
  728. USE_SOLID_BGND: Result := 'USE_SOLID_BGND';
  729. V_GRADIENT: Result := 'V_GRADIENT';
  730. USE_V_GRADIENT: Result := 'USE_V_GRADIENT';
  731. LO_SHADOW_BIAS: Result := 'LO_SHADOW_BIAS';
  732. HI_SHADOW_BIAS: Result := 'HI_SHADOW_BIAS';
  733. SHADOW_MAP_SIZE: Result := 'SHADOW_MAP_SIZE';
  734. SHADOW_SAMPLES: Result := 'SHADOW_SAMPLES';
  735. SHADOW_RANGE: Result := 'SHADOW_RANGE';
  736. SHADOW_FILTER: Result := 'SHADOW_FILTER';
  737. RAY_BIAS: Result := 'RAY_BIAS';
  738. O_CONSTS: Result := 'O_CONSTS';
  739. AMBIENT_LIGHT: Result := 'AMBIENT_LIGHT';
  740. FOG: Result := 'FOG';
  741. USE_FOG: Result := 'USE_FOG';
  742. FOG_BGND: Result := 'FOG_BGND';
  743. DISTANCE_CUE: Result := 'DISTANCE_CUE';
  744. USE_DISTANCE_CUE: Result := 'USE_DISTANCE_CUE';
  745. LAYER_FOG: Result := 'LAYER_FOG';
  746. USE_LAYER_FOG: Result := 'USE_LAYER_FOG';
  747. DCUE_BGND: Result := 'DCUE_BGND';
  748. DEFAULT_VIEW: Result := 'DEFAULT_VIEW';
  749. VIEW_TOP: Result := 'VIEW_TOP';
  750. VIEW_BOTTOM: Result := 'VIEW_BOTTOM';
  751. VIEW_LEFT: Result := 'VIEW_LEFT';
  752. VIEW_RIGHT: Result := 'VIEW_RIGHT';
  753. VIEW_FRONT: Result := 'VIEW_FRONT';
  754. VIEW_BACK: Result := 'VIEW_BACK';
  755. VIEW_USER: Result := 'VIEW_USER';
  756. VIEW_CAMERA: Result := 'VIEW_CAMERA';
  757. VIEW_WINDOW: Result := 'VIEW_WINDOW';
  758. NAMED_OBJECT: Result := 'NAMED_OBJECT';
  759. OBJ_HIDDEN: Result := 'OBJ_HIDDEN';
  760. OBJ_VIS_LOFTER: Result := 'OBJ_VIS_LOFTER';
  761. OBJ_DOESNT_CAST: Result := 'OBJ_DOESNT_CAST';
  762. OBJ_MATTE: Result := 'OBJ_MATTE';
  763. OBJ_FAST: Result := 'OBJ_FAST';
  764. OBJ_PROCEDURAL: Result := 'OBJ_PROCEDURAL';
  765. OBJ_FROZEN: Result := 'OBJ_FROZEN';
  766. OBJ_DONT_RCVSHADOW: Result := 'OBJ_DONT_RCVSHADOW';
  767. N_TRI_OBJECT: Result := 'N_TRI_OBJECT';
  768. POINT_ARRAY: Result := 'POINT_ARRAY';
  769. POINT_FLAG_ARRAY: Result := 'POINT_FLAG_ARRAY';
  770. FACE_ARRAY: Result := 'FACE_ARRAY';
  771. MSH_MAT_GROUP: Result := 'MSH_MAT_GROUP';
  772. OLD_MAT_GROUP: Result := 'OLD_MAT_GROUP';
  773. TEX_VERTS: Result := 'TEX_VERTS';
  774. SMOOTH_GROUP: Result := 'SMOOTH_GROUP';
  775. MESH_MATRIX: Result := 'MESH_MATRIX';
  776. MESH_COLOR: Result := 'MESH_COLOR';
  777. MESH_TEXTURE_INFO: Result := 'MESH_TEXTURE_INFO';
  778. PROC_NAME: Result := 'PROC_NAME';
  779. PROC_DATA: Result := 'PROC_DATA';
  780. MSH_BOXMAP: Result := 'MSH_BOXMAP';
  781. N_D_L_OLD: Result := 'N_D_L_OLD';
  782. N_CAM_OLD: Result := 'N_CAM_OLD';
  783. N_DIRECT_LIGHT: Result := 'N_DIRECT_LIGHT';
  784. DL_SPOTLIGHT: Result := 'DL_SPOTLIGHT';
  785. DL_OFF: Result := 'DL_OFF';
  786. DL_ATTENUATE: Result := 'DL_ATTENUATE';
  787. DL_RAYSHAD: Result := 'DL_RAYSHAD';
  788. DL_SHADOWED: Result := 'DL_SHADOWED';
  789. DL_LOCAL_SHADOW: Result := 'DL_LOCAL_SHADOW';
  790. DL_LOCAL_SHADOW2: Result := 'DL_LOCAL_SHADOW2';
  791. DL_SEE_CONE: Result := 'DL_SEE_CONE';
  792. DL_SPOT_RECTANGULAR: Result := 'DL_SPOT_RECTANGULAR';
  793. DL_SPOT_OVERSHOOT: Result := 'DL_SPOT_OVERSHOOT';
  794. DL_SPOT_PROJECTOR: Result := 'DL_SPOT_PROJECTOR';
  795. DL_EXCLUDE: Result := 'DL_EXCLUDE';
  796. DL_RANGE: Result := 'DL_RANGE';
  797. DL_SPOT_ROLL: Result := 'DL_SPOT_ROLL';
  798. DL_SPOT_ASPECT: Result := 'DL_SPOT_ASPECT';
  799. DL_RAY_BIAS: Result := 'DL_RAY_BIAS';
  800. DL_INNER_RANGE: Result := 'DL_INNER_RANGE';
  801. DL_OUTER_RANGE: Result := 'DL_OUTER_RANGE';
  802. DL_MULTIPLIER: Result := 'DL_MULTIPLIER';
  803. N_AMBIENT_LIGHT: Result := 'N_AMBIENT_LIGHT';
  804. N_CAMERA: Result := 'N_CAMERA';
  805. CAM_SEE_CONE: Result := 'CAM_SEE_CONE';
  806. CAM_RANGES: Result := 'CAM_RANGES';
  807. HIERARCHY: Result := 'HIERARCHY';
  808. PARENT_OBJECT: Result := 'PARENT_OBJECT';
  809. PIVOT_OBJECT: Result := 'PIVOT_OBJECT';
  810. PIVOT_LIMITS: Result := 'PIVOT_LIMITS';
  811. PIVOT_ORDER: Result := 'PIVOT_ORDER';
  812. XLATE_RANGE: Result := 'XLATE_RANGE';
  813. POLY_2D: Result := 'POLY_2D';
  814. // Flags in shaper file that tell whether polys make up an ok shape
  815. SHAPE_OK: Result := 'SHAPE_OK';
  816. SHAPE_NOT_OK: Result := 'SHAPE_NOT_OK';
  817. SHAPE_HOOK: Result := 'SHAPE_HOOK';
  818. PATH_3D: Result := 'PATH_3D';
  819. PATH_MATRIX: Result := 'PATH_MATRIX';
  820. SHAPE_2D: Result := 'SHAPE_2D';
  821. M_SCALE: Result := 'M_SCALE';
  822. M_TWIST: Result := 'M_TWIST';
  823. M_TEETER: Result := 'M_TEETER';
  824. M_FIT: Result := 'M_FIT';
  825. M_BEVEL: Result := 'M_BEVEL';
  826. XZ_CURVE: Result := 'XZ_CURVE';
  827. YZ_CURVE: Result := 'YZ_CURVE';
  828. INTERPCT: Result := 'INTERPCT';
  829. DEFORM_LIMIT: Result := 'DEFORM_LIMIT';
  830. // Flags for Modeler options
  831. USE_CONTOUR: Result := 'USE_CONTOUR';
  832. USE_TWEEN: Result := 'USE_TWEEN';
  833. USE_SCALE: Result := 'USE_SCALE';
  834. USE_TWIST: Result := 'USE_TWIST';
  835. USE_TEETER: Result := 'USE_TEETER';
  836. USE_FIT: Result := 'USE_FIT';
  837. USE_BEVEL: Result := 'USE_BEVEL';
  838. // Viewport description chunks
  839. VIEWPORT_LAYOUT_OLD: Result := 'VIEWPORT_LAYOUT_OLD';
  840. VIEWPORT_DATA_OLD: Result := 'VIEWPORT_DATA_OLD';
  841. VIEWPORT_LAYOUT: Result := 'VIEWPORT_LAYOUT';
  842. VIEWPORT_DATA: Result := 'VIEWPORT_DATA';
  843. VIEWPORT_DATA_3: Result := 'VIEWPORT_DATA_3';
  844. VIEWPORT_SIZE: Result := 'VIEWPORT_SIZE';
  845. NETWORK_VIEW: Result := 'NETWORK_VIEW';
  846. // External Application Data
  847. XDATA_SECTION: Result := 'XDATA_SECTION';
  848. XDATA_ENTRY: Result := 'XDATA_ENTRY';
  849. XDATA_APPNAME: Result := 'XDATA_APPNAME';
  850. XDATA_STRING: Result := 'XDATA_STRING';
  851. XDATA_FLOAT: Result := 'XDATA_FLOAT';
  852. XDATA_DOUBLE: Result := 'XDATA_DOUBLE';
  853. XDATA_SHORT: Result := 'XDATA_SHORT';
  854. XDATA_LONG: Result := 'XDATA_LONG';
  855. XDATA_VOID: Result := 'XDATA_procedure';
  856. XDATA_GROUP: Result := 'XDATA_GROUP';
  857. XDATA_RFU6: Result := 'XDATA_RFU6';
  858. XDATA_RFU5: Result := 'XDATA_RFU5';
  859. XDATA_RFU4: Result := 'XDATA_RFU4';
  860. XDATA_RFU3: Result := 'XDATA_RFU3';
  861. XDATA_RFU2: Result := 'XDATA_RFU2';
  862. XDATA_RFU1: Result := 'XDATA_RFU1';
  863. // Material Chunk IDs
  864. MAT_ENTRY: Result := 'MAT_ENTRY';
  865. MAT_NAME: Result := 'MAT_NAME';
  866. MAT_AMBIENT: Result := 'MAT_AMBIENT';
  867. MAT_DIFFUSE: Result := 'MAT_DIFFUSE';
  868. MAT_SPECULAR: Result := 'MAT_SPECULAR';
  869. MAT_SHININESS: Result := 'MAT_SHININESS';
  870. MAT_SHIN2PCT: Result := 'MAT_SHIN2PCT';
  871. MAT_SHIN3PCT: Result := 'MAT_SHIN3PCT';
  872. MAT_TRANSPARENCY: Result := 'MAT_TRANSPARENCY';
  873. MAT_XPFALL: Result := 'MAT_XPFALL';
  874. MAT_REFBLUR: Result := 'MAT_REFBLUR';
  875. MAT_SELF_ILLUM: Result := 'MAT_SELF_ILLUM';
  876. MAT_TWO_SIDE: Result := 'MAT_TWO_SIDE';
  877. MAT_DECAL: Result := 'MAT_DECAL';
  878. MAT_ADDITIVE: Result := 'MAT_ADDITIVE';
  879. MAT_SELF_ILPCT: Result := 'MAT_SELF_ILPCT';
  880. MAT_WIRE: Result := 'MAT_WIRE';
  881. MAT_SUPERSMP: Result := 'MAT_SUPERSMP';
  882. MAT_WIRESIZE: Result := 'MAT_WIRESIZE';
  883. MAT_FACEMAP: Result := 'MAT_FACEMAP';
  884. MAT_XPFALLIN: Result := 'MAT_XPFALLIN';
  885. MAT_PHONGSOFT: Result := 'MAT_PHONGSOFT';
  886. MAT_WIREABS: Result := 'MAT_WIREABS';
  887. MAT_SHADING: Result := 'MAT_SHADING';
  888. MAT_TEXMAP: Result := 'MAT_TEXMAP';
  889. MAT_OPACMAP: Result := 'MAT_OPACMAP';
  890. MAT_REFLMAP: Result := 'MAT_REFLMAP';
  891. MAT_BUMPMAP: Result := 'MAT_BUMPMAP';
  892. MAT_SPECMAP: Result := 'MAT_SPECMAP';
  893. MAT_USE_XPFALL: Result := 'MAT_USE_XPFALL';
  894. MAT_USE_REFBLUR: Result := 'MAT_USE_REFBLUR';
  895. MAT_BUMP_PERCENT: Result := 'MAT_BUMP_PERCENT';
  896. MAT_MAPNAME: Result := 'MAT_MAPNAME';
  897. MAT_ACUBIC: Result := 'MAT_ACUBIC';
  898. MAT_SXP_TEXT_DATA: Result := 'MAT_SXP_TEXT_DATA';
  899. MAT_SXP_TEXT2_DATA: Result := 'MAT_SXP_TEXT2_DATA';
  900. MAT_SXP_OPAC_DATA: Result := 'MAT_SXP_OPAC_DATA';
  901. MAT_SXP_BUMP_DATA: Result := 'MAT_SXP_BUMP_DATA';
  902. MAT_SXP_SPEC_DATA: Result := 'MAT_SXP_SPEC_DATA';
  903. MAT_SXP_SHIN_DATA: Result := 'MAT_SXP_SHIN_DATA';
  904. MAT_SXP_SELFI_DATA: Result := 'MAT_SXP_SELFI_DATA';
  905. MAT_SXP_TEXT_MASKDATA: Result := 'MAT_SXP_TEXT_MASKDATA';
  906. MAT_SXP_TEXT2_MASKDATA: Result := 'MAT_SXP_TEXT2_MASKDATA';
  907. MAT_SXP_OPAC_MASKDATA: Result := 'MAT_SXP_OPAC_MASKDATA';
  908. MAT_SXP_BUMP_MASKDATA: Result := 'MAT_SXP_BUMP_MASKDATA';
  909. MAT_SXP_SPEC_MASKDATA: Result := 'MAT_SXP_SPEC_MASKDATA';
  910. MAT_SXP_SHIN_MASKDATA: Result := 'MAT_SXP_SHIN_MASKDATA';
  911. MAT_SXP_SELFI_MASKDATA: Result := 'MAT_SXP_SELFI_MASKDATA';
  912. MAT_SXP_REFL_MASKDATA: Result := 'MAT_SXP_REFL_MASKDATA';
  913. MAT_TEX2MAP: Result := 'MAT_TEX2MAP';
  914. MAT_SHINMAP: Result := 'MAT_SHINMAP';
  915. MAT_SELFIMAP: Result := 'MAT_SELFIMAP';
  916. MAT_TEXMASK: Result := 'MAT_TEXMASK';
  917. MAT_TEX2MASK: Result := 'MAT_TEX2MASK';
  918. MAT_OPACMASK: Result := 'MAT_OPACMASK';
  919. MAT_BUMPMASK: Result := 'MAT_BUMPMASK';
  920. MAT_SHINMASK: Result := 'MAT_SHINMASK';
  921. MAT_SPECMASK: Result := 'MAT_SPECMASK';
  922. MAT_SELFIMASK: Result := 'MAT_SELFIMASK';
  923. MAT_REFLMASK: Result := 'MAT_REFLMASK';
  924. MAT_MAP_TILINGOLD: Result := 'MAT_MAP_TILINGOLD';
  925. MAT_MAP_TILING: Result := 'MAT_MAP_TILING';
  926. MAT_MAP_TEXBLUR_OLD: Result := 'MAT_MAP_TEXBLUR_OLD';
  927. MAT_MAP_TEXBLUR: Result := 'MAT_MAP_TEXBLUR';
  928. MAT_MAP_USCALE: Result := 'MAT_MAP_USCALE';
  929. MAT_MAP_VSCALE: Result := 'MAT_MAP_VSCALE';
  930. MAT_MAP_UOFFSET: Result := 'MAT_MAP_UOFFSET';
  931. MAT_MAP_VOFFSET: Result := 'MAT_MAP_VOFFSET';
  932. MAT_MAP_ANG: Result := 'MAT_MAP_ANG';
  933. MAT_MAP_COL1: Result := 'MAT_MAP_COL1';
  934. MAT_MAP_COL2: Result := 'MAT_MAP_COL2';
  935. MAT_MAP_RCOL: Result := 'MAT_MAP_RCOL';
  936. MAT_MAP_GCOL: Result := 'MAT_MAP_GCOL';
  937. MAT_MAP_BCOL: Result := 'MAT_MAP_BCOL';
  938. // Keyframe Chunk IDs
  939. KFDATA: Result := 'KFDATA';
  940. KFHDR: Result := 'KFHDR';
  941. AMBIENT_NODE_TAG: Result := 'AMBIENT_NODE_TAG';
  942. OBJECT_NODE_TAG: Result := 'OBJECT_NODE_TAG';
  943. CAMERA_NODE_TAG: Result := 'CAMERA_NODE_TAG';
  944. TARGET_NODE_TAG: Result := 'TARGET_NODE_TAG';
  945. LIGHT_NODE_TAG: Result := 'LIGHT_NODE_TAG';
  946. L_TARGET_NODE_TAG: Result := 'L_TARGET_NODE_TAG';
  947. SPOTLIGHT_NODE_TAG: Result := 'SPOTLIGHT_NODE_TAG';
  948. KFSEG: Result := 'KFSEG';
  949. KFCURTIME: Result := 'KFCURTIME';
  950. NODE_HDR: Result := 'NODE_HDR';
  951. PARENT_NAME: Result := 'PARENT_NAME';
  952. INSTANCE_NAME: Result := 'INSTANCE_NAME';
  953. PRESCALE: Result := 'PRESCALE';
  954. PIVOT: Result := 'PIVOT';
  955. BOUNDBOX: Result := 'BOUNDBOX';
  956. MORPH_SMOOTH: Result := 'MORPH_SMOOTH';
  957. POS_TRACK_TAG: Result := 'POS_TRACK_TAG';
  958. ROT_TRACK_TAG: Result := 'ROT_TRACK_TAG';
  959. SCL_TRACK_TAG: Result := 'SCL_TRACK_TAG';
  960. FOV_TRACK_TAG: Result := 'FOV_TRACK_TAG';
  961. ROLL_TRACK_TAG: Result := 'ROLL_TRACK_TAG';
  962. COL_TRACK_TAG: Result := 'COL_TRACK_TAG';
  963. MORPH_TRACK_TAG: Result := 'MORPH_TRACK_TAG';
  964. HOT_TRACK_TAG: Result := 'HOT_TRACK_TAG';
  965. FALL_TRACK_TAG: Result := 'FALL_TRACK_TAG';
  966. HIDE_TRACK_TAG: Result := 'HIDE_TRACK_TAG';
  967. NODE_ID: Result := 'NODE_ID';
  968. CMAGIC: Result := 'CMAGIC';
  969. C_MDRAWER: Result := 'C_MDRAWER';
  970. C_TDRAWER: Result := 'C_TDRAWER';
  971. C_SHPDRAWER: Result := 'C_SHPDRAWER';
  972. C_MODDRAWER: Result := 'C_MODDRAWER';
  973. C_RIPDRAWER: Result := 'C_RIPDRAWER';
  974. C_TXDRAWER: Result := 'C_TXDRAWER';
  975. C_PDRAWER: Result := 'C_PDRAWER';
  976. C_MTLDRAWER: Result := 'C_MTLDRAWER';
  977. C_FLIDRAWER: Result := 'C_FLIDRAWER';
  978. C_CUBDRAWER: Result := 'C_CUBDRAWER';
  979. C_MFILE: Result := 'C_MFILE';
  980. C_SHPFILE: Result := 'C_SHPFILE';
  981. C_MODFILE: Result := 'C_MODFILE';
  982. C_RIPFILE: Result := 'C_RIPFILE';
  983. C_TXFILE: Result := 'C_TXFILE';
  984. C_PFILE: Result := 'C_PFILE';
  985. C_MTLFILE: Result := 'C_MTLFILE';
  986. C_FLIFILE: Result := 'C_FLIFILE';
  987. C_PALFILE: Result := 'C_PALFILE';
  988. C_TX_STRING: Result := 'C_TX_STRING';
  989. C_CONSTS: Result := 'C_CONSTS';
  990. C_SNAPS: Result := 'C_SNAPS';
  991. C_GRIDS: Result := 'C_GRIDS';
  992. C_ASNAPS: Result := 'C_ASNAPS';
  993. C_GRID_RANGE: Result := 'C_GRID_RANGE';
  994. C_RENDTYPE: Result := 'C_RENDTYPE';
  995. C_PROGMODE: Result := 'C_PROGMODE';
  996. C_PREVMODE: Result := 'C_PREVMODE';
  997. C_MODWMODE: Result := 'C_MODWMODE';
  998. C_MODMODEL: Result := 'C_MODMODEL';
  999. C_ALL_LINES: Result := 'C_ALL_LINES';
  1000. C_BACK_TYPE: Result := 'C_BACK_TYPE';
  1001. C_MD_CS: Result := 'C_MD_CS';
  1002. C_MD_CE: Result := 'C_MD_CE';
  1003. C_MD_SML: Result := 'C_MD_SML';
  1004. C_MD_SMW: Result := 'C_MD_SMW';
  1005. C_LOFT_WITH_TEXTURE: Result := 'C_LOFT_WITH_TEXTURE';
  1006. C_LOFT_L_REPEAT: Result := 'C_LOFT_L_REPEAT';
  1007. C_LOFT_W_REPEAT: Result := 'C_LOFT_W_REPEAT';
  1008. C_LOFT_UV_NORMALIZE: Result := 'C_LOFT_UV_NORMALIZE';
  1009. C_WELD_LOFT: Result := 'C_WELD_LOFT';
  1010. C_MD_PDET: Result := 'C_MD_PDET';
  1011. C_MD_SDET: Result := 'C_MD_SDET';
  1012. C_RGB_RMODE: Result := 'C_RGB_RMODE';
  1013. C_RGB_HIDE: Result := 'C_RGB_HIDE';
  1014. C_RGB_MAPSW: Result := 'C_RGB_MAPSW';
  1015. C_RGB_TWOSIDE: Result := 'C_RGB_TWOSIDE';
  1016. C_RGB_SHADOW: Result := 'C_RGB_SHADOW';
  1017. C_RGB_AA: Result := 'C_RGB_AA';
  1018. C_RGB_OVW: Result := 'C_RGB_OVW';
  1019. C_RGB_OVH: Result := 'C_RGB_OVH';
  1020. C_RGB_PICTYPE: Result := 'C_RGB_PICTYPE';
  1021. C_RGB_OUTPUT: Result := 'C_RGB_OUTPUT';
  1022. C_RGB_TODISK: Result := 'C_RGB_TODISK';
  1023. C_RGB_COMPRESS: Result := 'C_RGB_COMPRESS';
  1024. C_JPEG_COMPRESSION: Result := 'C_JPEG_COMPRESSION';
  1025. C_RGB_DISPDEV: Result := 'C_RGB_DISPDEV';
  1026. C_RGB_HARDDEV: Result := 'C_RGB_HARDDEV';
  1027. C_RGB_PATH: Result := 'C_RGB_PATH';
  1028. C_BITMAP_DRAWER: Result := 'C_BITMAP_DRAWER';
  1029. C_RGB_FILE: Result := 'C_RGB_FILE';
  1030. C_RGB_OVASPECT: Result := 'C_RGB_OVASPECT';
  1031. C_RGB_ANIMTYPE: Result := 'C_RGB_ANIMTYPE';
  1032. C_RENDER_ALL: Result := 'C_RENDER_ALL';
  1033. C_REND_FROM: Result := 'C_REND_FROM';
  1034. C_REND_TO: Result := 'C_REND_TO';
  1035. C_REND_NTH: Result := 'C_REND_NTH';
  1036. C_REND_TSTEP: Result := 'C_REND_TSTEP';
  1037. C_VP_TSTEP: Result := 'C_VP_TSTEP';
  1038. C_PAL_TYPE: Result := 'C_PAL_TYPE';
  1039. C_RND_TURBO: Result := 'C_RND_TURBO';
  1040. C_RND_MIP: Result := 'C_RND_MIP';
  1041. C_BGND_METHOD: Result := 'C_BGND_METHOD';
  1042. C_AUTO_REFLECT: Result := 'C_AUTO_REFLECT';
  1043. C_VP_FROM: Result := 'C_VP_FROM';
  1044. C_VP_TO: Result := 'C_VP_TO';
  1045. C_VP_NTH: Result := 'C_VP_NTH';
  1046. C_SRDIAM: Result := 'C_SRDIAM';
  1047. C_SRDEG: Result := 'C_SRDEG';
  1048. C_SRSEG: Result := 'C_SRSEG';
  1049. C_SRDIR: Result := 'C_SRDIR';
  1050. C_HETOP: Result := 'C_HETOP';
  1051. C_HEBOT: Result := 'C_HEBOT';
  1052. C_HEHT: Result := 'C_HEHT';
  1053. C_HETURNS: Result := 'C_HETURNS';
  1054. C_HEDEG: Result := 'C_HEDEG';
  1055. C_HESEG: Result := 'C_HESEG';
  1056. C_HEDIR: Result := 'C_HEDIR';
  1057. C_QUIKSTUFF: Result := 'C_QUIKSTUFF';
  1058. C_SEE_LIGHTS: Result := 'C_SEE_LIGHTS';
  1059. C_SEE_CAMERAS: Result := 'C_SEE_CAMERAS';
  1060. C_SEE_3D: Result := 'C_SEE_3D';
  1061. C_MESHSEL: Result := 'C_MESHSEL';
  1062. C_MESHUNSEL: Result := 'C_MESHUNSEL';
  1063. C_POLYSEL: Result := 'C_POLYSEL';
  1064. C_POLYUNSEL: Result := 'C_POLYUNSEL';
  1065. C_SHPLOCAL: Result := 'C_SHPLOCAL';
  1066. C_MSHLOCAL: Result := 'C_MSHLOCAL';
  1067. C_NUM_FORMAT: Result := 'C_NUM_FORMAT';
  1068. C_ARCH_DENOM: Result := 'C_ARCH_DENOM';
  1069. C_IN_DEVICE: Result := 'C_IN_DEVICE';
  1070. C_MSCALE: Result := 'C_MSCALE';
  1071. C_COMM_PORT: Result := 'C_COMM_PORT';
  1072. C_TAB_BASES: Result := 'C_TAB_BASES';
  1073. C_TAB_DIVS: Result := 'C_TAB_DIVS';
  1074. C_MASTER_SCALES: Result := 'C_MASTER_SCALES';
  1075. C_SHOW_1STVERT: Result := 'C_SHOW_1STVERT';
  1076. C_SHAPER_OK: Result := 'C_SHAPER_OK';
  1077. C_LOFTER_OK: Result := 'C_LOFTER_OK';
  1078. C_EDITOR_OK: Result := 'C_EDITOR_OK';
  1079. C_KEYFRAMER_OK: Result := 'C_KEYFRAMER_OK';
  1080. C_PICKSIZE: Result := 'C_PICKSIZE';
  1081. C_MAPTYPE: Result := 'C_MAPTYPE';
  1082. C_MAP_DISPLAY: Result := 'C_MAP_DISPLAY';
  1083. C_TILE_XY: Result := 'C_TILE_XY';
  1084. C_MAP_XYZ: Result := 'C_MAP_XYZ';
  1085. C_MAP_SCALE: Result := 'C_MAP_SCALE';
  1086. C_MAP_MATRIX_OLD: Result := 'C_MAP_MATRIX_OLD';
  1087. C_MAP_MATRIX: Result := 'C_MAP_MATRIX';
  1088. C_MAP_WID_HT: Result := 'C_MAP_WID_HT';
  1089. C_OBNAME: Result := 'C_OBNAME';
  1090. C_CAMNAME: Result := 'C_CAMNAME';
  1091. C_LTNAME: Result := 'C_LTNAME';
  1092. C_CUR_MNAME: Result := 'C_CUR_MNAME';
  1093. C_CURMTL_FROM_MESH: Result := 'C_CURMTL_FROM_MESH';
  1094. C_GET_SHAPE_MAKE_FACES: Result := 'C_GET_SHAPE_MAKE_FACES';
  1095. C_DETAIL: Result := 'C_DETAIL';
  1096. C_VERTMARK: Result := 'C_VERTMARK';
  1097. C_MSHAX: Result := 'C_MSHAX';
  1098. C_MSHCP: Result := 'C_MSHCP';
  1099. C_USERAX: Result := 'C_USERAX';
  1100. C_SHOOK: Result := 'C_SHOOK';
  1101. C_RAX: Result := 'C_RAX';
  1102. C_STAPE: Result := 'C_STAPE';
  1103. C_LTAPE: Result := 'C_LTAPE';
  1104. C_ETAPE: Result := 'C_ETAPE';
  1105. C_KTAPE: Result := 'C_KTAPE';
  1106. C_SPHSEGS: Result := 'C_SPHSEGS';
  1107. C_GEOSMOOTH: Result := 'C_GEOSMOOTH';
  1108. C_HEMISEGS: Result := 'C_HEMISEGS';
  1109. C_PRISMSEGS: Result := 'C_PRISMSEGS';
  1110. C_PRISMSIDES: Result := 'C_PRISMSIDES';
  1111. C_TUBESEGS: Result := 'C_TUBESEGS';
  1112. C_TUBESIDES: Result := 'C_TUBESIDES';
  1113. C_TORSEGS: Result := 'C_TORSEGS';
  1114. C_TORSIDES: Result := 'C_TORSIDES';
  1115. C_CONESIDES: Result := 'C_CONESIDES';
  1116. C_CONESEGS: Result := 'C_CONESEGS';
  1117. C_NGPARMS: Result := 'C_NGPARMS';
  1118. C_PTHLEVEL: Result := 'C_PTHLEVEL';
  1119. C_MSCSYM: Result := 'C_MSCSYM';
  1120. C_MFTSYM: Result := 'C_MFTSYM';
  1121. C_MTTSYM: Result := 'C_MTTSYM';
  1122. C_SMOOTHING: Result := 'C_SMOOTHING';
  1123. C_MODICOUNT: Result := 'C_MODICOUNT';
  1124. C_FONTSEL: Result := 'C_FONTSEL';
  1125. C_TESS_TYPE: Result := 'C_TESS_TYPE';
  1126. C_TESS_TENSION: Result := 'C_TESS_TENSION';
  1127. C_SEG_START: Result := 'C_SEG_START';
  1128. C_SEG_END: Result := 'C_SEG_END';
  1129. C_CURTIME: Result := 'C_CURTIME';
  1130. C_ANIMLENGTH: Result := 'C_ANIMLENGTH';
  1131. C_PV_FROM: Result := 'C_PV_FROM';
  1132. C_PV_TO: Result := 'C_PV_TO';
  1133. C_PV_DOFNUM: Result := 'C_PV_DOFNUM';
  1134. C_PV_RNG: Result := 'C_PV_RNG';
  1135. C_PV_NTH: Result := 'C_PV_NTH';
  1136. C_PV_TYPE: Result := 'C_PV_TYPE';
  1137. C_PV_METHOD: Result := 'C_PV_METHOD';
  1138. C_PV_FPS: Result := 'C_PV_FPS';
  1139. C_VTR_FRAMES: Result := 'C_VTR_FRAMES';
  1140. C_VTR_HDTL: Result := 'C_VTR_HDTL';
  1141. C_VTR_HD: Result := 'C_VTR_HD';
  1142. C_VTR_TL: Result := 'C_VTR_TL';
  1143. C_VTR_IN: Result := 'C_VTR_IN';
  1144. C_VTR_PK: Result := 'C_VTR_PK';
  1145. C_VTR_SH: Result := 'C_VTR_SH';
  1146. // Material chunks
  1147. C_WORK_MTLS: Result := 'C_WORK_MTLS';
  1148. C_WORK_MTLS_2: Result := 'C_WORK_MTLS_2';
  1149. C_WORK_MTLS_3: Result := 'C_WORK_MTLS_3';
  1150. C_WORK_MTLS_4: Result := 'C_WORK_MTLS_4';
  1151. C_WORK_MTLS_5: Result := 'C_WORK_MTLS_5';
  1152. C_WORK_MTLS_6: Result := 'C_WORK_MTLS_6';
  1153. C_WORK_MTLS_7: Result := 'C_WORK_MTLS_7';
  1154. C_WORK_MTLS_8: Result := 'C_WORK_MTLS_8';
  1155. C_WORKMTL: Result := 'C_WORKMTL';
  1156. C_SXP_TEXT_DATA: Result := 'C_SXP_TEXT_DATA';
  1157. C_SXP_TEXT2_DATA: Result := 'C_SXP_TEXT2_DATA';
  1158. C_SXP_OPAC_DATA: Result := 'C_SXP_OPAC_DATA';
  1159. C_SXP_BUMP_DATA: Result := 'C_SXP_BUMP_DATA';
  1160. C_SXP_SPEC_DATA: Result := 'C_SXP_SPEC_DATA';
  1161. C_SXP_SHIN_DATA: Result := 'C_SXP_SHIN_DATA';
  1162. C_SXP_SELFI_DATA: Result := 'C_SXP_SELFI_DATA';
  1163. C_SXP_TEXT_MASKDATA: Result := 'C_SXP_TEXT_MASKDATA';
  1164. C_SXP_TEXT2_MASKDATA: Result := 'C_SXP_TEXT2_MASKDATA';
  1165. C_SXP_OPAC_MASKDATA: Result := 'C_SXP_OPAC_MASKDATA';
  1166. C_SXP_BUMP_MASKDATA: Result := 'C_SXP_BUMP_MASKDATA';
  1167. C_SXP_SPEC_MASKDATA: Result := 'C_SXP_SPEC_MASKDATA';
  1168. C_SXP_SHIN_MASKDATA: Result := 'C_SXP_SHIN_MASKDATA';
  1169. C_SXP_SELFI_MASKDATA: Result := 'C_SXP_SELFI_MASKDATA';
  1170. C_SXP_REFL_MASKDATA: Result := 'C_SXP_REFL_MASKDATA';
  1171. C_BGTYPE: Result := 'C_BGTYPE';
  1172. C_MEDTILE: Result := 'C_MEDTILE';
  1173. // Contrast
  1174. C_LO_CONTRAST: Result := 'C_LO_CONTRAST';
  1175. C_HI_CONTRAST: Result := 'C_HI_CONTRAST';
  1176. // 3D frozen display
  1177. C_FROZ_DISPLAY: Result := 'C_FROZ_DISPLAY';
  1178. // Booleans
  1179. C_BOOLWELD: Result := 'C_BOOLWELD';
  1180. C_BOOLTYPE: Result := 'C_BOOLTYPE';
  1181. C_ANG_THRESH: Result := 'C_ANG_THRESH';
  1182. C_SS_THRESH: Result := 'C_SS_THRESH';
  1183. C_TEXTURE_BLUR_DEFAULT: Result := 'C_TEXTURE_BLUR_DEFAULT';
  1184. C_MAPDRAWER: Result := 'C_MAPDRAWER';
  1185. C_MAPDRAWER1: Result := 'C_MAPDRAWER1';
  1186. C_MAPDRAWER2: Result := 'C_MAPDRAWER2';
  1187. C_MAPDRAWER3: Result := 'C_MAPDRAWER3';
  1188. C_MAPDRAWER4: Result := 'C_MAPDRAWER4';
  1189. C_MAPDRAWER5: Result := 'C_MAPDRAWER5';
  1190. C_MAPDRAWER6: Result := 'C_MAPDRAWER6';
  1191. C_MAPDRAWER7: Result := 'C_MAPDRAWER7';
  1192. C_MAPDRAWER8: Result := 'C_MAPDRAWER8';
  1193. C_MAPDRAWER9: Result := 'C_MAPDRAWER9';
  1194. C_MAPDRAWER_ENTRY: Result := 'C_MAPDRAWER_ENTRY';
  1195. // system options
  1196. C_BACKUP_FILE: Result := 'C_BACKUP_FILE';
  1197. C_DITHER_256: Result := 'C_DITHER_256';
  1198. C_SAVE_LAST: Result := 'C_SAVE_LAST';
  1199. C_USE_ALPHA: Result := 'C_USE_ALPHA';
  1200. C_TGA_DEPTH: Result := 'C_TGA_DEPTH';
  1201. C_REND_FIELDS: Result := 'C_REND_FIELDS';
  1202. C_REFLIP: Result := 'C_REFLIP';
  1203. C_SEL_ITEMTOG: Result := 'C_SEL_ITEMTOG';
  1204. C_SEL_RESET: Result := 'C_SEL_RESET';
  1205. C_STICKY_KEYINF: Result := 'C_STICKY_KEYINF';
  1206. C_WELD_THRESHOLD: Result := 'C_WELD_THRESHOLD';
  1207. C_ZCLIP_POINT: Result := 'C_ZCLIP_POINT';
  1208. C_ALPHA_SPLIT: Result := 'C_ALPHA_SPLIT';
  1209. C_KF_SHOW_BACKFACE: Result := 'C_KF_SHOW_BACKFACE';
  1210. C_OPTIMIZE_LOFT: Result := 'C_OPTIMIZE_LOFT';
  1211. C_TENS_DEFAULT: Result := 'C_TENS_DEFAULT';
  1212. C_CONT_DEFAULT: Result := 'C_CONT_DEFAULT';
  1213. C_BIAS_DEFAULT: Result := 'C_BIAS_DEFAULT';
  1214. C_DXFNAME_SRC: Result := 'C_DXFNAME_SRC ';
  1215. C_AUTO_WELD: Result := 'C_AUTO_WELD ';
  1216. C_AUTO_UNIFY: Result := 'C_AUTO_UNIFY ';
  1217. C_AUTO_SMOOTH: Result := 'C_AUTO_SMOOTH ';
  1218. C_DXF_SMOOTH_ANG: Result := 'C_DXF_SMOOTH_ANG ';
  1219. C_SMOOTH_ANG: Result := 'C_SMOOTH_ANG ';
  1220. // Special network-use chunks
  1221. C_NET_USE_VPOST: Result := 'C_NET_USE_VPOST';
  1222. C_NET_USE_GAMMA: Result := 'C_NET_USE_GAMMA';
  1223. C_NET_FIELD_ORDER: Result := 'C_NET_FIELD_ORDER';
  1224. C_BLUR_FRAMES: Result := 'C_BLUR_FRAMES';
  1225. C_BLUR_SAMPLES: Result := 'C_BLUR_SAMPLES';
  1226. C_BLUR_DUR: Result := 'C_BLUR_DUR';
  1227. C_HOT_METHOD: Result := 'C_HOT_METHOD';
  1228. C_HOT_CHECK: Result := 'C_HOT_CHECK';
  1229. C_PIXEL_SIZE: Result := 'C_PIXEL_SIZE';
  1230. C_DISP_GAMMA: Result := 'C_DISP_GAMMA';
  1231. C_FBUF_GAMMA: Result := 'C_FBUF_GAMMA';
  1232. C_FILE_OUT_GAMMA: Result := 'C_FILE_OUT_GAMMA';
  1233. C_FILE_IN_GAMMA: Result := 'C_FILE_IN_GAMMA';
  1234. C_GAMMA_CORRECT: Result := 'C_GAMMA_CORRECT';
  1235. C_APPLY_DISP_GAMMA: Result := 'C_APPLY_DISP_GAMMA';
  1236. C_APPLY_FBUF_GAMMA: Result := 'C_APPLY_FBUF_GAMMA';
  1237. C_APPLY_FILE_GAMMA: Result := 'C_APPLY_FILE_GAMMA';
  1238. C_FORCE_WIRE: Result := 'C_FORCE_WIRE';
  1239. C_RAY_SHADOWS: Result := 'C_RAY_SHADOWS';
  1240. C_MASTER_AMBIENT: Result := 'C_MASTER_AMBIENT';
  1241. C_SUPER_SAMPLE: Result := 'C_SUPER_SAMPLE';
  1242. C_OBJECT_MBLUR: Result := 'C_OBJECT_MBLUR';
  1243. C_MBLUR_DITHER: Result := 'C_MBLUR_DITHER';
  1244. C_DITHER_24: Result := 'C_DITHER_24';
  1245. C_SUPER_BLACK: Result := 'C_SUPER_BLACK';
  1246. C_SAFE_FRAME: Result := 'C_SAFE_FRAME';
  1247. C_VIEW_PRES_RATIO: Result := 'C_VIEW_PRES_RATIO';
  1248. C_BGND_PRES_RATIO: Result := 'C_BGND_PRES_RATIO';
  1249. C_NTH_SERIAL_NUM: Result := 'C_NTH_SERIAL_NUM';
  1250. VPDATA: Result := 'VPDATA';
  1251. P_QUEUE_ENTRY: Result := 'P_QUEUE_ENTRY';
  1252. P_QUEUE_IMAGE: Result := 'P_QUEUE_IMAGE';
  1253. P_QUEUE_USEIGAMMA: Result := 'P_QUEUE_USEIGAMMA';
  1254. P_QUEUE_PROC: Result := 'P_QUEUE_PROC';
  1255. P_QUEUE_SOLID: Result := 'P_QUEUE_SOLID';
  1256. P_QUEUE_GRADIENT: Result := 'P_QUEUE_GRADIENT';
  1257. P_QUEUE_KF: Result := 'P_QUEUE_KF';
  1258. P_QUEUE_MOTBLUR: Result := 'P_QUEUE_MOTBLUR';
  1259. P_QUEUE_MB_REPEAT: Result := 'P_QUEUE_MB_REPEAT';
  1260. P_QUEUE_NONE: Result := 'P_QUEUE_NONE';
  1261. P_QUEUE_RESIZE: Result := 'P_QUEUE_RESIZE';
  1262. P_QUEUE_OFFSET: Result := 'P_QUEUE_OFFSET';
  1263. P_QUEUE_ALIGN: Result := 'P_QUEUE_ALIGN';
  1264. P_CUSTOM_SIZE: Result := 'P_CUSTOM_SIZE';
  1265. P_ALPH_NONE: Result := 'P_ALPH_NONE';
  1266. P_ALPH_PSEUDO: Result := 'P_ALPH_PSEUDO';
  1267. P_ALPH_OP_PSEUDO: Result := 'P_ALPH_OP_PSEUDO';
  1268. P_ALPH_BLUR: Result := 'P_ALPH_BLUR';
  1269. P_ALPH_PCOL: Result := 'P_ALPH_PCOL';
  1270. P_ALPH_C0: Result := 'P_ALPH_C0';
  1271. P_ALPH_OP_KEY: Result := 'P_ALPH_OP_KEY';
  1272. P_ALPH_KCOL: Result := 'P_ALPH_KCOL';
  1273. P_ALPH_OP_NOCONV: Result := 'P_ALPH_OP_NOCONV';
  1274. P_ALPH_IMAGE: Result := 'P_ALPH_IMAGE';
  1275. P_ALPH_ALPHA: Result := 'P_ALPH_ALPHA';
  1276. P_ALPH_QUES: Result := 'P_ALPH_QUES';
  1277. P_ALPH_QUEIMG: Result := 'P_ALPH_QUEIMG';
  1278. P_ALPH_CUTOFF: Result := 'P_ALPH_CUTOFF';
  1279. P_ALPHANEG: Result := 'P_ALPHANEG';
  1280. P_TRAN_NONE: Result := 'P_TRAN_NONE';
  1281. P_TRAN_IMAGE: Result := 'P_TRAN_IMAGE';
  1282. P_TRAN_FRAMES: Result := 'P_TRAN_FRAMES';
  1283. P_TRAN_FADEIN: Result := 'P_TRAN_FADEIN';
  1284. P_TRAN_FADEOUT: Result := 'P_TRAN_FADEOUT';
  1285. P_TRANNEG: Result := 'P_TRANNEG';
  1286. P_RANGES: Result := 'P_RANGES';
  1287. P_PROC_DATA: Result := 'P_PROC_DATA'
  1288. else
  1289. Result := 'UNKNOWN_CHUNK';
  1290. end;
  1291. end;
  1292. //---------------------------------------------------------------------------------------------------------------------
  1293. const
  1294. IndentString: string = #9#9#9#9#9#9#9#9#9#9#9#9;
  1295. function Indent(Level: integer): string;
  1296. begin
  1297. Result := Copy(IndentString, 1, Level);
  1298. end;
  1299. //---------------------------------------------------------------------------------------------------------------------
  1300. procedure ChunkHeaderReport(var Strings: TStrings; Chunk: PChunk3DS;
  1301. IndentLevel: integer);
  1302. var
  1303. OutString: string;
  1304. begin
  1305. OutString := Format('%sChunk %s ($%x), Length is %d ($%3:x)',
  1306. [Indent(IndentLevel), ChunkTagToString(Chunk^.Tag), Chunk^.Tag, Chunk^.Size]);
  1307. Strings.Add(OutString);
  1308. end;
  1309. //---------------------------------------------------------------------------------------------------------------------
  1310. procedure DumpKeyHeader(Strings: TStrings; const Key: TKeyHeader3DS; IndentLevel: integer);
  1311. var
  1312. Output: string;
  1313. begin
  1314. Output := Format('%sFrame %d', [Indent(IndentLevel), Key.Time]);
  1315. if (Key.rflags and KeyUsesTension3DS) <> 0 then
  1316. Output := Output + Format(', Tens %.2f', [Key.Tension]);
  1317. if (Key.rflags and KeyUsesCont3DS) <> 0 then
  1318. Output := Output + Format(', Cont %.2f', [Key.Continuity]);
  1319. if (Key.rflags and KeyUsesBias3DS) <> 0 then
  1320. Output := Output + Format(', Bias %.2f', [Key.Bias]);
  1321. if (Key.rflags and KeyUsesEaseTo3DS) <> 0 then
  1322. Output := Output + Format(', Ease to %.2f', [Key.EaseTo]);
  1323. if (Key.rflags and KeyUsesEaseFrom3DS) <> 0 then
  1324. Output := Output + Format(', Ease from %.2f', [Key.EaseFrom]);
  1325. Strings.Add(Output);
  1326. end;
  1327. //-----------------------------------------------------------------------------
  1328. procedure DumpChunk(const Source: TFile3DS; var Strings: TStrings;
  1329. Chunk: PChunk3DS; IndentLevel: integer; DumpLevel: TDumpLevel);
  1330. // retrieves the Data for a Chunk from the given Source, formats the Data into
  1331. // one or more lines of text and puts the lines into the given Strings parameter
  1332. var
  1333. Child: PChunk3DS;
  1334. Output: string;
  1335. ID: string;
  1336. I: integer;
  1337. begin
  1338. ChunkHeaderReport(Strings, Chunk, IndentLevel);
  1339. ID := Indent(IndentLevel) + #9;
  1340. if DumpLevel <> dlTerseDump then
  1341. begin
  1342. case Chunk^.Tag of
  1343. MESH_VERSION:
  1344. begin
  1345. Source.ReadChunkData(Chunk);
  1346. Output := Format('%sVersion %d', [ID, Chunk^.Data.MeshVersion^]);
  1347. Strings.Add(Output);
  1348. end;
  1349. M3D_VERSION:
  1350. begin
  1351. Source.ReadChunkData(Chunk);
  1352. Output := Format('%sVersion %d', [ID, Chunk^.Data.M3DVersion^]);
  1353. Strings.Add(Output);
  1354. end;
  1355. COLOR_F:
  1356. begin
  1357. Source.ReadChunkData(Chunk);
  1358. Output := Format('%sColor R: %f, ', [ID, Chunk^.Data.ColorF^.Red]);
  1359. Output := Output + Format(' G: %f, ', [Chunk^.Data.ColorF^.Green]);
  1360. Output := Output + Format(' B: %f', [Chunk^.Data.ColorF^.Blue]);
  1361. Strings.Add(Output);
  1362. end;
  1363. LIN_COLOR_F:
  1364. begin
  1365. Source.ReadChunkData(Chunk);
  1366. Output := Format('%sColor R: %f, ', [ID, Chunk^.Data.LinColorF^.Red]);
  1367. Output := Output + Format(' G: %f, ', [Chunk^.Data.LinColorF^.Green]);
  1368. Output := Output + Format(' B: %f', [Chunk^.Data.LinColorF^.Blue]);
  1369. Strings.Add(Output);
  1370. end;
  1371. COLOR_24:
  1372. begin
  1373. Source.ReadChunkData(Chunk);
  1374. Output := Format('%sColor R: %d, ', [ID, Chunk^.Data.Color24^.Red]);
  1375. Output := Output + Format(' G: %d, ', [Chunk^.Data.Color24^.Green]);
  1376. Output := Output + Format(' B: %d', [Chunk^.Data.Color24^.Blue]);
  1377. Strings.Add(Output);
  1378. end;
  1379. LIN_COLOR_24:
  1380. begin
  1381. Source.ReadChunkData(Chunk);
  1382. Output := Format('%sColor R: %d, ', [ID, Chunk^.Data.LinColor24^.Red]);
  1383. Output := Output + Format(' G: %d, ', [Chunk^.Data.LinColor24^.Green]);
  1384. Output := Output + Format(' B: %d', [Chunk^.Data.LinColor24^.Blue]);
  1385. Strings.Add(Output);
  1386. end;
  1387. INT_PERCENTAGE:
  1388. begin
  1389. Source.ReadChunkData(Chunk);
  1390. Output := Format('%sPercentage of %d%%', [ID, Chunk^.Data.IntPercentage^]);
  1391. Strings.Add(Output);
  1392. end;
  1393. FLOAT_PERCENTAGE:
  1394. begin
  1395. Source.ReadChunkData(Chunk);
  1396. Output := Format('%sPercentage of %f%%', [ID, Chunk^.Data.FloatPercentage^]);
  1397. Strings.Add(Output);
  1398. end;
  1399. MASTER_SCALE:
  1400. begin
  1401. Source.ReadChunkData(Chunk);
  1402. Output := Format('%sMaster Scale %f', [ID, Chunk^.Data.MasterScale^]);
  1403. Strings.Add(Output);
  1404. end;
  1405. BIT_MAP:
  1406. begin
  1407. Source.ReadChunkData(Chunk);
  1408. Output := Format('%sBitmap Name %s', [ID, Chunk^.Data.BitMapName^]);
  1409. Strings.Add(Output);
  1410. end;
  1411. V_GRADIENT:
  1412. begin
  1413. Source.ReadChunkData(Chunk);
  1414. Output := Format('%sMidpoint %f', [ID, Chunk^.Data.VGradient^]);
  1415. Strings.Add(Output);
  1416. end;
  1417. LO_SHADOW_BIAS:
  1418. begin
  1419. Source.ReadChunkData(Chunk);
  1420. Output := Format('%sBias of %f', [ID, Chunk^.Data.LoShadowBias^]);
  1421. Strings.Add(Output);
  1422. end;
  1423. HI_SHADOW_BIAS:
  1424. begin
  1425. Source.ReadChunkData(Chunk);
  1426. Output := Format('%sBias of %f', [ID, Chunk^.Data.HiShadowBias^]);
  1427. Strings.Add(Output);
  1428. end;
  1429. RAY_BIAS:
  1430. begin
  1431. Source.ReadChunkData(Chunk);
  1432. Output := Format('%sBias of %f', [ID, Chunk^.Data.RayBias^]);
  1433. Strings.Add(Output);
  1434. end;
  1435. SHADOW_MAP_SIZE:
  1436. begin
  1437. Source.ReadChunkData(Chunk);
  1438. Output := Format('%sSize of %d', [ID, Chunk^.Data.ShadowMapSize^]);
  1439. Strings.Add(Output);
  1440. end;
  1441. SHADOW_SAMPLES:
  1442. begin
  1443. Source.ReadChunkData(Chunk);
  1444. Output := Format('%sSize of %d', [ID, Chunk^.Data.ShadowSamples^]);
  1445. Strings.Add(Output);
  1446. end;
  1447. SHADOW_RANGE:
  1448. begin
  1449. Source.ReadChunkData(Chunk);
  1450. Output := Format('%sRange of %d', [ID, Chunk^.Data.ShadowRange^]);
  1451. Strings.Add(Output);
  1452. end;
  1453. SHADOW_FILTER:
  1454. begin
  1455. Source.ReadChunkData(Chunk);
  1456. Output := Format('%sFilter of %f', [ID, Chunk^.Data.ShadowFilter^]);
  1457. Strings.Add(Output);
  1458. end;
  1459. O_CONSTS:
  1460. begin
  1461. Source.ReadChunkData(Chunk);
  1462. Output := Format('%sPlane at %f, %f, %f',
  1463. [ID, Chunk^.Data.OConsts^.X, Chunk^.Data.OConsts^.Y, Chunk^.Data.OConsts^.Z]);
  1464. Strings.Add(Output);
  1465. end;
  1466. FOG:
  1467. begin
  1468. Source.ReadChunkData(Chunk);
  1469. Output := Format('%sNear plane at %f', [ID, Chunk^.Data.Fog^.NearPlaneDist]);
  1470. Strings.Add(Output);
  1471. Output := Format('%sNear Density of %f',
  1472. [ID, Chunk^.Data.Fog^.NearPlaneDensity]);
  1473. Strings.Add(Output);
  1474. Output := Format('%sFar plane at %f', [ID, Chunk^.Data.Fog^.FarPlaneDist]);
  1475. Strings.Add(Output);
  1476. Output := Format('%sFar Density of %f',
  1477. [ID, Chunk^.Data.Fog^.FarPlaneDensity]);
  1478. Strings.Add(Output);
  1479. end;
  1480. LAYER_FOG:
  1481. begin
  1482. Source.ReadChunkData(Chunk);
  1483. Output := Format('%sFog Z range is %f to %f',
  1484. [ID, Chunk^.Data.LayerFog^.ZMin, Chunk^.Data.LayerFog^.ZMax]);
  1485. Strings.Add(Output);
  1486. Output := Format('%sFog Density is %f', [ID, Chunk^.Data.LayerFog^.Density]);
  1487. Strings.Add(Output);
  1488. Output := Format('%sFog type of $%x', [ID, Chunk^.Data.LayerFog^.AType]);
  1489. Strings.Add(Output);
  1490. end;
  1491. DISTANCE_CUE:
  1492. begin
  1493. Source.ReadChunkData(Chunk);
  1494. Output := Format('%sNear plane at %f',
  1495. [ID, Chunk^.Data.DistanceCue^.NearPlaneDist]);
  1496. Strings.Add(Output);
  1497. Output := Format('%sNear Density of %f',
  1498. [ID, Chunk^.Data.DistanceCue^.NearPlaneDimming]);
  1499. Strings.Add(Output);
  1500. Output := Format('%sFar plane at %f',
  1501. [ID, Chunk^.Data.DistanceCue^.FarPlaneDist]);
  1502. Strings.Add(Output);
  1503. Output := Format('%sFar Density of %f',
  1504. [ID, Chunk^.Data.DistanceCue^.FarPlaneDimming]);
  1505. Strings.Add(Output);
  1506. end;
  1507. VIEW_TOP,
  1508. VIEW_BOTTOM,
  1509. VIEW_LEFT,
  1510. VIEW_RIGHT,
  1511. VIEW_FRONT,
  1512. VIEW_BACK:
  1513. begin
  1514. Source.ReadChunkData(Chunk);
  1515. Output := Format('%sTarget at %f, %f, %f',
  1516. [ID, Chunk^.Data.ViewStandard^.ViewTargetCoord.X,
  1517. Chunk^.Data.ViewStandard^.ViewTargetCoord.Y,
  1518. Chunk^.Data.ViewStandard^.ViewTargetCoord.Z]);
  1519. Strings.Add(Output);
  1520. Output := Format('%sView Width of %f',
  1521. [ID, Chunk^.Data.ViewStandard^.ViewWidth]);
  1522. Strings.Add(Output);
  1523. end;
  1524. VIEW_USER:
  1525. begin
  1526. Source.ReadChunkData(Chunk);
  1527. Output := Format('%sTarget at %f, %f, %f',
  1528. [ID, Chunk^.Data.ViewUser^.ViewTargetCoord.X,
  1529. Chunk^.Data.ViewUser^.ViewTargetCoord.Y,
  1530. Chunk^.Data.ViewUser^.ViewTargetCoord.Z]);
  1531. Strings.Add(Output);
  1532. Output := Format('%sView Width of %f', [ID, Chunk^.Data.ViewUser^.ViewWidth]);
  1533. Strings.Add(Output);
  1534. Output := Format('%sHorizontal View angle of %f',
  1535. [ID, Chunk^.Data.ViewUser^.XYViewAngle]);
  1536. Strings.Add(Output);
  1537. Output := Format('%sVertical View angle of %f',
  1538. [ID, Chunk^.Data.ViewUser^.YZViewAngle]);
  1539. Strings.Add(Output);
  1540. Output := Format('%sBank angle of %f', [ID, Chunk^.Data.ViewUser^.BankAngle]);
  1541. Strings.Add(Output);
  1542. end;
  1543. VIEW_CAMERA:
  1544. begin
  1545. Source.ReadChunkData(Chunk);
  1546. Output := Format('%sCamera Name %s', [ID, Chunk^.Data.ViewCamera^]);
  1547. Strings.Add(Output);
  1548. end;
  1549. NAMED_OBJECT:
  1550. begin
  1551. Source.ReadChunkData(Chunk);
  1552. Output := Format('%sName: %s', [ID, Chunk^.Data.NamedObject^]);
  1553. Strings.Add(Output);
  1554. end;
  1555. POINT_ARRAY:
  1556. begin
  1557. Source.ReadChunkData(Chunk);
  1558. Output := Format('%s%d Vertices', [ID, Chunk^.Data.PointArray^.Vertices]);
  1559. Strings.Add(Output);
  1560. if DumpLevel = dlMaximumDump then
  1561. for I := 0 to Chunk^.Data.PointArray^.Vertices - 1 do
  1562. begin
  1563. Output := Format('%sVertex %d at %f, %f, %f',
  1564. [ID, I, Chunk^.Data.PointArray^.PointList^[I].X,
  1565. Chunk^.Data.PointArray^.PointList^[I].Y,
  1566. Chunk^.Data.PointArray^.PointList^[I].Z]);
  1567. Strings.Add(Output);
  1568. end;
  1569. end;
  1570. POINT_FLAG_ARRAY:
  1571. begin
  1572. Source.ReadChunkData(Chunk);
  1573. Output := Format('%sFlags: %d', [ID, Chunk^.Data.PointFlagArray^.Flags]);
  1574. Strings.Add(Output);
  1575. if DumpLevel = dlMaximumDump then
  1576. for I := 0 to Chunk^.Data.PointFlagArray^.Flags - 1 do
  1577. begin
  1578. Output := Format('%sFlag %d is %d',
  1579. [ID, I, Chunk^.Data.PointFlagArray^.FlagList^[I]]);
  1580. Strings.Add(Output);
  1581. end;
  1582. end;
  1583. FACE_ARRAY:
  1584. begin
  1585. Source.ReadChunkData(Chunk);
  1586. Output := Format('%s%d Faces', [ID, Chunk^.Data.FaceArray^.Faces]);
  1587. Strings.Add(Output);
  1588. if DumpLevel = dlMaximumDump then
  1589. for I := 0 to Chunk^.Data.FaceArray^.Faces - 1 do
  1590. begin
  1591. Output := Format('%sFace %d Vertices %d, %d, %d and flag $%x',
  1592. [ID, I, Chunk^.Data.FaceArray^.FaceList^[I].V1,
  1593. Chunk^.Data.FaceArray^.FaceList^[I].V2,
  1594. Chunk^.Data.FaceArray^.FaceList^[I].V3,
  1595. Chunk^.Data.FaceArray^.FaceList^[I].Flag]);
  1596. Strings.Add(Output);
  1597. end;
  1598. end;
  1599. MSH_MAT_GROUP:
  1600. begin
  1601. Source.ReadChunkData(Chunk);
  1602. Output := Format('%sMaterial Name of %s',
  1603. [ID, Chunk^.Data.MshMatGroup^.MatNameStr]);
  1604. Strings.Add(Output);
  1605. Output := Format('%sAssigned to %d Faces',
  1606. [ID, Chunk^.Data.MshMatGroup^.Faces]);
  1607. Strings.Add(Output);
  1608. end;
  1609. MSH_BOXMAP:
  1610. begin
  1611. Source.ReadChunkData(Chunk);
  1612. Output := Format('%sBoxmap consists of the following materials:', [ID]);
  1613. Strings.Add(Output);
  1614. for I := 0 to 5 do
  1615. begin
  1616. Output := Format('%s%s', [ID, Chunk^.Data.MshBoxmap^[I]]);
  1617. Strings.Add(Output);
  1618. end;
  1619. end;
  1620. TEX_VERTS:
  1621. begin
  1622. Source.ReadChunkData(Chunk);
  1623. Output := Format('%s%d Vertices', [ID, Chunk^.Data.TexVerts^.NumCoords]);
  1624. Strings.Add(Output);
  1625. if DumpLevel = dlMaximumDump then
  1626. begin
  1627. for I := 0 to Chunk^.Data.TexVerts^.NumCoords - 1 do
  1628. begin
  1629. Output := Format('%sVertex %d with tex vert of %f, %f',
  1630. [ID, I, Chunk^.Data.TexVerts^.TextVertList^[I].U,
  1631. Chunk^.Data.TexVerts^.TextVertList^[I].V]);
  1632. Strings.Add(Output);
  1633. end;
  1634. end;
  1635. end;
  1636. MESH_TEXTURE_INFO:
  1637. begin
  1638. Source.ReadChunkData(Chunk);
  1639. Output := Format('%sMap Type of %d',
  1640. [ID, Chunk^.Data.MeshTextureInfo^.MapType]);
  1641. Strings.Add(Output);
  1642. Output := Format('%sX Tiling of %f',
  1643. [ID, Chunk^.Data.MeshTextureInfo^.XTiling]);
  1644. Strings.Add(Output);
  1645. Output := Format('%sY Tiling of %f',
  1646. [ID, Chunk^.Data.MeshTextureInfo^.YTiling]);
  1647. Strings.Add(Output);
  1648. Output := Format('%sIcon position of %f, %f, %f',
  1649. [ID, Chunk^.Data.MeshTextureInfo^.IconPos.X,
  1650. Chunk^.Data.MeshTextureInfo^.IconPos.Y,
  1651. Chunk^.Data.MeshTextureInfo^.IconPos.Z]);
  1652. Strings.Add(Output);
  1653. I := 0;
  1654. while I < 12 do
  1655. begin
  1656. Output := Format('%s[%d] %f [%d] %f [%d] %f',
  1657. [ID, I, Chunk^.Data.MeshTextureInfo^.XMatrix[I], I +
  1658. 1, Chunk^.Data.MeshTextureInfo^.XMatrix[I + 1], I +
  1659. 2, Chunk^.Data.MeshTextureInfo^.XMatrix[I + 2]]);
  1660. Strings.Add(Output);
  1661. Inc(I, 3);
  1662. end;
  1663. Output := Format('%sScaling Value of %f',
  1664. [ID, Chunk^.Data.MeshTextureInfo^.IconScaling]);
  1665. Strings.Add(Output);
  1666. Output := Format('%sPlanar Icon Width of %f',
  1667. [ID, Chunk^.Data.MeshTextureInfo^.IconWidth]);
  1668. Strings.Add(Output);
  1669. Output := Format('%sPlanar Icon Height of %f',
  1670. [ID, Chunk^.Data.MeshTextureInfo^.IconHeight]);
  1671. Strings.Add(Output);
  1672. Output := Format('%sCylinder Icon Height of %f',
  1673. [ID, Chunk^.Data.MeshTextureInfo^.CylIconHeight]);
  1674. Strings.Add(Output);
  1675. end;
  1676. MESH_MATRIX:
  1677. begin
  1678. Source.ReadChunkData(Chunk);
  1679. I := 0;
  1680. while I < 12 do
  1681. begin
  1682. Output := Format('%s[%d] %f [%d] %f [%d] %f',
  1683. [ID, I, Chunk^.Data.MeshMatrix^[I], I + 1,
  1684. Chunk^.Data.MeshMatrix^[I + 1], I + 2, Chunk^.Data.MeshMatrix^[I + 2]]);
  1685. Strings.Add(Output);
  1686. Inc(I, 3);
  1687. end;
  1688. end;
  1689. PROC_NAME:
  1690. begin
  1691. Source.ReadChunkData(Chunk);
  1692. Output := Format('%sProcedure Name of %s', [ID, Chunk^.Data.ProcName^]);
  1693. Strings.Add(Output);
  1694. end;
  1695. MESH_COLOR:
  1696. begin
  1697. Source.ReadChunkData(Chunk);
  1698. Output := Format('%sColor index of %d', [ID, Chunk^.Data.MeshColor^]);
  1699. Strings.Add(Output);
  1700. end;
  1701. N_DIRECT_LIGHT:
  1702. begin
  1703. Source.ReadChunkData(Chunk);
  1704. Output := Format('%sLight at %f, %f, %f',
  1705. [ID, Chunk^.Data.NDirectLight^.X, Chunk^.Data.NDirectLight^.Y,
  1706. Chunk^.Data.NDirectLight^.Z]);
  1707. Strings.Add(Output);
  1708. end;
  1709. DL_EXCLUDE:
  1710. begin
  1711. Source.ReadChunkData(Chunk);
  1712. Output := Format('%sExclude %s', [ID, Chunk^.Data.DLExclude^]);
  1713. Strings.Add(Output);
  1714. end;
  1715. DL_OUTER_RANGE,
  1716. DL_INNER_RANGE:
  1717. begin
  1718. Source.ReadChunkData(Chunk);
  1719. Output := Format('%sRange of %f', [ID, Chunk^.Data.DlOuterRange^]);
  1720. Strings.Add(Output);
  1721. end;
  1722. DL_MULTIPLIER:
  1723. begin
  1724. Source.ReadChunkData(Chunk);
  1725. Output := Format('%sMultiple of %f', [ID, Chunk^.Data.DlMultiplier^]);
  1726. Strings.Add(Output);
  1727. end;
  1728. DL_SPOT_ROLL:
  1729. begin
  1730. Source.ReadChunkData(Chunk);
  1731. Output := Format('%sRoll angle of %f', [ID, Chunk^.Data.DlSpotRoll^]);
  1732. Strings.Add(Output);
  1733. end;
  1734. DL_SPOT_ASPECT:
  1735. begin
  1736. Source.ReadChunkData(Chunk);
  1737. Output := Format('%sSpot aspect of %f', [ID, Chunk^.Data.DlSpotAspect^]);
  1738. Strings.Add(Output);
  1739. end;
  1740. DL_SPOT_PROJECTOR:
  1741. begin
  1742. Source.ReadChunkData(Chunk);
  1743. Output := Format('%sFilename of projector is %s',
  1744. [ID, Chunk^.Data.DlSpotProjector^]);
  1745. Strings.Add(Output);
  1746. end;
  1747. DL_RAY_BIAS:
  1748. begin
  1749. Source.ReadChunkData(Chunk);
  1750. Output := Format('%sBias of %f', [ID, Chunk^.Data.DlRayBias^]);
  1751. Strings.Add(Output);
  1752. end;
  1753. DL_SPOTLIGHT:
  1754. begin
  1755. Source.ReadChunkData(Chunk);
  1756. Output := Format('%sTarget at %f, %f, %f',
  1757. [ID, Chunk^.Data.DlSpotlight^.SpotlightTarg.X,
  1758. Chunk^.Data.DlSpotlight^.SpotlightTarg.Y,
  1759. Chunk^.Data.DlSpotlight^.SpotlightTarg.Z]);
  1760. Strings.Add(Output);
  1761. Output := Format('%sHotspot cone of %f, ',
  1762. [ID, Chunk^.Data.DlSpotlight^.HotspotAngle]);
  1763. Output := Output + Format(' Falloff cone of %f',
  1764. [Chunk^.Data.DlSpotlight^.FalloffAngle]);
  1765. Strings.Add(Output);
  1766. end;
  1767. DL_LOCAL_SHADOW2:
  1768. begin
  1769. Source.ReadChunkData(Chunk);
  1770. Output := Format('%sShadow bias of %f',
  1771. [ID, Chunk^.Data.DlLocalShadow2^.LocalShadowBias]);
  1772. Strings.Add(Output);
  1773. Output := Format('%sShadow filter of %f',
  1774. [ID, Chunk^.Data.DlLocalShadow2^.LocalShadowFilter]);
  1775. Strings.Add(Output);
  1776. Output := Format('%sShadow Map Size of %f',
  1777. [ID, Chunk^.Data.DlLocalShadow2^.LocalShadowMapSize]);
  1778. Strings.Add(Output);
  1779. end;
  1780. N_CAMERA:
  1781. begin
  1782. Source.ReadChunkData(Chunk);
  1783. Output := Format('%sCamera at %f, %f, %f',
  1784. [ID, Chunk^.Data.NCamera^.CameraPos.X, Chunk^.Data.NCamera^.CameraPos.Y,
  1785. Chunk^.Data.NCamera^.CameraPos.Z]);
  1786. Strings.Add(Output);
  1787. Output := Format('%sTarget at %f, %f, %f',
  1788. [ID, Chunk^.Data.NCamera^.TargetPos.X, Chunk^.Data.NCamera^.TargetPos.Y,
  1789. Chunk^.Data.NCamera^.TargetPos.Z]);
  1790. Strings.Add(Output);
  1791. Output := Format('%sBank angle of %f', [ID, Chunk^.Data.NCamera^.CameraBank]);
  1792. Output := Output + Format(' and a foc of %f',
  1793. [Chunk^.Data.NCamera^.CameraFocalLength]);
  1794. Strings.Add(Output);
  1795. end;
  1796. CAM_RANGES:
  1797. begin
  1798. Source.ReadChunkData(Chunk);
  1799. Output := Format('%sCamera near range is %f and far range is %f',
  1800. [ID, Chunk^.Data.CamRanges^.NearPlane, Chunk^.Data.CamRanges^.FarPlane]);
  1801. Strings.Add(Output);
  1802. end;
  1803. VIEWPORT_LAYOUT:
  1804. begin
  1805. Source.ReadChunkData(Chunk);
  1806. Output := Format('%sForm of %d', [ID, Chunk^.Data.ViewportLayout^.Form]);
  1807. Strings.Add(Output);
  1808. Output := Format('%sTop of %d', [ID, Chunk^.Data.ViewportLayout^.Top]);
  1809. Strings.Add(Output);
  1810. Output := Format('%sReady of %d', [ID, Chunk^.Data.ViewportLayout^.Ready]);
  1811. Strings.Add(Output);
  1812. Output := Format('%sWState of %d', [ID, Chunk^.Data.ViewportLayout^.WState]);
  1813. Strings.Add(Output);
  1814. Output := Format('%sSwap WS of %d', [ID, Chunk^.Data.ViewportLayout^.SwapWS]);
  1815. Strings.Add(Output);
  1816. Output := Format('%sSwap Port of %d',
  1817. [ID, Chunk^.Data.ViewportLayout^.SwapPort]);
  1818. Strings.Add(Output);
  1819. Output := Format('%sSwap Cur of %d',
  1820. [ID, Chunk^.Data.ViewportLayout^.SwapCur]);
  1821. Strings.Add(Output);
  1822. end;
  1823. VIEWPORT_SIZE:
  1824. begin
  1825. Source.ReadChunkData(Chunk);
  1826. Output := Format('%sWork Area X: %d Y: %d W: %d H: %d',
  1827. [ID, Chunk^.Data.ViewportSize^.XPos, Chunk^.Data.ViewportSize^.YPos,
  1828. Chunk^.Data.ViewportSize^.Width,
  1829. Chunk^.Data.ViewportSize^.Height]);
  1830. Strings.Add(Output);
  1831. end;
  1832. VIEWPORT_DATA_3,
  1833. VIEWPORT_DATA:
  1834. begin
  1835. Source.ReadChunkData(Chunk);
  1836. with Chunk^.Data.ViewportData^ do
  1837. begin
  1838. Output := Format('%sFlags: $%x', [ID, Flags]);
  1839. Strings.Add(Output);
  1840. Output := Format('%sAxis Lockouts of $%x', [ID, AxisLockout]);
  1841. Strings.Add(Output);
  1842. Output := Format('%sWindow Position of %d, %d', [ID, WinXPos, WinYPos]);
  1843. Strings.Add(Output);
  1844. Output := Format('%sWindow Size of %d, %d', [ID, WinWidth, WinHeight]);
  1845. Strings.Add(Output);
  1846. Output := Format('%sWindow View of %d', [ID, View]);
  1847. Strings.Add(Output);
  1848. Output := Format('%sZoom Factor of %f', [ID, ZoomFactor]);
  1849. Strings.Add(Output);
  1850. Output := Format('%sWorld Center of %f, %f, %f',
  1851. [ID, Center.X, Center.Y, Center.Z]);
  1852. Strings.Add(Output);
  1853. Output := Format('%sHorizontal Angle of %f', [ID, HorizAng]);
  1854. Strings.Add(Output);
  1855. Output := Format('%sVertical Angle of %f', [ID, VertAng]);
  1856. Strings.Add(Output);
  1857. Output := Format('%sCamera Name of %s', [ID, CamNameStr]);
  1858. Strings.Add(Output);
  1859. end;
  1860. end;
  1861. XDATA_APPNAME:
  1862. begin
  1863. Source.ReadChunkData(Chunk);
  1864. Output := Format('%sApplication Name %s', [ID, Chunk^.Data.XDataAppName^]);
  1865. Strings.Add(Output);
  1866. end;
  1867. XDATA_STRING:
  1868. begin
  1869. Source.ReadChunkData(Chunk);
  1870. Output := Format('%sString value of %s', [ID, Chunk^.Data.XDataString^]);
  1871. Strings.Add(Output);
  1872. end;
  1873. MAT_NAME:
  1874. begin
  1875. Source.ReadChunkData(Chunk);
  1876. Output := Format('%sMaterial Name %s', [ID, Chunk^.Data.MatName^]);
  1877. Strings.Add(Output);
  1878. end;
  1879. MAT_SHADING:
  1880. begin
  1881. Source.ReadChunkData(Chunk);
  1882. Output := Format('%sShading value of %d', [ID, Chunk^.Data.MatShading^]);
  1883. Strings.Add(Output);
  1884. end;
  1885. MAT_ACUBIC:
  1886. begin
  1887. Source.ReadChunkData(Chunk);
  1888. with Chunk^.Data.MatAcubic^ do
  1889. begin
  1890. Output := Format('%sShade level of %d', [ID, ShadeLevel]);
  1891. Strings.Add(Output);
  1892. Output := Format('%sAntialias level of %d', [ID, AntiAlias]);
  1893. Strings.Add(Output);
  1894. Output := Format('%sFlags: %d', [ID, Flags]);
  1895. Strings.Add(Output);
  1896. Output := Format('%sMap Size of %d', [ID, MapSize]);
  1897. Strings.Add(Output);
  1898. Output := Format('%sFrame skip of %d', [ID, FrameInterval]);
  1899. Strings.Add(Output);
  1900. end;
  1901. end;
  1902. MAT_MAPNAME:
  1903. begin
  1904. Source.ReadChunkData(Chunk);
  1905. Output := Format('%sMap Name %s', [ID, Chunk^.Data.MatMapname^]);
  1906. Strings.Add(Output);
  1907. end;
  1908. MAT_WIRESIZE:
  1909. begin
  1910. Source.ReadChunkData(Chunk);
  1911. Output := Format('%sWire frame Size of %f', [ID, Chunk^.Data.MatWireSize^]);
  1912. Strings.Add(Output);
  1913. end;
  1914. MAT_MAP_TILING:
  1915. begin
  1916. Source.ReadChunkData(Chunk);
  1917. Output := Format('%sMap Flags: ', [ID]);
  1918. if (Chunk^.Data.MatMapTiling^ = 0) then
  1919. Output := Output + ' NONE'
  1920. else
  1921. begin
  1922. if (Chunk^.Data.MatMapTiling^ and TEX_DECAL) <> 0 then
  1923. Output := Output + ' TEX_DECAL, ';
  1924. if (Chunk^.Data.MatMapTiling^ and TEX_MIRROR) <> 0 then
  1925. Output := Output + ' TEX_MIRROR, ';
  1926. if (Chunk^.Data.MatMapTiling^ and TEX_UNUSED1) <> 0 then
  1927. Output := Output + ' TEX_UNUSED1, ';
  1928. if (Chunk^.Data.MatMapTiling^ and TEX_INVERT) <> 0 then
  1929. Output := Output + ' TEX_INVERT, ';
  1930. if (Chunk^.Data.MatMapTiling^ and TEX_NOWRAP) <> 0 then
  1931. Output := Output + ' TEX_NOWRAP, ';
  1932. if (Chunk^.Data.MatMapTiling^ and TEX_SAT) <> 0 then
  1933. Output := Output + ' TEX_SAT, ';
  1934. if (Chunk^.Data.MatMapTiling^ and TEX_ALPHA_SOURCE) <> 0 then
  1935. Output := Output + ' TEX_ALPHA_SOURCE, ';
  1936. if (Chunk^.Data.MatMapTiling^ and TEX_TINT) <> 0 then
  1937. Output := Output + ' TEX_TINT, ';
  1938. if (Chunk^.Data.MatMapTiling^ and TEX_DONT_USE_ALPHA) <> 0 then
  1939. Output := Output + ' TEX_DONT_USE_ALPHA, ';
  1940. if (Chunk^.Data.MatMapTiling^ and TEX_RGB_TINT) <> 0 then
  1941. Output := Output + ' TEX_RGB_TINT, ';
  1942. Delete(Output, Length(Output) - 1, 2); // take the last comma out
  1943. end;
  1944. Strings.Add(Output);
  1945. end;
  1946. MAT_MAP_COL1:
  1947. begin
  1948. Source.ReadChunkData(Chunk);
  1949. Output := Format('%sColor R: %d, ', [ID, Chunk^.Data.MatMapCol1^.Red]);
  1950. Output := Output + Format(' G: %d, ', [Chunk^.Data.MatMapCol1^.Green]);
  1951. Output := Output + Format(' B: %d', [Chunk^.Data.MatMapCol1^.Blue]);
  1952. Strings.Add(Output);
  1953. end;
  1954. MAT_MAP_COL2:
  1955. begin
  1956. Source.ReadChunkData(Chunk);
  1957. Output := Format('%sColor R: %d, ', [ID, Chunk^.Data.MatMapCol2^.Red]);
  1958. Output := Output + Format(' G: %d, ', [Chunk^.Data.MatMapCol2^.Green]);
  1959. Output := Output + Format(' B: %d', [Chunk^.Data.MatMapCol2^.Blue]);
  1960. Strings.Add(Output);
  1961. end;
  1962. MAT_MAP_RCOL:
  1963. begin
  1964. Source.ReadChunkData(Chunk);
  1965. Output := Format('%sColor R: %d, ', [ID, Chunk^.Data.MatMapRCol^.Red]);
  1966. Output := Output + Format(' G: %d, ', [Chunk^.Data.MatMapRCol^.Green]);
  1967. Output := Output + Format(' B: %d', [Chunk^.Data.MatMapRCol^.Blue]);
  1968. Strings.Add(Output);
  1969. end;
  1970. MAT_MAP_GCOL:
  1971. begin
  1972. Source.ReadChunkData(Chunk);
  1973. Output := Format('%sColor R: %d, ', [ID, Chunk^.Data.MatMapGCol^.Red]);
  1974. Output := Output + Format(' G: %d, ', [Chunk^.Data.MatMapGCol^.Green]);
  1975. Output := Output + Format(' B: %d', [Chunk^.Data.MatMapGCol^.Blue]);
  1976. Strings.Add(Output);
  1977. end;
  1978. MAT_MAP_BCOL:
  1979. begin
  1980. Source.ReadChunkData(Chunk);
  1981. Output := Format('%sColor R: %d, ', [ID, Chunk^.Data.MatMapBCol^.Red]);
  1982. Output := Output + Format(' G: %d, ', [Chunk^.Data.MatMapBCol^.Green]);
  1983. Output := Output + Format(' B: %d', [Chunk^.Data.MatMapBCol^.Blue]);
  1984. Strings.Add(Output);
  1985. end;
  1986. MAT_MAP_TEXBLUR:
  1987. begin
  1988. Source.ReadChunkData(Chunk);
  1989. Output := Format('%sMap bluring of %f', [ID, Chunk^.Data.MatMapTexblur^]);
  1990. Strings.Add(Output);
  1991. end;
  1992. MAT_MAP_USCALE:
  1993. begin
  1994. Source.ReadChunkData(Chunk);
  1995. Output := Format('%sMap U scale of %f', [ID, Chunk^.Data.MatMapUScale^]);
  1996. Strings.Add(Output);
  1997. end;
  1998. MAT_MAP_VSCALE:
  1999. begin
  2000. Source.ReadChunkData(Chunk);
  2001. Output := Format('%sMap V scale of %f', [ID, Chunk^.Data.MatMapVScale^]);
  2002. Strings.Add(Output);
  2003. end;
  2004. MAT_MAP_UOFFSET:
  2005. begin
  2006. Source.ReadChunkData(Chunk);
  2007. Output := Format('%sMap U offset of %f', [ID, Chunk^.Data.MatMapUOffset^]);
  2008. Strings.Add(Output);
  2009. end;
  2010. MAT_MAP_VOFFSET:
  2011. begin
  2012. Source.ReadChunkData(Chunk);
  2013. Output := Format('%sMap V offset of %f', [ID, Chunk^.Data.MatMapVOffset^]);
  2014. Strings.Add(Output);
  2015. end;
  2016. MAT_MAP_ANG:
  2017. begin
  2018. Source.ReadChunkData(Chunk);
  2019. Output := Format('%sMap rotation angle of %f', [ID, Chunk^.Data.MatMapAng^]);
  2020. Strings.Add(Output);
  2021. end;
  2022. MAT_BUMP_PERCENT:
  2023. begin
  2024. Source.ReadChunkData(Chunk);
  2025. Output := Format('%sPercentage of %d%%', [ID, Chunk^.Data.MatBumpPercent^]);
  2026. Strings.Add(Output);
  2027. end;
  2028. KFHDR:
  2029. begin
  2030. Source.ReadChunkData(Chunk);
  2031. Output := Format('%sRevision level of $%x', [ID, Chunk^.Data.KFHdr^.Revision]);
  2032. Strings.Add(Output);
  2033. Output := Format('%sFilename %s', [ID, Chunk^.Data.KFHdr^.FileName]);
  2034. Strings.Add(Output);
  2035. Output := Format('%sAnimation length of %d',
  2036. [ID, Chunk^.Data.KFHdr^.AnimLength]);
  2037. Strings.Add(Output);
  2038. end;
  2039. KFSEG:
  2040. begin
  2041. Source.ReadChunkData(Chunk);
  2042. Output := Format('%sSegment starts at %d and ends at %d',
  2043. [ID, Chunk^.Data.KFSeg^.First, Chunk^.Data.KFSeg^.Last]);
  2044. Strings.Add(Output);
  2045. end;
  2046. KFCURTIME:
  2047. begin
  2048. Source.ReadChunkData(Chunk);
  2049. Output := Format('%sCurrent frame is %d', [ID, Chunk^.Data.KFCurtime^]);
  2050. Strings.Add(Output);
  2051. end;
  2052. NODE_ID:
  2053. begin
  2054. Source.ReadChunkData(Chunk);
  2055. Output := Format('%sNode ID: %d', [ID, Chunk^.Data.KFID^]);
  2056. Strings.Add(Output);
  2057. end;
  2058. NODE_HDR:
  2059. begin
  2060. Source.ReadChunkData(Chunk);
  2061. Strings.Add(Format('%sObject Name: %s',
  2062. [ID, Chunk^.Data.NodeHdr^.ObjNameStr]));
  2063. //--- Flags 1
  2064. Strings.Add(Format('%sFlags 1: $%x', [ID, Chunk^.Data.NodeHdr^.Flags1]));
  2065. if DumpLevel = dlMaximumDump then
  2066. with Chunk^.Data.NodeHdr^ do
  2067. begin
  2068. if (Flags1 and NODE_RENDOB_HIDE) <> 0 then
  2069. Strings.Add(Format('%sNODE_RENDOB_HIDE', [ID]));
  2070. if (Flags1 and NODE_OFF) <> 0 then
  2071. Strings.Add(Format('%sNODE_OFF', [ID]));
  2072. if (Flags1 and ATKEY1) <> 0 then
  2073. Strings.Add(Format('%sATKEY1', [ID]));
  2074. if (Flags1 and ATKEY2) <> 0 then
  2075. Strings.Add(Format('%sATKEY2', [ID]));
  2076. if (Flags1 and ATKEY3) <> 0 then
  2077. Strings.Add(Format('%sATKEY3', [ID]));
  2078. if (Flags1 and ATKEY4) <> 0 then
  2079. Strings.Add(Format('%sATKEY4', [ID]));
  2080. if (Flags1 and ATKEY5) <> 0 then
  2081. Strings.Add(Format('%sATKEY5', [ID]));
  2082. if (Flags1 and ATKEYFLAGS) <> 0 then
  2083. Strings.Add(Format('%sATKEYFLAGS', [ID]));
  2084. if (Flags1 and MARK_NODE) <> 0 then
  2085. Strings.Add(Format('%sMARK_NODE', [ID]));
  2086. if (Flags1 and DISABLE_NODE) <> 0 then
  2087. Strings.Add(Format('%sDISABLE_NODE', [ID]));
  2088. if (Flags1 and HIDE_NODE) <> 0 then
  2089. Strings.Add(Format('%sHIDE_NODE', [ID]));
  2090. if (Flags1 and FAST_NODE) <> 0 then
  2091. Strings.Add(Format('%sFAST_NODE', [ID]));
  2092. if (Flags1 and PRIMARY_NODE) <> 0 then
  2093. Strings.Add(Format('%sPRIMARY_NODE', [ID]));
  2094. if (Flags1 and NODE_CALC_PATH) <> 0 then
  2095. Strings.Add(Format('%sNODE_CALC_PATH', [ID]));
  2096. end;
  2097. //--- Flags 2
  2098. Strings.Add(Format('%sFlags 2: $%x', [ID, Chunk^.Data.NodeHdr^.Flags2]));
  2099. if DumpLevel = dlMaximumDump then
  2100. with Chunk^.Data.NodeHdr^ do
  2101. begin
  2102. if (Flags2 and NODE_HAS_PATH) <> 0 then
  2103. Strings.Add(Format('%sNODE_HAS_PATH', [ID]));
  2104. if (Flags2 and NODE_AUTO_SMOOTH) <> 0 then
  2105. Strings.Add(Format('%sNODE_AUTO_SMOOTH', [ID]));
  2106. if (Flags2 and NODE_FROZEN) <> 0 then
  2107. Strings.Add(Format('%sNODE_FROZEN', [ID]));
  2108. if (Flags2 and NODE_ANI_HIDDEN) <> 0 then
  2109. Strings.Add(Format('%sNODE_ANI_HIDDEN', [ID]));
  2110. if (Flags2 and NODE_MOTION_BLUR) <> 0 then
  2111. Strings.Add(Format('%sNODE_MOTION_BLUR', [ID]));
  2112. if (Flags2 and NODE_BLUR_BRANCH) <> 0 then
  2113. Strings.Add(Format('%sNODE_BLUR_BRANCH', [ID]));
  2114. if (Flags2 and NODE_MORPH_MTL) <> 0 then
  2115. Strings.Add(Format('%sNODE_MORPH_MTL', [ID]));
  2116. if (Flags2 and NODE_MORPH_OB) <> 0 then
  2117. Strings.Add(Format('%sNODE_MORPH_OB', [ID]));
  2118. end;
  2119. if Chunk^.Data.NodeHdr^.ParentIndex = -1 then
  2120. Strings.Add(Format('%sNo Parent', [ID]))
  2121. else
  2122. Strings.Add(Format('%sParent %d', [ID, Chunk^.Data.NodeHdr^.ParentIndex]));
  2123. end;
  2124. INSTANCE_NAME:
  2125. begin
  2126. Source.ReadChunkData(Chunk);
  2127. Output := Format('%sInstance Name: %s', [ID, Chunk^.Data.InstanceName^]);
  2128. Strings.Add(Output);
  2129. end;
  2130. PARENT_NAME:
  2131. begin
  2132. Source.ReadChunkData(Chunk);
  2133. if Chunk^.Data.InstanceName = nil then
  2134. Strings.Add(Format('%sNo Parent', [ID]))
  2135. else
  2136. Strings.Add(Format('%sParent Name: %s', [ID, Chunk^.Data.InstanceName^]));
  2137. end;
  2138. PIVOT:
  2139. begin
  2140. Source.ReadChunkData(Chunk);
  2141. Output := Format('%sPivot at %f, %f, %f',
  2142. [ID, Chunk^.Data.Pivot^.X, Chunk^.Data.Pivot^.Y,
  2143. Chunk^.Data.Pivot^.Z]);
  2144. Strings.Add(Output);
  2145. end;
  2146. BOUNDBOX:
  2147. if Assigned(Chunk^.Data.Dummy) then
  2148. begin
  2149. Output := Format('%sMinimum at %f, %f, %f',
  2150. [ID, Chunk^.Data.BoundBox^.Min.X, Chunk^.Data.BoundBox^.Min.Y,
  2151. Chunk^.Data.BoundBox^.Min.Z]);
  2152. Strings.Add(Output);
  2153. Output := Format('%sMaximum at %f, %f, %f',
  2154. [ID, Chunk^.Data.BoundBox^.Max.X, Chunk^.Data.BoundBox^.Max.Y,
  2155. Chunk^.Data.BoundBox^.Max.Z]);
  2156. Strings.Add(Output);
  2157. end;
  2158. MORPH_SMOOTH:
  2159. begin
  2160. Source.ReadChunkData(Chunk);
  2161. Output := Format('%sMorph Smoothing Angle of %f',
  2162. [ID, Chunk^.Data.MorphSmooth^]);
  2163. Strings.Add(Output);
  2164. end;
  2165. POS_TRACK_TAG:
  2166. begin
  2167. Source.ReadChunkData(Chunk);
  2168. Output := Format('%s%d Keys, Flags: $%x',
  2169. [ID, Chunk^.Data.PosTrackTag^.TrackHdr.KeyCount,
  2170. Chunk^.Data.PosTrackTag^.TrackHdr.Flags]);
  2171. Strings.Add(Output);
  2172. for I := 0 to Chunk^.Data.PosTrackTag^.TrackHdr.KeyCount - 1 do
  2173. begin
  2174. DumpKeyHeader(Strings, Chunk^.Data.PosTrackTag^.KeyHdrList^[I],
  2175. IndentLevel + 1);
  2176. Output := Format('%sObject at %f, %f, %f',
  2177. [ID, Chunk^.Data.PosTrackTag^.PositionList^[I].X,
  2178. Chunk^.Data.PosTrackTag^.PositionList^[I].Y,
  2179. Chunk^.Data.PosTrackTag^.PositionList^[I].Z]);
  2180. Strings.Add(Output);
  2181. end;
  2182. end;
  2183. ROT_TRACK_TAG:
  2184. begin
  2185. Source.ReadChunkData(Chunk);
  2186. Output := Format('%s%d Keys, Flags: $%x',
  2187. [ID, Chunk^.Data.RotTrackTag^.TrackHdr.KeyCount,
  2188. Chunk^.Data.RotTrackTag^.TrackHdr.Flags]);
  2189. Strings.Add(Output);
  2190. for I := 0 to Chunk^.Data.RotTrackTag^.TrackHdr.KeyCount - 1 do
  2191. begin
  2192. DumpKeyHeader(Strings, Chunk^.Data.RotTrackTag^.KeyHdrList^[I],
  2193. IndentLevel + 1);
  2194. Output := Format('%sRotation of %f',
  2195. [ID, Chunk^.Data.RotTrackTag^.RotationList^[I].Angle]);
  2196. Strings.Add(Output);
  2197. Output := Format('%sAxis of %f, %f, %f',
  2198. [ID, Chunk^.Data.RotTrackTag^.RotationList^[I].X,
  2199. Chunk^.Data.RotTrackTag^.RotationList^[I].Y,
  2200. Chunk^.Data.RotTrackTag^.RotationList^[I].Z]);
  2201. Strings.Add(Output);
  2202. end;
  2203. end;
  2204. SCL_TRACK_TAG:
  2205. begin
  2206. Source.ReadChunkData(Chunk);
  2207. Output := Format('%s%d Keys, Flags: $%x',
  2208. [ID, Chunk^.Data.ScaleTrackTag^.TrackHdr.KeyCount,
  2209. Chunk^.Data.ScaleTrackTag^.TrackHdr.Flags]);
  2210. Strings.Add(Output);
  2211. for I := 0 to Chunk^.Data.ScaleTrackTag^.TrackHdr.KeyCount - 1 do
  2212. begin
  2213. DumpKeyHeader(Strings, Chunk^.Data.ScaleTrackTag^.KeyHdrList^[I],
  2214. IndentLevel + 1);
  2215. Output := Format('%sScale of %f, %f, %f',
  2216. [ID, Chunk^.Data.ScaleTrackTag^.ScaleList^[I].X,
  2217. Chunk^.Data.ScaleTrackTag^.ScaleList^[I].Y,
  2218. Chunk^.Data.ScaleTrackTag^.ScaleList^[I].Z]);
  2219. Strings.Add(Output);
  2220. end;
  2221. end;
  2222. FOV_TRACK_TAG:
  2223. begin
  2224. Source.ReadChunkData(Chunk);
  2225. Output := Format('%s%d Keys, Flags: $%x',
  2226. [ID, Chunk^.Data.FovTrackTag^.TrackHdr.KeyCount,
  2227. Chunk^.Data.FovTrackTag^.TrackHdr.Flags]);
  2228. Strings.Add(Output);
  2229. for I := 0 to Chunk^.Data.FovTrackTag^.TrackHdr.KeyCount - 1 do
  2230. begin
  2231. DumpKeyHeader(Strings, Chunk^.Data.FovTrackTag^.KeyHdrList^[I],
  2232. IndentLevel + 1);
  2233. Output := Format('%sCamera FOV of %f',
  2234. [ID, Chunk^.Data.FovTrackTag^.FOVAngleList^[I]]);
  2235. Strings.Add(Output);
  2236. end;
  2237. end;
  2238. ROLL_TRACK_TAG:
  2239. begin
  2240. Source.ReadChunkData(Chunk);
  2241. Output := Format('%s%d Keys, Flags: $%x',
  2242. [ID, Chunk^.Data.RollTrackTag^.TrackHdr.KeyCount,
  2243. Chunk^.Data.RollTrackTag^.TrackHdr.Flags]);
  2244. Strings.Add(Output);
  2245. for I := 0 to Chunk^.Data.RollTrackTag^.TrackHdr.KeyCount - 1 do
  2246. begin
  2247. DumpKeyHeader(Strings, Chunk^.Data.RollTrackTag^.KeyHdrList^[I],
  2248. IndentLevel + 1);
  2249. Output := Format('%sCamera Roll of %f',
  2250. [ID, Chunk^.Data.RollTrackTag^.RollAngleList^[I]]);
  2251. Strings.Add(Output);
  2252. end;
  2253. end;
  2254. COL_TRACK_TAG:
  2255. begin
  2256. Source.ReadChunkData(Chunk);
  2257. Output := Format('%s%d Keys, Flags: $%x',
  2258. [ID, Chunk^.Data.ColTrackTag^.TrackHdr.KeyCount,
  2259. Chunk^.Data.ColTrackTag^.TrackHdr.Flags]);
  2260. Strings.Add(Output);
  2261. for I := 0 to Chunk^.Data.ColTrackTag^.TrackHdr.KeyCount - 1 do
  2262. begin
  2263. DumpKeyHeader(Strings, Chunk^.Data.ColTrackTag^.KeyHdrList^[I],
  2264. IndentLevel + 1);
  2265. Output := Format('%sColor R: %f, ',
  2266. [ID, Chunk^.Data.ColTrackTag^.ColorList^[I].B]);
  2267. Output := Output + Format(' G: %f, ',
  2268. [Chunk^.Data.ColTrackTag^.ColorList^[I].G]);
  2269. Output := Output + Format(' B: %f',
  2270. [Chunk^.Data.ColTrackTag^.ColorList^[I].B]);
  2271. Strings.Add(Output);
  2272. end;
  2273. end;
  2274. MORPH_TRACK_TAG:
  2275. begin
  2276. Source.ReadChunkData(Chunk);
  2277. Output := Format('%s%d Keys, Flags: $%x',
  2278. [ID, Chunk^.Data.MorphTrackTag^.TrackHdr.KeyCount,
  2279. Chunk^.Data.MorphTrackTag^.TrackHdr.Flags]);
  2280. Strings.Add(Output);
  2281. for I := 0 to Chunk^.Data.MorphTrackTag^.TrackHdr.KeyCount - 1 do
  2282. begin
  2283. DumpKeyHeader(Strings, Chunk^.Data.MorphTrackTag^.KeyHdrList^[I],
  2284. IndentLevel + 1);
  2285. Output := Format('%sMorph to %s',
  2286. [ID, Chunk^.Data.MorphTrackTag^.MorphList^[I]]);
  2287. Strings.Add(Output);
  2288. end;
  2289. end;
  2290. HOT_TRACK_TAG:
  2291. begin
  2292. Source.ReadChunkData(Chunk);
  2293. Output := Format('%s%d Keys, Flags: $%x',
  2294. [ID, Chunk^.Data.HotTrackTag^.TrackHdr.KeyCount,
  2295. Chunk^.Data.HotTrackTag^.TrackHdr.Flags]);
  2296. Strings.Add(Output);
  2297. for I := 0 to Chunk^.Data.HotTrackTag^.TrackHdr.KeyCount - 1 do
  2298. begin
  2299. DumpKeyHeader(Strings, Chunk^.Data.HotTrackTag^.KeyHdrList^[I],
  2300. IndentLevel + 1);
  2301. Output := Format('%sHotspot angle of %f',
  2302. [ID, Chunk^.Data.HotTrackTag^.HotspotAngleList^[I]]);
  2303. Strings.Add(Output);
  2304. end;
  2305. end;
  2306. FALL_TRACK_TAG:
  2307. begin
  2308. Source.ReadChunkData(Chunk);
  2309. Output := Format('%s%d Keys, Flags: $%x',
  2310. [ID, Chunk^.Data.FallTrackTag^.TrackHdr.KeyCount,
  2311. Chunk^.Data.FallTrackTag^.TrackHdr.Flags]);
  2312. Strings.Add(Output);
  2313. for I := 0 to Chunk^.Data.FallTrackTag^.TrackHdr.KeyCount - 1 do
  2314. begin
  2315. DumpKeyHeader(Strings, Chunk^.Data.FallTrackTag^.KeyHdrList^[I],
  2316. IndentLevel + 1);
  2317. Output := Format('%sFalloff Angle of %f',
  2318. [ID, Chunk^.Data.FallTrackTag^.FalloffAngleList^[I]]);
  2319. Strings.Add(Output);
  2320. end;
  2321. end;
  2322. HIDE_TRACK_TAG:
  2323. begin
  2324. Source.ReadChunkData(Chunk);
  2325. Output := Format('%s%d Keys, Flags: $%x',
  2326. [ID, Chunk^.Data.HideTrackTag^.TrackHdr.KeyCount,
  2327. Chunk^.Data.HideTrackTag^.TrackHdr.Flags]);
  2328. Strings.Add(Output);
  2329. for I := 0 to Chunk^.Data.HideTrackTag^.TrackHdr.KeyCount - 1 do
  2330. DumpKeyHeader(Strings, Chunk^.Data.HideTrackTag^.KeyHdrList^[I],
  2331. IndentLevel + 1);
  2332. end;
  2333. end; // end case
  2334. end;
  2335. Child := Chunk^.Children;
  2336. while Assigned(Child) do
  2337. begin
  2338. DumpChunk(Source, Strings, Child, IndentLevel + 1, DumpLevel);
  2339. Child := Child^.Sibling;
  2340. end;
  2341. end;
  2342. //----------------- common support function ---------------------------------------------------------------------------
  2343. procedure AddChild(Parent, Child: PChunk3DS);
  2344. // AddChild puts the chunk at the end of the Sibling list
  2345. var
  2346. Current: PChunk3DS;
  2347. begin
  2348. if Parent^.Children = nil then
  2349. Parent^.Children := Child
  2350. else
  2351. begin
  2352. Current := Parent^.Children;
  2353. while Assigned(Current^.Sibling) do
  2354. Current := Current^.Sibling;
  2355. Current^.Sibling := Child;
  2356. end;
  2357. end;
  2358. //---------------------------------------------------------------------------------------------------------------------
  2359. procedure AddChildOrdered(Parent, Child: PChunk3DS);
  2360. // AddChildOrdered will insert the child among its siblings depending
  2361. // on the order of occurance set by the 3DS file.
  2362. var
  2363. Current, Prev: PChunk3DS;
  2364. ChildValue: integer;
  2365. begin
  2366. ChildValue := GetChunkValue(Child^.Tag);
  2367. if Parent^.Children = nil then
  2368. Parent^.Children := Child
  2369. else
  2370. begin
  2371. Current := Parent^.Children;
  2372. Prev := nil;
  2373. while Assigned(Current^.Sibling) do
  2374. begin
  2375. if ChildValue > GetChunkValue(Current^.Tag) then
  2376. break;
  2377. Prev := Current;
  2378. Current := Current^.Sibling;
  2379. end;
  2380. if ChildValue > GetChunkValue(Current^.Tag) then
  2381. begin
  2382. Child^.Sibling := Current;
  2383. if Assigned(Prev) then
  2384. Prev^.Sibling := Child
  2385. else
  2386. Parent^.Children := Child;
  2387. end
  2388. else
  2389. begin
  2390. Child^.Sibling := Current^.Sibling;
  2391. Current^.Sibling := Child;
  2392. end;
  2393. end;
  2394. end;
  2395. //---------------------------------------------------------------------------------------------------------------------
  2396. function FindChunk(Top: PChunk3DS; Tag: word): PChunk3DS;
  2397. // searchs the given top Chunk and its children for a match
  2398. var
  2399. Child, Match: PChunk3DS;
  2400. begin
  2401. Result := nil;
  2402. if Assigned(Top) then
  2403. if Top^.Tag = Tag then
  2404. Result := Top
  2405. else
  2406. begin
  2407. Child := Top^.Children;
  2408. while Assigned(Child) do
  2409. begin
  2410. Match := FindChunk(Child, Tag);
  2411. if Assigned(Match) then
  2412. begin
  2413. Result := Match;
  2414. Break;
  2415. end;
  2416. Child := Child^.Sibling;
  2417. end;
  2418. end;
  2419. end;
  2420. //---------------------------------------------------------------------------------------------------------------------
  2421. function FindNextChunk(Local: PChunk3DS; Tag: word): PChunk3DS;
  2422. var
  2423. Current: PChunk3DS;
  2424. begin
  2425. Result := nil;
  2426. Current := Local;
  2427. while Assigned(Current) and (Result = nil) do
  2428. begin
  2429. if Current^.Tag = Tag then
  2430. Result := Current;
  2431. Current := Current^.Sibling;
  2432. end;
  2433. end;
  2434. //---------------------------------------------------------------------------------------------------------------------
  2435. procedure FreeChunkData(var Chunk: PChunk3DS);
  2436. begin
  2437. if Assigned(Chunk^.Data.Dummy) then
  2438. begin
  2439. // do only care about Chunk^.Data fields that contain other pointers
  2440. // that need to be free
  2441. case Chunk^.Tag of
  2442. MAT_SXP_TEXT_DATA,
  2443. MAT_SXP_TEXT2_DATA,
  2444. MAT_SXP_OPAC_DATA,
  2445. MAT_SXP_BUMP_DATA,
  2446. MAT_SXP_SPEC_DATA,
  2447. MAT_SXP_SHIN_DATA,
  2448. MAT_SXP_SELFI_DATA,
  2449. MAT_SXP_TEXT_MASKDATA,
  2450. MAT_SXP_TEXT2_MASKDATA,
  2451. MAT_SXP_OPAC_MASKDATA,
  2452. MAT_SXP_BUMP_MASKDATA,
  2453. MAT_SXP_SPEC_MASKDATA,
  2454. MAT_SXP_SHIN_MASKDATA,
  2455. MAT_SXP_SELFI_MASKDATA,
  2456. MAT_SXP_REFL_MASKDATA,
  2457. PROC_DATA:
  2458. FreeMem(Chunk^.Data.IpasData^.Data);
  2459. POINT_ARRAY:
  2460. FreeMem(Chunk^.Data.PointArray^.PointList);
  2461. POINT_FLAG_ARRAY:
  2462. FreeMem(Chunk^.Data.PointFlagArray^.FlagList);
  2463. FACE_ARRAY:
  2464. Freemem(Chunk^.Data.FaceArray^.FaceList);
  2465. MSH_MAT_GROUP:
  2466. begin
  2467. Dispose(Chunk^.Data.MshMatGroup);
  2468. Chunk^.Data.MshMatGroup := nil;
  2469. end;
  2470. SMOOTH_GROUP:
  2471. FreeMem(Chunk^.Data.SmoothGroup^.GroupList);
  2472. TEX_VERTS:
  2473. FreeMem(Chunk^.Data.TexVerts^.TextVertList);
  2474. XDATA_ENTRY:
  2475. FreeMem(Chunk^.Data.XDataEntry^.Data);
  2476. POS_TRACK_TAG:
  2477. begin
  2478. FreeMem(Chunk^.Data.PosTrackTag^.KeyHdrList);
  2479. Freemem(Chunk^.Data.PosTrackTag^.PositionList);
  2480. end;
  2481. COL_TRACK_TAG:
  2482. begin
  2483. FreeMem(Chunk^.Data.ColTrackTag^.KeyHdrList);
  2484. FreeMem(Chunk^.Data.ColTrackTag^.ColorList);
  2485. end;
  2486. ROT_TRACK_TAG:
  2487. begin
  2488. FreeMem(Chunk^.Data.RotTrackTag^.KeyHdrList);
  2489. FreeMem(Chunk^.Data.RotTrackTag^.RotationList);
  2490. end;
  2491. SCL_TRACK_TAG:
  2492. begin
  2493. FreeMem(Chunk^.Data.ScaleTrackTag^.KeyHdrList);
  2494. FreeMem(Chunk^.Data.ScaleTrackTag^.ScaleList);
  2495. end;
  2496. MORPH_TRACK_TAG:
  2497. begin
  2498. FreeMem(Chunk^.Data.MorphTrackTag^.KeyHdrList);
  2499. FreeMem(Chunk^.Data.MorphTrackTag^.MorphList);
  2500. end;
  2501. FOV_TRACK_TAG:
  2502. begin
  2503. FreeMem(Chunk^.Data.FovTrackTag^.KeyHdrList);
  2504. FreeMem(Chunk^.Data.FovTrackTag^.FOVAngleList);
  2505. end;
  2506. ROLL_TRACK_TAG:
  2507. begin
  2508. FreeMem(Chunk^.Data.RollTrackTag^.KeyHdrList);
  2509. FreeMem(Chunk^.Data.RollTrackTag^.RollAngleList);
  2510. end;
  2511. HOT_TRACK_TAG:
  2512. begin
  2513. FreeMem(Chunk^.Data.HotTrackTag^.KeyHdrList);
  2514. FreeMem(Chunk^.Data.HotTrackTag^.HotspotAngleList);
  2515. end;
  2516. FALL_TRACK_TAG:
  2517. begin
  2518. FreeMem(Chunk^.Data.FallTrackTag^.KeyHdrList);
  2519. FreeMem(Chunk^.Data.FallTrackTag^.FalloffAngleList);
  2520. end;
  2521. KFHDR:
  2522. begin
  2523. Dispose(Chunk^.Data.KFHdr);
  2524. Chunk^.Data.KFHdr := nil;
  2525. end;
  2526. NODE_HDR:
  2527. begin
  2528. Dispose(Chunk^.Data.NodeHdr);
  2529. Chunk^.Data.NodeHdr := nil;
  2530. end;
  2531. HIDE_TRACK_TAG:
  2532. FreeMem(Chunk^.Data.HideTrackTag^.KeyHdrList);
  2533. end; // case end
  2534. // finally free the data chunk
  2535. FreeMem(Chunk^.Data.Dummy);
  2536. Chunk^.Data.Dummy := nil;
  2537. end;
  2538. end;
  2539. //---------------------------------------------------------------------------------------------------------------------
  2540. procedure InitChunk(var Chunk: PChunk3DS);
  2541. // initializes and allocates memory for a chunk
  2542. begin
  2543. New(Chunk);
  2544. if Chunk = nil then
  2545. ShowError(strError3DS_NO_MEM);
  2546. // set default values
  2547. with Chunk^ do
  2548. begin
  2549. Tag := NULL_CHUNK;
  2550. Size := 0;
  2551. Position := 0;
  2552. Data.Dummy := nil;
  2553. Sibling := nil;
  2554. Children := nil;
  2555. end;
  2556. end;
  2557. //---------------------------------------------------------------------------------------------------------------------
  2558. procedure InitChunkList(var List: PChunklist3DS; Count: integer);
  2559. begin
  2560. if List = nil then
  2561. begin
  2562. List := AllocMem(SizeOf(TChunklist3DS));
  2563. if List = nil then
  2564. ShowError(strError3DS_NO_MEM);
  2565. end;
  2566. List^.Count := Count;
  2567. if Count > 0 then
  2568. begin
  2569. List^.List := AllocMem(Count * SizeOf(TChunkListEntry3DS));
  2570. if List^.List = nil then
  2571. ShowError(strError3DS_NO_MEM);
  2572. end;
  2573. end;
  2574. //---------------------------------------------------------------------------------------------------------------------
  2575. function PutGenericNode(TagID: word; ParentChunk: PChunk3DS): PChunk3DS;
  2576. // put a tag into database as a child of ParentChunk
  2577. begin
  2578. InitChunk(Result);
  2579. Result^.Tag := TagID;
  2580. AddChildOrdered(ParentChunk, Result);
  2581. end;
  2582. //---------------------------------------------------------------------------------------------------------------------
  2583. procedure ReleaseChunk(var Chunk: PChunk3DS);
  2584. var
  2585. Sibling: PChunk3DS;
  2586. begin
  2587. // free memory associated with chunk and substructure
  2588. while Assigned(Chunk) do
  2589. begin
  2590. Sibling := Chunk^.Sibling;
  2591. ReleaseChunk(Chunk^.Children);
  2592. FreeChunkData(Chunk);
  2593. FreeMem(Chunk);
  2594. Chunk := Sibling;
  2595. end;
  2596. end;
  2597. //---------------------------------------------------------------------------------------------------------------------
  2598. procedure ReleaseChunkList(var List: PChunkList3DS);
  2599. var
  2600. I: integer;
  2601. begin
  2602. if Assigned(List) then
  2603. begin
  2604. // tell the string management that we don't need these strings any longer
  2605. for I := 0 to List^.Count - 1 do
  2606. List^.List^[I].NameStr := '';
  2607. if Assigned(List^.List) then
  2608. FreeMem(List^.List);
  2609. FreeMem(List);
  2610. List := nil;
  2611. end;
  2612. end;
  2613. //---------------------------------------------------------------------------------------------------------------------
  2614. function CopyChunk(Chunk: PChunk3DS): PChunk3DS;
  2615. // copies the structure of Chunk to Result, assigned data of Chunk will not be copied, but
  2616. // moved to Result (actually references will be moved)
  2617. var
  2618. ChildIn: PChunk3DS;
  2619. ChildOut: ^PChunk3DS;
  2620. begin
  2621. if Chunk = nil then
  2622. ShowError(strERROR3DS_INVALID_ARG);
  2623. InitChunk(Result);
  2624. with Result^ do
  2625. begin
  2626. Tag := Chunk^.Tag;
  2627. Size := Chunk^.Size;
  2628. Position := Chunk^.Position;
  2629. if Assigned(Chunk^.Data.Dummy) then
  2630. begin
  2631. Data.Dummy := Chunk^.Data.Dummy;
  2632. Chunk^.Data.Dummy := nil;
  2633. end;
  2634. ChildIn := Chunk^.Children;
  2635. ChildOut := @Children;
  2636. while Assigned(ChildIn) do
  2637. begin
  2638. ChildOut^ := CopyChunk(ChildIn);
  2639. ChildIn := ChildIn^.Sibling;
  2640. ChildOut := @ChildOut^.Sibling;
  2641. end;
  2642. end;
  2643. end;
  2644. //----------------- list update routines ------------------------------------------------------------------------------
  2645. procedure UpdateMatEntryList(const Source: TFile3DS; var DB: TDatabase3DS);
  2646. var
  2647. Parent, MatName, MatEntry: PChunk3DS;
  2648. I, MatCount: integer;
  2649. begin
  2650. if DB.MatlistDirty then
  2651. begin
  2652. ReleaseChunkList(DB.MatList);
  2653. Parent := FindChunk(DB.TopChunk, MDATA);
  2654. if Parent = nil then
  2655. Parent := FindChunk(DB.TopChunk, MLIBMAGIC);
  2656. MatCount := 0;
  2657. if Assigned(Parent) then
  2658. begin
  2659. MatEntry := FindChunk(Parent, MAT_ENTRY);
  2660. while Assigned(MatEntry) do
  2661. begin
  2662. MatEntry := FindNextChunk(MatEntry^.Sibling, MAT_ENTRY);
  2663. Inc(MatCount);
  2664. end;
  2665. end;
  2666. InitChunkList(DB.MatList, MatCount);
  2667. if Parent = nil then
  2668. Exit;
  2669. I := 0;
  2670. MatEntry := FindChunk(Parent, MAT_ENTRY);
  2671. while Assigned(MatEntry) do
  2672. begin
  2673. MatName := FindChunk(MatEntry, MAT_NAME);
  2674. Source.ReadChunkData(MatName);
  2675. DB.MatList^.List^[I].Chunk := MatEntry;
  2676. DB.MatList^.List^[I].NameStr := string(MatName^.Data.MatName);
  2677. MatEntry := FindNextChunk(MatEntry^.Sibling, MAT_ENTRY);
  2678. Inc(I);
  2679. end;
  2680. DB.MatlistDirty := False;
  2681. end;
  2682. end;
  2683. //---------------------------------------------------------------------------------------------------------------------
  2684. procedure UpdateNamedObjectList(Source: TFile3DS; var DB: TDatabase3DS);
  2685. var
  2686. MDataChunk, Current: PChunk3DS;
  2687. I: integer;
  2688. begin
  2689. if DB.ObjListDirty then
  2690. begin
  2691. ReleaseChunkList(DB.ObjList);
  2692. MDataChunk := FindChunk(DB.TopChunk, MDATA);
  2693. I := 0;
  2694. if Assigned(MDataChunk) then
  2695. begin
  2696. Current := FindChunk(MDataChunk, NAMED_OBJECT);
  2697. while Assigned(Current) do
  2698. begin
  2699. Inc(I);
  2700. Current := FindNextChunk(Current^.Sibling, NAMED_OBJECT);
  2701. end;
  2702. end;
  2703. InitChunkList(DB.ObjList, I);
  2704. if MDataChunk = nil then
  2705. Exit;
  2706. I := 0;
  2707. Current := FindChunk(MDataChunk, NAMED_OBJECT);
  2708. while Assigned(Current) do
  2709. begin
  2710. Source.ReadChunkData(Current);
  2711. DB.ObjList^.List^[I].Chunk := Current;
  2712. DB.ObjList^.List^[I].NameStr := string(Current^.Data.NamedObject);
  2713. Current := FindNextChunk(Current^.Sibling, NAMED_OBJECT);
  2714. Inc(I);
  2715. end;
  2716. DB.ObjListDirty := False;
  2717. end;
  2718. end;
  2719. //---------------------------------------------------------------------------------------------------------------------
  2720. procedure UpdateNodeTagList(Source: TFile3DS; var DB: TDatabase3DS);
  2721. var
  2722. KFDataChunk, Chunk, Current: PChunk3DS;
  2723. I: integer;
  2724. begin
  2725. if DB.NodeListDirty then
  2726. begin
  2727. ReleaseChunkList(DB.NodeList);
  2728. KFDataChunk := FindChunk(DB.TopChunk, KFDATA);
  2729. I := 0;
  2730. // if there is a keyframe section then count the number of node tags
  2731. if Assigned(KFDataChunk) then
  2732. begin
  2733. Current := KFDataChunk^.Children;
  2734. while Assigned(Current) do
  2735. begin
  2736. case Current^.Tag of
  2737. AMBIENT_NODE_TAG,
  2738. OBJECT_NODE_TAG,
  2739. CAMERA_NODE_TAG,
  2740. TARGET_NODE_TAG,
  2741. LIGHT_NODE_TAG,
  2742. L_TARGET_NODE_TAG,
  2743. SPOTLIGHT_NODE_TAG:
  2744. Inc(I);
  2745. end;
  2746. Current := Current^.Sibling;
  2747. end;
  2748. end;
  2749. InitChunkList(DB.NodeList, I);
  2750. if I = 0 then
  2751. Exit;
  2752. I := 0;
  2753. Current := KFDataChunk^.Children;
  2754. while Assigned(Current) do
  2755. begin
  2756. case Current^.Tag of
  2757. AMBIENT_NODE_TAG,
  2758. OBJECT_NODE_TAG,
  2759. CAMERA_NODE_TAG,
  2760. TARGET_NODE_TAG,
  2761. LIGHT_NODE_TAG,
  2762. L_TARGET_NODE_TAG,
  2763. SPOTLIGHT_NODE_TAG:
  2764. begin
  2765. Chunk := FindNextChunk(Current^.Children, NODE_HDR);
  2766. if Assigned(Chunk) then
  2767. begin
  2768. Source.ReadChunkData(Chunk);
  2769. DB.NodeList^.List^[I].Chunk := Current;
  2770. DB.NodeList^.List^[I].NameStr := Chunk^.Data.NodeHdr^.ObjNameStr;
  2771. FreeChunkData(Chunk);
  2772. end;
  2773. // Object tags may have an instance name as well, which gets appended to
  2774. // the object name with a "." seperator
  2775. if Current^.Tag = OBJECT_NODE_TAG then
  2776. begin
  2777. Chunk := FindNextChunk(Current^.Children, INSTANCE_NAME);
  2778. if Assigned(Chunk) then
  2779. begin
  2780. Source.ReadChunkData(Chunk);
  2781. DB.NodeList^.List^[I].NameStr :=
  2782. DB.NodeList^.List^[I].NameStr + '.' + string(Chunk^.Data.InstanceName);
  2783. FreeChunkData(Chunk);
  2784. end;
  2785. end;
  2786. Inc(I); // Increment index counter
  2787. end;
  2788. end;
  2789. Current := Current^.Sibling;
  2790. end;
  2791. DB.NodeListDirty := False;
  2792. end;
  2793. end;
  2794. //----------------- other support function ----------------------------------------------------------------------------
  2795. function GetGenericNodeCount(const Source: TFile3DS; var DB: TDatabase3DS;
  2796. Tag: word): integer;
  2797. var
  2798. I: integer;
  2799. begin
  2800. UpdateNodeTagList(Source, DB);
  2801. Result := 0;
  2802. for I := 0 to DB.NodeList^.Count - 1 do
  2803. if DB.NodeList^.List^[I].Chunk^.Tag = Tag then
  2804. Inc(Result);
  2805. end;
  2806. //---------------------------------------------------------------------------------------------------------------------
  2807. procedure GetGenericNodeNameList(const Source: TFile3DS; var DB: TDatabase3DS;
  2808. TagID: word; List: TStringList);
  2809. var
  2810. I: cardinal;
  2811. begin
  2812. UpdateNodeTagList(Source, DB);
  2813. List.Clear;
  2814. for I := 0 to DB.NodeList^.Count - 1 do
  2815. if DB.NodeList^.List^[I].Chunk^.Tag = TagID then
  2816. List.Add(DB.NodeList^.List^[I].NameStr);
  2817. end;
  2818. //---------------------------------------------------------------------------------------------------------------------
  2819. function FindNamedAndTaggedChunk(const Source: TFile3DS; var DB: TDatabase3DS;
  2820. const Name: string; TagID: word): PChunk3DS;
  2821. // Look through the keyframer stuff and find named chunk of the tag type TagID.
  2822. // Has to be a chunk that has a node header: CAMERA_NODE, LIGHT_NODE, , .
  2823. var
  2824. KfChunk, NodeHdrChunk: PChunk3DS;
  2825. begin
  2826. // find Keyframe Chunk
  2827. KfChunk := FindChunk(DB.TopChunk, KFDATA);
  2828. // look for the target tag
  2829. Result := FindChunk(KfChunk, TagID);
  2830. while Assigned(Result) do
  2831. begin
  2832. NodeHdrChunk := FindNextChunk(Result^.Children, NODE_HDR);
  2833. if Assigned(NodeHdrChunk) then
  2834. begin
  2835. Source.ReadChunkData(NodeHdrChunk);
  2836. // match name, set pointer (case sensitive comparation!)
  2837. if CompareStr(Name, NodeHdrChunk^.Data.NodeHdr^.ObjNameStr) = 0 then
  2838. begin
  2839. FreeChunkData(NodeHdrChunk);
  2840. Break;
  2841. end;
  2842. FreeChunkData(NodeHdrChunk);
  2843. end;
  2844. Result := FindNextChunk(Result^.Sibling, TagID);
  2845. end;
  2846. end;
  2847. //---------------------------------------------------------------------------------------------------------------------
  2848. function FindNodeTagByIndexAndType(const Source: TFile3DS; var DB: TDatabase3DS;
  2849. Index: cardinal; AType: word): PChunk3DS;
  2850. var
  2851. I, Count: cardinal;
  2852. begin
  2853. Result := nil;
  2854. Count := 0;
  2855. UpdateNodeTagList(Source, DB);
  2856. for I := 0 to DB.NodeList^.Count - 1 do
  2857. if DB.NodeList^.List^[I].Chunk^.Tag = AType then
  2858. begin
  2859. if Count = Index then
  2860. begin
  2861. Result := DB.NodeList^.List^[I].Chunk;
  2862. Break;
  2863. end;
  2864. Inc(Count);
  2865. end;
  2866. end;
  2867. //---------------------------------------------------------------------------------------------------------------------
  2868. function FindNodeTagByNameAndType(const Source: TFile3DS; DB: TDatabase3DS;
  2869. const Name: string; AType: word): PChunk3DS;
  2870. var
  2871. I: integer;
  2872. begin
  2873. Result := nil;
  2874. UpdateNodeTagList(Source, DB);
  2875. for I := 0 to DB.NodeList^.Count - 1 do
  2876. if (DB.NodeList^.List^[I].Chunk^.Tag = AType) and
  2877. (CompareStr(Name, DB.NodeList^.List^[I].NameStr) = 0) then
  2878. begin
  2879. Result := DB.NodeList^.List^[I].Chunk;
  2880. Exit;
  2881. end;
  2882. end;
  2883. //----------------- material handling ---------------------------------------------------------------------------------
  2884. function GetMaterialCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  2885. begin
  2886. UpdateMatEntryList(Source, DB);
  2887. if DB.MatList = nil then
  2888. Result := 0
  2889. else
  2890. Result := DB.MatList^.Count;
  2891. end;
  2892. //---------------------------------------------------------------------------------------------------------------------
  2893. function FindMatEntryByIndex(Source: TFile3DS; DB: TDatabase3DS;
  2894. Index: integer): PChunk3DS;
  2895. begin
  2896. if DB.TopChunk = nil then
  2897. ShowError(strError3DS_INVALID_DATABASE);
  2898. if (DB.TopChunk^.Tag <> MLIBMAGIC) and (DB.TopChunk^.Tag <> M3DMAGIC) and
  2899. (DB.TopChunk^.Tag <> CMAGIC) then
  2900. ShowError(strError3DS_WRONG_DATABASE);
  2901. UpdateMatEntryList(Source, DB);
  2902. if Index < DB.MatList^.Count then
  2903. Result := DB.MatList^.List^[Index].Chunk
  2904. else
  2905. Result := nil;
  2906. end;
  2907. //---------------------------------------------------------------------------------------------------------------------
  2908. procedure InitBitmap(var Map: TBitmap3DS);
  2909. begin
  2910. FillChar(Map, SizeOf(Map), 0);
  2911. with Map do
  2912. begin
  2913. UScale := 1;
  2914. VScale := 1;
  2915. Tint2.R := 1;
  2916. Tint2.G := 1;
  2917. Tint2.B := 1;
  2918. RedTint.R := 1;
  2919. GreenTint.G := 1;
  2920. BlueTint.B := 1;
  2921. end;
  2922. end;
  2923. //---------------------------------------------------------------------------------------------------------------------
  2924. procedure InitMaterial(var Mat: TMaterial3DS);
  2925. begin
  2926. FillChar(Mat, SizeOf(Mat), 0);
  2927. with Mat do
  2928. begin
  2929. WireSize := 1;
  2930. Shading := stPhong;
  2931. Reflect.AutoMap.Size := 100;
  2932. Reflect.AutoMap.nthFrame := 1;
  2933. InitBitmap(Texture.Map);
  2934. InitBitmap(Texture.Mask);
  2935. InitBitmap(Texture2.Map);
  2936. InitBitmap(Texture2.Mask);
  2937. InitBitmap(Opacity.Map);
  2938. InitBitmap(Opacity.Mask);
  2939. InitBitmap(Reflect.Map);
  2940. InitBitmap(Reflect.Mask);
  2941. InitBitmap(Bump.Map);
  2942. InitBitmap(Bump.Mask);
  2943. InitBitmap(SpecMap.Map);
  2944. InitBitmap(SpecMap.Mask);
  2945. InitBitmap(ShinMap.Map);
  2946. InitBitmap(ShinMap.Mask);
  2947. InitBitmap(IllumMap.Map);
  2948. InitBitmap(IllumMap.Mask);
  2949. end;
  2950. end;
  2951. //---------------------------------------------------------------------------------------------------------------------
  2952. procedure ReleaseMaterial(Mat: PMaterial3DS);
  2953. begin
  2954. if Assigned(Mat) then
  2955. begin
  2956. FreeMem(Mat^.Texture.Map.Data);
  2957. FreeMem(Mat^.Texture.Mask.Data);
  2958. FreeMem(Mat^.Texture2.Map.Data);
  2959. FreeMem(Mat^.Texture2.Mask.Data);
  2960. FreeMem(Mat^.Opacity.Map.Data);
  2961. FreeMem(Mat^.Opacity.Mask.Data);
  2962. FreeMem(Mat^.Reflect.Mask.Data);
  2963. FreeMem(Mat^.Bump.Map.Data);
  2964. FreeMem(Mat^.Bump.Mask.Data);
  2965. FreeMem(Mat^.Specmap.Map.Data);
  2966. FreeMem(Mat^.SpecMap.Mask.Data);
  2967. FreeMem(Mat^.ShinMap.Map.Data);
  2968. FreeMem(Mat^.ShinMap.Mask.Data);
  2969. FreeMem(Mat^.IllumMap.Map.Data);
  2970. FreeMem(Mat^.IllumMap.Mask.Data);
  2971. Dispose(Mat);
  2972. end;
  2973. end;
  2974. //---------------------------------------------------------------------------------------------------------------------
  2975. function FindNamedObjectByIndex(Source: TFile3DS; DB: TDatabase3DS;
  2976. AType: word; Index: integer): PChunk3DS;
  2977. // searches the database for a named object by index position and object type
  2978. // returns the NAMED_OBJECT chunk if found, nil otherwise
  2979. var
  2980. Chunk: PChunk3DS;
  2981. I, Count: integer;
  2982. begin
  2983. UpdateNamedObjectList(Source, DB);
  2984. Count := 0;
  2985. Result := nil;
  2986. for I := 0 to DB.ObjList^.Count - 1 do
  2987. begin
  2988. if AType = DL_SPOTLIGHT then
  2989. begin
  2990. Chunk := FindChunk(DB.ObjList^.List^[I].Chunk, N_DIRECT_LIGHT);
  2991. if Assigned(Chunk) then
  2992. Chunk := FindChunk(Chunk, AType);
  2993. end
  2994. else
  2995. Chunk := FindChunk(DB.ObjList^.List^[I].Chunk, AType);
  2996. if Assigned(Chunk) then
  2997. begin
  2998. if Count = Index then
  2999. begin
  3000. Result := DB.ObjList^.List^[I].Chunk;
  3001. Break;
  3002. end
  3003. else
  3004. Inc(Count);
  3005. end;
  3006. end;
  3007. end;
  3008. //---------------------------------------------------------------------------------------------------------------------
  3009. procedure DeleteChunk(var Chunk: PChunk3DS);
  3010. // returns a chunk to its untagged state state, but leaves it
  3011. // connected to any siblings it might have
  3012. begin
  3013. if Assigned(Chunk) then
  3014. begin
  3015. // release any children
  3016. if Assigned(Chunk^.Children) then
  3017. ReleaseChunk(Chunk^.Children);
  3018. // release any data
  3019. if Assigned(Chunk^.Data.Dummy) then
  3020. FreeChunkData(Chunk);
  3021. // return to a semi-uninitialized state
  3022. Chunk^.Tag := NULL_CHUNK;
  3023. Chunk^.Size := 0;
  3024. Chunk^.Position := 0;
  3025. end;
  3026. end;
  3027. //---------------------------------------------------------------------------------------------------------------------
  3028. function ReadPercentageChunk(Source: TFile3DS; Chunk: PChunk3DS): single;
  3029. var
  3030. DataChunk: PChunk3DS;
  3031. begin
  3032. DataChunk := FindChunk(Chunk, INT_PERCENTAGE);
  3033. if Assigned(DataChunk) then
  3034. begin
  3035. Source.ReadChunkData(DataChunk);
  3036. Result := DataChunk^.Data.IntPercentage^ / 100;
  3037. FreeChunkData(DataChunk);
  3038. end
  3039. else
  3040. begin
  3041. DataChunk := FindChunk(Chunk, FLOAT_PERCENTAGE);
  3042. if Assigned(DataChunk) then
  3043. begin
  3044. Source.ReadChunkData(DataChunk);
  3045. Result := DataChunk^.Data.FloatPercentage^;
  3046. FreeChunkData(DataChunk);
  3047. end
  3048. else
  3049. Result := 0;
  3050. end;
  3051. end;
  3052. //---------------------------------------------------------------------------------------------------------------------
  3053. procedure GetBitmapChunk(const DataSource: TFile3DS; Chunk: PChunk3DS;
  3054. var Bitmap: TBitmap3DS);
  3055. var
  3056. Current: PChunk3DS;
  3057. begin
  3058. Current := Chunk^.Children;
  3059. while Assigned(Current) do
  3060. begin
  3061. with Bitmap do
  3062. begin
  3063. case Current^.Tag of
  3064. INT_PERCENTAGE:
  3065. begin
  3066. DataSource.ReadChunkData(Current);
  3067. Percent := Current^.Data.IntPercentage^ / 100;
  3068. FreeChunkData(Current);
  3069. end;
  3070. FLOAT_PERCENTAGE:
  3071. begin
  3072. DataSource.ReadChunkData(Current);
  3073. Percent := Current^.Data.FloatPercentage^;
  3074. FreeChunkData(Current);
  3075. end;
  3076. MAT_MAPNAME:
  3077. begin
  3078. DataSource.ReadChunkData(Current);
  3079. NameStr := StrPas(Current^.Data.MatMapname);
  3080. FreeChunkData(Current);
  3081. end;
  3082. MAT_MAP_TILING:
  3083. begin
  3084. DataSource.ReadChunkData(Current);
  3085. if (Current^.Data.MatMapTiling^ and TEX_DECAL) <> 0 then
  3086. if (Current^.Data.MatMapTiling^ and TEX_NOWRAP) <> 0 then
  3087. Tiling := ttDecal
  3088. else
  3089. Tiling := ttBoth
  3090. else
  3091. tiling := ttTile;
  3092. IgnoreAlpha := (Current^.Data.MatMapTiling^ and TEX_DONT_USE_ALPHA) <> 0;
  3093. if (Current^.Data.MatMapTiling^ and TEX_SAT) <> 0 then
  3094. Filter := ftSummedArea
  3095. else
  3096. Filter := ftPyramidal;
  3097. Mirror := (Current^.Data.MatMapTiling^ and TEX_MIRROR) <> 0;
  3098. Negative := (Current^.Data.MatMapTiling^ and TEX_INVERT) <> 0;
  3099. if (Current^.Data.MatMapTiling^ and TEX_TINT) <> 0 then
  3100. if (Current^.Data.MatMapTiling^ and TEX_ALPHA_SOURCE) <> 0 then
  3101. Source := ttAlphaTint
  3102. else
  3103. Source := ttRGBLumaTint
  3104. else if (Current^.Data.MatMapTiling^ and TEX_RGB_TINT) <> 0 then
  3105. Source := ttRGBTint
  3106. else if (Current^.Data.MatMapTiling^ and TEX_ALPHA_SOURCE) <> 0 then
  3107. Source := ttAlpha
  3108. else
  3109. Source := ttRGB;
  3110. FreeChunkData(Current);
  3111. end;
  3112. MAT_MAP_USCALE:
  3113. begin
  3114. DataSource.ReadChunkData(Current);
  3115. UScale := Current^.Data.MatMapUScale^;
  3116. FreeChunkData(Current);
  3117. end;
  3118. MAT_MAP_VSCALE:
  3119. begin
  3120. DataSource.ReadChunkData(Current);
  3121. VScale := Current^.Data.MatMapVScale^;
  3122. FreeChunkData(Current);
  3123. end;
  3124. MAT_MAP_UOFFSET:
  3125. begin
  3126. DataSource.ReadChunkData(Current);
  3127. UOffset := Current^.Data.MatMapUOffset^;
  3128. FreeChunkData(Current);
  3129. end;
  3130. MAT_MAP_VOFFSET:
  3131. begin
  3132. DataSource.ReadChunkData(Current);
  3133. VOffset := Current^.Data.MatMapVOffset^;
  3134. FreeChunkData(Current);
  3135. end;
  3136. MAT_MAP_ANG:
  3137. begin
  3138. DataSource.ReadChunkData(Current);
  3139. Rotation := Current^.Data.MatMapAng^;
  3140. FreeChunkData(Current);
  3141. end;
  3142. MAT_BUMP_PERCENT:
  3143. ; // value is really stored in TMaterial3DS structure
  3144. MAT_MAP_COL1:
  3145. begin
  3146. DataSource.ReadChunkData(Current);
  3147. Tint1.R := Current^.Data.MatMapCol1^.Red / 255;
  3148. Tint1.G := Current^.Data.MatMapCol1^.Green / 255;
  3149. Tint1.B := Current^.Data.MatMapCol1^.Blue / 255;
  3150. FreeChunkData(Current);
  3151. end;
  3152. MAT_MAP_COL2:
  3153. begin
  3154. DataSource.ReadChunkData(Current);
  3155. Tint2.R := Current^.Data.MatMapCol2^.Red / 255;
  3156. Tint2.G := Current^.Data.MatMapCol2^.Green / 255;
  3157. Tint2.B := Current^.Data.MatMapCol2^.Blue / 255;
  3158. FreeChunkData(Current);
  3159. end;
  3160. MAT_MAP_RCOL:
  3161. begin
  3162. DataSource.ReadChunkData(Current);
  3163. RedTint.R := Current^.Data.MatMapRCol^.Red / 255;
  3164. RedTint.G := Current^.Data.MatMapRCol^.Green / 255;
  3165. RedTint.B := Current^.Data.MatMapRCol^.Blue / 255;
  3166. FreeChunkData(Current);
  3167. end;
  3168. MAT_MAP_GCOL:
  3169. begin
  3170. DataSource.ReadChunkData(Current);
  3171. GreenTint.R := Current^.Data.MatMapGCol^.Red / 255;
  3172. GreenTint.G := Current^.Data.MatMapGCol^.Green / 255;
  3173. GreenTint.B := Current^.Data.MatMapGCol^.Blue / 255;
  3174. FreeChunkData(Current);
  3175. end;
  3176. MAT_MAP_BCOL:
  3177. begin
  3178. DataSource.ReadChunkData(Current);
  3179. BlueTint.R := Current^.Data.MatMapBCol^.Red / 255;
  3180. BlueTint.G := Current^.Data.MatMapBCol^.Green / 255;
  3181. BlueTint.B := Current^.Data.MatMapBCol^.Blue / 255;
  3182. FreeChunkData(Current);
  3183. end;
  3184. MAT_MAP_TEXBLUR:
  3185. begin
  3186. DataSource.ReadChunkData(Current);
  3187. Blur := Current^.Data.MatMapTexBlur^; // float percents
  3188. FreeChunkData(Current);
  3189. end;
  3190. end; // case Current^.Tag of
  3191. Current := Current^.Sibling;
  3192. end; // with Bitmap do
  3193. end; // while Assigned(Current) do
  3194. end;
  3195. //---------------------------------------------------------------------------------------------------------------------
  3196. function ReadMatEntryChunk(Source: TFile3DS; MatEntry: PChunk3DS): TMaterial3DS;
  3197. var
  3198. Current, DataChunk, Color: PChunk3DS;
  3199. MatColor: PFColor3DS;
  3200. begin
  3201. if MatEntry^.Tag <> MAT_ENTRY then
  3202. ShowError(strError3DS_INVALID_CHUNK);
  3203. InitMaterial(Result);
  3204. with Result do
  3205. begin
  3206. Current := MatEntry^.Children;
  3207. while Assigned(Current) do
  3208. begin
  3209. if (Current^.Tag and $FF00) <> $8000 then // ignore xdata
  3210. case Current^.Tag of
  3211. MAT_NAME:
  3212. begin
  3213. Source.ReadChunkData(Current);
  3214. NameStr := StrPas(Current^.Data.MatName);
  3215. FreeChunkData(Current);
  3216. end;
  3217. MAT_AMBIENT,
  3218. MAT_DIFFUSE,
  3219. MAT_SPECULAR:
  3220. begin
  3221. case Current^.Tag of
  3222. MAT_DIFFUSE:
  3223. MatColor := @Diffuse;
  3224. MAT_SPECULAR:
  3225. MatColor := @Specular;
  3226. else
  3227. MatColor := @Ambient; // MAT_AMBIENT
  3228. end;
  3229. Color := FindChunk(Current, COLOR_24);
  3230. if Assigned(color) then
  3231. begin
  3232. Source.ReadChunkData(Color);
  3233. MatColor^.R := Color^.Data.Color24^.Red / 255;
  3234. MatColor^.G := Color^.Data.Color24^.Green / 255;
  3235. MatColor^.B := Color^.Data.Color24^.Blue / 255;
  3236. FreeChunkData(Color);
  3237. end;
  3238. Color := FindChunk(Current, COLOR_F);
  3239. if Assigned(Color) then
  3240. begin
  3241. Source.ReadChunkData(Color);
  3242. MatColor^.R := Color^.Data.ColorF^.Red;
  3243. MatColor^.G := Color^.Data.ColorF^.Green;
  3244. MatColor^.B := Color^.Data.ColorF^.Blue;
  3245. FreeChunkData(Color);
  3246. end;
  3247. Color := FindChunk(Current, LIN_COLOR_24);
  3248. if Assigned(Color) then
  3249. begin
  3250. Source.ReadChunkData(Color);
  3251. MatColor^.R := Color^.Data.LinColor24^.Red / 255;
  3252. MatColor^.G := Color^.Data.LinColor24^.Green / 255;
  3253. MatColor^.B := Color^.Data.LinColor24^.Blue / 255;
  3254. FreeChunkData(Color);
  3255. end;
  3256. end;
  3257. MAT_SHININESS:
  3258. Shininess := ReadPercentageChunk(Source, Current);
  3259. MAT_SHIN2PCT:
  3260. ShinStrength := ReadPercentageChunk(Source, Current);
  3261. MAT_SHIN3PCT:
  3262. ; // just skip for now
  3263. MAT_REFBLUR:
  3264. Blur := ReadPercentageChunk(Source, Current);
  3265. MAT_TRANSPARENCY:
  3266. Transparency := ReadPercentageChunk(Source, Current);
  3267. MAT_XPFALL:
  3268. TransFalloff := ReadPercentageChunk(Source, Current);
  3269. MAT_SELF_ILPCT:
  3270. SelfIllumPct := ReadPercentageChunk(Source, Current);
  3271. MAT_WIRE:
  3272. Shading := stWire;
  3273. MAT_WIREABS:
  3274. UseWireAbs := True;
  3275. MAT_XPFALLIN:
  3276. Transparency := -Transparency;
  3277. MAT_WIRESIZE:
  3278. begin
  3279. Source.ReadChunkData(Current);
  3280. WireSize := Current^.Data.MatWireSize^;
  3281. FreeChunkData(Current);
  3282. end;
  3283. MAT_USE_XPFALL:
  3284. UseFall := True;
  3285. MAT_USE_REFBLUR:
  3286. Useblur := True;
  3287. MAT_SELF_ILLUM:
  3288. SelfIllum := True;
  3289. MAT_TWO_SIDE:
  3290. TwoSided := True;
  3291. MAT_ADDITIVE:
  3292. Additive := True;
  3293. MAT_SHADING:
  3294. begin
  3295. Source.ReadChunkData(Current);
  3296. Shading := TShadeType3DS(Current^.Data.MatShading^);
  3297. FreeChunkData(Current);
  3298. end;
  3299. MAT_FACEMAP:
  3300. FaceMap := True;
  3301. MAT_PHONGSOFT:
  3302. Soften := True;
  3303. MAT_TEXMAP:
  3304. GetBitmapChunk(Source, Current, Texture.Map);
  3305. MAT_TEXMASK:
  3306. GetBitmapChunk(Source, Current, Texture.Mask);
  3307. MAT_TEX2MAP:
  3308. GetBitmapChunk(Source, Current, Texture2.Map);
  3309. MAT_TEX2MASK:
  3310. GetBitmapChunk(Source, Current, Texture2.Mask);
  3311. MAT_OPACMAP:
  3312. GetBitmapChunk(Source, Current, Opacity.Map);
  3313. MAT_OPACMASK:
  3314. GetBitmapChunk(Source, Current, Opacity.Mask);
  3315. MAT_REFLMAP:
  3316. GetBitmapChunk(Source, Current, Reflect.Map);
  3317. MAT_ACUBIC:
  3318. begin
  3319. Source.ReadChunkData(Current);
  3320. Reflect.UseAuto := True;
  3321. Reflect.AutoMap.FirstFrame :=
  3322. (Current^.Data.MatAcubic^.Flags and ACubicFirst3DS) <> 0;
  3323. Reflect.AutoMap.Flat :=
  3324. (Current^.Data.MatAcubic^.Flags and ACubicFlat3DS) <> 0;
  3325. Reflect.AutoMap.Size := Current^.Data.MatAcubic^.MapSize;
  3326. Reflect.AutoMap.nthFrame := Current^.Data.MatAcubic^.FrameInterval;
  3327. FreeChunkData(Current);
  3328. end;
  3329. MAT_REFLMASK:
  3330. GetBitmapChunk(Source, Current, Reflect.Mask);
  3331. MAT_BUMPMAP:
  3332. begin
  3333. GetBitmapChunk(Source, Current, Bump.Map);
  3334. DataChunk := FindChunk(Current, MAT_BUMP_PERCENT);
  3335. if Assigned(DataChunk) then
  3336. begin
  3337. Source.ReadChunkData(DataChunk);
  3338. Bump.Map.Percent := DataChunk^.Data.MatBumpPercent^ / 100;
  3339. FreeChunkData(DataChunk);
  3340. end;
  3341. end;
  3342. MAT_BUMPMASK:
  3343. GetBitmapChunk(Source, Current, Bump.Mask);
  3344. MAT_SPECMAP:
  3345. GetBitmapChunk(Source, Current, SpecMap.Map);
  3346. MAT_SPECMASK:
  3347. GetBitmapChunk(Source, Current, SpecMap.Mask);
  3348. MAT_SHINMAP:
  3349. GetBitmapChunk(Source, Current, ShinMap.Map);
  3350. MAT_SHINMASK:
  3351. GetBitmapChunk(Source, Current, Shinmap.Mask);
  3352. MAT_SELFIMAP:
  3353. GetBitmapChunk(Source, Current, IllumMap.Map);
  3354. MAT_SELFIMASK:
  3355. GetBitmapChunk(Source, Current, IllumMap.Mask);
  3356. MAT_SXP_TEXT_DATA:
  3357. begin
  3358. Source.ReadChunkData(Current);
  3359. Texture.Map.DataSize := Current^.Data.IpasData^.Size;
  3360. Texture.Map.Data := Current^.Data.IpasData^.Data;
  3361. // avoid releasing the data memory
  3362. Current^.Data.IpasData^.Data := nil;
  3363. FreeChunkData(Current);
  3364. end;
  3365. MAT_SXP_TEXT_MASKDATA:
  3366. begin
  3367. Source.ReadChunkData(Current);
  3368. Texture.Mask.DataSize := Current^.Data.IpasData^.Size;
  3369. Texture.Mask.Data := Current^.Data.IpasData^.Data;
  3370. Current^.Data.IpasData^.Data := nil;
  3371. FreeChunkData(Current);
  3372. end;
  3373. MAT_SXP_TEXT2_DATA:
  3374. begin
  3375. Source.ReadChunkData(Current);
  3376. Texture2.Map.DataSize := Current^.Data.IpasData^.Size;
  3377. Texture2.Map.Data := Current^.Data.IpasData^.Data;
  3378. Current^.Data.IpasData^.Data := nil;
  3379. FreeChunkData(Current);
  3380. end;
  3381. MAT_SXP_TEXT2_MASKDATA:
  3382. begin
  3383. Source.ReadChunkData(Current);
  3384. Texture2.Mask.DataSize := Current^.Data.IpasData^.Size;
  3385. Texture2.Mask.Data := Current^.Data.IpasData^.Data;
  3386. Current^.Data.IpasData^.Data := nil;
  3387. FreeChunkData(Current);
  3388. end;
  3389. MAT_SXP_OPAC_DATA:
  3390. begin
  3391. Source.ReadChunkData(Current);
  3392. Opacity.Map.DataSize := Current^.Data.IpasData^.Size;
  3393. Opacity.Map.Data := Current^.Data.IpasData^.Data;
  3394. Current^.Data.IpasData^.Data := nil;
  3395. FreeChunkData(Current);
  3396. end;
  3397. MAT_SXP_OPAC_MASKDATA:
  3398. begin
  3399. Source.ReadChunkData(Current);
  3400. Opacity.Mask.DataSize := Current^.Data.IpasData^.Size;
  3401. Opacity.Mask.Data := Current^.Data.IpasData^.Data;
  3402. Current^.Data.IpasData^.Data := nil;
  3403. FreeChunkData(Current);
  3404. end;
  3405. MAT_SXP_REFL_MASKDATA:
  3406. begin
  3407. Source.ReadChunkData(Current);
  3408. Reflect.Mask.DataSize := Current^.Data.IpasData^.Size;
  3409. Reflect.Mask.Data := Current^.Data.IpasData^.Data;
  3410. Current^.Data.IpasData^.Data := nil;
  3411. FreeChunkData(Current);
  3412. end;
  3413. MAT_SXP_BUMP_DATA:
  3414. begin
  3415. Source.ReadChunkData(Current);
  3416. Bump.Map.DataSize := Current^.Data.IpasData^.Size;
  3417. Bump.Map.Data := Current^.Data.IpasData^.Data;
  3418. Current^.Data.IpasData^.Data := nil;
  3419. FreeChunkData(Current);
  3420. end;
  3421. MAT_SXP_BUMP_MASKDATA:
  3422. begin
  3423. Source.ReadChunkData(Current);
  3424. Bump.Mask.DataSize := Current^.Data.IpasData^.Size;
  3425. Bump.Mask.Data := Current^.Data.IpasData^.Data;
  3426. Current^.Data.IpasData^.Data := nil;
  3427. FreeChunkData(Current);
  3428. end;
  3429. MAT_SXP_SPEC_DATA:
  3430. begin
  3431. Source.ReadChunkData(Current);
  3432. SpecMap.Map.DataSize := Current^.Data.IpasData^.Size;
  3433. SpecMap.Map.Data := Current^.Data.IpasData^.Data;
  3434. Current^.Data.IpasData^.Data := nil;
  3435. FreeChunkData(Current);
  3436. end;
  3437. MAT_SXP_SPEC_MASKDATA:
  3438. begin
  3439. Source.ReadChunkData(Current);
  3440. Specmap.Mask.DataSize := Current^.Data.IpasData^.Size;
  3441. Specmap.Mask.Data := Current^.Data.IpasData^.Data;
  3442. Current^.Data.IpasData^.Data := nil;
  3443. FreeChunkData(Current);
  3444. end;
  3445. MAT_SXP_SHIN_DATA:
  3446. begin
  3447. Source.ReadChunkData(Current);
  3448. ShinMap.Map.DataSize := Current^.Data.IpasData^.Size;
  3449. ShinMap.Map.Data := Current^.Data.IpasData^.Data;
  3450. Current^.Data.IpasData^.Data := nil;
  3451. FreeChunkData(Current);
  3452. end;
  3453. MAT_SXP_SHIN_MASKDATA:
  3454. begin
  3455. Source.ReadChunkData(Current);
  3456. ShinMap.Mask.DataSize := Current^.Data.IpasData^.Size;
  3457. ShinMap.Mask.Data := Current^.Data.IpasData^.Data;
  3458. Current^.Data.IpasData^.Data := nil;
  3459. FreeChunkData(Current);
  3460. end;
  3461. MAT_SXP_SELFI_DATA:
  3462. begin
  3463. Source.ReadChunkData(Current);
  3464. IllumMap.Map.DataSize := Current^.Data.IpasData^.Size;
  3465. IllumMap.Map.Data := Current^.Data.IpasData^.Data;
  3466. Current^.Data.IpasData^.Data := nil;
  3467. FreeChunkData(Current);
  3468. end;
  3469. MAT_SXP_SELFI_MASKDATA:
  3470. begin
  3471. Source.ReadChunkData(Current);
  3472. IllumMap.Mask.DataSize := Current^.Data.IpasData^.Size;
  3473. IllumMap.Mask.Data := Current^.Data.IpasData^.Data;
  3474. Current^.Data.IpasData^.Data := nil;
  3475. FreeChunkData(Current);
  3476. end;
  3477. MAT_DECAL:
  3478. ; // don't know what do to with it
  3479. else
  3480. ShowError(strError3DS_INVALID_CHUNK)
  3481. end;
  3482. Current := Current^.Sibling;
  3483. end; // while Assigned(Current) do
  3484. end; // with Result do
  3485. end;
  3486. //---------------------------------------------------------------------------------------------------------------------
  3487. function GetChunkValue(Tag: word): integer;
  3488. // Computes a chunk weighting used to determine proper chunk order,
  3489. // higher values appear earlier in the parent than lower values
  3490. begin
  3491. // only chunks where an explicit order matters are handled
  3492. Result := 0;
  3493. case Tag of
  3494. NULL_CHUNK:
  3495. Inc(Result); // These should just be ignored
  3496. SMAGIC:
  3497. Inc(Result, 2);
  3498. LMAGIC:
  3499. Inc(Result, 3);
  3500. M3DMAGIC:
  3501. Inc(Result, 4);
  3502. M3D_VERSION:
  3503. Inc(Result, 5);
  3504. MDATA:
  3505. Inc(Result, 6);
  3506. KFDATA:
  3507. Inc(Result, 7);
  3508. COLOR_24:
  3509. Inc(Result, 8);
  3510. LIN_COLOR_24:
  3511. Inc(Result, 9);
  3512. MESH_VERSION:
  3513. Inc(Result, 10);
  3514. MAT_ENTRY:
  3515. Inc(Result, 11);
  3516. KFHDR:
  3517. Inc(Result, 12);
  3518. MASTER_SCALE:
  3519. Inc(Result, 13);
  3520. VIEWPORT_LAYOUT:
  3521. Inc(Result, 14);
  3522. LO_SHADOW_BIAS:
  3523. Inc(Result, 15);
  3524. SHADOW_MAP_SIZE:
  3525. Inc(Result, 16);
  3526. SHADOW_FILTER:
  3527. Inc(Result, 17);
  3528. RAY_BIAS:
  3529. Inc(Result, 18);
  3530. O_CONSTS:
  3531. Inc(Result, 19);
  3532. AMBIENT_LIGHT:
  3533. Inc(Result, 20);
  3534. SOLID_BGND:
  3535. Inc(Result, 21);
  3536. BIT_MAP:
  3537. Inc(Result, 22);
  3538. V_GRADIENT:
  3539. Inc(Result, 23);
  3540. USE_BIT_MAP:
  3541. Inc(Result, 24);
  3542. USE_SOLID_BGND:
  3543. Inc(Result, 25);
  3544. USE_V_GRADIENT:
  3545. Inc(Result, 26);
  3546. FOG:
  3547. Inc(Result, 27);
  3548. LAYER_FOG:
  3549. Inc(Result, 28);
  3550. DISTANCE_CUE:
  3551. Inc(Result, 29);
  3552. DEFAULT_VIEW:
  3553. Inc(Result, 30);
  3554. NAMED_OBJECT:
  3555. Inc(Result, 31);
  3556. KFSEG:
  3557. Inc(Result, 32);
  3558. KFCURTIME:
  3559. Inc(Result, 33);
  3560. TARGET_NODE_TAG,
  3561. L_TARGET_NODE_TAG,
  3562. OBJECT_NODE_TAG,
  3563. CAMERA_NODE_TAG,
  3564. SPOTLIGHT_NODE_TAG:
  3565. Inc(Result, 34);
  3566. AMBIENT_NODE_TAG:
  3567. Inc(Result, 35);
  3568. N_TRI_OBJECT,
  3569. N_CAMERA,
  3570. N_DIRECT_LIGHT:
  3571. Inc(Result);
  3572. OBJ_HIDDEN:
  3573. Inc(Result);
  3574. end;
  3575. end;
  3576. //---------------------------------------------------------------------------------------------------------------------
  3577. function GetMaterialByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  3578. Index: integer): TMaterial3DS;
  3579. var
  3580. Chunk: PChunk3DS;
  3581. begin
  3582. FillChar(Result, SizeOf(Result), 0);
  3583. Chunk := FindMatEntryByIndex(Source, DB, Index);
  3584. if Assigned(Chunk) then
  3585. Result := ReadMatEntryChunk(Source, Chunk)
  3586. else
  3587. ShowErrorFormatted(strError3DS_INVALID_INDEX, [Index]);
  3588. end;
  3589. //----------------- mesh object handling ------------------------------------------------------------------------------
  3590. function GetMeshCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  3591. // returns the number of mesh objects referenced in the chunk list
  3592. var
  3593. I: integer;
  3594. Chunk: PChunk3DS;
  3595. begin
  3596. // update the index to named objects if the list has changed recently
  3597. UpdateNamedObjectList(Source, DB);
  3598. Result := 0;
  3599. if DB.ObjList = nil then
  3600. Exit;
  3601. // scan through the list of named objects
  3602. for I := 0 to DB.ObjList^.Count - 1 do
  3603. begin
  3604. Chunk := FindChunk(DB.ObjList^.List^[I].Chunk, N_TRI_OBJECT);
  3605. if Assigned(Chunk) then
  3606. Inc(Result);
  3607. end;
  3608. end;
  3609. //---------------------------------------------------------------------------------------------------------------------
  3610. function GetMeshMatCount(Current: PChunk3DS): integer;
  3611. // aids the GetMeshEntryChunk3DS in determining
  3612. // how many materials are defined within the mesh object
  3613. var
  3614. Chunk: PChunk3DS;
  3615. begin
  3616. Result := 0;
  3617. Chunk := FindChunk(Current, MSH_MAT_GROUP);
  3618. while Assigned(Chunk) do
  3619. begin
  3620. Chunk := FindNextChunk(Chunk^.Sibling, MSH_MAT_GROUP);
  3621. Inc(Result);
  3622. end;
  3623. end;
  3624. //---------------------------------------------------------------------------------------------------------------------
  3625. procedure RelMeshObjField(var Mesh: TMesh3DS; Field: integer);
  3626. var
  3627. I: integer;
  3628. begin
  3629. if ((Field and RelVertexArray3DS) <> 0) and Assigned(Mesh.VertexArray) then
  3630. begin
  3631. FreeMem(Mesh.VertexArray);
  3632. Mesh.VertexArray := nil;
  3633. end;
  3634. if ((Field and RelTextArray3DS) <> 0) and Assigned(Mesh.TextArray) then
  3635. begin
  3636. FreeMem(Mesh.TextArray);
  3637. Mesh.TextArray := nil;
  3638. end;
  3639. if ((Field and RelFaceArray3DS) <> 0) and Assigned(Mesh.FaceArray) then
  3640. begin
  3641. FreeMem(Mesh.FaceArray);
  3642. Mesh.FaceArray := nil;
  3643. end;
  3644. if ((Field and RelMatArray3DS) <> 0) and Assigned(Mesh.MatArray) then
  3645. begin
  3646. for I := 0 to Mesh.NMats - 1 do
  3647. begin
  3648. // name is always assigned
  3649. Mesh.MatArray^[I].NameStr := '';
  3650. if Assigned(Mesh.MatArray^[I].FaceIndex) then
  3651. begin
  3652. FreeMem(Mesh.MatArray^[I].FaceIndex);
  3653. Mesh.MatArray^[I].FaceIndex := nil;
  3654. end;
  3655. end;
  3656. FreeMem(Mesh.MatArray);
  3657. Mesh.MatArray := nil;
  3658. end;
  3659. if ((Field and RelSmoothArray3DS) <> 0) and Assigned(Mesh.SmoothArray) then
  3660. begin
  3661. FreeMem(Mesh.SmoothArray);
  3662. Mesh.SmoothArray := nil;
  3663. end;
  3664. if ((Field and RelProcData3DS) <> 0) and Assigned(Mesh.ProcData) then
  3665. begin
  3666. FreeMem(Mesh.ProcData);
  3667. Mesh.ProcData := nil;
  3668. end;
  3669. if ((Field and RelVFlagArray3DS) <> 0) and Assigned(Mesh.VFlagArray) then
  3670. begin
  3671. FreeMem(Mesh.VFlagArray);
  3672. Mesh.VFlagArray := nil;
  3673. end;
  3674. end;
  3675. //---------------------------------------------------------------------------------------------------------------------
  3676. procedure InitMeshObjField(var aMesh: TMesh3DS; Field: integer);
  3677. var
  3678. I: integer;
  3679. begin
  3680. with aMesh do
  3681. begin
  3682. // test to see if Vertices are being allocated
  3683. if (Field and InitVertexArray3DS) <> 0 then
  3684. begin
  3685. // if the vertex count is 0 then free the array
  3686. if NVertices = 0 then
  3687. RelMeshObjField(aMesh, RelVertexArray3DS)
  3688. else
  3689. begin
  3690. // if this is the very first allocation
  3691. if VertexArray = nil then
  3692. begin
  3693. // allocate the new block of memory
  3694. VertexArray := AllocMem(NVertices * SizeOf(TPoint3DS));
  3695. if VertexArray = nil then
  3696. ShowError(strError3DS_NO_MEM);
  3697. // this is done by AllocMem already
  3698. // initialize the new block
  3699. //for I := 0 to NVertices - 1 do VertexArray[I] := DefPoint3DS;
  3700. end
  3701. else // else this is an existing block
  3702. begin
  3703. // just resize it
  3704. ReallocMem(VertexArray, SizeOf(TPoint3DS) * NVertices);
  3705. if VertexArray = nil then
  3706. ShowError(strError3DS_NO_MEM);
  3707. end;
  3708. end;
  3709. end;
  3710. if (Field and InitTextArray3DS) <> 0 then
  3711. begin
  3712. if NTextVerts = 0 then
  3713. RelMeshObjField(aMesh, RelTextArray3DS)
  3714. else
  3715. begin
  3716. if TextArray = nil then
  3717. begin
  3718. TextArray := Allocmem(NTextVerts * SizeOf(TTexVert3DS));
  3719. if TextArray = nil then
  3720. ShowError(strError3DS_NO_MEM);
  3721. for I := 0 to NTextVerts - 1 do
  3722. TextArray^[I] := DefTextVert3DS;
  3723. end
  3724. else
  3725. begin
  3726. Reallocmem(TextArray, SizeOf(TTexVert3DS) * NTextVerts);
  3727. if TextArray = nil then
  3728. ShowError(strError3DS_NO_MEM);
  3729. end;
  3730. end;
  3731. end;
  3732. if (Field and InitFaceArray3DS) <> 0 then
  3733. begin
  3734. if NFaces = 0 then
  3735. RelMeshObjField(aMesh, RelFaceArray3DS)
  3736. else
  3737. begin
  3738. if FaceArray = nil then
  3739. begin
  3740. FaceArray := AllocMem(NFaces * SizeOf(TFace3DS));
  3741. if FaceArray = nil then
  3742. ShowError(strError3DS_NO_MEM);
  3743. for I := 0 to NFaces - 1 do
  3744. FaceArray^[I] := DefFace3DS;
  3745. end
  3746. else
  3747. begin
  3748. ReallocMem(FaceArray, SizeOf(TFace3DS) * NFaces);
  3749. if FaceArray = nil then
  3750. ShowError(strError3DS_NO_MEM);
  3751. end;
  3752. end;
  3753. end;
  3754. if (Field and InitMatArray3DS) <> 0 then
  3755. begin
  3756. if NMats = 0 then
  3757. RelMeshObjField(aMesh, RelMatArray3DS)
  3758. else
  3759. begin
  3760. if Matarray = nil then
  3761. begin
  3762. MatArray := AllocMem(NMats * SizeOf(TObjmat3DS));
  3763. if MatArray = nil then
  3764. ShowError(strError3DS_NO_MEM);
  3765. for I := 0 to NMats - 1 do
  3766. MatArray^[I] := DefObjMat3DS;
  3767. end
  3768. else
  3769. begin
  3770. ReallocMem(MatArray, SizeOf(TObjmat3DS) * NMats);
  3771. if MatArray = nil then
  3772. ShowError(strError3DS_NO_MEM);
  3773. end;
  3774. end;
  3775. end;
  3776. if (Field and InitSmoothArray3DS) <> 0 then
  3777. begin
  3778. if NFaces = 0 then
  3779. RelMeshObjField(aMesh, RelSmoothArray3DS)
  3780. else
  3781. begin
  3782. if SmoothArray = nil then
  3783. begin
  3784. SmoothArray := AllocMem(NFaces * SizeOf(integer));
  3785. if SmoothArray = nil then
  3786. ShowError(strError3DS_NO_MEM);
  3787. // done by AllocMem
  3788. // for I := 0 to NFaces - 1 do SmoothArray[I] := 0;
  3789. end
  3790. else
  3791. begin
  3792. ReallocMem(SmoothArray, SizeOf(integer) * NFaces);
  3793. if SmoothArray = nil then
  3794. ShowError(strError3DS_NO_MEM);
  3795. end;
  3796. end;
  3797. end;
  3798. if (Field and InitProcData3DS) <> 0 then
  3799. begin
  3800. if ProcSize = 0 then
  3801. RelMeshObjField(aMesh, RelProcData3DS)
  3802. else
  3803. begin
  3804. if ProcData = nil then
  3805. begin
  3806. ProcData := AllocMem(ProcSize * SizeOf(byte));
  3807. if ProcData = nil then
  3808. ShowError(strError3DS_NO_MEM);
  3809. end
  3810. else
  3811. begin
  3812. ReallocMem(ProcData, SizeOf(byte) * ProcSize);
  3813. if ProcData = nil then
  3814. ShowError(strError3DS_NO_MEM);
  3815. end;
  3816. end;
  3817. end;
  3818. if (Field and InitVFlagArray3DS) <> 0 then
  3819. begin
  3820. if NVertices = 0 then
  3821. RelMeshObjField(aMesh, RelVFlagArray3DS)
  3822. else
  3823. begin
  3824. if VFlagArray = nil then
  3825. begin
  3826. VFlagArray := AllocMem(NVertices * SizeOf(word));
  3827. if VFlagArray = nil then
  3828. ShowError(strError3DS_NO_MEM);
  3829. end
  3830. else
  3831. begin
  3832. ReallocMem(VFlagArray, SizeOf(word) * NVertices);
  3833. if VFlagArray = nil then
  3834. ShowError(strError3DS_NO_MEM);
  3835. end;
  3836. end;
  3837. end;
  3838. end;
  3839. end;
  3840. //---------------------------------------------------------------------------------------------------------------------
  3841. function InitMeshObj(VertexCount, FaceCount, InitFlags: word): TMesh3DS;
  3842. begin
  3843. FillChar(Result, SizeOf(Result), 0);
  3844. with Result do
  3845. begin
  3846. NVertices := VertexCount;
  3847. Map.TileX := 1;
  3848. Map.TileY := 1;
  3849. Map.Scale := 1;
  3850. Map.Matrix[0] := 1;
  3851. Map.Matrix[4] := 1;
  3852. Map.PW := 1;
  3853. Map.PH := 1;
  3854. Map.CH := 1;
  3855. NFaces := FaceCount;
  3856. InitMeshObjField(Result, InitVertexArray3DS or InitFaceArray3DS);
  3857. if (InitFlags and InitTextArray3DS) <> 0 then
  3858. begin
  3859. NTextVerts := VertexCount;
  3860. InitMeshObjField(Result, InitTextArray3DS);
  3861. end;
  3862. if (InitFlags and InitVFlagArray3DS) <> 0 then
  3863. begin
  3864. NVFlags := VertexCount;
  3865. InitMeshObjField(Result, InitVFlagArray3DS);
  3866. end;
  3867. if (InitFlags and InitSmoothArray3DS) <> 0 then
  3868. InitMeshObjField(Result, InitSmoothArray3DS);
  3869. end;
  3870. end;
  3871. //---------------------------------------------------------------------------------------------------------------------
  3872. procedure ReleaseMeshObj(Mesh: PMesh3DS);
  3873. begin
  3874. if Assigned(Mesh) then
  3875. begin
  3876. RelMeshObjField(Mesh^, RelAll3DS);
  3877. Dispose(Mesh);
  3878. end;
  3879. end;
  3880. //---------------------------------------------------------------------------------------------------------------------
  3881. function GetMeshEntryChunk(const Source: TFile3DS; Chunk: PChunk3DS): TMesh3DS;
  3882. var
  3883. NTriChunk, FaceArrayChunk, DataChunk, Current: PChunk3DS;
  3884. I: integer;
  3885. begin
  3886. NTriChunk := FindNextChunk(Chunk^.Children, N_TRI_OBJECT);
  3887. if NTriChunk = nil then
  3888. ShowError(strError3DS_WRONG_OBJECT);
  3889. Result := InitMeshObj(0, 0, 0);
  3890. with Result do
  3891. begin
  3892. // get the mesh name
  3893. Source.ReadChunkData(Chunk);
  3894. NameStr := StrPas(Chunk^.Data.NamedObject);
  3895. Current := NTriChunk^.Children;
  3896. while Assigned(Current) do
  3897. begin
  3898. case Current^.Tag of
  3899. POINT_ARRAY:
  3900. begin
  3901. Source.ReadChunkData(Current);
  3902. NVertices := Current^.Data.PointArray^.Vertices;
  3903. VertexArray := Current^.Data.PointArray^.PointList;
  3904. // avoid freeing the just allocated memory
  3905. Current^.Data.PointArray^.PointList := nil;
  3906. FreeChunkData(Current);
  3907. end;
  3908. POINT_FLAG_ARRAY:
  3909. begin
  3910. Source.ReadChunkData(Current);
  3911. NVFlags := Current^.Data.PointFlagArray^.Flags;
  3912. VFlagArray := Current^.Data.PointFlagArray^.FlagList;
  3913. Current^.Data.PointFlagArray^.FlagList := nil;
  3914. FreeChunkData(Current);
  3915. end;
  3916. FACE_ARRAY:
  3917. begin
  3918. Source.ReadChunkData(Current);
  3919. NFaces := Current^.Data.FaceArray^.Faces;
  3920. FaceArray := Current^.Data.FaceArray^.FaceList;
  3921. Current^.Data.FaceArray^.FaceList := nil;
  3922. if Assigned(Current^.Children) then
  3923. begin
  3924. // begin search for MESH_MAT_GROUP and SMOOTH_GROUP
  3925. FaceArrayChunk := Current;
  3926. // creates a list of all mesh mat groups
  3927. DataChunk := FindChunk(FaceArrayChunk, MSH_MAT_GROUP);
  3928. if Assigned(DataChunk) then
  3929. begin
  3930. NMats := GetMeshMatCount(DataChunk);
  3931. MatArray := AllocMem(NMats * SizeOf(TObjMat3DS));
  3932. for I := 0 to NMats - 1 do
  3933. begin
  3934. Source.ReadChunkData(DataChunk);
  3935. MatArray^[I].NameStr := DataChunk^.Data.MshMatGroup^.MatNameStr;
  3936. MatArray^[I].NFaces := DataChunk^.Data.MshMatGroup^.Faces;
  3937. MatArray^[I].FaceIndex := DataChunk^.Data.MshMatGroup^.FaceList;
  3938. DataChunk^.Data.MshMatGroup^.FaceList := nil;
  3939. FreeChunkData(DataChunk);
  3940. DataChunk := FindNextChunk(DataChunk^.Sibling, MSH_MAT_GROUP);
  3941. end;
  3942. end;
  3943. DataChunk := FindNextChunk(FaceArrayChunk^.Children, SMOOTH_GROUP);
  3944. if Assigned(DataChunk) then
  3945. begin
  3946. Source.ReadChunkData(DataChunk);
  3947. SmoothArray := DataChunk^.Data.SmoothGroup^.GroupList;
  3948. DataChunk^.Data.SmoothGroup^.GroupList := nil;
  3949. FreeChunkData(DataChunk);
  3950. end;
  3951. DataChunk := FindNextChunk(FaceArrayChunk^.Children, MSH_BOXMAP);
  3952. if Assigned(DataChunk) then
  3953. begin
  3954. Source.ReadChunkData(DataChunk);
  3955. for I := 0 to 5 do
  3956. BoxMapStr[I] := string(DataChunk^.Data.MshBoxmap^[I]);
  3957. UseBoxmap := True;
  3958. FreeChunkData(DataChunk);
  3959. end;
  3960. end;
  3961. FreeChunkData(Current);
  3962. end;
  3963. TEX_VERTS:
  3964. begin
  3965. Source.ReadChunkData(Current);
  3966. ntextverts := Current^.Data.TexVerts^.NumCoords;
  3967. TextArray := Current^.Data.TexVerts^.TextVertList;
  3968. Current^.Data.TexVerts^.TextVertList := nil;
  3969. FreeChunkData(Current);
  3970. end;
  3971. MESH_MATRIX:
  3972. begin
  3973. Source.ReadChunkData(Current);
  3974. LocMatrix := Current^.Data.MeshMatrix^;
  3975. FreeChunkData(Current);
  3976. end;
  3977. MESH_TEXTURE_INFO:
  3978. begin
  3979. UseMapInfo := True;
  3980. Source.ReadChunkData(Current);
  3981. Map.MapType := Current^.Data.MeshTextureInfo^.MapType;
  3982. Map.TileX := Current^.Data.MeshTextureInfo^.XTiling;
  3983. Map.TileY := Current^.Data.MeshTextureInfo^.YTiling;
  3984. Map.CenX := Current^.Data.MeshTextureInfo^.IconPos.X;
  3985. Map.CenY := Current^.Data.MeshTextureInfo^.IconPos.Y;
  3986. Map.CenZ := Current^.Data.MeshTextureInfo^.IconPos.Z;
  3987. Map.Scale := Current^.Data.MeshTextureInfo^.IconScaling;
  3988. Map.Matrix := Current^.Data.MeshTextureInfo^.XMatrix;
  3989. Map.PW := Current^.Data.MeshTextureInfo^.IconWidth;
  3990. Map.PH := Current^.Data.MeshTextureInfo^.IconHeight;
  3991. Map.CH := Current^.Data.MeshTextureInfo^.CylIconHeight;
  3992. FreeChunkData(Current);
  3993. end;
  3994. PROC_NAME:
  3995. begin
  3996. Source.ReadChunkData(Current);
  3997. ProcNameStr := string(StrPas(Current^.Data.ProcName));
  3998. FreeChunkData(Current);
  3999. end;
  4000. PROC_DATA:
  4001. begin
  4002. Source.ReadChunkData(Current);
  4003. ProcSize := Current^.Data.IpasData^.Size;
  4004. ProcData := Current^.Data.IpasData^.Data;
  4005. Current^.Data.IpasData^.Data := nil;
  4006. FreeChunkData(Current);
  4007. end;
  4008. MESH_COLOR:
  4009. begin
  4010. Source.ReadChunkData(Current);
  4011. MeshColor := Current^.Data.MeshColor^;
  4012. FreeChunkData(Current);
  4013. end;
  4014. end;
  4015. Current := Current^.Sibling;
  4016. end;
  4017. IsHidden := Assigned(FindNextChunk(Chunk^.Children, OBJ_HIDDEN));
  4018. IsVisLofter := Assigned(FindNextChunk(Chunk^.Children, OBJ_VIS_LOFTER));
  4019. IsNoCast := Assigned(FindNextChunk(Chunk^.Children, OBJ_DOESNT_CAST));
  4020. IsMatte := Assigned(FindNextChunk(Chunk^.Children, OBJ_MATTE));
  4021. IsFast := Assigned(FindNextChunk(Chunk^.Children, OBJ_FAST));
  4022. IsFrozen := Assigned(FindNextChunk(Chunk^.Children, OBJ_FROZEN));
  4023. IsNoRcvShad := Assigned(FindNextChunk(Chunk^.Children, OBJ_DONT_RCVSHADOW));
  4024. UseProc := Assigned(FindNextChunk(Chunk^.Children, OBJ_PROCEDURAL));
  4025. end;
  4026. end;
  4027. //---------------------------------------------------------------------------------------------------------------------
  4028. function GetMeshByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  4029. Index: integer): TMesh3DS;
  4030. // fills a mesh structure from the (index)th mesh reference found in DB
  4031. var
  4032. Current: PChunk3DS;
  4033. I, Count: integer;
  4034. begin
  4035. FillChar(Result, SizeOf(Result), 0);
  4036. if DB.TopChunk = nil then
  4037. ShowError(strError3DS_INVALID_DATABASE);
  4038. if (DB.TopChunk^.Tag <> M3DMAGIC) and (DB.TopChunk^.Tag <> CMAGIC) then
  4039. ShowError(strError3DS_WRONG_DATABASE);
  4040. // update the index to named objects if the list has changed recently
  4041. UpdateNamedObjectList(Source, DB);
  4042. // scan through the list of named objects
  4043. Count := 0;
  4044. for I := 0 to DB.ObjList^.Count - 1 do
  4045. begin
  4046. // search each named object for a mesh chunk
  4047. Current := FindChunk(DB.ObjList^.List^[I].Chunk, N_TRI_OBJECT);
  4048. // if a mesh chunk is found
  4049. if Assigned(Current) then
  4050. begin
  4051. // increment the running total
  4052. Inc(Count);
  4053. // if this is the (index)th mesh, fill out the structure
  4054. if (Count - 1) = Index then
  4055. begin
  4056. Result := GetMeshEntryChunk(Source, DB.ObjList^.List^[I].Chunk);
  4057. Break;
  4058. end;
  4059. end;
  4060. end;
  4061. end;
  4062. //----------------- spot and omni light handling ----------------------------------------------------------------------
  4063. function GetOmnilightCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  4064. var
  4065. DLite, SpotL: PChunk3DS;
  4066. I: integer;
  4067. begin
  4068. // update the index to named objects if the list has changed recently
  4069. UpdateNamedObjectList(Source, DB);
  4070. Result := 0;
  4071. if DB.ObjList = nil then
  4072. Exit;
  4073. // scan through the list of named objects looking for lights
  4074. for I := 0 to DB.ObjList^.Count - 1 do
  4075. begin
  4076. // search each object for a Light chunk
  4077. DLite := FindChunk(DB.ObjList^.List^[I].chunk, N_DIRECT_LIGHT);
  4078. // if one was found, check to see if its a spotlight
  4079. if Assigned(DLite) then
  4080. begin
  4081. SpotL := FindChunk(DLite, DL_SPOTLIGHT);
  4082. // if it isn't a spotlight then increment the count
  4083. if SpotL = nil then
  4084. Inc(Result);
  4085. end;
  4086. end;
  4087. end;
  4088. //---------------------------------------------------------------------------------------------------------------------
  4089. function GetSpotlightCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  4090. var
  4091. DLite, SpotL: PChunk3DS;
  4092. I: integer;
  4093. begin
  4094. // update the index to named objects if the list has changed recently
  4095. UpdateNamedObjectList(Source, DB);
  4096. Result := 0;
  4097. if DB.ObjList = nil then
  4098. Exit;
  4099. // scan through the list of named objects looking for lights
  4100. for I := 0 to DB.ObjList^.Count - 1 do
  4101. begin
  4102. // search each object for a Light chunk
  4103. DLite := FindChunk(DB.ObjList^.List^[I].Chunk, N_DIRECT_LIGHT);
  4104. // if one was found, check to see if its a spotlight
  4105. if Assigned(DLite) then
  4106. begin
  4107. SpotL := FindChunk(DLite, DL_SPOTLIGHT);
  4108. // if it is a spotlight then increment the count
  4109. if Assigned(SpotL) then
  4110. Inc(Result);
  4111. end;
  4112. end;
  4113. end;
  4114. //---------------------------------------------------------------------------------------------------------------------
  4115. procedure InitLight(var Light: TLight3DS);
  4116. // Initializes the Light structure
  4117. begin
  4118. FillChar(Light, SizeOf(Light), 0);
  4119. with Light do
  4120. begin
  4121. NameStr := '';
  4122. Color.R := 0.708852;
  4123. Color.G := 0.708852;
  4124. Color.B := 0.708852;
  4125. Multiplier := 1;
  4126. Attenuation.Inner := 10;
  4127. Attenuation.Outer := 100;
  4128. Exclude := TStringList.Create;
  4129. end;
  4130. end;
  4131. //---------------------------------------------------------------------------------------------------------------------
  4132. procedure ReleaseLight(Light: PLight3DS);
  4133. begin
  4134. Light^.Exclude.Free;
  4135. Light^.Exclude := nil;
  4136. if Assigned(Light^.Spot) then
  4137. begin
  4138. Light^.Spot^.Projector.BitmapStr := '';
  4139. FreeMem(Light^.Spot);
  4140. end;
  4141. Dispose(Light);
  4142. end;
  4143. //---------------------------------------------------------------------------------------------------------------------
  4144. procedure InitSpotLight(var SpotLight: TLight3DS);
  4145. begin
  4146. // do the common Light initialization
  4147. InitLight(SpotLight);
  4148. SpotLight.Spot := AllocMem(SizeOf(TSpotLight3DS));
  4149. with SpotLight.Spot^ do
  4150. begin
  4151. Target.X := 1;
  4152. Target.Y := 1;
  4153. Target.Z := 1;
  4154. Hotspot := 44;
  4155. Falloff := 45;
  4156. Aspect := 1;
  4157. Shadows.AType := ssUseShadowMap;
  4158. Shadows.Bias := 1;
  4159. Shadows.Filter := 3;
  4160. Shadows.Mapsize := 512;
  4161. Shadows.RayBias := 1;
  4162. Cone.AType := csCircular;
  4163. end;
  4164. end;
  4165. //---------------------------------------------------------------------------------------------------------------------
  4166. function GetLightEntryChunk(const Source: TFile3DS; Chunk: PChunk3DS): TLight3DS;
  4167. // fills out the given Light structure with the Light pointed to by Chunk
  4168. var
  4169. DLite, SpotChunk, Current: PChunk3DS;
  4170. begin
  4171. DLite := FindNextChunk(Chunk^.Children, N_DIRECT_LIGHT);
  4172. if DLite = nil then
  4173. ShowError(strError3DS_WRONG_OBJECT);
  4174. DLite := FindChunk(Chunk^.Children, N_DIRECT_LIGHT);
  4175. SpotChunk := FindChunk(Chunk, DL_SPOTLIGHT);
  4176. if Assigned(DLite) then
  4177. with Result do
  4178. begin
  4179. // initilize Light
  4180. if SpotChunk = nil then
  4181. InitLight(Result)
  4182. else
  4183. InitSpotLight(Result);
  4184. // read object name
  4185. Source.ReadChunkData(Chunk);
  4186. NameStr := StrPas(Chunk^.Data.NamedObject);
  4187. FreeChunkData(Chunk);
  4188. // read Light postion
  4189. Source.ReadChunkData(DLite);
  4190. Pos := DLite^.Data.NDirectLight^;
  4191. // scan all the chunks the Light contains
  4192. Current := DLite^.Children;
  4193. while Assigned(Current) do
  4194. begin
  4195. case Current^.Tag of
  4196. COLOR_F:
  4197. begin
  4198. Source.ReadChunkData(Current);
  4199. Color.R := Current^.Data.ColorF^.Red;
  4200. Color.G := Current^.Data.ColorF^.Green;
  4201. Color.B := Current^.Data.ColorF^.Blue;
  4202. FreeChunkData(Current);
  4203. end;
  4204. COLOR_24:
  4205. begin
  4206. Source.ReadChunkData(Current);
  4207. Color.R := Current^.Data.Color24^.Red / 255;
  4208. Color.G := Current^.Data.Color24^.Green / 255;
  4209. Color.B := Current^.Data.Color24^.Blue / 255;
  4210. FreeChunkData(Current);
  4211. end;
  4212. DL_MULTIPLIER:
  4213. begin
  4214. Source.ReadChunkData(Current);
  4215. Multiplier := Current^.Data.DlMultiplier^;
  4216. FreeChunkData(Current);
  4217. end;
  4218. DL_INNER_RANGE:
  4219. begin
  4220. Source.ReadChunkData(Current);
  4221. // assuming since there is a value it is on
  4222. Attenuation.Inner := Current^.Data.DlInnerRange^;
  4223. FreeChunkData(Current);
  4224. end;
  4225. DL_OUTER_RANGE:
  4226. begin
  4227. Source.ReadChunkData(Current);
  4228. // assuming since there is a value it is on
  4229. Attenuation.Outer := Current^.Data.DlOuterRange^;
  4230. FreeChunkData(Current);
  4231. end;
  4232. DL_EXCLUDE:
  4233. begin
  4234. Source.ReadChunkData(Current);
  4235. Exclude.Add(string(Current^.Data.DlExclude^));
  4236. FreeChunkData(Current);
  4237. end;
  4238. DL_OFF:
  4239. DLOff := True;
  4240. DL_ATTENUATE:
  4241. Attenuation.IsOn := True;
  4242. end;
  4243. Current := Current^.Sibling;
  4244. end;
  4245. // DL_SPOTLIGHT chunk
  4246. if Assigned(SpotChunk) then
  4247. begin
  4248. // read spotlight data
  4249. Source.ReadChunkData(SpotChunk);
  4250. Spot^.Target := SpotChunk^.Data.DlSpotlight^.SpotLightTarg;
  4251. Spot^.Hotspot := SpotChunk^.Data.DlSpotlight^.HotspotAngle;
  4252. Spot^.Falloff := SpotChunk^.Data.DlSpotlight^.FalloffAngle;
  4253. // scan all the chunks the spotlight contains
  4254. Current := SpotChunk^.Children;
  4255. while Assigned(Current) do
  4256. begin
  4257. case Current^.Tag of
  4258. DL_SPOT_ROLL:
  4259. begin
  4260. Source.ReadChunkData(Current);
  4261. Spot^.Roll := Current^.Data.DlSpotRoll^;
  4262. FreeChunkData(Current);
  4263. end;
  4264. DL_LOCAL_SHADOW:
  4265. Spot^.Shadows.Cast := True;
  4266. DL_LOCAL_SHADOW2:
  4267. begin
  4268. Source.ReadChunkData(Current);
  4269. Spot^.Shadows.Bias := Current^.Data.DlLocalShadow2^.LocalShadowBias;
  4270. Spot^.Shadows.Filter := Current^.Data.DlLocalShadow2^.LocalShadowFilter;
  4271. Spot^.Shadows.Mapsize :=
  4272. Current^.Data.DlLocalShadow2^.LocalShadowMapSize;
  4273. Spot^.Shadows.Local := True;
  4274. FreeChunkData(Current);
  4275. end;
  4276. DL_SHADOWED:
  4277. Spot^.Shadows.Cast := True;
  4278. DL_SPOT_RECTANGULAR:
  4279. Spot^.Cone.AType := csRectangular;
  4280. DL_SEE_CONE:
  4281. Spot^.Cone.Show := True;
  4282. DL_SPOT_OVERSHOOT:
  4283. Spot^.Cone.Overshoot := True;
  4284. DL_SPOT_ASPECT:
  4285. begin
  4286. Source.ReadChunkData(Current);
  4287. Spot^.Aspect := Current^.Data.DlSpotAspect^;
  4288. FreeChunkData(Current);
  4289. end;
  4290. DL_RAY_BIAS:
  4291. begin
  4292. Source.ReadChunkData(Current);
  4293. Spot^.Shadows.RayBias := Current^.Data.DlRayBias^;
  4294. FreeChunkData(Current);
  4295. end;
  4296. DL_RAYSHAD:
  4297. Spot^.Shadows.AType := ssUseRayTraceShadow;
  4298. DL_SPOT_PROJECTOR:
  4299. begin
  4300. Source.ReadChunkData(Current);
  4301. Spot^.Projector.BitmapStr :=
  4302. string(StrPas(Current^.Data.DlSpotProjector));
  4303. Spot^.Projector.Use := True;
  4304. FreeChunkData(Current);
  4305. end;
  4306. end;
  4307. Current := Current^.Sibling;
  4308. end;
  4309. end;
  4310. end;
  4311. end;
  4312. //---------------------------------------------------------------------------------------------------------------------
  4313. function GetOmnilightByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  4314. Index: integer): TLight3DS;
  4315. // fills out the omnilight structure from the (index)th mesh reference found in DB
  4316. var
  4317. LightChunk, SpotChunk: PChunk3DS;
  4318. I, Count: integer;
  4319. begin
  4320. FillChar(Result, SizeOf(Result), 0);
  4321. if (DB.TopChunk = nil) then
  4322. ShowError(strError3DS_INVALID_DATABASE);
  4323. if not (DB.TopChunk^.Tag = M3DMAGIC) and not (DB.TopChunk^.Tag = CMAGIC) then
  4324. ShowError(strError3DS_WRONG_DATABASE);
  4325. // update the list if it's changed recently
  4326. UpdateNamedObjectList(Source, DB);
  4327. // Scan through the List
  4328. Count := 0;
  4329. for I := 0 to DB.ObjList^.Count - 1 do
  4330. begin
  4331. // search for a Light chunk
  4332. LightChunk := FindChunk(DB.ObjList^.List^[I].Chunk, N_DIRECT_LIGHT);
  4333. // if one was found check to see if its a spot
  4334. if Assigned(LightChunk) then
  4335. begin
  4336. SpotChunk := FindChunk(LightChunk, DL_SPOTLIGHT);
  4337. // if its not a spot then increment the count
  4338. if SpotChunk = nil then
  4339. begin
  4340. Inc(Count);
  4341. // if this is the (index)th Light file out the structure
  4342. if (Count - 1) = Index then
  4343. begin
  4344. Result := GetLightEntryChunk(Source, DB.ObjList^.List^[I].Chunk);
  4345. Break;
  4346. end;
  4347. end;
  4348. end;
  4349. end;
  4350. end;
  4351. //---------------------------------------------------------------------------------------------------------------------
  4352. function GetSpotlightByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  4353. Index: integer): TLight3DS;
  4354. // fills out the Spot structure from the (index)th spot reference found in DB
  4355. var
  4356. LightChunk, SpotChunk: PChunk3DS;
  4357. I, Count: integer;
  4358. begin
  4359. FillChar(Result, SizeOf(Result), 0);
  4360. if (DB.TopChunk = nil) then
  4361. ShowError(strError3DS_INVALID_DATABASE);
  4362. if not (DB.TopChunk^.Tag = M3DMAGIC) and not (DB.TopChunk^.Tag = CMAGIC) then
  4363. ShowError(strError3DS_WRONG_DATABASE);
  4364. // update the list if it's changed recently
  4365. UpdateNamedObjectList(Source, DB);
  4366. // Scan through the List
  4367. Count := 0;
  4368. for I := 0 to DB.ObjList^.Count - 1 do
  4369. begin
  4370. // search for a Light chunk
  4371. LightChunk := FindChunk(DB.ObjList^.List^[I].Chunk, N_DIRECT_LIGHT);
  4372. // if one was found check to see if its a spot
  4373. if Assigned(LightChunk) then
  4374. begin
  4375. SpotChunk := FindChunk(LightChunk, DL_SPOTLIGHT);
  4376. // if its not a spot then increment the count
  4377. if Assigned(SpotChunk) then
  4378. begin
  4379. Inc(Count);
  4380. // if this is the (index)th Light file out the structure
  4381. if (Count - 1) = Index then
  4382. begin
  4383. Result := GetLightEntryChunk(Source, DB.ObjList^.List^[I].Chunk);
  4384. Break;
  4385. end;
  4386. end;
  4387. end;
  4388. end;
  4389. end;
  4390. //----------------- camera handling -----------------------------------------------------------------------------------
  4391. procedure InitCamera(var Camera: TCamera3DS);
  4392. begin
  4393. FillChar(Camera, SizeOf(Camera), 0);
  4394. with Camera do
  4395. begin
  4396. Target.X := 1;
  4397. Target.Y := 1;
  4398. Target.Z := 1;
  4399. FOV := 45;
  4400. Ranges.CamNear := 10;
  4401. Ranges.CamFar := 1000;
  4402. end;
  4403. end;
  4404. //---------------------------------------------------------------------------------------------------------------------
  4405. procedure ReleaseCamera(Camera: PCamera3DS);
  4406. begin
  4407. if Assigned(Camera) then
  4408. begin
  4409. Dispose(Camera);
  4410. end;
  4411. end;
  4412. //---------------------------------------------------------------------------------------------------------------------
  4413. function GetCameraCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  4414. var
  4415. Chunk: PChunk3DS;
  4416. I: integer;
  4417. begin
  4418. UpdateNamedObjectList(Source, DB);
  4419. Result := 0;
  4420. if Assigned(DB.ObjList) then
  4421. for I := 0 to DB.ObjList^.Count - 1 do
  4422. begin
  4423. Chunk := FindChunk(DB.ObjList^.List^[I].Chunk, N_CAMERA);
  4424. if Assigned(Chunk) then
  4425. Inc(Result);
  4426. end;
  4427. end;
  4428. //---------------------------------------------------------------------------------------------------------------------
  4429. function GetCameraEntry(const Source: TFile3DS; Chunk: PChunk3DS): TCamera3DS;
  4430. var
  4431. Current, Camera: PChunk3DS;
  4432. begin
  4433. if Chunk^.Tag <> NAMED_OBJECT then
  4434. ShowError(strError3DS_WRONG_OBJECT);
  4435. Camera := FindNextChunk(Chunk^.Children, N_CAMERA);
  4436. if Camera = nil then
  4437. ShowError(strError3DS_WRONG_OBJECT);
  4438. with Result do
  4439. begin
  4440. InitCamera(Result);
  4441. Camera := FindNextChunk(Chunk^.Children, N_CAMERA);
  4442. Source.ReadChunkData(Chunk);
  4443. NameStr := StrPas(Chunk^.Data.NamedObject);
  4444. FreeChunkData(Chunk);
  4445. Source.ReadChunkData(Camera);
  4446. Position.X := Camera^.Data.NCamera^.CameraPos.X;
  4447. Position.Y := Camera^.Data.NCamera^.CameraPos.Y;
  4448. Position.Z := Camera^.Data.NCamera^.CameraPos.Z;
  4449. Target.X := Camera^.Data.NCamera^.TargetPos.X;
  4450. Target.Y := Camera^.Data.NCamera^.TargetPos.Y;
  4451. Target.Z := Camera^.Data.NCamera^.TargetPos.Z;
  4452. Roll := Camera^.Data.NCamera^.CameraBank;
  4453. FOV := 2400 / Camera^.Data.NCamera^.CameraFocalLength;
  4454. FreeChunkData(Camera);
  4455. Current := Camera^.Children;
  4456. while Assigned(Current) do
  4457. begin
  4458. case Current^.Tag of
  4459. CAM_SEE_CONE:
  4460. ShowCone := True;
  4461. CAM_RANGES:
  4462. begin
  4463. Source.ReadChunkData(Current);
  4464. Ranges.CamNear := Current^.Data.CamRanges^.NearPlane;
  4465. Ranges.CamFar := Current^.Data.CamRanges^.FarPlane;
  4466. FreeChunkData(Current);
  4467. end;
  4468. end;
  4469. Current := Current^.Sibling;
  4470. end;
  4471. end;
  4472. end;
  4473. //---------------------------------------------------------------------------------------------------------------------
  4474. function GetCameraByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  4475. Index: integer): TCamera3DS;
  4476. var
  4477. Camera: PChunk3DS;
  4478. I, Count: integer;
  4479. begin
  4480. FillChar(Result, SizeOf(Result), 0);
  4481. UpdateNamedObjectList(Source, DB);
  4482. Count := 0;
  4483. for I := 0 to DB.ObjList^.Count - 1 do
  4484. begin
  4485. Camera := FindChunk(DB.ObjList^.List^[I].Chunk, N_CAMERA);
  4486. if Assigned(Camera) then
  4487. begin
  4488. Inc(Count);
  4489. if (Count - 1) = Index then
  4490. Result := GetCameraEntry(Source, DB.ObjList^.List^[I].Chunk);
  4491. end;
  4492. end;
  4493. end;
  4494. //----------------- common animation settings -------------------------------------------------------------------------
  4495. procedure InitKfSets(var Key: TKFSets3DS);
  4496. begin
  4497. Key.Anim.Length := 30;
  4498. Key.Anim.CurFrame := 0;
  4499. Key.Seg.Use := False;
  4500. Key.Seg.SegBegin := 0;
  4501. Key.Seg.SegEnd := 30;
  4502. end;
  4503. //---------------------------------------------------------------------------------------------------------------------
  4504. function GetKFSeg(TopChunk: PChunk3DS): PChunk3DS;
  4505. // all the keyframe information has to go in the appropriate segment KFDATA
  4506. begin
  4507. // look for KFDATA
  4508. Result := FindNextChunk(TopChunk^.Children, KFDATA);
  4509. if Result = nil then
  4510. Result := PutGenericNode(KFDATA, TopChunk);
  4511. end;
  4512. //---------------------------------------------------------------------------------------------------------------------
  4513. function GetKeyInfo(const Source: TFile3DS; var DB: TDatabase3DS): TKFKeyInfo3DS;
  4514. var
  4515. KFData, KFHdrChunk, KFCTChunk: PChunk3DS;
  4516. begin
  4517. KFData := GetKfSeg(DB.TopChunk);
  4518. KFHdrChunk := FindNextChunk(KFData^.Children, KFHDR);
  4519. if Assigned(KFHdrChunk) then
  4520. begin
  4521. Source.ReadChunkData(KFHdrChunk);
  4522. Result.Length := KFHdrChunk^.Data.KFHdr^.AnimLength;
  4523. FreeChunkData(KFHdrChunk);
  4524. end;
  4525. KFCTChunk := FindNextChunk(KFData^.Children, KFCURTIME);
  4526. if Assigned(KFCTChunk) then
  4527. begin
  4528. Source.ReadChunkData(KFCTChunk);
  4529. Result.CurFrame := KFCTChunk^.Data.KFCurTime^;
  4530. FreeChunkData(KFCTChunk);
  4531. end;
  4532. end;
  4533. //---------------------------------------------------------------------------------------------------------------------
  4534. function GetKFSegment(const Source: TFile3DS; var DB: TDatabase3DS): TKFSegment3DS;
  4535. var
  4536. DataChunk, SegChunk: PChunk3DS;
  4537. begin
  4538. Result.SegBegin := 0;
  4539. Result.SegEnd := 0;
  4540. Result.Use := False;
  4541. DataChunk := GetKFSeg(DB.TopChunk);
  4542. SegChunk := FindNextChunk(DataChunk^.Children, KFSEG);
  4543. if Assigned(SegChunk) then
  4544. begin
  4545. Source.ReadChunkData(SegChunk);
  4546. Result.Use := True;
  4547. Result.SegBegin := SegChunk^.Data.KFSeg^.First;
  4548. Result.SegEnd := SegChunk^.Data.KFSeg^.Last;
  4549. FreeChunkData(SegChunk);
  4550. end;
  4551. end;
  4552. //---------------------------------------------------------------------------------------------------------------------
  4553. function GetKFSettings(const Source: TFile3DS; var DB: TDatabase3DS): TKFSets3DS;
  4554. begin
  4555. FillChar(Result, SizeOf(Result), 0);
  4556. if DB.TopChunk = nil then
  4557. ShowError(strError3DS_INVALID_DATABASE);
  4558. if (DB.TopChunk^.Tag <> M3DMAGIC) and (DB.TopChunk^.Tag <> CMAGIC) then
  4559. ShowError(strError3DS_WRONG_DATABASE);
  4560. InitKFSets(Result);
  4561. Result.Anim := GetKeyInfo(Source, DB);
  4562. Result.Seg := GetKFSegment(Source, DB);
  4563. end;
  4564. //----------------- Camera animation ----------------------------------------------------------------------------------
  4565. procedure InitCameraMotion(var Camera: TKFCamera3DS;
  4566. NewNPKeys, NewNFKeys, NewNRKeys, NewNTKeys: cardinal);
  4567. var
  4568. I: integer;
  4569. begin
  4570. with Camera do
  4571. begin
  4572. // free any previously allocated memory first
  4573. if Assigned(PKeys) then
  4574. FreeMem(PKeys);
  4575. if Assigned(Pos) then
  4576. FreeMem(Pos);
  4577. if Assigned(FKeys) then
  4578. FreeMem(FKeys);
  4579. if Assigned(FOV) then
  4580. FreeMem(FOV);
  4581. if Assigned(RKeys) then
  4582. FreeMem(RKeys);
  4583. if Assigned(Roll) then
  4584. FreeMem(Roll);
  4585. if Assigned(TKeys) then
  4586. FreeMem(TKeys);
  4587. if Assigned(TPos) then
  4588. FreeMem(TPos);
  4589. FillChar(Camera, SizeOf(TKFCamera3DS), 0);
  4590. NPKeys := NewNPKeys;
  4591. NFKeys := NewNFKeys;
  4592. NRKeys := NewNRKeys;
  4593. NTKeys := NewNTKeys;
  4594. if NPKeys <> 0 then
  4595. begin
  4596. NPFlag := TrackSingle3DS;
  4597. PKeys := AllocMem(NPKeys * SizeOf(TKeyHeader3DS));
  4598. for I := 0 to NPKeys - 1 do
  4599. PKeys^[I] := DefKeyHeader3DS;
  4600. Pos := AllocMem(NPKeys * SizeOf(TPoint3DS));
  4601. for I := 0 to NPKeys - 1 do
  4602. Pos^[I] := DefPoint3DS;
  4603. end;
  4604. if NFKeys <> 0 then
  4605. begin
  4606. NFFlag := TrackSingle3DS;
  4607. FKeys := AllocMem(NFKeys * SizeOf(TKeyHeader3DS));
  4608. for I := 0 to NFKeys - 1 do
  4609. FKeys^[I] := DefKeyHeader3DS;
  4610. FOV := AllocMem(NFKeys * SizeOf(single));
  4611. for I := 0 to NFKeys - 1 do
  4612. FOV^[I] := 60;
  4613. end;
  4614. if NRKeys <> 0 then
  4615. begin
  4616. NRFlag := TrackSingle3DS;
  4617. RKeys := AllocMem(NRKeys * SizeOf(TKeyHeader3DS));
  4618. for I := 0 to NRKeys - 1 do
  4619. RKeys^[I] := DefKeyHeader3DS;
  4620. Roll := AllocMem(NRKeys * SizeOf(single));
  4621. end;
  4622. if NTKeys <> 0 then
  4623. begin
  4624. NTFlag := TrackSingle3DS;
  4625. TFlags1 := 0;
  4626. TFlags2 := 0;
  4627. TKeys := AllocMem(NTKeys * SizeOf(TKeyHeader3DS));
  4628. for I := 0 to NTKeys - 1 do
  4629. TKeys^[I] := DefKeyHeader3DS;
  4630. TPos := AllocMem(NTKeys * SizeOf(TPoint3DS));
  4631. for I := 0 to NTKeys - 1 do
  4632. TPos^[I] := DefPoint3DS;
  4633. end;
  4634. end;
  4635. end;
  4636. //---------------------------------------------------------------------------------------------------------------------
  4637. procedure ReleaseCameraMotion(Camera: PKFCamera3DS);
  4638. begin
  4639. if Assigned(Camera) then
  4640. begin
  4641. with Camera^ do
  4642. begin
  4643. if Assigned(PKeys) then
  4644. FreeMem(PKeys);
  4645. if Assigned(Pos) then
  4646. FreeMem(Pos);
  4647. if Assigned(FKeys) then
  4648. FreeMem(FKeys);
  4649. if Assigned(FOV) then
  4650. FreeMem(FOV);
  4651. if Assigned(RKeys) then
  4652. FreeMem(RKeys);
  4653. if Assigned(Roll) then
  4654. FreeMem(Roll);
  4655. if Assigned(TKeys) then
  4656. FreeMem(TKeys);
  4657. if Assigned(TPos) then
  4658. FreeMem(TPos);
  4659. end;
  4660. Dispose(Camera);
  4661. end;
  4662. end;
  4663. //---------------------------------------------------------------------------------------------------------------------
  4664. procedure GetCameraNodeNameList(const Source: TFile3DS; var DB: TDatabase3DS;
  4665. List: TStringList);
  4666. begin
  4667. GetGenericNodeNameList(Source, DB, CAMERA_NODE_TAG, List);
  4668. end;
  4669. //---------------------------------------------------------------------------------------------------------------------
  4670. function GetCameraNodeCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  4671. begin
  4672. Result := GetGenericNodeCount(Source, DB, CAMERA_NODE_TAG);
  4673. end;
  4674. //---------------------------------------------------------------------------------------------------------------------
  4675. function GetParentName(const Source: TFile3DS; Chunk: PChunk3DS): string;
  4676. // get parent name if there is one
  4677. var
  4678. NameChunk: PChunk3DS;
  4679. begin
  4680. Result := '';
  4681. NameChunk := FindChunk(Chunk, PARENT_NAME);
  4682. if Assigned(NameChunk) then
  4683. begin
  4684. Source.ReadChunkData(NameChunk);
  4685. Result := string(NameChunk^.Data.NamedObject);
  4686. FreeChunkData(NameChunk);
  4687. end;
  4688. end;
  4689. //---------------------------------------------------------------------------------------------------------------------
  4690. function GetCameraMotion(const Source: TFile3DS;
  4691. CamChunk, TargetChunk: PChunk3DS): TKFCamera3DS;
  4692. // gets camera keyframe information from chunk
  4693. // CamChunk : CAMERA_NODE_TAG chunk to extract data from
  4694. // TargetChunk : TARGET_NODE_TAG chunk to extract target data from
  4695. // KFCamera : Structure to fill in with chunk data
  4696. var
  4697. NodeHdrChunk, PosChunk, FovChunk, RollChunk, TargetPosChunk,
  4698. TargetHdrChunk: PChunk3DS;
  4699. PosKeys, FovKeys, RollKeys, TargetKeys: integer;
  4700. begin
  4701. FillChar(Result, SizeOf(Result), 0);
  4702. TargetPosChunk := nil;
  4703. TargetHdrChunk := nil;
  4704. PosKeys := 0;
  4705. FovKeys := 0;
  4706. RollKeys := 0;
  4707. TargetKeys := 0;
  4708. // get information from chunks
  4709. // search children of camera Chunk
  4710. NodeHdrChunk := FindChunk(CamChunk, NODE_HDR);
  4711. PosChunk := FindChunk(CamChunk, POS_TRACK_TAG);
  4712. FovChunk := FindChunk(CamChunk, FOV_TRACK_TAG);
  4713. RollChunk := FindChunk(CamChunk, ROLL_TRACK_TAG);
  4714. Source.ReadChunkData(NodeHdrChunk);
  4715. if Assigned(PosChunk) then
  4716. begin
  4717. Source.ReadChunkData(PosChunk);
  4718. PosKeys := PosChunk^.Data.PosTrackTag^.TrackHdr.KeyCount;
  4719. end;
  4720. if Assigned(FOVChunk) then
  4721. begin
  4722. Source.ReadChunkData(FOVChunk);
  4723. FovKeys := FOVChunk^.Data.FOVTrackTag^.TrackHdr.KeyCount;
  4724. end;
  4725. if Assigned(RollChunk) then
  4726. begin
  4727. Source.ReadChunkData(RollChunk);
  4728. RollKeys := RollChunk^.Data.RollTrackTag^.TrackHdr.KeyCount;
  4729. end;
  4730. if Assigned(TargetChunk) then
  4731. begin
  4732. TargetHdrChunk := FindChunk(TargetChunk, NODE_HDR);
  4733. if Assigned(TargetHdrChunk) then
  4734. Source.ReadChunkData(TargetHdrChunk);
  4735. TargetPosChunk := FindChunk(TargetChunk, POS_TRACK_TAG);
  4736. if Assigned(TargetPosChunk) then
  4737. begin
  4738. Source.ReadChunkData(TargetPosChunk);
  4739. TargetKeys := TargetPosChunk^.Data.PosTrackTag^.TrackHdr.KeyCount;
  4740. end;
  4741. end;
  4742. // set-up and fill-in the kfcamera structure
  4743. InitCameraMotion(Result, PosKeys, FOVKeys, RollKeys, TargetKeys);
  4744. with Result do
  4745. begin
  4746. // header Information
  4747. if Assigned(NodeHdrChunk) then
  4748. begin
  4749. NameStr := ansistring(NodeHdrChunk^.Data.NodeHdr^.ObjNameStr);
  4750. Flags1 := NodeHdrChunk^.Data.NodeHdr^.Flags1;
  4751. Flags2 := NodeHdrChunk^.Data.NodeHdr^.Flags2;
  4752. end;
  4753. // parents
  4754. ParentStr := ansistring(GetParentName(Source, NodeHdrChunk));
  4755. TParentStr := GetParentName(Source, TargetHdrChunk);
  4756. // target information
  4757. if TargetKeys <> 0 then
  4758. begin
  4759. NTFlag := TargetPosChunk^.Data.PosTrackTag^.TrackHdr.Flags;
  4760. Move(TargetPosChunk^.Data.PosTrackTag^.KeyHdrList^, TKeys^,
  4761. TargetKeys * SizeOf(TKeyHeader3DS));
  4762. Move(TargetPosChunk^.Data.PosTrackTag^.PositionList^, TPos^,
  4763. TargetKeys * SizeOf(TPoint3DS));
  4764. end;
  4765. if Assigned(TargetHdrChunk) then
  4766. begin
  4767. TFlags1 := TargetHdrChunk^.Data.NodeHdr^.Flags1;
  4768. TFlags2 := TargetHdrChunk^.Data.NodeHdr^.Flags2;
  4769. end;
  4770. // position information
  4771. if PosKeys <> 0 then
  4772. begin
  4773. NPFlag := PosChunk^.Data.PosTrackTag^.TrackHdr.Flags;
  4774. Move(PosChunk^.Data.PosTrackTag^.KeyHdrList^, PKeys^, PosKeys *
  4775. SizeOf(TKeyHeader3DS));
  4776. Move(PosChunk^.Data.PosTrackTag^.PositionList^, Pos^, PosKeys * SizeOf(TPoint3DS));
  4777. end;
  4778. // field of view information
  4779. if FOVKeys <> 0 then
  4780. begin
  4781. NFFlag := FOVChunk^.Data.FOVTrackTag^.TrackHdr.Flags;
  4782. Move(FOVChunk^.Data.FOVTrackTag^.KeyHdrList^, FKeys^, FOVKeys *
  4783. SizeOf(TKeyHeader3DS));
  4784. Move(FOVChunk^.Data.FOVTrackTag^.FOVAngleList^, FOV^, FOVKeys * SizeOf(single));
  4785. end;
  4786. // roll track information
  4787. if RollKeys <> 0 then
  4788. begin
  4789. NRFlag := RollChunk^.Data.RollTrackTag^.TrackHdr.Flags;
  4790. Move(RollChunk^.Data.RollTrackTag^.KeyHdrList^, RKeys^, RollKeys *
  4791. SizeOf(TKeyHeader3DS));
  4792. Move(RollChunk^.Data.RollTrackTag^.RollangleList^, Roll^,
  4793. RollKeys * SizeOf(single));
  4794. end;
  4795. // free chunk data
  4796. if Assigned(PosChunk) then
  4797. FreeChunkData(PosChunk);
  4798. if Assigned(FovChunk) then
  4799. FreeChunkData(FovChunk);
  4800. if Assigned(RollChunk) then
  4801. FreeChunkData(RollChunk);
  4802. if Assigned(NodeHdrChunk) then
  4803. FreeChunkData(NodeHdrChunk);
  4804. if Assigned(TargetPosChunk) then
  4805. FreeChunkData(TargetPosChunk);
  4806. if Assigned(TargetHdrChunk) then
  4807. FreeChunkData(TargetHdrChunk);
  4808. end;
  4809. end;
  4810. //---------------------------------------------------------------------------------------------------------------------
  4811. function GetCameraMotionByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  4812. Index: integer): TKFCamera3DS;
  4813. var
  4814. CameraChunk, TargetChunk: PChunk3DS;
  4815. List: TStringList;
  4816. begin
  4817. FillChar(Result, SizeOf(Result), 0);
  4818. List := TStringList.Create;
  4819. try
  4820. GetCameraNodeNameList(Source, DB, List);
  4821. if Index < List.Count then
  4822. begin
  4823. CameraChunk := FindNamedAndTaggedChunk(Source, DB, List[Index], CAMERA_NODE_TAG);
  4824. if Assigned(CameraChunk) then
  4825. begin
  4826. TargetChunk := FindNamedAndTaggedChunk(Source, DB, List[Index], TARGET_NODE_TAG);
  4827. Result := GetCameraMotion(Source, CameraChunk, TargetChunk);
  4828. end;
  4829. end;
  4830. finally
  4831. List.Free;
  4832. end;
  4833. end;
  4834. //----------------- Ambient Light animation ---------------------------------------------------------------------------
  4835. procedure InitAmbientLightMotion(var Light: TKFAmbient3DS; NewNCKeys: cardinal);
  4836. var
  4837. I: integer;
  4838. begin
  4839. with Light do
  4840. begin
  4841. if Assigned(Color) then
  4842. FreeMem(Color);
  4843. if Assigned(CKeys) then
  4844. FreeMem(CKeys);
  4845. FillChar(Light, SizeOf(Light), 0);
  4846. NCKeys := NewNCKeys;
  4847. if NCKeys <> 0 then
  4848. begin
  4849. NCFlag := TrackSingle3DS;
  4850. CKeys := AllocMem(NCKeys * SizeOf(TKeyHeader3DS));
  4851. for I := 0 to NCKeys - 1 do
  4852. CKeys^[I] := DefKeyHeader3DS;
  4853. Color := AllocMem(NCKeys * SizeOf(TFColor3DS));
  4854. for I := 0 to NCKeys - 1 do
  4855. begin
  4856. Color^[I].R := 1;
  4857. Color^[I].G := 1;
  4858. Color^[I].B := 1;
  4859. end;
  4860. end;
  4861. end;
  4862. end;
  4863. //---------------------------------------------------------------------------------------------------------------------
  4864. procedure ReleaseAmbientLightMotion(Light: PKFAmbient3DS);
  4865. begin
  4866. if Assigned(Light) then
  4867. begin
  4868. with Light^ do
  4869. begin
  4870. if Assigned(CKeys) then
  4871. FreeMem(CKeys);
  4872. if Assigned(Color) then
  4873. FreeMem(Color);
  4874. end;
  4875. Dispose(Light);
  4876. end;
  4877. end;
  4878. //---------------------------------------------------------------------------------------------------------------------
  4879. function GetAmbientLightMotionChunk(const Source: TFile3DS;
  4880. AmbientChunk: PChunk3DS): TKFAmbient3DS;
  4881. // AmbientChunk : SPOTAMBIENT_NODE_TAG chunk to extract data from
  4882. // TargetChunk : L_TARGET_NODE_TAG chunk to extract target data from
  4883. // KFSpot : Structure to fill in with chunk data
  4884. // Gets AmbientLight keyframe information from chunk
  4885. // L_TARGET
  4886. // ...
  4887. // NODE_HDR
  4888. // APP_DATA
  4889. // COL_TRACK
  4890. var
  4891. NodeHdrChunk, ColChunk: PChunk3DS;
  4892. ColKeys: integer;
  4893. begin
  4894. if AmbientChunk = nil then
  4895. ShowError(strERROR3DS_INVALID_ARG);
  4896. FillChar(Result, SizeOf(Result), 0);
  4897. // get information from chunks
  4898. // search children of AmbientLight chunk
  4899. NodeHdrChunk := FindChunk(AmbientChunk, NODE_HDR);
  4900. ColChunk := FindChunk(AmbientChunk, COL_TRACK_TAG);
  4901. if Assigned(NodeHdrChunk) then
  4902. Source.ReadChunkData(NodeHdrChunk);
  4903. if Assigned(ColChunk) then
  4904. begin
  4905. Source.ReadChunkData(ColChunk);
  4906. ColKeys := ColChunk^.Data.ColTrackTag^.TrackHdr.KeyCount;
  4907. end
  4908. else
  4909. ColKeys := 0;
  4910. // eat-up and fill-in the PKFAmbient3DS structure
  4911. InitAmbientLightMotion(Result, ColKeys);
  4912. // header information
  4913. if Assigned(NodeHdrChunk) then
  4914. begin
  4915. Result.Flags1 := NodeHdrChunk^.Data.NodeHdr^.Flags1;
  4916. Result.Flags2 := NodeHdrChunk^.Data.NodeHdr^.Flags2;
  4917. end;
  4918. // color information
  4919. if Assigned(ColChunk) then
  4920. begin
  4921. if ColKeys <> 0 then
  4922. begin
  4923. Result.NCFlag := ColChunk^.Data.ColTrackTag^.TrackHdr.Flags;
  4924. Move(ColChunk^.Data.ColTrackTag^.KeyHdrList^, Result.CKeys^,
  4925. ColKeys * SizeOf(TKeyHeader3DS));
  4926. Move(ColChunk^.Data.ColTrackTag^.ColorList^, Result.Color^,
  4927. ColKeys * SizeOf(TFColor3DS));
  4928. end;
  4929. end;
  4930. // free chunk data
  4931. if Assigned(NodeHdrChunk) then
  4932. FreeChunkData(NodeHdrChunk);
  4933. if Assigned(ColChunk) then
  4934. FreeChunkData(ColChunk);
  4935. end;
  4936. //---------------------------------------------------------------------------------------------------------------------
  4937. function GetAmbientLightMotion(const Source: TFile3DS;
  4938. var DB: TDatabase3DS): TKFAmbient3DS;
  4939. // Ambient Light a special case: only one ambient node per keyframe data Chunk^.
  4940. var
  4941. KFChunk, Chunk: PChunk3DS;
  4942. begin
  4943. FillChar(Result, SizeOf(Result), 0);
  4944. // find keyframe chunk
  4945. KFChunk := FindChunk(DB.TopChunk, KFDATA);
  4946. if Assigned(KFChunk) then
  4947. begin
  4948. Chunk := FindChunk(KFChunk, AMBIENT_NODE_TAG);
  4949. if Assigned(Chunk) then
  4950. Result := GetAmbientLightMotionChunk(Source, Chunk);
  4951. end;
  4952. end;
  4953. //----------------- Mesh object animation -----------------------------------------------------------------------------
  4954. procedure InitObjectMotion(var Obj: TKFMesh3DS; NewNPKeys, // Number of position keys
  4955. NewNRKeys, // Number of rot keys
  4956. NewNSKeys, // Number of scale keys
  4957. NewNMKeys, // Number of morph keys
  4958. NewNHKeys: cardinal); // Number of hide keys
  4959. var
  4960. I: integer;
  4961. begin
  4962. with Obj do
  4963. begin
  4964. if Assigned(PKeys) then
  4965. FreeMem(PKeys);
  4966. if Assigned(Pos) then
  4967. FreeMem(Pos);
  4968. if Assigned(RKeys) then
  4969. FreeMem(RKeys);
  4970. if Assigned(Rot) then
  4971. FreeMem(Rot);
  4972. if Assigned(SKeys) then
  4973. FreeMem(SKeys);
  4974. if Assigned(Scale) then
  4975. FreeMem(Scale);
  4976. if Assigned(MKeys) then
  4977. FreeMem(MKeys);
  4978. if Assigned(Morph) then
  4979. FreeMem(Morph);
  4980. if Assigned(HKeys) then
  4981. FreeMem(HKeys);
  4982. FillChar(Obj, SizeOf(Obj), 0);
  4983. Pivot := DefPoint3DS;
  4984. BoundMin := DefPoint3DS;
  4985. BoundMax := DefPoint3DS;
  4986. NPKeys := NewNPKeys;
  4987. NRKeys := NewNRKeys;
  4988. NSKeys := NewNSKeys;
  4989. NMKeys := NewNMKeys;
  4990. NHKeys := NewNHKeys;
  4991. MSAngle := 24;
  4992. if NPKeys <> 0 then
  4993. begin
  4994. NPFlag := TrackSingle3DS;
  4995. PKeys := AllocMem(NPKeys * SizeOf(TKeyHeader3DS));
  4996. for I := 0 to NPKeys - 1 do
  4997. PKeys^[I] := DefKeyHeader3DS;
  4998. Pos := AllocMem(NPKeys * SizeOf(TPoint3DS));
  4999. for I := 0 to NPKeys - 1 do
  5000. Pos^[I] := DefPoint3DS;
  5001. end;
  5002. if NRKeys <> 0 then
  5003. begin
  5004. NRFlag := TrackSingle3DS;
  5005. RKeys := AllocMem(NRKeys * SizeOf(TKeyHeader3DS));
  5006. for I := 0 to NRKeys - 1 do
  5007. RKeys^[I] := DefKeyHeader3DS;
  5008. Rot := AllocMem(NRKeys * SizeOf(TKFRotKey3DS));
  5009. for I := 0 to NRKeys - 1 do
  5010. Rot^[I] := DefKfRotKey3DS;
  5011. end;
  5012. if NSKeys <> 0 then
  5013. begin
  5014. NSFlag := TrackSingle3DS;
  5015. SKeys := AllocMem(NSKeys * SizeOf(TKeyHeader3DS));
  5016. for I := 0 to NSKeys - 1 do
  5017. SKeys^[I] := DefKeyHeader3DS;
  5018. Scale := AllocMem(NSKeys * SizeOf(TPoint3DS));
  5019. for I := 0 to NSKeys - 1 do
  5020. begin
  5021. Scale^[I].X := 1;
  5022. Scale^[I].Y := 1;
  5023. Scale^[I].Z := 1;
  5024. end;
  5025. end;
  5026. if NMKeys <> 0 then
  5027. begin
  5028. NMFlag := TrackSingle3DS;
  5029. MKeys := AllocMem(NMKeys * SizeOf(TKeyHeader3DS));
  5030. for I := 0 to NMKeys - 1 do
  5031. MKeys^[I] := DefKeyHeader3DS;
  5032. Morph := AllocMem(NMKeys * SizeOf(TKFMorphKey3DS));
  5033. for I := 0 to NMKeys - 1 do
  5034. Morph^[I] := ' ';
  5035. end;
  5036. if NHKeys <> 0 then
  5037. begin
  5038. NHFlag := TrackSingle3DS;
  5039. HKeys := AllocMem(NHKeys * SizeOf(TKeyHeader3DS));
  5040. for I := 0 to NMKeys - 1 do
  5041. MKeys^[I] := DefKeyHeader3DS;
  5042. end;
  5043. end;
  5044. end;
  5045. //---------------------------------------------------------------------------------------------------------------------
  5046. procedure ReleaseObjectMotion(Obj: PKFMesh3DS);
  5047. begin
  5048. if Assigned(Obj) then
  5049. begin
  5050. with Obj^ do
  5051. begin
  5052. if Assigned(PKeys) then
  5053. FreeMem(PKeys);
  5054. if Assigned(Pos) then
  5055. FreeMem(Pos);
  5056. if Assigned(RKeys) then
  5057. FreeMem(RKeys);
  5058. if Assigned(Rot) then
  5059. FreeMem(Rot);
  5060. if Assigned(SKeys) then
  5061. FreeMem(SKeys);
  5062. if Assigned(Scale) then
  5063. FreeMem(Scale);
  5064. if Assigned(MKeys) then
  5065. FreeMem(MKeys);
  5066. if Assigned(Morph) then
  5067. FreeMem(Morph);
  5068. if Assigned(HKeys) then
  5069. FreeMem(HKeys);
  5070. end;
  5071. Dispose(Obj);
  5072. end;
  5073. end;
  5074. //---------------------------------------------------------------------------------------------------------------------
  5075. function GetObjectNodeCount(const Source: TFile3DS; var DB: TDatabase3DS): integer;
  5076. begin
  5077. Result := GetGenericNodeCount(Source, DB, OBJECT_NODE_TAG);
  5078. end;
  5079. //---------------------------------------------------------------------------------------------------------------------
  5080. procedure GetObjectNodeNameList(const Source: TFile3DS; var DB: TDatabase3DS;
  5081. List: TStringList);
  5082. begin
  5083. GetGenericNodeNameList(Source, DB, OBJECT_NODE_TAG, List);
  5084. end;
  5085. //---------------------------------------------------------------------------------------------------------------------
  5086. function GetObjectMotion(const Source: TFile3DS; MeshChunk: PChunk3DS): TKFMesh3DS;
  5087. // Gets mesh keyframe information from chunk
  5088. // NODE_ID
  5089. // NODE_HDR
  5090. // APP_DATA
  5091. // INSTANCE_NAME
  5092. // PRESCALE a no-op in 3DS code
  5093. // POS_TRACK
  5094. // ROT_TRACK
  5095. // SCL_TRACK
  5096. // MORPH_TRACK
  5097. // MORPH_SMOOTH
  5098. // HIDE_TRACK
  5099. // This function is really confusing, because instead of loading the MeshChunk and its children, reading the
  5100. // data out and freeing it, the chunk structure is copied, its data is moved to the copy (so MeshChunk is then without
  5101. // any data), the copy is parsed and then it is freed. I don't know why this is so, but I don't want to change
  5102. // the way it works in case this has (or will later have) side effects I don't see yet. ml
  5103. var
  5104. NodeHdrChunk, InstChunk, PivotChunk, BboxChunk, MsChunk,
  5105. PosChunk, RotChunk, ScaleChunk, MorphChunk, HideChunk,
  5106. ObjTag: PChunk3DS;
  5107. PosKeys, RotKeys, ScaleKeys, MorphKeys, HideKeys: integer;
  5108. PivotData: PPivot;
  5109. InstData: PInstanceName;
  5110. BBoxData: PBoundBox;
  5111. MsData: PMorphSmooth;
  5112. PosData: PPosTrackTag;
  5113. RotData: PRotTrackTag;
  5114. ScaleData: PScaleTrackTag;
  5115. MorphData: PMorphTrackTag;
  5116. HideData: PHideTrackTag;
  5117. begin
  5118. PosKeys := 0;
  5119. RotKeys := 0;
  5120. ScaleKeys := 0;
  5121. MorphKeys := 0;
  5122. HideKeys := 0;
  5123. PivotData := nil;
  5124. InstData := nil;
  5125. BboxData := nil;
  5126. MsData := nil;
  5127. PosData := nil;
  5128. RotData := nil;
  5129. ScaleData := nil;
  5130. MorphData := nil;
  5131. HideData := nil;
  5132. if MeshChunk^.Tag <> OBJECT_NODE_TAG then
  5133. ShowError(strERROR3DS_WRONG_OBJECT);
  5134. ObjTag := CopyChunk(MeshChunk);
  5135. // get information from chunks
  5136. // search children of MeshLight chunk
  5137. NodeHdrChunk := FindChunk(ObjTag, NODE_HDR);
  5138. InstChunk := FindChunk(ObjTag, INSTANCE_NAME);
  5139. PivotChunk := FindChunk(ObjTag, PIVOT);
  5140. BboxChunk := FindChunk(ObjTag, BOUNDBOX);
  5141. MsChunk := FindChunk(ObjTag, MORPH_SMOOTH);
  5142. PosChunk := FindChunk(ObjTag, POS_TRACK_TAG);
  5143. RotChunk := FindChunk(ObjTag, ROT_TRACK_TAG);
  5144. ScaleChunk := FindChunk(ObjTag, SCL_TRACK_TAG);
  5145. MorphChunk := FindChunk(ObjTag, MORPH_TRACK_TAG);
  5146. HideChunk := FindChunk(ObjTag, HIDE_TRACK_TAG);
  5147. Source.ReadChunkData(NodeHdrChunk);
  5148. if Assigned(InstChunk) then
  5149. begin
  5150. Source.ReadChunkData(InstChunk);
  5151. InstData := InstChunk^.Data.Dummy;
  5152. InstChunk^.Data.Dummy := nil;
  5153. end;
  5154. if Assigned(PivotChunk) then
  5155. begin
  5156. Source.ReadChunkData(PivotChunk);
  5157. PivotData := PivotChunk^.Data.Dummy;
  5158. PivotChunk^.Data.Dummy := nil;
  5159. end;
  5160. if Assigned(BboxChunk) then
  5161. begin
  5162. Source.ReadChunkData(BboxChunk);
  5163. BboxData := BboxChunk^.Data.Dummy;
  5164. BboxChunk^.Data.Dummy := nil;
  5165. end;
  5166. if Assigned(MsChunk) then
  5167. begin
  5168. Source.ReadChunkData(MsChunk);
  5169. MsData := MsChunk^.Data.Dummy;
  5170. MsChunk^.Data.Dummy := nil;
  5171. end;
  5172. if Assigned(PosChunk) then
  5173. begin
  5174. Source.ReadChunkData(PosChunk);
  5175. PosData := PosChunk^.Data.Dummy;
  5176. PosKeys := PosData^.TrackHdr.KeyCount;
  5177. PosChunk^.Data.Dummy := nil;
  5178. end;
  5179. if Assigned(RotChunk) then
  5180. begin
  5181. Source.ReadChunkData(RotChunk);
  5182. RotData := RotChunk^.Data.Dummy;
  5183. RotKeys := RotData^.TrackHdr.KeyCount;
  5184. RotChunk^.Data.Dummy := nil;
  5185. end;
  5186. if Assigned(ScaleChunk) then
  5187. begin
  5188. Source.ReadChunkData(ScaleChunk);
  5189. ScaleData := ScaleChunk^.Data.Dummy;
  5190. ScaleKeys := ScaleData^.TrackHdr.KeyCount;
  5191. ScaleChunk^.Data.Dummy := nil;
  5192. end;
  5193. if Assigned(MorphChunk) then
  5194. begin
  5195. Source.ReadChunkData(MorphChunk);
  5196. MorphData := MorphChunk^.Data.Dummy;
  5197. MorphKeys := MorphData^.TrackHdr.KeyCount;
  5198. MorphChunk^.Data.Dummy := nil;
  5199. end;
  5200. if Assigned(HideChunk) then
  5201. begin
  5202. Source.ReadChunkData(HideChunk);
  5203. HideData := HideChunk^.Data.Dummy;
  5204. HideKeys := HideData^.TrackHdr.KeyCount;
  5205. HideChunk^.Data.Dummy := nil;
  5206. end;
  5207. // set-up and fill-in the TKFMesh3DS structure
  5208. with Result do
  5209. begin
  5210. //--- header Information
  5211. NameStr := AnsiString(NodeHdrChunk^.Data.NodeHdr^.ObjNameStr);
  5212. Flags1 := NodeHdrChunk^.Data.NodeHdr^.Flags1;
  5213. Flags2 := NodeHdrChunk^.Data.NodeHdr^.Flags2;
  5214. //--- get parent name if there is one
  5215. ParentStr := AnsiString(GetParentName(Source, NodeHdrChunk));
  5216. //--- Instance
  5217. if Assigned(InstData) then
  5218. begin
  5219. InstanceStr := StrPas(InstData);
  5220. NameStr := NameStr + '.' + InstanceStr;
  5221. FreeMem(InstData);
  5222. end
  5223. else
  5224. InstanceStr := '';
  5225. //--- Pivot
  5226. if Assigned(PivotData) then
  5227. begin
  5228. Pivot := PivotData^;
  5229. FreeMem(PivotData);
  5230. end
  5231. else
  5232. Pivot := DefPoint3DS;
  5233. //--- Bound
  5234. if Assigned(BboxData) then
  5235. begin
  5236. BoundMin := BboxData^.Min;
  5237. BoundMax := BboxData^.Max;
  5238. FreeMem(BboxData);
  5239. end
  5240. else
  5241. begin
  5242. BoundMin := DefPoint3DS;
  5243. BoundMax := DefPoint3DS;
  5244. end;
  5245. //--- MorphSmooth Angle
  5246. if Assigned(MsData) then
  5247. begin
  5248. MSAngle := MsData^;
  5249. FreeMem(MsData);
  5250. end
  5251. else
  5252. MSAngle := 0;
  5253. //--- Position
  5254. NPKeys := PosKeys;
  5255. if PosKeys <> 0 then
  5256. begin
  5257. PKeys := PosData^.KeyHdrList;
  5258. Pos := PosData^.PositionList;
  5259. NPFlag := PosData^.TrackHdr.Flags;
  5260. FreeMem(PosData);
  5261. end
  5262. else
  5263. begin
  5264. PKeys := nil;
  5265. Pos := nil;
  5266. NPFlag := 0;
  5267. end;
  5268. //--- Rotation
  5269. NRKeys := RotKeys;
  5270. if RotKeys <> 0 then
  5271. begin
  5272. RKeys := RotData^.KeyHdrList;
  5273. Rot := RotData^.RotationList;
  5274. NRFlag := RotData^.TrackHdr.Flags;
  5275. FreeMem(RotData);
  5276. end
  5277. else
  5278. begin
  5279. RKeys := nil;
  5280. Rot := nil;
  5281. NRFlag := 0;
  5282. end;
  5283. //--- Scale
  5284. NSKeys := ScaleKeys;
  5285. if ScaleKeys <> 0 then
  5286. begin
  5287. SKeys := ScaleData^.KeyHdrList;
  5288. Scale := ScaleData^.ScaleList;
  5289. NSFlag := ScaleData^.TrackHdr.Flags;
  5290. FreeMem(ScaleData);
  5291. end
  5292. else
  5293. begin
  5294. SKeys := nil;
  5295. Scale := nil;
  5296. NSFlag := 0;
  5297. end;
  5298. //--- Morph
  5299. NMKeys := MorphKeys;
  5300. if MorphKeys <> 0 then
  5301. begin
  5302. MKeys := MorphData^.KeyHdrList;
  5303. Morph := MorphData^.MorphList;
  5304. NMFlag := MorphData^.TrackHdr.Flags;
  5305. FreeMem(MorphData);
  5306. end
  5307. else
  5308. begin
  5309. MKeys := nil;
  5310. Morph := nil;
  5311. NMFlag := 0;
  5312. end;
  5313. NHKeys := HideKeys;
  5314. if HideKeys <> 0 then
  5315. begin
  5316. HKeys := HideData^.KeyHdrList;
  5317. NHFlag := HideData^.TrackHdr.Flags;
  5318. FreeMem(HideData);
  5319. end
  5320. else
  5321. begin
  5322. HKeys := nil;
  5323. NHFlag := 0;
  5324. end;
  5325. end;
  5326. //-- ADDITIONAL Morph INFO HERE
  5327. //--- free chunk data: only free those that arent being copied
  5328. ReleaseChunk(ObjTag);
  5329. end;
  5330. //---------------------------------------------------------------------------------------------------------------------
  5331. function GetObjectMotionByName(const Source: TFile3DS; var DB: TDatabase3DS;
  5332. const Name: string): TKFMesh3DS;
  5333. var
  5334. ObjectChunk: PChunk3DS;
  5335. begin
  5336. FillChar(Result, SizeOf(Result), 0);
  5337. ObjectChunk := FindNodeTagByNameAndType(Source, DB, Name, OBJECT_NODE_TAG);
  5338. if Assigned(ObjectChunk) then
  5339. Result := GetObjectMotion(Source, ObjectChunk);
  5340. end;
  5341. //---------------------------------------------------------------------------------------------------------------------
  5342. function GetObjectMotionByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  5343. Index: cardinal): TKFMesh3DS;
  5344. var
  5345. Chunk: PChunk3DS;
  5346. begin
  5347. FillChar(Result, SizeOf(Result), 0);
  5348. Chunk := FindNodeTagByIndexAndType(Source, DB, Index, OBJECT_NODE_TAG);
  5349. if Assigned(Chunk) then
  5350. Result := GetObjectMotion(Source, Chunk);
  5351. end;
  5352. //----------------- Omni Light animation ------------------------------------------------------------------------------
  5353. procedure InitOmnilightMotion(var Light: TKFOmni3DS; NewNPKeys, NewNCKeys: cardinal);
  5354. var
  5355. I: integer;
  5356. begin
  5357. with Light do
  5358. begin
  5359. if Assigned(PKeys) then
  5360. FreeMem(PKeys);
  5361. if Assigned(Pos) then
  5362. FreeMem(Pos);
  5363. if Assigned(CKeys) then
  5364. FreeMem(CKeys);
  5365. if Assigned(Color) then
  5366. FreeMem(Color);
  5367. FillChar(Light, SizeOf(Light), 0);
  5368. NPKeys := NewNPKeys;
  5369. NCKeys := NewNCKeys;
  5370. if NPKeys <> 0 then
  5371. begin
  5372. NPFlag := TrackSingle3DS;
  5373. PKeys := AllocMem(NPKeys * SizeOf(TKeyHeader3DS));
  5374. for I := 0 to NPKeys - 1 do
  5375. PKeys^[I] := DefKeyHeader3DS;
  5376. Pos := AllocMem(NPKeys * SizeOf(TPoint3DS));
  5377. for I := 0 to NPKeys - 1 do
  5378. Pos^[I] := DefPoint3DS;
  5379. end;
  5380. if NCKeys <> 0 then
  5381. begin
  5382. NCFlag := TrackSingle3DS;
  5383. CKeys := AllocMem(NCKeys * SizeOf(TKeyHeader3DS));
  5384. for I := 0 to NCKeys - 1 do
  5385. CKeys^[I] := DefKeyHeader3DS;
  5386. Color := AllocMem(NCKeys * SizeOf(TFColor3DS));
  5387. for I := 0 to NCKeys - 1 do
  5388. begin
  5389. Color^[I].R := 1;
  5390. Color^[I].G := 1;
  5391. Color^[I].B := 1;
  5392. end;
  5393. end;
  5394. end;
  5395. end;
  5396. //---------------------------------------------------------------------------------------------------------------------
  5397. procedure ReleaseOmnilightMotion(Light: PKFOmni3DS);
  5398. begin
  5399. if Assigned(Light) then
  5400. begin
  5401. with Light^ do
  5402. begin
  5403. if Assigned(PKeys) then
  5404. FreeMem(PKeys);
  5405. if Assigned(Pos) then
  5406. FreeMem(Pos);
  5407. if Assigned(CKeys) then
  5408. FreeMem(CKeys);
  5409. if Assigned(Color) then
  5410. FreeMem(Color);
  5411. end;
  5412. Dispose(Light);
  5413. end;
  5414. end;
  5415. //---------------------------------------------------------------------------------------------------------------------
  5416. function GetOmnilightNodeCount(const Source: TFile3DS; var DB: TDatabase3DS): cardinal;
  5417. begin
  5418. Result := GetGenericNodeCount(Source, DB, LIGHT_NODE_TAG);
  5419. end;
  5420. //---------------------------------------------------------------------------------------------------------------------
  5421. procedure GetOmnilightNodeNameList(const Source: TFile3DS; var DB: TDatabase3DS;
  5422. List: TStringList);
  5423. begin
  5424. GetGenericNodeNameList(Source, DB, LIGHT_NODE_TAG, List);
  5425. end;
  5426. //---------------------------------------------------------------------------------------------------------------------
  5427. function GetOmnilightMotion(const Source: TFile3DS; OmniChunk: PChunk3DS): TKFOmni3DS;
  5428. // Gets Omnilight keyframe information from chunk
  5429. // L_TARGET
  5430. // NODE_ID
  5431. // NODE_HDR
  5432. // APP_DATA
  5433. // POS_TRACK
  5434. // COL_TRACK
  5435. // HOT_TRACK
  5436. // FALL_TRACK
  5437. // ROLL_TRACK
  5438. var
  5439. NodeHdrChunk, PosChunk, ColChunk: PChunk3DS;
  5440. PosKeys, ColKeys: cardinal;
  5441. begin
  5442. PosKeys := 0;
  5443. ColKeys := 0;
  5444. // get information from chunks
  5445. // search children of OmniLight chunk
  5446. NodeHdrChunk := FindChunk(OmniChunk, NODE_HDR);
  5447. PosChunk := FindChunk(OmniChunk, POS_TRACK_TAG);
  5448. ColChunk := FindChunk(OmniChunk, COL_TRACK_TAG);
  5449. Source.ReadChunkData(NodeHdrChunk);
  5450. if Assigned(PosChunk) then
  5451. begin
  5452. Source.ReadChunkData(PosChunk);
  5453. PosKeys := PosChunk^.Data.PosTrackTag^.TrackHdr.KeyCount;
  5454. end;
  5455. if Assigned(ColChunk) then
  5456. begin
  5457. Source.ReadChunkData(ColChunk);
  5458. ColKeys := ColChunk^.Data.ColTrackTag^.TrackHdr.KeyCount;
  5459. end;
  5460. // set-up and fill-in the TKFOmni3DS structure
  5461. FillChar(Result, SizeOf(Result), $00);
  5462. InitOmnilightMotion(Result, PosKeys, ColKeys);
  5463. with Result do
  5464. begin
  5465. //--- Header Information
  5466. Name := ansistring(NodeHdrChunk^.Data.NodeHdr^.ObjNameStr);
  5467. Flags1 := NodeHdrChunk^.Data.NodeHdr^.Flags1;
  5468. Flags2 := NodeHdrChunk^.Data.NodeHdr^.Flags2;
  5469. Parent := ansistring(GetParentName(Source, NodeHdrChunk));
  5470. //--- Position Information
  5471. if PosKeys <> 0 then
  5472. begin
  5473. NPFlag := PosChunk^.Data.PosTrackTag^.TrackHdr.Flags;
  5474. Move(PosChunk^.Data.PosTrackTag^.KeyHdrList^, PKeys^, PosKeys *
  5475. SizeOf(TKeyHeader3DS));
  5476. Move(PosChunk^.Data.PosTrackTag^.PositionList^, Pos^, PosKeys * SizeOf(TPoint3DS));
  5477. end;
  5478. //--- Color Information
  5479. if ColKeys <> 0 then
  5480. begin
  5481. NCFlag := PosChunk^.Data.ColTrackTag^.TrackHdr.Flags;
  5482. Move(ColChunk^.Data.ColTrackTag^.KeyHdrList^, CKeys^, ColKeys *
  5483. SizeOf(TKeyHeader3DS));
  5484. Move(ColChunk^.Data.ColTrackTag^.ColorList^, Color^, ColKeys * SizeOf(TFColor3DS));
  5485. end;
  5486. //--- Free Chunk Data
  5487. if Assigned(NodeHdrChunk) then
  5488. FreeChunkData(NodeHdrChunk);
  5489. if Assigned(PosChunk) then
  5490. FreeChunkData(PosChunk);
  5491. if Assigned(ColChunk) then
  5492. FreeChunkData(ColChunk);
  5493. end;
  5494. end;
  5495. //---------------------------------------------------------------------------------------------------------------------
  5496. function GetOmnilightMotionByName(const Source: TFile3DS; var DB: TDatabase3DS;
  5497. const Name: string): TKFOmni3DS;
  5498. var
  5499. Chunk: PChunk3DS;
  5500. begin
  5501. FillChar(Result, SizeOf(Result), 0);
  5502. Chunk := FindNamedAndTaggedChunk(Source, DB, Name, LIGHT_NODE_TAG);
  5503. if Assigned(Chunk) then
  5504. Result := GetOmnilightMotion(Source, Chunk);
  5505. end;
  5506. //---------------------------------------------------------------------------------------------------------------------
  5507. function GetOmnilightMotionByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  5508. Index: cardinal): TKFOmni3DS;
  5509. var
  5510. Chunk: PChunk3DS;
  5511. List: TStringList;
  5512. begin
  5513. FillChar(Result, SizeOf(Result), 0);
  5514. List := TStringList.Create;
  5515. try
  5516. GetOmnilightNodeNameList(Source, DB, List);
  5517. if Index < cardinal(List.Count) then
  5518. begin
  5519. Chunk := FindNamedAndTaggedChunk(Source, DB, List[Index], LIGHT_NODE_TAG);
  5520. if Assigned(Chunk) then
  5521. Result := GetOmnilightMotion(Source, Chunk);
  5522. end;
  5523. finally
  5524. List.Free;
  5525. end;
  5526. end;
  5527. //----------------- Spot Light animation ------------------------------------------------------------------------------
  5528. procedure InitSpotlightMotion(var Spot: TKFSpot3DS;
  5529. NewNPKeys, // Number of position keys
  5530. NewNCKeys, // Number of Color keys
  5531. NewNHKeys, // Number of hot spot angle keys
  5532. NewNFKeys, // Number of falloff angle keys
  5533. NewNRKeys, // Number of roll keys
  5534. NewNTKeys: cardinal); // Number of target position keys
  5535. var
  5536. I: cardinal;
  5537. begin
  5538. with Spot do
  5539. begin
  5540. if Assigned(PKeys) then
  5541. FreeMem(PKeys);
  5542. if Assigned(Pos) then
  5543. FreeMem(Pos);
  5544. if Assigned(CKeys) then
  5545. FreeMem(CKeys);
  5546. if Assigned(Color) then
  5547. FreeMem(Color);
  5548. if Assigned(HKeys) then
  5549. FreeMem(HKeys);
  5550. if Assigned(Hot) then
  5551. FreeMem(Hot);
  5552. if Assigned(FKeys) then
  5553. FreeMem(FKeys);
  5554. if Assigned(Fall) then
  5555. FreeMem(Fall);
  5556. if Assigned(RKeys) then
  5557. FreeMem(RKeys);
  5558. if Assigned(Roll) then
  5559. FreeMem(Roll);
  5560. if Assigned(TKeys) then
  5561. FreeMem(TKeys);
  5562. if Assigned(TPos) then
  5563. FreeMem(TPos);
  5564. FillChar(Spot, SizeOf(Spot), 0);
  5565. NPKeys := NewNPKeys;
  5566. NCKeys := NewNCKeys;
  5567. NFKeys := NewNFKeys;
  5568. NTKeys := NewNTKeys;
  5569. NHKeys := NewNHKeys;
  5570. NRKeys := NewNRKeys;
  5571. //--- POSITION KEYS -----------------------------------------------------
  5572. if NPKeys <> 0 then
  5573. begin
  5574. NPFlag := TrackSingle3DS;
  5575. PKeys := AllocMem(NPKeys * SizeOf(TKeyHeader3DS));
  5576. for I := 0 to NPKeys - 1 do
  5577. PKeys^[I] := DefKeyHeader3DS;
  5578. Pos := AllocMem(NPKeys * SizeOf(TPoint3DS));
  5579. for I := 0 to NPKeys - 1 do
  5580. Pos^[I] := DefPoint3DS;
  5581. end;
  5582. //--- Color KEYS ----------------------------------------------------------
  5583. if NCKeys <> 0 then
  5584. begin
  5585. NCFlag := TrackSingle3DS;
  5586. CKeys := AllocMem(NCKeys * SizeOf(TKeyHeader3DS));
  5587. for I := 0 to NCKeys - 1 do
  5588. CKeys^[I] := DefKeyHeader3DS;
  5589. Color := AllocMem(NCKeys * SizeOf(TFColor3DS));
  5590. // Initialization is unclear, even the original developers didn't know what's up.
  5591. // They put this part in an '#ifdef LATER #endif' block. ml
  5592. // for I := 0 to NCKeys - 1 do Color[I] := localDColor.bDefFColor3DS;
  5593. end;
  5594. //---Hot-Spot ANGLE KEYS---------------------------------------------------
  5595. if NHKeys <> 0 then
  5596. begin
  5597. NHFlag := TrackSingle3DS;
  5598. HKeys := AllocMem(NHKeys * SizeOf(TKeyHeader3DS));
  5599. for I := 0 to NHKeys - 1 do
  5600. HKeys^[I] := DefKeyHeader3DS;
  5601. Hot := AllocMem(NHKeys * SizeOf(single));
  5602. // default Hot Spot ange 90.0 for now, get real value later (1..174.5)
  5603. for I := 0 to NHKeys - 1 do
  5604. Hot^[I] := 90;
  5605. end;
  5606. //---FALLOFF ANGLE KEYS----------------------------------------------------
  5607. if NFKeys <> 0 then
  5608. begin
  5609. NFFlag := TrackSingle3DS;
  5610. FKeys := AllocMem(NFKeys * SizeOf(TKeyHeader3DS));
  5611. for I := 0 to NFKeys - 1 do
  5612. FKeys^[I] := DefKeyHeader3DS;
  5613. Fall := AllocMem(NFKeys * SizeOf(single));
  5614. // default falloff ange 90.0 for now, get real value later (1..175)
  5615. for I := 0 to NFKeys - 1 do
  5616. Fall^[I] := 90;
  5617. end;
  5618. //--- Roll KEYS ----------------------------------------------------------
  5619. if NRKeys <> 0 then
  5620. begin
  5621. NRFlag := TrackSingle3DS;
  5622. RKeys := AllocMem(NRKeys * SizeOf(TKeyHeader3DS));
  5623. for I := 0 to NRKeys - 1 do
  5624. RKeys^[I] := DefKeyHeader3DS;
  5625. Roll := AllocMem(NRKeys * SizeOf(single));
  5626. for I := 0 to NRKeys - 1 do
  5627. Roll^[I] := 0;
  5628. end;
  5629. //---L_TARGET Pos KEYS ------------------------------------------------
  5630. if NTKeys <> 0 then
  5631. begin
  5632. NTFlag := TrackSingle3DS;
  5633. TKeys := AllocMem(NTKeys * SizeOf(TKeyHeader3DS));
  5634. for I := 0 to NTKeys - 1 do
  5635. TKeys^[I] := DefKeyHeader3DS;
  5636. TPos := AllocMem(NTKeys * SizeOf(TPoint3DS));
  5637. // default target position, 0, 0, 0 sjw fix later if necessary
  5638. for I := 0 to NTKeys - 1 do
  5639. TPos^[I] := DefPoint3DS;
  5640. end;
  5641. end;
  5642. end;
  5643. //---------------------------------------------------------------------------------------------------------------------
  5644. procedure ReleaseSpotlightMotion(Spot: PKFSpot3DS);
  5645. begin
  5646. if Assigned(Spot) then
  5647. begin
  5648. with Spot^ do
  5649. begin
  5650. if Assigned(PKeys) then
  5651. FreeMem(PKeys);
  5652. if Assigned(Pos) then
  5653. FreeMem(Pos);
  5654. if Assigned(CKeys) then
  5655. FreeMem(CKeys);
  5656. if Assigned(Color) then
  5657. FreeMem(Color);
  5658. if Assigned(HKeys) then
  5659. FreeMem(HKeys);
  5660. if Assigned(Hot) then
  5661. FreeMem(Hot);
  5662. if Assigned(FKeys) then
  5663. FreeMem(FKeys);
  5664. if Assigned(Fall) then
  5665. FreeMem(Fall);
  5666. if Assigned(RKeys) then
  5667. FreeMem(RKeys);
  5668. if Assigned(Roll) then
  5669. FreeMem(Roll);
  5670. if Assigned(TKeys) then
  5671. FreeMem(TKeys);
  5672. if Assigned(TPos) then
  5673. FreeMem(TPos);
  5674. end;
  5675. Dispose(Spot);
  5676. end;
  5677. end;
  5678. //---------------------------------------------------------------------------------------------------------------------
  5679. function GetSpotlightNodeCount(const Source: TFile3DS; var DB: TDatabase3DS): cardinal;
  5680. begin
  5681. Result := GetGenericNodeCount(Source, DB, SPOTLIGHT_NODE_TAG);
  5682. end;
  5683. //---------------------------------------------------------------------------------------------------------------------
  5684. procedure GetSpotlightNodeNameList(const Source: TFile3DS; var DB: TDatabase3DS;
  5685. List: TStringList);
  5686. begin
  5687. GetGenericNodeNameList(Source, DB, SPOTLIGHT_NODE_TAG, List);
  5688. end;
  5689. //---------------------------------------------------------------------------------------------------------------------
  5690. function GetSpotlightMotion(const Source: TFile3DS;
  5691. SpotChunk, TargetChunk: PChunk3DS): TKFSpot3DS;
  5692. // gets Spotlight keyframe information from chunk
  5693. // L_TARGET
  5694. // ...
  5695. // NODE_HDR
  5696. // APP_DATA
  5697. // POS_TRACK
  5698. // COL_TRACK
  5699. // HOT_TRACK
  5700. // FALL_TRACK
  5701. // ROLL_TRACK
  5702. var
  5703. NodeHdrChunk, PosChunk, ColChunk, TargetPosChunk, HotChunk,
  5704. FallChunk, RollChunk, TargetHdrChunk: PChunk3DS;
  5705. PosKeys, ColKeys, HotKeys, FallKeys, RollKeys, TargetKeys: cardinal;
  5706. begin
  5707. TargetPosChunk := nil;
  5708. TargetHdrChunk := nil;
  5709. PosKeys := 0;
  5710. ColKeys := 0;
  5711. HotKeys := 0;
  5712. FallKeys := 0;
  5713. RollKeys := 0;
  5714. TargetKeys := 0;
  5715. // get information from chunks
  5716. // search children of Spotlight chunk
  5717. NodeHdrChunk := FindChunk(SpotChunk, NODE_HDR);
  5718. PosChunk := FindChunk(SpotChunk, POS_TRACK_TAG);
  5719. ColChunk := FindChunk(SpotChunk, COL_TRACK_TAG);
  5720. HotChunk := FindChunk(SpotChunk, HOT_TRACK_TAG);
  5721. FallChunk := FindChunk(SpotChunk, FALL_TRACK_TAG);
  5722. RollChunk := FindChunk(SpotChunk, ROLL_TRACK_TAG);
  5723. Source.ReadChunkData(NodeHdrChunk);
  5724. if Assigned(PosChunk) then
  5725. begin
  5726. Source.ReadChunkData(PosChunk);
  5727. PosKeys := PosChunk^.Data.PosTrackTag^.TrackHdr.KeyCount;
  5728. end;
  5729. if Assigned(ColChunk) then
  5730. begin
  5731. Source.ReadChunkData(ColChunk);
  5732. ColKeys := ColChunk^.Data.ColTrackTag^.TrackHdr.KeyCount;
  5733. end;
  5734. if Assigned(HotChunk) then
  5735. begin
  5736. Source.ReadChunkData(HotChunk);
  5737. HotKeys := HotChunk^.Data.HotTrackTag^.TrackHdr.KeyCount;
  5738. end;
  5739. if Assigned(FallChunk) then
  5740. begin
  5741. Source.ReadChunkData(FallChunk);
  5742. FallKeys := FallChunk^.Data.FallTrackTag^.TrackHdr.KeyCount;
  5743. end;
  5744. if Assigned(RollChunk) then
  5745. begin
  5746. Source.ReadChunkData(RollChunk);
  5747. RollKeys := RollChunk^.Data.RollTrackTag^.TrackHdr.KeyCount;
  5748. end;
  5749. if Assigned(TargetChunk) then
  5750. begin
  5751. TargetHdrChunk := FindChunk(TargetChunk, NODE_HDR);
  5752. if Assigned(TargetHdrChunk) then
  5753. Source.ReadChunkData(TargetHdrChunk);
  5754. TargetPosChunk := FindChunk(TargetChunk, POS_TRACK_TAG);
  5755. if Assigned(TargetPosChunk) then
  5756. begin
  5757. Source.ReadChunkData(TargetPosChunk);
  5758. TargetKeys := TargetPosChunk^.Data.PosTrackTag^.TrackHdr.KeyCount;
  5759. end;
  5760. end;
  5761. // set-up and fill-in the TKFSpot3DS structure
  5762. InitSpotlightMotion(Result, PosKeys, ColKeys, HotKeys, FallKeys, RollKeys, TargetKeys);
  5763. with Result do
  5764. begin
  5765. // header Information
  5766. Name := ansistring(NodeHdrChunk^.Data.NodeHdr^.ObjNameStr);
  5767. Flags1 := NodeHdrChunk^.Data.NodeHdr^.Flags1;
  5768. Flags2 := NodeHdrChunk^.Data.NodeHdr^.Flags2;
  5769. // get parent name if there is one
  5770. Parent := ansistring(GetParentName(Source, NodeHdrChunk));
  5771. TParent := ansistring(GetParentName(Source, TargetHdrChunk));
  5772. if Assigned(TargetHdrChunk) then
  5773. begin
  5774. TFlags1 := TargetHdrChunk^.Data.NodeHdr^.Flags1;
  5775. TFlags2 := TargetHdrChunk^.Data.NodeHdr^.Flags2;
  5776. end
  5777. else
  5778. begin
  5779. TFlags1 := 0;
  5780. TFlags2 := 0;
  5781. end;
  5782. // target information
  5783. if TargetKeys <> 0 then
  5784. begin
  5785. NTFlag := TargetPosChunk^.Data.PosTrackTag^.TrackHdr.Flags;
  5786. Move(TargetPosChunk^.Data.PosTrackTag^.KeyHdrList^, TKeys^,
  5787. TargetKeys * SizeOf(TKeyHeader3DS));
  5788. Move(TargetPosChunk^.Data.PosTrackTag^.PositionList^, TPos^,
  5789. TargetKeys * SizeOf(TPoint3DS));
  5790. end;
  5791. // position information
  5792. if PosKeys <> 0 then
  5793. begin
  5794. NPFlag := PosChunk^.Data.PosTrackTag^.TrackHdr.Flags;
  5795. Move(PosChunk^.Data.PosTrackTag^.KeyHdrList^, PKeys^, PosKeys *
  5796. SizeOf(TKeyHeader3DS));
  5797. Move(PosChunk^.Data.PosTrackTag^.PositionList^, Pos^, PosKeys * SizeOf(TPoint3DS));
  5798. end;
  5799. // color information
  5800. if ColKeys <> 0 then
  5801. begin
  5802. NCFlag := ColChunk^.Data.ColTrackTag^.TrackHdr.Flags;
  5803. Move(ColChunk^.Data.ColTrackTag^.KeyHdrList^, CKeys^, ColKeys *
  5804. SizeOf(TKeyHeader3DS));
  5805. Move(ColChunk^.Data.ColTrackTag^.ColorList^, Color^, ColKeys * SizeOf(TFColor3DS));
  5806. end;
  5807. // hot spot information
  5808. if HotKeys <> 0 then
  5809. begin
  5810. NHFlag := HotChunk^.Data.HotTrackTag^.TrackHdr.Flags;
  5811. Move(HotChunk^.Data.HotTrackTag^.KeyHdrList^, HKeys^, HotKeys *
  5812. SizeOf(TKeyHeader3DS));
  5813. Move(HotChunk^.Data.HotTrackTag^.HotSpotAngleList^, Hot^, HotKeys *
  5814. SizeOf(single));
  5815. end;
  5816. // falloff information
  5817. if FallKeys <> 0 then
  5818. begin
  5819. NFFlag := FallChunk^.Data.FallTrackTag^.TrackHdr.Flags;
  5820. Move(FallChunk^.Data.FallTrackTag^.KeyHdrList^, FKeys^, FallKeys *
  5821. SizeOf(TKeyHeader3DS));
  5822. Move(FallChunk^.Data.FallTrackTag^.FallOffAngleList^, Fall^,
  5823. FallKeys * SizeOf(single));
  5824. end;
  5825. // roll track Information
  5826. if RollKeys <> 0 then
  5827. begin
  5828. NRFlag := RollChunk^.Data.RollTrackTag^.TrackHdr.Flags;
  5829. Move(RollChunk^.Data.RollTrackTag^.KeyHdrList^, RKeys^, RollKeys *
  5830. SizeOf(TKeyHeader3DS));
  5831. Move(RollChunk^.Data.RollTrackTag^.RollAngleList^, Roll^,
  5832. RollKeys * SizeOf(single));
  5833. end;
  5834. end;
  5835. //--- Free Chunk Data
  5836. if Assigned(NodeHdrChunk) then
  5837. FreeChunkData(NodeHdrChunk);
  5838. if Assigned(PosChunk) then
  5839. FreeChunkData(PosChunk);
  5840. if Assigned(ColChunk) then
  5841. FreeChunkData(ColChunk);
  5842. if Assigned(HotChunk) then
  5843. FreeChunkData(HotChunk);
  5844. if Assigned(FallChunk) then
  5845. FreeChunkData(FallChunk);
  5846. if Assigned(RollChunk) then
  5847. FreeChunkData(RollChunk);
  5848. if Assigned(TargetPosChunk) then
  5849. FreeChunkData(TargetPosChunk);
  5850. end;
  5851. //---------------------------------------------------------------------------------------------------------------------
  5852. function GetSpotlightMotionByName(const Source: TFile3DS; var DB: TDatabase3DS;
  5853. const Name: string): TKFSpot3DS;
  5854. var
  5855. SpotlightChunk, TargetChunk: PChunk3DS;
  5856. begin
  5857. FillChar(Result, SizeOf(Result), 0);
  5858. SpotlightChunk := FindNamedAndTaggedChunk(Source, DB, Name, SPOTLIGHT_NODE_TAG);
  5859. if Assigned(SpotlightChunk) then
  5860. begin
  5861. TargetChunk := FindNamedAndTaggedChunk(Source, DB, Name, L_TARGET_NODE_TAG);
  5862. Result := GetSpotlightMotion(Source, SpotlightChunk, TargetChunk);
  5863. end;
  5864. end;
  5865. //---------------------------------------------------------------------------------------------------------------------
  5866. function GetSpotlightMotionByIndex(const Source: TFile3DS; var DB: TDatabase3DS;
  5867. Index: cardinal): TKFSpot3DS;
  5868. var
  5869. SpotChunk, TargetChunk: PChunk3DS;
  5870. List: TStringList;
  5871. begin
  5872. FillChar(Result, SizeOf(Result), 0);
  5873. List := TStringList.Create;
  5874. try
  5875. GetSpotlightNodeNameList(Source, DB, List);
  5876. if Index < cardinal(List.Count) then
  5877. begin
  5878. SpotChunk := FindNamedAndTaggedChunk(Source, DB, List[Index], SPOTLIGHT_NODE_TAG);
  5879. if Assigned(SpotChunk) then
  5880. begin
  5881. TargetChunk := FindNamedAndTaggedChunk(Source, DB, List[Index],
  5882. L_TARGET_NODE_TAG);
  5883. if Assigned(TargetChunk) then
  5884. Result := GetSpotlightMotion(Source, SpotChunk, TargetChunk);
  5885. end;
  5886. end;
  5887. finally
  5888. List.Free;
  5889. end;
  5890. end;
  5891. //----------------- Versioninformation --------------------------------------------------------------------------------
  5892. function GetM3dMagicRelease(const Source: TFile3DS; var DB: TDatabase3DS): TReleaseLevel;
  5893. // Scans the database for M3D_VERSION chunk and returnes its release
  5894. var
  5895. Chunk: PChunk3DS;
  5896. begin
  5897. Result := rlReleaseNotKnown;
  5898. // If the database is a 3DS file
  5899. if DB.TopChunk^.Tag = M3DMAGIC then
  5900. begin
  5901. Chunk := FindChunk(DB.TopChunk, M3D_VERSION);
  5902. if Assigned(Chunk) then
  5903. begin
  5904. Source.ReadChunkData(Chunk);
  5905. case Chunk^.Data.M3dVersion^ of
  5906. 1:
  5907. Result := rlRelease1;
  5908. 2:
  5909. Result := rlRelease2;
  5910. 3:
  5911. Result := rlRelease3;
  5912. else
  5913. Result := rlReleaseNotKnown;
  5914. end;
  5915. end;
  5916. end;
  5917. end;
  5918. //---------------------------------------------------------------------------------------------------------------------
  5919. function GetMeshRelease(const Source: TFile3DS; var DB: TDatabase3DS): TReleaseLevel;
  5920. // Scans the database for MESH_VERSION chunk and returnes its release
  5921. var
  5922. Chunk: PChunk3DS;
  5923. begin
  5924. Result := rlReleaseNotKnown;
  5925. // If the database is a 3DS file
  5926. if (DB.TopChunk^.Tag = M3DMAGIC) or (DB.TopChunk^.Tag = CMAGIC) then
  5927. begin
  5928. Chunk := FindChunk(DB.TopChunk, MESH_VERSION);
  5929. if Assigned(Chunk) then
  5930. begin
  5931. Source.ReadChunkData(Chunk);
  5932. case Chunk^.Data.MeshVersion^ of
  5933. 1:
  5934. Result := rlRelease1;
  5935. 2:
  5936. Result := rlRelease2;
  5937. 3:
  5938. Result := rlRelease3;
  5939. else
  5940. Result := rlReleaseNotKnown;
  5941. end;
  5942. end;
  5943. end;
  5944. end;
  5945. //---------------------------------------------------------------------------
  5946. function GetKfRelease(const Source: TFile3DS; var DB: TDatabase3DS): TReleaseLevel;
  5947. // Scans the database for KFHDR chunk and returnes its release level
  5948. var
  5949. KFChunk, Chunk: PChunk3DS;
  5950. begin
  5951. Result := rlReleaseNotKnown;
  5952. // If the database is a 3DS file
  5953. if (DB.TopChunk^.Tag = M3DMAGIC) or (DB.TopChunk^.Tag = CMAGIC) then
  5954. begin
  5955. KFChunk := FindChunk(DB.TopChunk, KFDATA);
  5956. if Assigned(KFChunk) then
  5957. Chunk := FindChunk(DB.TopChunk, KFHDR)
  5958. else
  5959. Chunk := nil;
  5960. if Assigned(Chunk) then
  5961. begin
  5962. Source.ReadChunkData(Chunk);
  5963. case Chunk^.Data.KFHdr^.Revision of
  5964. 1:
  5965. Result := rlRelease1;
  5966. 2:
  5967. Result := rlRelease2;
  5968. 3:
  5969. Result := rlRelease3;
  5970. else
  5971. Result := rlReleaseNotKnown;
  5972. end;
  5973. end;
  5974. end;
  5975. end;
  5976. //-----------------------------------------------------------------------------
  5977. function GetDatabaseRelease(const Source: TFile3DS; var DB: TDatabase3DS): TReleaseLevel;
  5978. begin
  5979. case DB.TopChunk^.Tag of
  5980. M3DMAGIC:
  5981. Result := GetM3dMagicRelease(Source, DB);
  5982. CMAGIC:
  5983. Result := GetMeshRelease(Source, DB);
  5984. MLIBMAGIC:
  5985. Result := rlRelease3;
  5986. else
  5987. Result := rlReleaseNotKnown;
  5988. end;
  5989. end;
  5990. //----------------------------------------------------------------------------
  5991. end.