| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425 |
- //
- // This unit is part of the GLScene Engine, http://glscene.org
- //
- (*-------------------------------------------------------------------------------
- Unit Name: Lightwave
- Author: Brian Johns [email protected]
- Purpose: Lightwave object support unit for Delphi.
- Notes: For the Lightwave Object File Format documentation please refer to
- http://www.lightwave3d.com/developer.
- License: This unit is distributed under the Mozilla Public License.
- For license details, refer to http://www.mozilla.org
- Lightwave3D is a registered trademark of Newtek Incorporated.
- -------------------------------------------------------------------------------*)
- unit FileLWObjects;
- interface
- {$I GLScene.inc}
- uses
- System.Classes,
- System.SysUtils,
- System.Math,
- GLVectorGeometry;
- type
- TID4 = array[0..3] of AnsiChar;
- PID4 = ^TID4;
- TID4DynArray = array of TID4;
- const
- ID_NULL = '#0#0#0#0'; // NULL ID
- ID_LWSC: TID4 = 'LWSC'; // Lightwave scene file
- ID_FORM: TID4 = 'FORM'; // IFF Form
- ID_LWOB: TID4 = 'LWOB'; // Lightwave Object version 1.0 - 5.x
- ID_LWLO: TID4 = 'LWLO'; // Lightwave Layered Object
- ID_LAYR: TID4 = 'LAYR'; // LAYER
- ID_PNTS: TID4 = 'PNTS'; // Points chunk
- ID_SRFS: TID4 = 'SRFS'; // Surface Names chunk
- ID_POLS: TID4 = 'POLS'; // Polygons chunk
- ID_CRVS: TID4 = 'CRVS'; // Curves chunk
- ID_PCHS: TID4 = 'PCHS'; // Patches chunk
- ID_SURF: TID4 = 'SURF'; // Surfaces chunk
- ID_COLR: TID4 = 'COLR'; // Color chunk
- ID_FLAG: TID4 = 'FLAG'; // Surface Flags
- ID_LUMI: TID4 = 'LUMI'; // Luminosity
- ID_DIFF: TID4 = 'DIFF'; // Diffuse
- ID_SPEC: TID4 = 'SPEC'; // Specular
- ID_REFL: TID4 = 'REFL'; // Reflective
- ID_TRAN: TID4 = 'TRAN'; // Transparency
- ID_VLUM: TID4 = 'VLUM'; // Luminosity
- ID_VDIF: TID4 = 'VDIF'; // Diffuse
- ID_VSPC: TID4 = 'VSPC'; // Specularity
- ID_VRFL: TID4 = 'VRFL'; // Reflective
- ID_VTRN: TID4 = 'VTRN'; // Transparency
- ID_GLOS: TID4 = 'GLOS'; // Glossiness SmallInt
- ID_SIDE: TID4 = 'SIDE'; // Sidedness
- ID_RFLT: TID4 = 'RFLT'; // REFLECTION MODE (PRE 6.0)
- ID_RFOP: TID4 = 'RFOP'; // REFLECTION OPTIONS
- ID_RIMG: TID4 = 'RIMG'; // REFLECTION IMAGE
- ID_RSAN: TID4 = 'RSAN'; // REFLECTION MAP SEAM ANGLE
- ID_RIND: TID4 = 'RIND'; // REFRACTIVE INDEX
- ID_EDGE: TID4 = 'EDGE'; // EDGE TRANSPARENCY THRESHOLD
- ID_SMAN: TID4 = 'SMAN'; // SMOOTHING ANGLE RADIANS
- ID_ALPH: TID4 = 'ALPH'; // ALPHA MODE
- ID_CTEX: TID4 = 'CTEX'; // COLOR TEXTURE
- ID_DTEX: TID4 = 'DTEX'; // DIFFUSE TEXTURE
- ID_STEX: TID4 = 'STEX'; // SPECULAR TEXTURE
- ID_RTEX: TID4 = 'RTEX'; // REFLECTIION TEXTURE
- ID_TTEX: TID4 = 'TTEX'; // TRANSPARENCY TEXTURE
- ID_LTEX: TID4 = 'LTEX'; // LUMINANCE TEXTURE
- ID_BTEX: TID4 = 'BTEX'; // BUMP TEXTURE
- ID_TFLG: TID4 = 'TFLG'; // TEXTURE FLAGS
- ID_TSIZ: TID4 = 'TSIZ'; // TEXTURE SIZE
- ID_TCTR: TID4 = 'TCTR'; // TEXTURE CENTER
- ID_TFAL: TID4 = 'TFAL'; // TEXTURE FALLOFF
- ID_TVEL: TID4 = 'TVAL'; // TEXTURE VALUE
- ID_TREF: TID4 = 'TREF'; // TEXTURE REFERENCE
- ID_TCLR: TID4 = 'TCLR'; // TEXTURE COLOR
- ID_TVAL: TID4 = 'TVAL'; // TEXTURE VALUE
- ID_TAMP: TID4 = 'TAMP'; // TEXTURE AMPLITUDE
- ID_TFP0: TID4 = 'TFP0'; // TEXTURE PARAMETERS
- ID_TFP1: TID4 = 'TFP1'; //
- ID_TFP2: TID4 = 'TFP2'; //
- ID_TIP0: TID4 = 'TIP0'; //
- ID_TIP1: TID4 = 'TIP1'; //
- ID_TIP2: TID4 = 'TIP2'; //
- ID_TSP0: TID4 = 'TSP0'; //
- ID_TSP1: TID4 = 'TSP1'; //
- ID_TSP2: TID4 = 'TSP2'; //
- ID_TFRQ: TID4 = 'TFRQ'; //
- ID_TIMG: TID4 = 'TIMG'; // TEXTURE IMG
- ID_TALP: TID4 = 'TALP'; //
- ID_TWRP: TID4 = 'TWRP'; // TEXTURE WRAP
- ID_TAAS: TID4 = 'TAAS'; //
- ID_TOPC: TID4 = 'TOPC'; //
- ID_SHDR: TID4 = 'SHDR'; //
- ID_SDAT: TID4 = 'SDAT'; //
- ID_IMSQ: TID4 = 'IMSQ'; // IMAGE SEQUENCE
- ID_FLYR: TID4 = 'FLYR'; // FLYER SEQUENCE
- ID_IMCC: TID4 = 'IMCC'; //
- SURF_FLAG_LUMINOUS = 1;
- SURF_FLAG_OUTLINE = 2;
- SURF_FLAG_SMOOTHING = 4;
- SURF_FLAG_COLORHIGHLIGHTS = 8;
- SURF_FLAG_COLORFILTER = 16;
- SURF_FLAG_OPAQUEEDGE = 32;
- SURF_FLAG_TRANSPARENTEDGE = 64;
- SURF_FLAG_SHARPTERMINATOR = 128;
- SURF_FLAG_DOUBLESIDED = 256;
- SURF_FLAG_ADDITIVE = 512;
- SURF_FLAG_SHADOWALPHA = 1024;
- CURV_CONTINUITY_FIRST = 1;
- CURV_CONTINUITY_LAST = 2;
- IMSQ_FLAG_LOOP = 1;
- IMSQ_FLAG_INTERLACE = 2;
- ID_LWO2: TID4 = 'LWO2'; // OBJECT
- ID_VMAP: TID4 = 'VMAP'; // VERTEX MAP
- ID_TAGS: TID4 = 'TAGS'; // TAGS?
- ID_PTAG: TID4 = 'PTAG'; // POLYGON TAG MAP
- ID_VMAD: TID4 = 'VMAD'; // DISCONTINUOUS VERTEX MAP
- ID_ENVL: TID4 = 'ENVL'; // ENVELOPE
- ID_CLIP: TID4 = 'CLIP'; // CLIP
- ID_BBOX: TID4 = 'BBOX'; // BOUNDING BOX
- ID_DESC: TID4 = 'DESC'; // DESCRIPTION
- ID_TEXT: TID4 = 'TEXT'; // TEXT
- ID_ICON: TID4 = 'ICON'; // ICON
- ENVL_PRE: TID4 = 'PRE'#0; // PRE-BEHAVIOUR
- ENVL_POST: TID4 = 'POST'; // POST
- ENVL_KEY: TID4 = 'KEY'#0; // KEY
- ENVL_SPAN: TID4 = 'SPAN'; // SPAN
- ENVL_CHAN: TID4 = 'CHAN'; // CHAN
- ENVL_NAME: TID4 = 'NAME'; // NAME
- ID_STIL: TID4 = 'STIL'; // STILL IMAGE FILENAME
- ID_ISEQ: TID4 = 'ISEQ'; // IMAGE SEQUENCE
- ID_ANIM: TID4 = 'ANIM'; // PLUGIN ANIMATION
- ID_STCC: TID4 = 'STCC'; // COLOR CYCLING STILL
- ID_CONT: TID4 = 'CONT'; // CONTRAST
- ID_BRIT: TID4 = 'BRIT'; // BRIGHTNESS
- ID_SATR: TID4 = 'SATR'; // SATURATION
- ID_HUE: TID4 = 'HUE'#0; // HUE
- ID_GAMMA: TID4 = 'GAMM'; // GAMMA
- ID_NEGA: TID4 = 'NEGA'; // NEGATIVE IMAGE
- ID_IFLT: TID4 = 'IFLT'; // IMAGE PLUG-IN FILTER
- ID_PFLT: TID4 = 'PFLT'; // PIXEL PLUG-IN FILTER
- POLS_TYPE_FACE: TID4 = 'FACE'; // FACES
- POLS_TYPE_CURV: TID4 = 'CURV'; // CURVE
- POLS_TYPE_PTCH: TID4 = 'PTCH'; // PATCH
- POLS_TYPE_MBAL: TID4 = 'MBAL'; // METABALL
- POLS_TYPE_BONE: TID4 = 'BONE'; // SKELEGON?
- VMAP_TYPE_PICK: TID4 = 'PICK'; // SELECTION SET
- VMAP_TYPE_WGHT: TID4 = 'WGHT'; // WEIGHT MAP
- VMAP_TYPE_MNVW: TID4 = 'MNVW'; // SUBPATCH WEIGHT MAP
- VMAP_TYPE_TXUV: TID4 = 'TXUV'; // UV MAP
- VMAP_TYPE_RGB: TID4 = 'RGB'#0; // RGB MAP
- VMAP_TYPE_RGBA: TID4 = 'RGBA'; // RGBA MAP
- VMAP_TYPE_MORF: TID4 = 'MORF'; // MORPH MAP: RELATIVE VERTEX DISPLACEMENT
- VMAP_TYPE_SPOT: TID4 = 'SPOT'; // SPOT MAP: ABSOLUTE VERTEX POSITIONS
- PTAG_TYPE_SURF: TID4 = 'SURF'; // SURFACE
- PTAG_TYPE_PART: TID4 = 'PART'; // PARENT PART
- PTAG_TYPE_SMGP: TID4 = 'SMGP'; // SMOOTH GROUP
- PRE_POST_RESET = 0; // RESET
- PRE_POST_CONSTANT = 1; // CONSTANT
- PRE_POST_REPEAT = 2; // REPEAT
- PRE_POST_OSCILLATE = 3; // OSCILLATE
- PRE_POST_OFFSET = 4; // OFFSET REPEAT
- PRE_POST_LINEAR = 5; // LINEAR
- POLS_VCOUNT_MASK = $3FF;
- POLS_FLAGS_MASK = $FC00;
- SIDE_FRONT = 1;
- SIDE_BACK = 2;
- SIDE_FRONT_AND_BACK = SIDE_FRONT and SIDE_BACK;
- RFOP_BACKDROP = 0;
- RFOP_RAYTRACEANDBACKDROP = 1;
- RFOP_SPHERICALMAP = 2;
- RFOP_RAYTRACEANDSPHERICALMAP = 3;
- type
- TI1 = ShortInt;
- PI1 = ^TI1;
- TI2 = SmallInt;
- PI2 = ^TI2;
- TI4 = LongInt;
- PI4 = ^TI4;
- TU1 = Byte;
- PU1 = ^TU1;
- TU1DynArray = array of TU1;
- TU2 = Word;
- PU2 = ^TU2;
- TU2Array = array [0..65534] of TU2;
- PU2Array = ^TU2Array;
- TU2DynArray = array of TU2;
- TU4 = LongWord;
- PU4 = ^TU4;
- TU4Array = array [0..65534] of TU4;
- PU4Array = ^TU4Array;
- TU4DynArray = array of TU4;
- TF4 = Single;
- PF4 = ^TF4;
- TF4Array = array [0..65534] of TF4;
- PF4Array = ^TF4Array;
- TF4DynArray = array of TF4;
- TANG4 = TF4;
- PANG4 = ^TANG4;
- // TS0 = PAnsiChar;
- TVec12 = array[0..2] of TF4;
- PVec12 = ^TVec12;
- TVec12Array = array [0..65534] of TVec12;
- PVec12Array = ^TVec12Array;
- TVec12DynArray = array of TVec12;
- TColr12 = TVec12;
- PColr12 = ^TColr12;
- TColr12DynArray = array of TColr12;
- TColr4 = array[0..3] of TU1;
- PColr4 = ^TColr4;
- { Lightwave Chunk Struct - Used in TLWOReadCallback }
- PLWChunkRec = ^TLWChunkRec;
- TLWChunkRec = record
- id: TID4;
- size: TU4;
- data: Pointer;
- end;
- { Lightwave SubChunk Struct - Used in TLWOReadCallback }
- PLWSubChunkRec = ^TLWSubChunkRec;
- TLWSubChunkRec = record
- id: TID4;
- size: TU2;
- data: Pointer;
- end;
- TLWPolsInfo = record
- norm: TVec12;
- vnorms: TVec12DynArray;
- surfid: TU2;
- end;
- TLWPolsInfoDynArray = array of TLWPolsInfo;
- TLWPntsInfo = record
- npols: TU2;
- pols: TU2DynArray;
- end;
- TLWPntsInfoDynArray = array of TLWPntsInfo;
- TLWPolsDynArray = TU2DynArray;
- TLWPolyTagMapDynArray = TU2DynArray;
- TLWPolyTagMap = record
- poly: TU2;
- tag: TU2;
- end;
- PLWPolyTagMap = ^TLWPolyTagMap;
- { Value Map }
- TLWVertexMap = record
- vert: TU2;
- values: TF4DynArray;
- end;
- TLWVertexMapDynArray = array of TLWVertexMap;
- TLWChunkList = class;
- TLWParentChunk = class;
- TLWChunk = class (TPersistent)
- private
- FData: Pointer;
- FID: TID4;
- FSize: TU4;
- FParentChunk: TLWParentChunk;
- FOwner: TLWChunkList;
- function GetRootChunks: TLWChunkList;
- function GetIndex: Integer;
- protected
- procedure Clear; virtual;
- procedure LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- virtual;
- procedure Loaded; virtual;
- public
- destructor Destroy; override;
- class function GetID: TID4; virtual;
- procedure LoadFromStream(AStream: TStream); virtual;
- property Data: Pointer read FData;
- property ID: TID4 read FID;
- property Size: TU4 read FSize;
- { ParentChunk may be nil indicating this is a root chunk. ie. TLWLayr }
- property ParentChunk: TLWParentChunk read FParentChunk;
- property RootChunks: TLWChunkList read GetRootChunks;
- property Index: Integer read GetIndex;
- property Owner: TLWChunkList read FOwner;
- end;
- TLWChunkClass = class of TLWChunk;
- TLWSubChunk = class (TLWChunk)
- public
- procedure LoadFromStream(AStream: TStream); override;
- end;
- TLWChunkFind = procedure(AChunk: TLWChunk; Criteria: Pointer; var Found: boolean);
- TLWChunkList = class (TList)
- private
- FOwnsItems: Boolean;
- FOwner: TObject;
- function GetItem(Index: Integer): TLWChunk;
- protected
- procedure Loaded; virtual;
- public
- constructor Create(AOwnsItems: boolean; AOwner: TObject);
- destructor Destroy; override;
- function Add(AChunk: TLWChunk): Integer;
- procedure Clear; override;
- procedure Delete(Index: Integer);
- function FindChunk(ChunkFind: TLWChunkFind; Criteria: Pointer; StartIndex: Integer = 0): Integer;
- property Items[Index: Integer]: TLWChunk read GetItem; default;
- property OwnsItems: Boolean read FOwnsItems;
- property Owner: TObject read FOwner;
- end;
- TLWParentChunk = class (TLWChunk)
- private
- FItems: TLWChunkList;
- function GetItems: TLWChunkList;
- function GetFloatParam(Param: TID4): Single;
- function GetWordParam(Param: TID4): Word;
- function GetVec3Param(Param: TID4): TVec12;
- function GetLongParam(Param: TID4): LongWord;
- function GetVXParam(Param: TID4): Word;
- protected
- function GetParamAddr(Param: TID4): Pointer; virtual;
- procedure Clear; override;
- procedure Loaded; override;
- public
- property Items: TLWChunkList read GetItems;
- property ParamAddr[Param: TID4]: Pointer read GetParamAddr;
- property FloatParam[Param: TID4]: Single read GetFloatParam;
- property WordParam[Param: TID4]: Word read GetWordParam;
- property LongParam[Param: TID4]: LongWord read GetLongParam;
- property Vec3Param[Param: TID4]: TVec12 read GetVec3Param;
- property VXParam[Param: TID4]: Word read GetVXParam;
- end;
- TLWVMap = class;
- TLWPnts = class (TLWParentChunk)
- private
- FPnts: TVEC12DynArray;
- FPntsInfo: TLWPntsInfoDynArray;
- function GetPntsCount: LongWord;
- function AddPoly(PntIdx, PolyIdx: Integer): Integer;
- protected
- procedure Clear; override;
- procedure LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- override;
- public
- class function GetID: TID4; override;
- function GetVMap(VMapID: TID4; out VMap: TLWVMap): Boolean;
- property PntsCount: LongWord read GetPntsCount;
- property Pnts: TVEC12DynArray read FPnts;
- property PntsInfo: TLWPntsInfoDynArray read FPntsInfo;
- end;
- TLWPols = class (TLWParentChunk)
- private
- FPolsType: TID4;
- FPols: TLWPolsDynArray;
- FPolsInfo: TLWPolsInfoDynArray;
- FPolsCount: Integer;
- function GetPolsByIndex(AIndex: TU2): Integer;
- function GetIndiceCount: TU4;
- function GetIndice(AIndex: Integer): TU2;
- function GetPolsCount: Integer;
- procedure CalcPolsNormals;
- procedure CalcPntsNormals;
- protected
- procedure Clear; override;
- procedure LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- override;
- procedure Loaded; override;
- public
- class function GetID: TID4; override;
- function GetPolsByPntIdx(VertIdx: TU2; var VertPolys: TU2DynArray): Integer;
- property PolsByIndex[AIndex: TU2]: Integer read GetPolsByIndex;
- property IndiceCount: TU4 read GetIndiceCount;
- property Indices[AIndex: Integer]: TU2 read GetIndice;
- property PolsType: TID4 read FPolsType;
- property PolsCount: Integer read GetPolsCount;
- property PolsInfo: TLWPolsInfoDynArray read FPolsInfo;
- end;
- TLWVMap = class (TLWChunk)
- private
- FDimensions: TU2;
- FName: string;
- FValues: TLWVertexMapDynArray;
- FVMapType: TID4;
- function GetValue(AIndex: TU2): TLWVertexMap;
- function GetValueCount: Integer;
- protected
- procedure Clear; override;
- procedure LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- override;
- public
- class function GetID: TID4; override;
- property Dimensions: TU2 read FDimensions;
- property Name: string read FName;
- property Value[AIndex: TU2]: TLWVertexMap read GetValue;
- property ValueCount: Integer read GetValueCount;
- property VMapType: TID4 read FVMapType;
- end;
- TLWTags = class (TLWChunk)
- private
- FTags: TStrings;
- function GetTags: TStrings;
- protected
- procedure Clear; override;
- procedure LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- override;
- public
- destructor Destroy; override;
- class function GetID: TID4; override;
- function TagToName(Tag: TU2): string;
- property Tags: TStrings read GetTags;
- end;
- TLWSurf = class (TLWParentChunk)
- private
- FName: string;
- FSource: string;
- function GetSurfId: Integer;
- protected
- function GetParamAddr(Param: TID4): Pointer; override;
- procedure LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- override;
- public
- destructor Destroy; override;
- class function GetID: TID4; override;
- property SurfId: Integer read GetSurfId;
- property Name: string read FName;
- property Source: string read FSource;
- end;
- TLWLayr = class (TLWParentChunk)
- private
- FFlags: TU2;
- FName: string;
- FNumber: TU2;
- FParent: TU2;
- FPivot: TVec12;
- protected
- procedure LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- override;
- public
- destructor Destroy; override;
- class function GetID: TID4; override;
- property Flags: TU2 read FFlags;
- property Name: string read FName;
- property Number: TU2 read FNumber;
- property Parent: TU2 read FParent;
- property Pivot: TVec12 read FPivot;
- end;
- TLWPTag = class (TLWChunk)
- private
- FMapType: TID4;
- FTagMaps: TLWPolyTagMapDynArray;
- FTags: TU2DynArray;
- function AddTag(Value: TU2): Integer;
- function GetTag(AIndex: Integer): TU2;
- function GetTagCount: Integer;
- function GetTagMapCount: Integer;
- function GetTagMaps(AIndex: Integer): TLWPolyTagMap;
- procedure ValidateTagInfo;
- protected
- procedure Clear; override;
- procedure LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- override;
- public
- constructor Create;
- function GetPolsByTag(Tag: TU2; var PolyIndices: TU2DynArray): Integer;
- class function GetID: TID4; override;
- property MapType: TID4 read FMapType;
- property TagCount: Integer read GetTagCount;
- property TagMapCount: Integer read GetTagMapCount;
- property TagMaps[AIndex: Integer]: TLWPolyTagMap read GetTagMaps; default;
- property Tags[AIndex: Integer]: TU2 read GetTag;
- end;
-
- TLWObjectFile = class (TObject)
- private
- FChunks: TLWChunkList;
- FFileName: string;
- function GetChunks: TLWChunkList;
- function GetCount: Integer;
- function GetSurfaceByName(Index: string): TLWSurf;
- function GetSurfaceByTag(Index: TU2): TLWSurf;
- public
- constructor Create;
- destructor Destroy; override;
- function TagToName(Tag: TU2): string;
- procedure LoadFromFile(const AFilename: string);
- procedure LoadFromStream(AStream: TStream);
- property ChunkCount: Integer read GetCount;
- property Chunks: TLWChunkList read GetChunks;
- property FileName: string read FFileName;
- property SurfaceByName[Index: string]: TLWSurf read GetSurfaceByName;
- property SurfaceByTag[Index: TU2]: TLWSurf read GetSurfaceByTag;
- end;
- TLWClip = class(TLWParentChunk)
- private
- FClipIndex: TU4;
- protected
- procedure LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- override;
- public
- class function GetID: TID4; override;
- property ClipIndex: TU4 read FClipIndex;
- end;
- TLWContentNotify = procedure(Sender: TObject; var Content: string) of object;
- TLWContentDir = class
- private
- FSubDirs: TStrings;
- FRoot: string;
- function GetSubDirs: TStrings;
- procedure SetRoot(const Value: string);
- procedure SetSubDirs(const Value: TStrings);
- // function ContentSearch(AFilename: string): string;
- public
- destructor Destroy; override;
- function FindContent(AFilename: string): string;
- property Root: string read FRoot write SetRoot;
- property SubDirs: TStrings read GetSubDirs write SetSubDirs;
- end;
- TLWOReadCallback = procedure(Chunk: TLWChunkRec; Data: Pointer); cdecl;
- procedure RegisterChunkClass(ChunkClass: TLWChunkClass);
- function LoadLW0FromStream(Stream: TStream; ReadCallback: TLWOReadCallback; UserData: Pointer): LongWord; cdecl;
- function LoadLWOFromFile(const AFilename: string; ReadCallback: TLWOReadCallback; UserData: Pointer): LongWord;
- procedure ReadMotorolaNumber(Stream: TStream; Data: Pointer; ElementSize:
- Integer; Count: Integer = 1);
- function WriteMotorolaNumber(Stream: TStream; Data: Pointer; ElementSize:
- Integer; Count: Integer = 1): Integer;
- function ReadS0(Stream: TStream; out Str: string): Integer;
- procedure WriteS0(Stream: TStream; Data: string);
- procedure WriteU4AsVX(Stream:TStream; Data: Pointer; Count: Integer);
- function ReadVXAsU4(Stream: TStream; Data: Pointer; Count: Integer = 1): Integer;
- procedure ReverseByteOrder(ValueIn: Pointer; Size: Integer; Count: Integer = 1);
- function ToDosPath(const Path: string): string;
- function ToUnixPath(const Path: string): string;
- function ID4ToInt(const Id: TID4): Integer;
- // ChunkFind procedures
- procedure FindChunkById(AChunk: TLWChunk; Data: Pointer; var Found: boolean);
- procedure FindSurfaceByName(AChunk: TLWChunk; AName: Pointer; var Found: boolean);
- procedure FindSurfaceByTag(AChunk: TLWChunk; ATag: Pointer; var Found: boolean);
- procedure FindVMapByName(AChunk: TLWChunk; AName: Pointer; var Found: boolean);
- procedure FindClipByClipIndex(AChunk: TLWChunk; AIndex: Pointer; var Found: boolean);
- function GetContentDir: TLWContentDir;
- //--------------------------------------------------------------------
- //--------------------------------------------------------------------
- //--------------------------------------------------------------------
- implementation
- //--------------------------------------------------------------------
- //--------------------------------------------------------------------
- //--------------------------------------------------------------------
- uses
- GLApplicationFileIO;
- type
- PWord = ^Word;
- PLongWord = ^LongWord;
- var
- ChunkClasses: TList;
- ContentDir: TLWContentDir;
- function ToDosPath(const Path: string): string;
- var
- i: Integer;
- begin
- result := Path;
- for i := 1 to Length(result) do
- if result[i] = '/' then
- result[i] := '\';
- end;
- function ToUnixPath(const Path: string): string;
- var
- i: Integer;
- begin
- result := Path;
- for i := 1 to Length(result) do
- if result[i] = '\' then
- result[i] := '/';
- end;
- function GetContentDir: TLWContentDir;
- begin
- if ContentDir = nil then
- ContentDir := TLWContentDir.Create;
- result := ContentDir;
- end;
- procedure FindChunkById(AChunk: TLWChunk; Data: Pointer; var Found: boolean);
- begin
- if AChunk.FID = PID4(Data)^ then
- Found := true
- else
- Found := false;
- end;
- procedure FindClipByClipIndex(AChunk: TLWChunk; AIndex: Pointer; var Found: boolean);
- begin
- if (AChunk is TLWClip) and
- (TLWClip(AChunk).ClipIndex = PU2(AIndex)^) then
- Found := true;
- end;
- procedure FindSurfaceByName(AChunk: TLWChunk; AName: Pointer; var Found: boolean);
- begin
- if (AChunk is TLWSurf) and
- (TLWSurf(AChunk).Name = PString(AName)^) then
- Found := true;
- end;
- procedure FindSurfaceByTag(AChunk: TLWChunk; ATag: Pointer; var Found: boolean);
- begin
- if (AChunk is TLWSurf) and
- (TLWSurf(AChunk).SurfId = PU2(ATag)^) then
- Found := true;
- end;
- procedure FindVMapByName(AChunk: TLWChunk; AName: Pointer; var Found: boolean);
- begin
- if (AChunk is TLWVMap) and
- (TLWVMap(AChunk).Name = PString(AName)^) then
- Found := true;
- end;
- function VecAdd(v1,v2: TVec12):TVec12;
- begin
- result[0]:=v1[0]+v2[0];
- result[1]:=v1[1]+v2[1];
- result[2]:=v1[2]+v2[2];
- end;
- function VecSub(v1,v2: TVec12): TVec12;
- begin
- result[0]:=v1[0]-v2[0];
- result[1]:=v1[1]-v2[1];
- result[2]:=v1[2]-v2[2];
- end;
- function VecCross(v1,v2: TVec12): TVec12;
- begin
- result[0]:=v1[1]*v2[2]-v1[2]*v2[1];
- result[1]:=v1[2]*v2[0]-v1[0]*v2[2];
- result[2]:=v1[0]*v2[1]-v1[1]*v2[0];
- end;
- function VecDot(v1, v2: TVec12): TF4;
- begin
- result:=v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
- end;
- function VecNorm(v: TVec12) : TVec12;
- var
- mag: TF4;
- begin
- mag := Sqrt(VecDot(v,v));
- if mag >0 then mag := 1/mag;
- result[0]:=v[0]*mag;
- result[1]:=v[1]*mag;
- result[2]:=v[2]*mag;
- end;
- function CalcPlaneNormal(v1,v2,v3: TVec12): TVec12;
- var
- e1, e2: TVec12;
- begin
- e1:=VecSub(v2,v1);
- e2:=VecSub(v3,v1);
- result:=VecCross(e1,e2);
- result:=VecNorm(result);
- end;
- procedure FindSurfByName(Chunk: TLWChunk; var Found: boolean);
- begin
- end;
- {-----------------------------------------------------------------------------
- Procedure: GetChunkClasses
- Date: 08-Aug-2002
- Arguments: None
- Result: TClassList
- Singleton access for the chunk class list.
- -----------------------------------------------------------------------------}
- function GetChunkClasses: TList;
- begin
- if ChunkClasses=nil then
- ChunkClasses:=TList.Create;
- result:=ChunkClasses;
- end;
- procedure UnRegisterChunkClasses;
- var
- i: Integer;
- begin
- with GetChunkClasses do
- for i:=0 to Count-1 do
- UnregisterClass(TPersistentClass(Items[i]));
- end;
- {-----------------------------------------------------------------------------
- Procedure: RegisterChunkClass
- Date: 08-Aug-2002
- Arguments: ChunkClass: TLWChunkClass
- Result: None
- Adds a user defined chunk class to the chunk class list.
- -----------------------------------------------------------------------------}
- procedure RegisterChunkClass(ChunkClass: TLWChunkClass);
- begin
- GetChunkClasses.Add(ChunkClass);
- // if FindClass(ChunkClass.ClassName) <> nil then
- // UnRegisterClass(ChunkClass);
- // RegisterClass(ChunkClass);
- end;
- {-----------------------------------------------------------------------------
- Procedure: GetChunkClass
- Date: 08-Aug-2002
- Arguments: ChunkID: TID4
- Result: TLWChunkClass
- Returns the chunk class associated with ChunkID.
- -----------------------------------------------------------------------------}
- function GetChunkClass(ChunkID: TID4; ADefault: TLWChunkClass): TLWChunkClass;
- var
- i: Integer;
- begin
- if ADefault = nil then
- result:=TLWChunk
- else
- result:=ADefault;
- for i:=0 to ChunkClasses.Count-1 do
- begin
- if TLWChunkClass(ChunkClasses.Items[i]).GetID=ChunkID then
- begin
- result:=TLWChunkClass(ChunkClasses.Items[i]);
- Exit;
- end;
- end;
- end;
- {-----------------------------------------------------------------------------
- Procedure: Tokenize
- Date: 08-Aug-2002
- Arguments: const Src: string; Delimiter: Char; Dst: TStrings
- Result: None
- Breaks up a string into TStrings items when the Delimiter character is
- encountered.
- -----------------------------------------------------------------------------}
- procedure Tokenize(const Src: string; Delimiter: Char; Dst: TStrings);
- var
- i,L,SL: Integer;
- SubStr: string;
- begin
- if Dst=nil then Exit;
- L:=Length(Src);
- if (L=0) or (Dst=nil) then Exit;
- SubStr:='';
- for i:=1 to L do
- begin
- if (Src[i]<>Delimiter) then SubStr:=SubStr+Src[i] else
- begin
- SL:=Length(SubStr);
- if SL>0 then
- begin
- Dst.Add(SubStr);
- SubStr:='';
- end;
- end;
- end;
- if Length(SubStr)>0 then Dst.Add(SubStr);
- end;
- {-----------------------------------------------------------------------------
- Procedure: LoadLW0FromStream
- Date: 08-Aug-2002
- Arguments: Stream: TStream; ReadCallback: TLWOReadCallback; UserData: Pointer
- Result: LongWord
- -----------------------------------------------------------------------------}
- function LoadLW0FromStream(Stream: TStream; ReadCallback: TLWOReadCallback; UserData: Pointer): LongWord;
- var
- Chunk: TLWChunkRec;
- CurId: TID4;
- StartPos, CurSize: TU4;
- begin
- try
- Stream.Read(CurId,4);
- ReadMotorolaNumber(Stream,@CurSize,4);
- if UpperCase(string(CurId)) = 'FORM' then
- begin
- Stream.Read(CurId,4);
- end else raise Exception.Create('Invalid magic number. Not a valid Lightwave Object');
- with Stream do while Position < Size do
- begin
- Read(Chunk,8);
- ReverseByteOrder(@Chunk.size,4);
- StartPos:=Position;
- GetMem(Chunk.data,Chunk.size);
- Stream.Read(Chunk.data^,Chunk.size);
- if Assigned(ReadCallback) then ReadCallback(Chunk,UserData);
- FreeMem(Chunk.data,Chunk.size);
- Position:=StartPos+Chunk.size+(StartPos+Chunk.size) mod 2;
- end;
- Stream.Free;
- result:=High(LongWord);
- except
- On E: Exception do
- begin
- Stream.Free;
- result := 0;
- end;
- end;
- end;
- // LoadLWOFromFile
- //
- function LoadLWOFromFile(const aFilename : String; readCallback : TLWOReadCallback; userData : Pointer) : LongWord;
- var
- stream : TStream;
- begin
- stream:=CreateFileStream(aFilename, fmOpenRead);
- try
- Result:=LoadLW0FromStream(stream, readCallback, userData);
- finally
- stream.Free;
- end;
- end;
- procedure ReverseByteOrder(ValueIn: Pointer; Size: Integer; Count: Integer = 1);
- var
- W: Word;
- pB: PByte;
- Blo, Bhi: Byte;
- L: LongWord;
- i: Integer;
- begin
- i:=0;
- case Size of
- 2: begin
- while i < Count do
- begin
- W := PU2Array(ValueIn)^[i];
- pB := @W;
- Blo := pB^;
- Inc(pB);
- Bhi := pB^;
- pB^ := Blo;
- Dec(pB);
- pB^ := Bhi;
- PU2Array(ValueIn)^[i] := w;
- Inc(i);
- end;
- end;
- 4: begin
- while i < Count do
- begin
- L := PU4Array(ValueIn)^[i];
- pB := @W;
- Blo := pB^;
- Inc(pB);
- Bhi := pB^;
- pB^ := Blo;
- Dec(pB);
- pB^ := Bhi;
- PU4Array(ValueIn)^[i] := l;
- Inc(i);
- end;
- end;
- else
- raise Exception.Create('Lightwave.ReverseByteOrder: Invalid Size = ' + IntToStr(Size));
- end;
- end;
- procedure ReadMotorolaNumber(Stream: TStream; Data: Pointer; ElementSize:
- Integer; Count: Integer = 1);
- begin
- Stream.Read(Data^,Count * ElementSize);
- if (ElementSize = 2) or (ElementSize = 4) then
- ReverseByteOrder(Data,ElementSize,Count);
- end;
- function WriteMotorolaNumber(Stream: TStream; Data: Pointer; ElementSize:
- Integer; Count: Integer = 1): Integer;
- var
- TempData: Pointer;
- begin
- result := 0;
- if Data <> nil then
- begin
- TempData := AllocMem(ElementSize * Count);
- try
- if (ElementSize = 2) or (ElementSize = 4) then
- ReverseByteOrder(TempData,ElementSize,Count);
- result := Stream.Write(Data,Count * ElementSize);
- except
- on E: Exception do
- begin
- FreeMem(TempData,Count * ElementSize);
- raise;
- end;
- end;
- end;
- end;
- function ReadS0(Stream: TStream; out Str: string): Integer;
- var
- Buf: array[0..1] of AnsiChar;
- StrBuf: string;
- begin
- Stream.Read(Buf,2);
- StrBuf:='';
- while Buf[1] <> #0 do
- begin
- StrBuf := StrBuf + string(Buf);
- Stream.Read(Buf,2);
- end;
- if Buf[0] <> #0 then StrBuf := StrBuf + Char(Buf[0]);
- Str := Copy(StrBuf,1,Length(StrBuf));
- result := Length(Str) + 1;
- result := result + (result mod 2);
- end;
- function ValueOfVX(VX: Pointer): TU4;
- var
- TmpU2: TU2;
- TmpU4: TU4;
- begin
- if PU1(VX)^ = $FF then
- begin
- TmpU4 := TU4(PU1(VX)^) and $FFFFFFF0;
- ReverseByteOrder(@TmpU4,4);
- end else
- begin
- TmpU2 := TU2(PU2(VX)^);
- ReverseByteOrder(@TmpU2,2);
- TmpU4 := TmpU2;
- end;
- result := TmpU4;
- end;
- function ReadVXAsU4(Stream: TStream; Data: Pointer; Count: Integer = 1): Integer;
- var
- i, ReadCount: Integer;
- BufByte: byte;
- TempU2: TU2;
- begin
- ReadCount := 0;
- for i := 0 to Count -1 do
- begin
- Stream.Read(BufByte,1);
- Stream.Position := Stream.Position - 1;
- if BufByte = 255 then
- begin
- Stream.Read(Data^,SizeOf(TU4));
- PU4Array(Data)^[i] := PU4Array(Data)^[i] and $FFFFFFF0;
- ReverseByteOrder(Data,SizeOf(TU4));
- Inc(ReadCount,4);
- end else
- begin
- Stream.Read(TempU2,SizeOf(TU2));
- ReverseByteOrder(@TempU2,SizeOf(TU2));
- PU4Array(Data)^[i] := TempU2;
- Inc(ReadCount,2);
- end;
- end;
- result := ReadCount;
- end;
- function ReadVXAsU2(Stream: TStream; Data: Pointer; Count: Integer = 1): Integer;
- var
- i, ReadCount: Integer;
- BufByte: byte;
- TempU2: TU2;
- begin
- ReadCount := 0;
- for i := 0 to Count -1 do
- begin
- Stream.Read(BufByte,1);
- Stream.Position := Stream.Position - 1;
- if BufByte = 255 then
- begin
- Stream.Position := Stream.Position + 4;
- PU2Array(Data)^[i] := 0;
- Inc(ReadCount,4);
- end else
- begin
- Stream.Read(TempU2,SizeOf(TU2));
- ReverseByteOrder(@TempU2,SizeOf(TU2));
- PU2Array(Data)^[i] := TempU2;
- Inc(ReadCount,2);
- end;
- end;
- result := ReadCount;
- end;
- procedure WriteS0(Stream: TStream; Data: string);
- begin
- {ToDo: WriteS0}
- end;
- procedure WriteU4AsVX(Stream:TStream; Data: Pointer; Count: Integer);
- var
- i: Integer;
- TempU2: TU2;
- begin
- for i := 0 to Count - 1 do
- begin
- if PU4Array(Data)^[i] < 65280 then
- begin
- TempU2 := PU4Array(Data)^[i];
- WriteMotorolaNumber(Stream,@TempU2,SizeOf(TU2));
- end else
- WriteMotorolaNumber(Stream,Data,SizeOf(TU4));
- end;
- end;
- type
- PInteger = ^Integer;
- function ID4ToInt(const Id: TId4): Integer;
- var
- TmpId: AnsiString;
- begin
- TmpId := Id;
- TmpId := AnsiString(UpperCase(string(Id)));
- result := PInteger(@TmpId)^;
- end;
- { TLWChunk }
- {
- *********************************** TLWChunk ***********************************
- }
- destructor TLWChunk.Destroy;
- begin
- Clear;
- inherited;
- end;
- procedure TLWChunk.Clear;
- begin
- FreeMem(FData,FSize);
- FSize := 0;
- FData := nil;
- end;
- class function TLWChunk.GetID: TID4;
- begin
- result := #0#0#0#0;
- end;
- procedure TLWChunk.LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- begin
- GetMem(FData,DataSize);
- AStream.Read(PByteArray(FData)^[0],DataSize);
- end;
- procedure TLWChunk.LoadFromStream(AStream: TStream);
- var
- DataStart: Integer;
- DataSize: TU4;
- begin
- with AStream do
- begin
-
- ReadMotorolaNumber(AStream,@DataSize,4);
-
- DataStart := Position;
- FSize := DataSize;
-
- LoadData(AStream, DataStart,DataSize);
-
- Position := Cardinal(DataStart) + DataSize + (Cardinal(DataStart) + DataSize) mod 2;
-
- end;
- end;
- { TLWChunks }
- {
- ********************************* TLWChunkList *********************************
- }
- constructor TLWChunkList.Create(AOwnsItems: boolean; AOwner: TObject);
- begin
- inherited Create;
- FOwnsItems := AOwnsItems;
- FOwner := AOwner;
- end;
- destructor TLWChunkList.Destroy;
- begin
-
- Clear;
-
- inherited;
-
- end;
- procedure TLWChunkList.Clear;
- begin
- while Count > 0 do
- Delete(Count - 1);
- inherited;
- end;
- procedure TLWChunkList.Delete(Index: Integer);
- begin
- if FOwnsItems then
- Items[Index].Free;
- inherited Delete(Index);
- end;
- function TLWChunkList.GetItem(Index: Integer): TLWChunk;
- begin
- result := TLWChunk(inherited Items[Index]);
- end;
- { TLWObjectFile }
- {
- ******************************** TLWObjectFile *********************************
- }
- constructor TLWObjectFile.Create;
- begin
-
- inherited;
-
- end;
- destructor TLWObjectFile.Destroy;
- begin
- FreeAndNil(FChunks);
- inherited;
- end;
- function TLWObjectFile.GetChunks: TLWChunkList;
- begin
- if FChunks = nil then
- FChunks := TLWChunkList.Create(true,Self);
- result := FChunks;
-
- end;
- function TLWObjectFile.GetCount: Integer;
- begin
- result := Chunks.Count;
- end;
- function TLWObjectFile.GetSurfaceByName(Index: string): TLWSurf;
- var
- SurfIdx: Integer;
- begin
- SurfIdx := Chunks.FindChunk(@FindSurfaceByName,@Index,0);
- if SurfIdx <> -1 then
- result := TLWSurf(Chunks[SurfIdx])
- else
- result := nil;
- end;
- function TLWObjectFile.GetSurfaceByTag(Index: TU2): TLWSurf;
- var
- TagName: string;
- begin
- TagName := TagToName(Index);
- result := SurfaceByName[TagName];
- end;
- procedure TLWObjectFile.LoadFromFile(const AFilename: string);
- var
- Stream: TMemoryStream;
- begin
-
- Stream := TMemoryStream.Create;
- try
- Stream.LoadFromFile(AFilename);
-
- LoadFromStream(Stream);
- Stream.Free;
- FFileName := AFilename;
- except
- on E: Exception do
- begin
- Stream.Free;
- raise;
- end;
- end;
-
- end;
- procedure TLWObjectFile.LoadFromStream(AStream: TStream);
- var
- CurId: TID4;
- CurSize: LongWord;
- CurPnts, CurPols, CurItems: TLWChunkList;
- begin
- CurPols:=nil;
- CurPnts:=nil;
- AStream.Read(CurId,4);
- ReadMotorolaNumber(AStream,@CurSize,4);
- if UpperCase(string(CurId)) = 'FORM' then
- begin
- AStream.Read(CurId,4);
- if CurId <> 'LWO2' then
- raise Exception.Create('Only Version 6.0+ version objects are supported.');
- end else raise Exception.Create('Invalid magic number. Not a valid Lightwave Object');
- CurItems := Chunks;
- while AStream.Position < AStream.Size do
- begin
- AStream.Read(CurId,4);
- if (CurId = ID_PTAG) then
- begin
- CurPols.Add(GetChunkClass(CurId, TLWChunk).Create);
- with CurPols[CurPols.Count - 1] do
- begin
- FID := CurId;
- LoadFromStream(AStream);
- end;
- end else
- if (CurId = ID_VMAP) or (CurId = ID_VMAD) then
- begin
- CurPnts.Add(GetChunkClass(CurId, TLWChunk).Create);
- with CurPnts[CurPnts.Count - 1] do
- begin
- FID := CurId;
- LoadFromStream(AStream);
- end;
- end else
- begin
- if (CurId = ID_LAYR) or (CurId = ID_SURF) or
- (CurId = ID_TAGS) or (CurId = ID_CLIP) then CurItems := Chunks;
- CurItems.Add(GetChunkClass(CurId, TLWChunk).Create);
- with CurItems[CurItems.Count - 1] do
- begin
- FID := CurId;
- LoadFromStream(AStream);
- end;
- end;
- if CurId = ID_LAYR then
- CurItems := TLWParentChunk(CurItems[CurItems.Count - 1]).Items
- else if CurId = ID_POLS then
- CurPols := TLWParentChunk(CurItems[CurItems.Count - 1]).Items
- else if CurId = ID_PNTS then
- CurPnts := TLWParentChunk(CurItems[CurItems.Count - 1]).Items;
- end;
- Chunks.Loaded;
- end;
- { TLWPnts }
- {
- *********************************** TLWPnts ************************************
- }
- function TLWPnts.AddPoly(PntIdx, PolyIdx: Integer): Integer;
- var
- i,L: Integer;
- begin
- {DONE: Pnts.AddPoly}
- for i := 0 to FPntsInfo[PntIdx].npols -1 do
- begin
- if FPntsInfo[PntIdx].pols[i] = PolyIdx then
- begin
- result := i;
- Exit;
- end;
- end;
- L := Length(FPntsInfo[PntIdx].pols);
- SetLength(FPntsInfo[PntIdx].pols,L + 1);
- FPntsInfo[PntIdx].npols := L + 1;
- FPntsInfo[PntIdx].pols[L] := PolyIdx;
- result := L;
- end;
- procedure TLWPnts.Clear;
- var
- i: Integer;
- begin
- for i := 0 to PntsCount -1 do
- SetLength(FPntsInfo[i].pols,0);
- SetLength(FPntsInfo,0);
- SetLength(FPnts,0);
- end;
- function TLWPnts.GetPntsCount: LongWord;
- begin
- result := Length(FPnts);
- end;
- class function TLWPnts.GetID: TID4;
- begin
- result := ID_PNTS;
- end;
- function TLWPnts.GetVMap(VMapID: TID4; out VMap: TLWVMap): Boolean;
- var
- i: Integer;
- begin
- result := false;
- for i := 0 to Items.Count - 1 do
- begin
- if (Items[i] is TLWVMap) and (TLWVMap(Items[i]).VMapType = VMapID) then
- begin
-
- result := true;
- VMap := TLWVMap(Items[i]);
- Exit;
- end;
-
- end;
-
- end;
- procedure TLWPnts.LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- begin
- SetLength(FPnts,DataSize div 12); // allocate storage for DataSize div 12 points
- SetLength(FPntsInfo,DataSize div 12); // Point info
- ReadMotorolaNumber(AStream,@FPnts[0],4,DataSize div 4); // read the point data
- end;
- { TLWPols }
- {
- *********************************** TLWPols ************************************
- }
- procedure TLWPols.CalcPolsNormals;
- var
- i,j,PolyIdx: Integer;
- Pnts: TLWPnts;
- begin
- if IndiceCount = 0 then Exit;
- with ParentChunk as TLWLayr do
- Pnts := TLWPnts(Items[Items.FindChunk(@FindChunkById,@ID_PNTS,0)]);
- for PolyIdx := 0 to FPolsCount - 1 do
- begin
- {DONE: call Pnts.AddPoly}
- i := PolsByIndex[PolyIdx];
- with Pnts do
- begin
- for j := 1 to Indices[i] do
- AddPoly(Indices[i + j],PolyIdx);
- SetLength(FPolsInfo[PolyIdx].vnorms,Indices[i]);
- if Indices[PolyIdx]>2 then
- FPolsInfo[PolyIdx].norm:=CalcPlaneNormal(Pnts[Indices[i+1]],Pnts[Indices[i+2]],Pnts[Indices[i+3]])
- else
- FPolsInfo[PolyIdx].norm := VecNorm(Pnts[Indices[i+1]]);
- end;
- end;
- end;
- procedure TLWPols.Clear;
- var
- i: Integer;
- begin
- for i := 0 to FPolsCount-1 do
- SetLength(FPolsInfo[i].vnorms,0);
- SetLength(FPolsInfo,0);
- SetLength(FPols,0);
- end;
- function TLWPols.GetPolsByIndex(AIndex: TU2): Integer;
- var
- i, cnt: Cardinal;
- begin
- result := -1;
- i := 0;
- cnt := 0;
- if AIndex = 0 then
- begin
- result := 0;
- Exit;
- end;
- while (i < IndiceCount - 1) and (cnt <> AIndex) do
- begin
- Inc(i,Indices[i]+1);
- Inc(cnt);
- end;
- if cnt = AIndex then
- result := i;
- end;
- class function TLWPols.GetID: TID4;
- begin
- result := ID_POLS;
- end;
- function TLWPols.GetIndiceCount: TU4;
- begin
- result := Length(FPols);
- end;
- function TLWPols.GetIndice(AIndex: Integer): TU2;
- begin
- result := FPols[AIndex];
- end;
- function TLWPols.GetPolsCount: Integer;
- begin
- result := FPolsCount;
- end;
- procedure TLWPols.LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- var
- EndPos: Integer;
- Idx: TU4;
- TmpU2: TU2;
- begin
- Idx := 0;
- EndPos := DataStart + DataSize;
- with AStream do
- begin
- Read(FPolsType,4);
- // To avoid memory manager hits, set an estimate length of indices
- SetLength(FPols,(DataSize - 4) div 2);
- while Position < EndPos do
- begin
- ReadMotorolaNumber(AStream,@FPols[Idx],2);
- TmpU2 := FPols[Idx] and POLS_VCOUNT_MASK;
- ReadVXAsU2(AStream,@FPols[Idx + 1],TmpU2);
- Inc(Idx,FPols[Idx] + 1);
- Inc(FPolsCount);
- end;
- // correct length estimate errors if any
- if (Idx + 1) < Cardinal(Length(FPols)) then
- SetLength(FPols,Idx + 1);
- end;
- SetLength(FPolsInfo,FPolsCount);
- CalcPolsNormals;
- end;
- { TLWVMap }
- {
- *********************************** TLWVMap ************************************
- }
- procedure TLWVMap.Clear;
- var
- i: Integer;
- begin
- for i := 0 to Length(FValues) - 1 do
- SetLength(FValues[i].values,0);
-
- SetLength(FValues,0);
- end;
- class function TLWVMap.GetID: TID4;
- begin
-
- result := ID_VMAP;
-
- end;
- function TLWVMap.GetValue(AIndex: TU2): TLWVertexMap;
- begin
- result := FValues[AIndex];
-
- end;
- function TLWVMap.GetValueCount: Integer;
- begin
- result := Length(FValues);
- end;
- procedure TLWVMap.LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- var
- Idx: TU4;
- begin
- Idx := 0;
-
- with AStream do
- begin
-
- Read(FVMapType,4);
- ReadMotorolaNumber(AStream,@FDimensions,2);
-
- ReadS0(AStream,FName);
-
- if FDimensions > 0 then
- begin
-
- while Cardinal(Position) < (DataStart + DataSize) do
- begin
- SetLength(FValues,Length(FValues) + 1);
-
- ReadVXAsU2(AStream,@FValues[Idx].vert,1);
- SetLength(FValues[Idx].values,Dimensions * 4);
- ReadMotorolaNumber(AStream,@FValues[Idx].values[0],4,Dimensions);
-
- Inc(Idx);
- end;
-
- end;
-
- end;
- end;
- { TLWTags }
- {
- *********************************** TLWTags ************************************
- }
- destructor TLWTags.Destroy;
- begin
- inherited;
- end;
- procedure TLWTags.Clear;
- begin
- FreeAndNil(FTags);
- end;
- class function TLWTags.GetID: TID4;
- begin
- result := ID_TAGS;
- end;
- function TLWTags.GetTags: TStrings;
- begin
- if FTags = nil then
- FTags := TStringList.Create;
- result := FTags;
- end;
- procedure TLWTags.LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- var
- EndPos: TU4;
- TmpStr: string;
- begin
- EndPos := DataStart + DataSize;
- while Cardinal(AStream.Position) < Cardinal(EndPos) do
- begin
- ReadS0(AStream,TmpStr);
- Tags.Add(TmpStr);
- TmpStr := '';
- end;
- end;
- function TLWTags.TagToName(Tag: TU2): string;
- begin
- result := Tags[Tag];
- end;
- { TLWSubChunk }
- {
- ********************************* TLWSubChunk **********************************
- }
- procedure TLWSubChunk.LoadFromStream(AStream: TStream);
- var
- DataStart: Integer;
- DataSize: TU2;
- begin
-
- with AStream do
- begin
- ReadMotorolaNumber(AStream,@DataSize,2);
- DataStart := Position;
- FSize := DataSize;
- LoadData(AStream,DataStart,DataSize);
- Position := DataStart + DataSize + (DataStart + DataSize) mod 2;
-
- end;
-
- end;
- {
- *********************************** TLWLayr ************************************
- }
- destructor TLWLayr.Destroy;
- begin
- inherited;
- end;
- class function TLWLayr.GetID: TID4;
- begin
- result := ID_LAYR;
- end;
- procedure TLWLayr.LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- begin
-
- ReadMotorolaNumber(AStream,@FNumber,2);
- ReadMotorolaNumber(AStream,@FFlags,2);
- ReadMotorolaNumber(AStream,@FPivot,4,3);
- ReadS0(AStream,FName);
-
- if ((DataStart + DataSize) - Cardinal(AStream.Position)) > 2 then
- ReadMotorolaNumber(AStream,@FParent,2);
- end;
- { TLWSurf }
- {
- *********************************** TLWSurf ************************************
- }
- destructor TLWSurf.Destroy;
- begin
- inherited;
- end;
- class function TLWSurf.GetID: TID4;
- begin
- result := ID_SURF;
- end;
- function TLWSurf.GetParamAddr(Param: TID4): Pointer;
- var
- Idx: Integer;
- sParam: string;
- begin
- result:=inherited GetParamAddr(Param);
- if (result=nil) and (Source<>'') then
- begin
- sParam := string(Param);
- Idx:=RootChunks.FindChunk(@FindSurfaceByName,@sParam,0);
- if Idx<>-1 then
- result:=TLWSurf(RootChunks[Idx]).ParamAddr[Param];
- end;
- end;
- function TLWSurf.GetSurfId: Integer;
- var
- c, SurfIdx: Integer;
- begin
- c := 0;
- SurfIdx := Owner.FindChunk(@FindChunkById,@ID_SURF);
- while (SurfIdx <> -1) and (Owner[SurfIdx] <> Self) do
- begin
- SurfIdx := Owner.FindChunk(@FindChunkById,@ID_SURF,SurfIdx + 1);
- Inc(c);
- end;
- result := c;
- end;
- procedure TLWSurf.LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- var
- CurId: TID4;
- begin
- ReadS0(AStream,FName);
- ReadS0(AStream,FSource);
- while Cardinal(AStream.Position) < (DataStart + DataSize) do
- begin
- AStream.Read(CurId,4);
- Items.Add(GetChunkClass(CurId, TLWSubChunk).Create);
- with Items[Items.Count - 1] do
- begin
- FID:=CurId;
- LoadFromStream(AStream);
- end;
- end;
- end;
- { TLWPTag }
- {
- *********************************** TLWPTag ************************************
- }
- constructor TLWPTag.Create;
- begin
- inherited;
- end;
- function TLWPTag.AddTag(Value: TU2): Integer;
- var
- i, L: Integer;
- begin
- result := -1;
- L := Length(FTags);
- for i := 0 to L - 1 do
- if Value = FTags[i] then
- begin
- result := i;
- Exit;
- end;
- if result = -1 then
- begin
- SetLength(FTags,L + 1);
- FTags[L] := Value;
- result := L;
- end;
- end;
- procedure TLWPTag.Clear;
- begin
- SetLength(FTagMaps,0);
- SetLength(FTags,0);
- end;
- function TLWPTag.GetPolsByTag(Tag: TU2; var PolyIndices: TU2DynArray): Integer;
- var
- i: Integer;
- procedure AddPoly(Value: TU2);
- var
- L: Integer;
- begin
- L := Length(PolyIndices);
- SetLength(PolyIndices,L+1);
- PolyIndices[L] := Value;
- end;
- begin
- for i := 0 to TagMapCount -1 do
- if TagMaps[i].tag = Tag then
- AddPoly(TagMaps[i].poly);
- result := Length(PolyIndices);
- end;
- class function TLWPTag.GetID: TID4;
- begin
- result := ID_PTAG;
- end;
- function TLWPTag.GetTag(AIndex: Integer): TU2;
- begin
- ValidateTagInfo;
- result := FTags[AIndex];
- end;
- function TLWPTag.GetTagCount: Integer;
- begin
- ValidateTagInfo;
- result := Length(FTags);
- end;
- function TLWPTag.GetTagMapCount: Integer;
- begin
- result := Length(FTagMaps) div 2;
- end;
- function TLWPTag.GetTagMaps(AIndex: Integer): TLWPolyTagMap;
- begin
- result := PLWPolyTagMap(@FTagMaps[AIndex * 2])^;
- end;
- procedure TLWPTag.LoadData(AStream: TStream; DataStart, DataSize: LongWord);
- var
- Idx: Integer;
- begin
- Idx := 0;
- with AStream do
- begin
- Read(FMapType,4);
- SetLength(FTagMaps,(DataSize - 4) div 2);
- while Cardinal(Position) < (DataStart + DataSize) do
- begin
- ReadVXAsU2(AStream, @FTagMaps[Idx]);
- ReadMotorolaNumber(AStream,@FTagMaps[Idx + 1],2);
- Inc(Idx, 2);
- end;
- // correct length guestimate errors if any
- if (Idx + 1) < Length(FTagMaps) then
- SetLength(FTagMaps,Idx + 1);
- end;
- end;
- procedure TLWPTag.ValidateTagInfo;
- var
- i: Integer;
- begin
- if Length(FTags) > 0 then Exit;
- for i := 0 to TagMapCount -1 do
- AddTag(TagMaps[i].tag);
- end;
- { TLWParentChunk }
- {
- ******************************** TLWParentChunk ********************************
- }
- procedure TLWParentChunk.Clear;
- begin
- FreeAndNil(FItems);
- inherited;
- end;
- function TLWParentChunk.GetFloatParam(Param: TID4): Single;
- var
- pdata: Pointer;
- begin
- pdata:=ParamAddr[Param];
- if pdata <> nil then
- begin
- result:=PF4(pdata)^;
- ReverseByteOrder(@result,4);
- end else
- result:=0.0;
- end;
- function TLWParentChunk.GetItems: TLWChunkList;
- begin
- if FItems = nil then
- FItems := TLWChunkList.Create(true,Self);
- result := FItems;
- end;
- function TLWParentChunk.GetLongParam(Param: TID4): LongWord;
- var
- pdata: Pointer;
- begin
- pdata:=ParamAddr[Param];
- if pdata <> nil then
- begin
- result:=PU4(pdata)^;
- ReverseByteOrder(@result,4);
- end else
- result:=0;
- end;
- function TLWParentChunk.GetParamAddr(Param: TID4): Pointer;
- var
- Idx: Integer;
- begin
- result := nil;
- Idx := Items.FindChunk(@FindChunkById,@Param,0);
- if Idx <> -1 then
- result := Items[Idx].Data;
- end;
- function TLWPols.GetPolsByPntIdx(VertIdx: TU2;
- var VertPolys: TU2DynArray): Integer;
- var
- i,j,L: Integer;
- begin
- L:=0;
- if Length(VertPolys) >0 then
- SetLength(VertPolys,0);
- for i := 0 to PolsCount -1 do
- begin
- for j := 1 to Indices[PolsByIndex[i]] do
- begin
- if Indices[PolsByIndex[i] + j] = VertIdx then
- begin
- L := Length(VertPolys);
- SetLength(VertPolys, L + 1);
- VertPolys[L] := i;
- end;
- end;
- end;
- result := L;
- end;
- function TLWChunkList.Add(AChunk: TLWChunk): Integer;
- begin
- if (FOwner<>nil) and (FOwner is TLWParentChunk) then
- AChunk.FParentChunk := TLWParentChunk(FOwner);
- AChunk.FOwner := self;
- result := inherited Add(AChunk);
- end;
- procedure TLWPols.CalcPntsNormals;
- var
- i,j,k,PntIdx,PolyIdx,SurfIdx: Integer;
- Pnts: TLWPnts;
- // PTags: TLWPTag;
- TmpAddr: Pointer;
- sman: TF4;
- begin
- {Todo: CalcPntsNormals}
- if IndiceCount = 0 then Exit;
- with ParentChunk as TLWLayr do
- Pnts := TLWPnts(Items[Items.FindChunk(@FindChunkById,@ID_PNTS,0)]);
- for PolyIdx := 0 to PolsCount-1 do
- begin
- i := PolsByIndex[PolyIdx];
- SurfIdx := RootChunks.FindChunk(@FindSurfaceByTag,@FPolsInfo[PolyIdx].surfid);
- TmpAddr := TLWSurf(RootChunks[SurfIdx]).ParamAddr[ID_SMAN];
- if TmpAddr <> nil then
- begin
- sman := PF4(TmpAddr)^;
- ReverseByteOrder(@sman,4);
- end else
- sman := 0;
- for j := 1 to Indices[i] do
- begin
- FPolsInfo[PolyIdx].vnorms[j-1] := FPolsInfo[PolyIdx].norm;
- if sman <= 0 then continue;
- PntIdx := Indices[i + j];
- for k := 0 to Pnts.PntsInfo[PntIdx].npols -1 do
- begin
- if Pnts.PntsInfo[PntIdx].pols[k] = PolyIdx then continue;
- if ArcCos(VecDot(FPolsInfo[PolyIdx].norm,FPolsInfo[Pnts.PntsInfo[PntIdx].pols[k]].norm)) > sman then continue;
- FPolsInfo[PolyIdx].vnorms[j-1]:=VecAdd(FPolsInfo[PolyIdx].vnorms[j-1],FPolsInfo[Pnts.PntsInfo[PntIdx].pols[k]].norm);
- end;
- FPolsInfo[PolyIdx].vnorms[j-1]:=VecNorm(FPolsInfo[PolyIdx].vnorms[j-1]);
- end;
- end;
- end;
- function TLWChunk.GetRootChunks: TLWChunkList;
- var
- Parent: TLWParentChunk;
- begin
- result := nil;
- if (FParentChunk = nil) then
- begin
- if (FOwner is TLWChunkList) then
- begin
- result := FOwner;
- Exit;
- end;
- end else
- begin
- Parent := FParentChunk;
- while not(Parent.ParentChunk = nil) do
- Parent := Parent.ParentChunk;
- result := Parent.Owner;
- end;
- end;
- function TLWChunkList.FindChunk(ChunkFind: TLWChunkFind; Criteria: Pointer; StartIndex: Integer): Integer;
- var
- Found: boolean;
- begin
- Found := false;
- result := -1;
- while (StartIndex < Count) and (not Found) do
- begin
- ChunkFind(Items[StartIndex],Criteria,Found);
- if Found then
- begin
- result := StartIndex;
- Exit;
- end;
- Inc(StartIndex);
- end;
- end;
- function TLWChunk.GetIndex: Integer;
- begin
- result := Owner.IndexOf(Self);
- end;
- procedure TLWChunk.Loaded;
- begin
- // do nothing
- end;
- procedure TLWChunkList.Loaded;
- var
- i: Integer;
- begin
- for i := 0 to Count-1 do
- begin
- Items[i].Loaded;
- end;
- end;
- function TLWParentChunk.GetVec3Param(Param: TID4): TVec12;
- var
- pdata: Pointer;
- begin
- pdata:=ParamAddr[Param];
- if pdata <> nil then
- begin
- result:=PVec12(pdata)^;
- ReverseByteOrder(@result,4,3);
- end else
- begin
- result[0]:=0;
- result[1]:=1;
- result[2]:=2;
- end;
- end;
- function TLWParentChunk.GetVXParam(Param: TID4): Word;
- var
- pdata: Pointer;
- begin
- pdata:=ParamAddr[Param];
- if pdata <> nil then
- result:=ValueOfVX(pdata)
- else
- result:=0;
- end;
- function TLWParentChunk.GetWordParam(Param: TID4): Word;
- var
- pdata: Pointer;
- begin
- pdata:=ParamAddr[Param];
- if pdata <> nil then
- begin
- result:=PU4(pdata)^;
- ReverseByteOrder(@result,2);
- end else
- result:=0;
- end;
- procedure TLWParentChunk.Loaded;
- begin
- Items.Loaded;
- end;
- procedure TLWPols.Loaded;
- begin
- inherited;
- CalcPntsNormals;
- end;
- function TLWObjectFile.TagToName(Tag: TU2): string;
- var
- TagsIdx: Integer;
- begin
- TagsIdx := Chunks.FindChunk(@FindChunkById,@ID_TAGS);
- if TagsIdx <> -1 then
- result := TLWTags(Chunks[TagsIdx]).TagToName(Tag);
- end;
- { TLWClip }
- class function TLWClip.GetID: TID4;
- begin
- result := ID_CLIP;
- end;
- procedure TLWClip.LoadData(AStream: TStream; DataStart,
- DataSize: LongWord);
- var
- CurId: TID4;
- begin
- ReadMotorolaNumber(AStream,@FClipIndex,4);
- while Cardinal(AStream.Position) < (DataStart + DataSize) do
- begin
- AStream.Read(CurId,4);
- Items.Add(GetChunkClass(CurId, TLWSubChunk).Create);
- with Items[Items.Count - 1] do
- begin
- FID:=CurId;
- LoadFromStream(AStream);
- end;
- end;
- end;
- { TLWContentDir }
- {function TLWContentDir.ContentSearch(AFilename: string): string;
- var
- i: Integer;
- begin
- if not FileExists(AFilename) then
- begin
- result := ExtractFileName(AFilename);
- if not FileExists(result) then
- begin
- for i := 0 to SubDirs.Count - 1 do
- begin
- if FileExists(Root+'\'+SubDirs[i]+'\'+result) then
- begin
- result:=Root+'\'+SubDirs[i]+'\'+result;
- Exit;
- end;
- end;
- result := '';
- end;
- end;
- end;}
- destructor TLWContentDir.Destroy;
- begin
- FreeAndNil(FSubDirs);
- inherited;
- end;
- function TLWContentDir.FindContent(AFilename: string): string;
- var
- i: Integer;
- begin
- if not FileExists(AFilename) then
- begin
- result := ExtractFileName(AFilename);
- if not FileExists(result) then
- begin
- for i := 0 to SubDirs.Count - 1 do
- begin
- if FileExists(Root+'\'+SubDirs[i]+'\'+result) then
- begin
- result:=Root+'\'+SubDirs[i]+'\'+result;
- Exit;
- end;
- end;
- result := '';
- end;
- end;
- end;
- function TLWContentDir.GetSubDirs: TStrings;
- begin
- if FSubDirs = nil then
- FSubDirs := TStringList.Create;
- result := FSubDirs;
- end;
- procedure TLWContentDir.SetRoot(const Value: string);
- begin
- FRoot := Value;
- end;
- procedure TLWContentDir.SetSubDirs(const Value: TStrings);
- begin
- SubDirs.Assign(Value);
- end;
- initialization
- { Pnts }
- RegisterChunkClass(TLWPnts);
- { Pols }
- RegisterChunkClass(TLWPols);
- { VMap }
- RegisterChunkClass(TLWVMap);
- { Tags }
- RegisterChunkClass(TLWTags);
- { PTAG }
- RegisterChunkClass(TLWPTAG);
- { SURF }
- RegisterChunkClass(TLWSurf);
- { LAYR }
- RegisterChunkClass(TLWLayr);
- { CLIP }
- RegisterChunkClass(TLWClip);
- finalization
- // UnRegisterChunkClasses;
- FreeAndNil(ChunkClasses);
- FreeAndNil(ContentDir);
- end.
|