File3DSUtils.pas 217 KB

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