Formats.m3DSUtils.pas 210 KB

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