This document describes the high-level format of the file, and describes in detail all the elements of the file. There is a sample file at the end displayed as an annotated dump.
The atomic (or lowest-level) types in the file are listed below along with their type name (I2, F4, etc.). These are used interpret sequences of bytes in the file.
The chunks can occur in any order except when the data in a chunk depends on knowing the values in previous chunks, in which case the dependant chunk must occur after the chunk it depends upon. Different applications may write their chunks in slightly different orders, so it is important for parsers to support order-independence.
The LightWave format has some composite datatypes that it uses consistently which are built from the fundamental types.
This chunk signals the start of a new layer. All the data chunks which follow will be included in this layer until another layer chunk is encountered. If data is encountered before a layer chunk, it goes into an arbitrary layer. The parent index indicates the default parent for this layer and can be -1 or missing to indicate no parent.
This chunk contains a list of the X, Y, and Z coordinates for a set of points. Since each coordinate has three components, and each component is stored as a four byte floating point number, the number of points in an object can be determined by dividing the size in bytes of the PNTS chunk by 12.
By convention, the +X direction is to the right or east, the +Y direction is upward, and the +Z direction is forward or north. For models of real-world objects, the unit size is usually considered to be one meter. The coordinates are specified relative to an object's pivot point. See the LightWave Modeler manual for more information about LightWave 3D's geometric conventions.
Points in a PNTS chunk are numbered in the order they occur, starting with zero. This index is then used by polygons to define their vertices. The PNTS chunk must be before the POLS or VMAP chunks that refer to it.
This chunk contains a set of floating point vectors associated with a set of vertices. Each one has a type which is a four-character ID code, a dimension and a name string. After that follows a list of vertex / vector pairs, with the vertex given by a vertex index in VX format and an array of "dimension" floating-point values. There can be any number of these chunks, although they should all have different types or names.
Some possible type codes are TXUV for UV mapping coordinates, MNVW for MetaNURBS vertex weights, MORF for vector offsets defining an alternate object shape, SPOT for alternate vertex positions, RGBA for coloring, etc.
This chunk contains a list of polygons for the current layer. The 'type' code indicates the polygon type and can be FACE, CURV, PACH, or possibly other values. Each entry starts with a short integer specifying the number of vertices in the polygon. The 6 high-order bits of the number of vertices are flags bits with different meaning for each polygon type, so there are a maximum of 1023 vertices per polygon. The vertex list is the specified number of two or four byte VX vertex indices (relative to the most recent points list). The vertex list for each polygon should begin at a convex vertex and proceed clockwise as seen from the visible side of the polygon (LightWave 3D polygons are single-sided, except for those whose surfaces have the double-sided flag set). Polygons should be read from the file until as many bytes as the chunk size specifies have been read.
This chunk lists the tags strings that can be associated with polygons by the PTAG chunk. Strings should be read until as many bytes as the chunk size specifies have been read, and each string is assigned an index starting from zero.
This chunk contains the all the tags of a given type for some subset of the polygons defined in the preceding POLS chunk. The type of the tag association is given by the first element of the chunk and is an normal 4-character ID code. The rest of the chunk is a list of polygon/tag associations. The polygon is identified by its index into the previous POLS chunk, and the tag is given by its index into the previous TAGS chunk. Any number of polygons may be mapped with this type of tag, and mappings should be read from the file until as many bytes as the chunk size specifies have been read.
Polygon tags types and their values are extensible, but there are some pre-defined types. The SURF type tags each polygon with the name of its surface. In LightWave 3D terminology, a "surface" is defined as a named set of shading attributes and may be described in the object file in SURF chunks. Another pre-defined type is PART which describes what aspect of the mesh each polygon belongs to, and SMGP which names the smoothing group for each polygon. Not all polygons have a value for every tag type, and the behavior for polygon which lack a certain tag depends on the type.
Each ENVL chunk defines the time-varying curve for a single parameter channel. The index is used to identify this envelope uniquely, and can have any non-zero value less than 0x1000000. Following the index is a series of sub-chunks, which are like normal IFF chunks except that their sizes are specified by short integers instead of longs. The number of sub-chunks may vary depending on the complexity of the envelope, so sub-chunks should be read from the file until as many bytes as the chunk size specifies have been read. New types of sub-chunks may be introduced as the program capabilities increase, but any unknown sub-chunks may be skipped over by using their size.
Each CLIP chunk defines a image which can be used for applying as a texture map in surfaces. The term 'clip' is used to describe these since they may be time-varying sequences or animations rather than just stills. The index identifies this clip uniquely and may be any non-zero value less than 0x1000000. The attributes which define the source imagery and modifiers follow as a variable list of sub-chunks.
Each SURF chunk describes the shading attributes of a particular surface. These chunks begin with the name of the surface being described plus the name of the source surface. If the source name is non-null, then this surface is derived from the source surface. The base attributes of the source surface can be overridden by this surface, and texture blocks can be added to the source surface. The material attributes follow as a variable list of sub-chunks.
This is an optional chunk which can be included to store the bounding box for the vertex data in a layer. The min and max vectors are the lower and upper corners of the bounding box.
This is an optional chunk which can be used to hold an object description. This should be a simple line of upper and lowercase characters, punctuation and spaces which describes the contents of the object file. There should be no control characters in this text string and it should generally be kept short.
This is another optional chunk which can be used to hold comments about the object. The text is just like the DESC chunk, but it can be about any subject, it may contain newline characters and it does not need to be particularly short.
This optional chunk contains an iconic or thumbnail image for the object which can be used when viewing the file in a browser. The encoding is a code for the data format which can only be zero for now meaning uncompressed, unsigned bytes as RGB triples. The width specifies the number of pixels contained in each row of the image. The data consists of rows of pixels (RGB triples for now), and the height of the image is determined by the length of the data.
Envelopes are referenced by clips and surfaces by their index. The index value is given in the preamble of the ENVL chunk, and index values of zero indicate no envelope for a parameter.
The pre-behavior for an envelope defines the signal value for times before the first key. The integer code selects one of several predefined behaviors, starting from zero: Reset, Constant, Repeat, Ocsillate, Offset Repeat, Linear.
The post-behavior determines the signal value for times after the last key. The type codes are the same as for pre-behaviors.
This chunk defines the time and value for an envelope keyframe. The signal value for the envelope is exactly the value of the key when the signal is evaluated at the time of the key. Values between keyframes are interpolations of adjacent keyframe values.
This sub-chunk defines the interpolation between the most recently specified KEY chunk and the keyframe immediately before it in time. The type ID code defines the interpolation algorithm and can be STEP, LINE, TCB, HERM or BEZI. The variable number of parameters values that follow define the particulars of the interpolation.
Channel filters can be layered on top of a basic keyframed envelope to provide some more elaborate effects. Each channel chunk contains the name of the plug-in server and some flags bits. Only the first flag bit is defined, which if set indicates that the filter is disabled. The plug-in data follows as raw bytes.
This is an optional envelope sub-chunk which is not used by LightWave in any way. It is only provided to allow external programs to browse through the envelopes available in an object fille.
This source chunk describes a single still image. The image is referenced by a filename in neutral path format.
This source chuck describes an image sequence, which is basically a filename with a number in the middle. The number of digits is the number of zeros used to encode the sequence number in the filename. The flags has bits for looping and interlace. Offset and loop-length define the frames in the sequence. The prefix and suffix are stuck before and after the frame number to make the filename for each frame, which is in neutral path format.
This chunk indicates that the source imagery comes from a plug-in animation loader. The loader is defined by the server name and its data which just follows as binary bytes.
The source for a clip can also be a different clip, which is identified by its index value, stored in variable-length format.
A still image with color-cycling is a source defined by a neutral-format name and cycling parameters. If lo is less than hi, the colors cycle forward, and if hi is less than lo, they go backwards.
This modifier alters the contrast of the image up or down by the given percentage.
This modifier alters the brightness of the image up or down by the given percentage.
This modifier alters the saturation of the image up or down by the given percentage.
This modifier rotates the hue of the image 360 degrees for 100% of hue rotation.
This modifier applies the given gamma to the image, where a value of 1.0 is no change.
If the value is true, this modifier performs a negation of the image.
This operator crops the image by a window specified as fractions of the total. After the operator is applied, the value of the image at (x,y) is now found at (0.0,0.0) and the value at (x+w,y+h) is found at (1.0,1.0).
This modifier takes a different clip (referenced by index) and uses its grayscale value as the alpha for this image.
This modifier takes a different clip (referenced by index) and composites it on top of the current image. The alpha for the other image is multiplied by the blend percentage before it is composited with this image.
Plug-in image filters can be used to pre-filter an image before rendering. The filter has to be able to exist outside of the special environment of rendering in order to work here. Filters are given by a server name, an enable flag, and plug-in server data as raw bytes.
Pixel filters may also be used as clip modifiers, and they are stored and used in a way that is exactly like image filters above.
The shading parameters for a polygon are the result of composing the surface parameters of the SURF chunk with the parameters from any source surface (which may itself be a composite). If the same basic surface parameter is found in both this surface and its source, then the values in this surface take precedence. All the blocks in both this surface and in the source surface are composed together, sorting on the ordinal string.
This defines the base color of the surface, which is the color that lies under all the other texturing attributes.
These sub-chunks specify the base level of the surface's diffuse, luminosity, specular, reflection, transparency, or tranlucency settings. If any of these sub-chunks are absent for a surface, a value of zero is assumed.
Glossiness is encoded as a floating point percentage and is only needed if the specular value of a surface is non-zero. This glossiness percentage is converted to a specular exponent by the formula 2(10 * glossiness + 2). Thus a glossiness of 20% (0.2) gives a specular exponent of 24, or 16 which is equivalent to the old "Low" glossiness preset. Likewise 40% is 64 or "Medium," 60% is 256 or "High," and 80% is 1024 or "Maximum." If this chunk is missing a value of 40% is assumed.
Diffuse sharpness replaces the old "Sharp Terminator" flag with a smoothly varying percentage value. The default value of zero results in normal shading, and a 50% value is the same as the old sharp terminator setting.
This encodes the basic bump map intensity. I'm not totally sure how this is used in the shading equation.
The sidedness of a polygon can be 1 for front-only, or 3 for front and back. This replaces the old "Double Sided" flag bit. If missing, single-sided polygons are assumed.
This specifies the maximum angle between two adjacent polygons that can be smooth shaded. Polygons with a greater angle between them will appear to meet at a sharp seam. If this chunk is missing, or if the value is zero or less, then the polygons are not smoothed.
Reflection options is a numeric code that describes how reflections are handled for this surface and is only meaningful if the reflectivity of the surface is non-zero. If the mode is 0, then only the backdrop colors in the scene are reflected. If the mode is 1, it is the same as 0 except that raytracing is used for objects in the scene when it is enabled. If the mode is 2 and an image is provided by the RIMG sub-chunk, then the image wrapped spherically around the scene is reflected. If the mode is 3, it is the same as 2 except that raytracing is used when enabled. If there is no RFOP sub-chunk, a value of 3 is assumed.
The reflection image is wrapped around the scene and is used for reflection mapping if the RFOP mode is set to use an image and the reflectivity of the surface is non-zero. If the RFOP mode setting expects an image and there is no RIMG chunk, then the backdrop colors are reflected. The image is the index of a CLIP chunk, or zero to indicate no image.
This angle is the heading angle of the reflection map seam. If missing, a value of zero is assumed.
The surface's refractive index determines how much light rays bend when passing into or out of this material, and is defined as the ratio of the speed of light in a vacuum to the speed of light in the material. Since light is fastest in a vacuum, this value should therefore be greater than or equal to 1.0.
The color highlight percentage determines how much the reflections on a surface, including specular highlights, are tinted by the color of the surface. This replaces the old discrete "Color Highlights" flag.
Transparency options are just the same as reflection options except that they describe how refraction is handled. Refraction can be any combination of background color, image or raytracing.
The refraction image is wrapped around the scene and is used for refraction mapping if the TROP mode is set to use an image and the transparency of the surface is non-zero. This setting is the refractive analogue of RIMG.
The color filter percentage determines how much rays passing through a transparent surface are tinted by the color of the surface. This replaces the old discrete "Color Filter" flag.
This percentage selects how "additive" transparency effect are. The default value of zero indicates that transparent surfaces fully attenuate the background color while a value of 100% indicates that that the background color is full strength under the transparent surface.
The glow effect causes a surface to spread and effect neighboring areas of the image. The type can be 0 for Hastings glow, and 1 for image convolution. The size and intensity modulate how large and how strong the effect is, but the exact units are unclear.
The line effect draws illustrations-like outlines around the borders of objects and surfaces. The lines are drawn with the given thickness and the given color, but how thickness is reckoned is unclear.
This chunk defines the alpha channel output options for the surface. If mode is 0, this surface does not affect the Alpha channel at all when rendered. If mode is 1, the alpha channel will have a fixed value which is the second parameter in the chunk and should have a value from 0 to 255. If mode is 2, the alpha value is derived from surface opacity, which is the default if the ALPH chunk is missing. If mode is 3, the alpha value comes from shadow density.
While each type of texture layer has sub-chunks that are specific to that block type, there are some common sub-chunks that may be present in some or all of the different texture types.
This sub-chunk is required in all texture blocks and can have a value of COLR, DIFF, LUMI, SPEC, REFL, TRAN, TRNL, or BUMP, corresponding to a modulation of the color, diffuse, luminosity, specular, reflection, transparency, translucency, or bump attribute.
This is a character string identifying the name of the algorithm used for this texturing layer. For image maps this is the name of the projection used; for gradients it is the name of the input parameter; and for procedurals it is the name of the texture algorithm.
This flag is either 1 for an enabled texture layer, or 0 for a texture layer that should be ignored. If the chunk is missing, the texture is assumed to be enabled.
This specifies how opaque this texture is with respect to the textures before it. The types can be 0 for additive opacity, 1 for subtractive opacity, 2 for difference, 3 for multiply, 4 for divide, 5 for alpha and 6 for texture displacement opacity mode. If no opacity parameters are specified, 100% additive opacity is assumed.
This short integer has bits which specify various options for the current texture. Currently only a few least significant bits are used. The options that set bits indicate are (starting with the least significant bit): World Coords, Negative Image, Pixel Blending, and Antialiasing. Some obviously apply only to image maps.
This short integer can be 0, 1 or 2 indicating that the major axis of the texture is given by the X, Y or Z axis, respectively.
These sub-chunks each consist of a vector for the texture's size, center and rotation. The size and center are normal positional vectors in meters, and the rotation is a vector of heading, pitch and bank in radians. If missing, the center and rotation are assumed to be zero. The size should always be specified if it to be used for any given mapping.
This subchuck specifies a reference object for the texture. The reference object is given by name, and the position, rotation and scale of the object are used to compute the texture mapping at any given time. Does this override the previous chunks or just modify them? -- I don't know.
Texture effects may fall off from the texture center if this sub-chunk is present. The type can be 0 to indicate that the falloff is independent in each axis, or it can be 1 to indicate that the falloff is based on distance from the center. How the vector is interpreted in distance-based falloff is also unclear.
This specifies an image to be used for image texture mapping as an index of a CLIP chunk.
This specifies how image-based textures will interpret the color of areas outside the image. If the mode is 0, then outside the image is considered to be black. If the mode is 1, areas outside the image are clamped to the closest image edge value. If the mode is 2, then the image repeats outside the image area resulting in a uniform tiling. If the mode is 3, then the image repeats but with mirroring, so that each each adjacent repetition is reversed. If no wrap options are specified, 2 is assumed.
For mapping modes that wrap around in the width or height directions, like "Cylindrical" or "Spherical," these parameters control how many times the image repeats over each full interval.
For mapping modes that depend on texture coordinates at each vertex, this selects the name of the TXUV vertex map that contains those coordinates.
This specifies the strength of antialiasing used for the texture. If the Antialiasing bit is set in the TFLG sub-chunk and this sub-chunk is missing, 100% is assumed. This setting currently only affects image-based textures.
If the texture is set to modify the COLR shading channel, then this is the alternate color value to use.
Textures that modify anything other than the COLR channel are scalar values, and this is the alternate value.
The FTPS sub-chunk contains a sequence of floating point numbers that specify texture-type specific parameters (such as Contrast, Turbulence, Wavelength, etc). The ETPS sub-chunk contains a sequence of envelopes that correspond to each floating point parameter. The ITPS sub-chunk is similar but is used for integer parameters (such as number of Frequencies, Wave Sources, etc). In general, these parameters are stored in the sequence they are found on the interface panel, and the number of each type of parameter can be computed from the sub-chunk length.
These two sub-chunks store the start and end of the input range. These values do not affect rendering at all and are stored only for the user-interface.
The transfer function is defined as a series of keys, each with an input value and a vector of RGBA output values. Given an input value, the gradient can be evaluated by selecting the keys whose positions bracket the value and linearly interpolating between their outputs. If the input value is lower than the first key or higher than the last key, the gradient value is the value of the closest key. There is always at least one key, so every FTPS sub-chunk will have at least five values or there is no gradient.
Plug-in shaders are identified by their server name, which is stored in this sub-chunk.
A shader can store up to 65,535 bytes of data to describe its settings, and these are stored directly in this sub-chunk without modification. The length and contents of this chunk will depend completely on the shader specified by the previous NAME chunk.
NOTE: This example is a bit out of date. It was created before the surface atom reformation and the polygon tag revolution.
464f524d 000003c2 FORM { IFF file header; FORM chunk file length is 962 + 8 bytes 4c574f32 LWO2 FORM type ID for LW OBjects
53524653 00000016 SRFS { Surface name list 42 6c 75 65 20 50 6c 61 73 74 65 72 00 00 "Blue Plaster" name 0 43 68 72 6f 6d 65 00 00 "Chrome" name 1 }
4c415952 0000001a LAYR { Start New layer 0000 0000 0, 0 layer number, flags 00000000 00000000 00000000 0.0, 0.0, 0.0 pivot point 57 61 6c 6c 20 42 6f 78 00 00 "Wall Box" layer name }
504e5453 00000060 PNTS { Points (96 / 12 = 8 points) 3f800000 3f800000 3f800000 1.0, 1.0, 1.0 point 0 3f800000 bf800000 3f800000 1.0, -1.0, 1.0 point 1 bf800000 bf800000 3f800000 -1.0, -1.0, 1.0 point 2 bf800000 3f800000 3f800000 -1.0, 1.0, 1.0 point 3 3f800000 3f800000 bf800000 1.0, 1.0, -1.0 point 4 3f800000 bf800000 bf800000 1.0, -1.0, -1.0 point 5 bf800000 bf800000 bf800000 -1.0, -1.0, -1.0 point 6 bf800000 3f800000 bf800000 -1.0, 1.0, -1.0 point 7 }
42424f58 00000018 BBOX { Bounding Box (optional) bf800000 bf800000 bf800000 -1.0, -1.0, -1.0 low corner 3f800000 3f800000 3f800000 1.0, 1.0, 1.0 high corner }
564d4150 00000060 VMAP { Vertex Map 55564d50 0002 UVMP, 2 type code, dimension 49 6d 61 67 65 20 55 56 00 00 "Image UV" map name 0000 0 point 0 mapped to: 3f800000 3f800000 1.0, 1.0 these 2 float values 0001 1 point 1 3f800000 00000000 1.0, 0.0 0002 2 point 2 00000000 00000000 0.0, 0.0 0003 3 point 3 00000000 3f800000 0.0, 1.0 0004 4 point 4 3f800000 3f800000 1.0, 1.0 0005 5 point 5 3f800000 00000000 1.0, 0.0 0006 6 point 6 00000000 00000000 0.0, 0.0 0007 7 point 7 00000000 3f800000 0.0, 1.0 }
504f4c53 0000004c POLS { Polygons 46414345 FACE type (facets) 0004 0000 4, 0 4 vertices, surface 0 ("Blue Plaster") 0000 0001 0002 0003 0, 1, 2, 3 point indices for vertices 0004 0000 4, 0 0004 0005 0006 0007 4, 5, 6, 7 0004 0000 4, 0 0000 0001 0005 0004 0, 1, 5, 4 0004 0000 4, 0 0001 0002 0006 0005 1, 2, 6, 5 0004 0000 4, 0 0002 0003 0007 0006 2, 3, 7, 6 0004 0000 4, 0 0003 0000 0004 0007 3, 0, 4, 7 }
4c415952 00000012 LAYR { Start New Layer 0001 0000 1, 0 layer number, flags 00000000 00000000 00000000 0.0, 0.0, 0.0 pivot point 0000 "" name (none) }
504e5453 00000048 PNTS { Points (72 / 12 = 6 points) 00000000 3fb4fdf4 00000000 0.0, 1.414, 0.0 point 0 3fb4fdf4 00000000 00000000 1.414, 0.0, 0.0 point 1 00000000 00000000 3fb4fdf4 0.0, 0.0, 1.414 point 2 bfb4fdf4 00000000 00000000 -1.414, 0.0, 0.0 point 3 00000000 00000000 bfb4fdf4 0.0, 0.0, -1.414 point 4 00000000 bfb4fdf4 00000000 0.0, -1.414, 0.0 point 5 }
42424f58 00000018 BBOX { Bounding Box (optional) bfb4fdf4 bfb4fdf4 bfb4fdf4 -1.414, -1.414, -1.414 3fb4fdf4 3fb4fdf4 3fb4fdf4 1.414, 1.414, 1.414 }
564d4150 0000004c VMAP { Vertex Map 55564d50 0002 UVMP, 2 type, dimension 49 6d 61 67 65 20 55 56 00 00 "Image UV" map name 0000 0 3f000000 3f000000 1.0, 1.0 0001 1 3f800000 3f800000 0.5, 0.5 0002 2 3f800000 00000000 0.5, 0.0 0003 3 00000000 00000000 0.0, 0.0 0004 4 00000000 3f800000 0.0, 0.5 0005 5 3f000000 3f000000 1.0, 1.0 }
564d4150 00000018 VMAP { Vertex Map 5049434b 0000 PICK, 0 type, dimension 50 69 63 6b 20 53 65 74 00 00 "Pick Set" map name 0001 1 0002 2 0003 3 0004 4 }
504f4c53 00000054 POLS { 46414345 FACE 0003 0001 3, 1 0000 0001 0002 0, 1, 2 0003 0001 3, 1 0000 0002 0003 0, 2, 3 0003 0001 3, 1 0000 0003 0004 0, 3, 4 0003 0001 3, 1 0000 0004 0001 0, 4, 1 0003 0001 3, 1 0005 0001 0004 5, 1, 4 0003 0001 3, 1 0005 0004 0003 5, 4, 3 0003 0001 3, 1 0005 0003 0002 5, 3, 2 0003 0001 3, 1 0005 0002 0001 5, 2, 1 }
53555246 00000020 SURF { 42 6c 75 65 20 50 6c 61 73 74 65 72 00 00 "Blue Plaster" 50 6c 61 73 74 65 72 00 "Plaster" 434f4c52 0003 COLR { a0 a0 c8 00 160, 160, 200 } }
53555246 00000040 SURF { 43 68 72 6f 6d 65 00 00 "Chrome" 44 65 66 61 75 6c 74 00 "Default" 434f4c52 0003 COLR { c8c8dc00 200, 200, 220 } 44494646 0004 DIFF { 3e99999a 0.3 } 474c4f53 0002 GLOS { 0040 64 } 5245464c 0004 REFL { 3f400000 0.75 } 53504543 0004 SPEC { 3eb33333 0.35 } }
53555246 00000068 SURF { 50 6c 61 73 74 65 72 00 "Plaster" 44 65 66 61 75 6c 74 00 "Default" 474c4f53 0002 GLOS { 0018 } 53504543 0004 SPEC { 3e4ccccd } 424c4f4b 0040 BLOK { 41544558 ATEX 80 00 128 4e414d45 000e NAME { 46 72 61 63 74 61 6c 20 4e 6f 69 73 65 00 "Fractal Noise" } 53495a45 000c SIZE { 3f000000 3f000000 3f000000 0.5, 0.5, 0.5 } 54595045 0004 TYPE { 44494646 DIFF } 56414c55 0004 VALU { 3f400000 0.75 } } }