Thanks to
History
Updated: 14/may/00
Conventions
Values are as follows unless other wise noted. For reference these are Delphi Pascal Units.
OPT
Files General
OPT Files have an elaborate offset and header system. They contain the 3D information and textures palettes etc needed to render an XWvT ship. The following is the "general" structure
The XWA General Structure is:
The first one is found in the Main Header. It may appear to be an arbitrary number, This number in BOP files is a combination of what appears to be a time stamp plus an offset . When you read the number you must subtract 8 from it's value before you can use it. The resultant number is used as a global offset number. When you encounter a jump offset value you subtract this global number from it to arrive at the offset in decimal from the beginning of file.
This global number can be set to " 8 " and at each place later in the file
where an offset is needed you use file offset(decimal) + 8 to create a valid
offset to where you want the offset to point in the file. Bop then created a
much bigger number as the apparent time stamp of file creation was added to each
offset. All bop files created for a mission will have the same global offset
numbers. Later or earlier files will have different global offsets. Thus you
could have the same op1 file with different offsets depending on when the file
was created. Op1 files are the same as bop opt files.
Main Header
Main Header ----------- FBFF FFFF File size // size of file - 8 bytes Global Offset Number // to get the number to use subtract 8 // use this number to subtract from jump offsets to arrive at offset from beginning of file. to write a file set to "8" and add 8 to all other offsets + file offset from beginning of file |
Main Jump Header
Next is the 02 Header. This contains the jump offsets to the Main Mesh Headers. One mesh header exists for each piece of the 3D object (mesh).
02 Header XWA ----------- 2 // (byte) unknown use // maybe a word ,Color index to a palette or color value 0 // (byte) unknown use NumOfOffsets // (Longint) the number of jump offsets to Main Mesh Headers ** See Note above Jump to Offsets // Points to first offset [1..NumOfOffsets] // (beginning at offset 22) |
Main Mesh Header
XWVT:: Main Mesh Headers can have any number of blocks to read so a file reader should not rely on the (003) byte format to locate this block. Each has different information. The one caveat is the number of block 22 to read. If the Main Mesh header block starts with a 3 there are no block 22's(hard point info) to read. An opt file reader to be reasonably accurate of what it is encountering should not rely on what will appear in each of these headers instead it should test to see what is at that offset and take the appropriate action. This is especially true in bop files where there may be an offset to a null entry.
BOP:: Main Mesh Headers have even more blocks to read. see the Main Mesh Header BOP structure.
The Mesh Master Reverse Offset (MMRV).
This number is similar to
the file global offset, however it is used to go back "x" number of bytes,
usually if you need to go back to the Mesh Master header. To use the number
simply store the mesh master reverse offset, when you encounter a reverse offset
in a Mesh Info header you subtract the MMRV from the Info headers RV number to
get the number of bytes to go back.
The reverse offset can also be used to get to the next MMH block, Take the first MMH RV offset you encounter in the file, add any Main Jump offset (blk 02) to it. The result will be exactly 178 bytes more than the offset to that MMH blocks list of jumps.
With all that above, If the reverse offsets are set to "null" when writing a file , then they will not be changed when bop writes the op1 file. So either they are redundant code ,or some sort of material flags settings. Either way the opt seems no different under 3d conditions with these set to null.
Main Mesh Header XWA ----------- 0 0 NumOfMeshSub headers // num of block 22+ num of block 28 + 3 = num sub headers Offset to Jump Offsets 1 mesh master reverse offset // Mesh Global reverse offset offset to 03 // vertices offset to 11 // vertex normals offset to 13 // texture normals offset to 28 block // Engine Glows offset to 22 // Hard points offset to 23 block // Insertion offset, and scale offset to 25 block // Collision Box offset to 004 block // Mesh Info Header |
Mesh Descriptor 025 Block Header
Mesh Descriptor O25 Block Header ----------- 0 25 0 0 1 Jump to mesh type Mesh type // see list below Explosion type // see below array[0..11]of single; (float) //Hit zone info see below for note on calculating targeting group id // longint array[0..2] of single; (float) // Targeting box coords ***** see notes below |
Here is a list of the Mesh Types
Explosion Type
0,1,4,5,8,9 = Mesh continues in straight line when destroyed 2,3,6,10 = Mesh breaks off and explodes 7 = destructible parts
Hit Zone floats array[0..11] of single how to calculate values
The floats are in 4 sets representing X,Y,Z as follows.
How to calculate The SPAN X,Y,Z.
SpanX = MaxX subtract MinX,repeat for Y,Z.
How to calculate the Hit Zone center point.
CenterX = SpanX divided by negative 2 then add MaxXrepeat for Y,Z.
Targeting Group ID
The targeting group id is used to describe which and where the small yellow targeting boxes show up in the Hud with the "," key. You can associate several meshes together by assigning them the same coordinates in the float array + the same group id number. Turrets/generators etc are set to coordinates "0,0,0" because they can be blown up.In that case the mesh center is used( Could be the Turret block coordinate too but the mesh hit zone center makes more sense).
IE: Two separate main hull meshes could be set to Id number 2 and both sets of floats are set to the same X,Y,Z coordinate of where you want the targeting box to show up at in the HUD.
conversely you could have each Mesh show up as as separate target by giving ea a different id and set of coordinates.
The Ids start from 0 to ~.
Rotation Scale Block Header
This block describes various aspects about which way the mesh is oriented. These are not fully tested yet. the last three sets of floats are vectors. Most notably used in turrets to describe which is the plane of rotation and aiming.
Rotation/Scale Block Header ----------- 0 23 0 0 1 jump to floats array[0..2] of float // Pivot point array[3..5] of float // axis of rotation (z) array[6..8] of float // aim direction (x) array[9..11]of float // 90 deg to aim direction |
XWA Engine Glow Block Header
Engine glow blocks ,jumps to these are in mesh header that has the engines in it. The two colors use the RGB from the longint and the extra high byte seems to be a density or transparency value. There is two colors the core is like a cross right in the middle surrounded by the second color. You can set multi engine models to different colors if you wish , though in original models they are set to the same within model. The Last three sets of floats are likely fog density`s value 0 - 1.0 these are floats.Not sure why so many values though. Most likely for shaping reasons.The main vector should be the end of d3d fog setting , need to play with that one a bit more.
XWA Engine Glow Block Header ----------- 0 28 0 0 1 jump to "0" 0 Core Color Longint // with alpha component Outer Color longint // with alpha component array[0..2] of float // vector 1 Point in middle of Engine face array[3..5] of float // vector 2 x= width , y= height , z= length (next is 3 axis) // unknown function (0,1,0) array[0..2] of float (0,0,1) array[3..5] of float (1,0,0) array[6..8] of float |
Hard Point Block Header
Block 22 describes the location of the hard points on ships ,ie the end of the gun barrels... Ships such as a platform have two sets sometimes of Hard points in the same location, one set is empire weapons the other set is rebel weapons.
XWA Hard points some additional Hard points have been added beyond this list , (not researched up to 39 hp)
hard point Block Header ----------- 0 22 0 0 1 jump to hard point type hard point type // hard point type ie: Rebel laser 3 Floats // hard point coordinate |
Here is a list of the Hard points.
Mesh Info Header
Mesh Info Headers contain
Main Info Header 004 block "A" --------- 0 0 4 jump to jumps 1 Reverse Offset // Subtract the mesh reverse num from block 3 to // arrive at how many bytes to get back there 0 // Null vertex jump 0 // Null Texture vertex jump 0 // Null Vertex normal jump Jump to 21 block // Jump to Face Jump |
may also have this section with no "Nulls" as below.
Mesh Info Header "B"
Main Info Header 001 block "B" --------- 0 0 1 jump to jumps 1 Reverse Offset // Subtract the mesh reverse num from block 3 to // arrive at how many bytes to get back there Jump to 21 block // Jump to Face Jump |
Mesh Info Header "C"
Main Info Header 001 block "C" --------- 0 0 1 jump to jumps 1 Unknown Longint // longint of unknown function 0 // Null vertex jump 0 // Null Texture vertex jump Jump to 21 block // Jump to Face Jump |
Can be found in planetaryfighter.opt
Mesh Vertex Header
Mesh Vertex Headers contain the float type data for the vertices.
03 Vertex Header ------------------ 0 3 0 0 NumVertices // (Longint) Jump to Floats Vertices // NumVertices*3 Floats (x,y,z) |
Texture Vertex Header
Texture Vertex Headers contain the float type data for aligning textures on faces. these are normalized u,v or s,t
13 Texture Vertex Header ------------------ 0 13 0 0 NumTexVertices // (Longint) Jump to Floats TexVertices // NumTexVertices*2 Floats (u,v) |
Vertex Normal Header
Vertex Normal Headers contain the float type data describing the normalized direction of the vertices. This is found by averaging the normals of all the faces that use this vertex.
11 Vertex Normal Header ------------------ 0 11 0 0 NumVertNorms // (Longint) Jump to Floats VertNorms // NumVertNorms*3 Floats (i,j,k) |
Mesh Data Header
This is a directory for master face groups. Follow the MFH Jumps to get to Face Headers (Face Headers then have their own groupings of faces). A small float is included.
Mesh Data Header ------------------ 0 21 1 // Number of Face Data Header Jumps Jump to the MFH Block Jump 1 // Number of jumps to face data headers Jump to Float Jump to Mesh Face Header // High Res Face Data Header Jump to Mesh Face Header // Low Res Face Data Header if present see Notes** LOD Float[array] // One float for ea Face Data Header jump (Lo res distance numbers) |
NOTES on Model Resolutions
If the Number of Face Data Headers is >1 then ,each successive Face data header represents a lower detail model.
Ie: an Xwing has 3 detail models, the highest would be FDH 0, next highest detail would be FDH 1 , and finally the lowest detail model is FDH 2.
XWA , all except one model only have two levels of detail.
To roughly convert the raw distance value found int the OPT to kilometers, you must use the equation:
km = .000028537 x (RawValue ^ -1.0848093)
To convert kilometers to a raw value, use the equation:
raw = (km / .000028537) ^ (1/-1.0848093)
A raw value of 0 means that the detail level is always visible, and a value
of 1 means that the detail level is never visible.
Mesh Face Header
This Block jumps to various areas related to the geometry and appearance of faces. Various "face groups" can be specified so different textures will be used.
Mesh Face Header ------------------ 0 0 NumFaceGroups // Num of 20/00/01/07/24 blocks to read Offset to Jumps 1 Reverse Offset // Jump to 20 Block // Texturing Block ** many variations ** Jump to 00 block // Unknown texturing block suspect bug in code Jump to 01 Block // Face Data Jump to 07 Block // texture name re declared for reuse on another face. Jump to 24 block // Texture Jump list, for Flight Group Textures in XWA , XWA also seems to be used for animations |
*** Does not always have block 20/07/24 to read only 01 block if num is 1.
*** 20 block new texture.
*** 24 Block New Group of textures ,generally
the flight group color textures( not always 4 in xwa)? Has other uses in XWA
*** 07 Block Re use texture on this face
*** 01 Face Data
20 Texture Header
Includes Texture and MipMaps. MipMaps are a series of images that decrease in
dimensions by a factor of 2. Three MipMaps are included along with the main
image.
ie. A Texture would include an image that is 64x64, 32x32, 16x16, and
8x8.
Texture data is stored like a bmp (upside down to convention) , Ie bottom right pixel of image is first byte and top right pixel last byte ,unlike a bmp there is no padding of the bytes.
Texture headers have been found in several variations.
Texture Header "AA" (XWA) ------------------ JumpToTex // Points the 'T' in "Tex00000" 20 1 Jump to 26 block jump UID // unique Id per texture Jump To "Palette offset " jump Byte[0..8] // "Tex00000" + '\0' (null term string (9-bytes)) Jump to 26 Texture block Jump to "Palettes" // beginning of Palettes 8192k for XWA 0 TexSize // Size without MipMaps (Width*Height) DataSize // Size including MipMap Sizes Widthbs // Width of Image Height // Height of Image Byte[0..DataSize-1] // Image Data + MipMap Data |
Following this block is the palettes then a 0,26 block (E ) texture block.
Texture Header "AAA" (XWA) ------------------ JumpToTex // Points the 'T' in "Tex00000" 20 0 0 UID // unique Id per texture Jump To "Palette offset " jump Byte[0..8] // "Tex00000" + '\0' (null term string (9-bytes)) Jump to "Palettes" // beginning of Palettes 8192k for XWA 0 TexSize // Size without MipMaps (Width*Height) DataSize // Size including MipMap Sizes Width // Width of Image Height // Height of Image Byte[0..DataSize-1] // Image Data + MipMap Data |
Standard XWA texture block
Texture Header "B" ------------------ 0 7 0 0 1 JumpToTex // Points the 'T' in "Tex00000" Byte[0..8] // "Tex00000" + '\0' (null term string (9-bytes)) |
Texture Header "C" ------------------ 0 24 NumOfJumps // Number of (20,07) offsets to read JumpListOffset // Offset to Jump List 1 Reverse Offset Array Of Offsets // these offsets point to the first entry in a Texture Header"A" Block |
XWA , Does not seem to only have 4 "NUmOFJumps" in checking several models found up to 37 jump entries in though the first four were different the remaining were the same as 4th entry, strange it `s like this in more than one model though , was hoping it was a bug. Still think it is.
Texture Header "CC" XWA ------------------ 0 24 1 JumpListOffset // Offset to Jump List 0 0 Offset // to 20 Texture Header"AAA" Block |
XWA , points to one texture 20 only , seems to be multiple of these in front of a regular 20 texture, probably overlays
Texture Header "CCC" XWA ------------------ 0 24 num of jumps // JumpListOffset // Offset to Jump List 0 0 Offsets // can be a combination of AAA texture blocks and normal 07 blocks |
XWA , The 07 textures seem to be repeated or mixed for some reason , whether it is some sort of animation.
Texture Header "E" (XWA) ------------------ 0 26 0 0 NumOfBYTES (image+mipmaps) JumptoBytes Bytes |
Appears to be an alpha mask , image values are either "00" or "FF" the image is the same as the 0,20,1 image plus mipmaps.
Any value ranging from 0 to 255 can be used in the alpha mask, where a hex value of 0xFF means that that specific pixel of the texture is completely nontransparent and a value of 0x00 is completely transparent. The standard is 0x6F.
Palettes
Palettes are found by using the Jump to palettes offset in the 20 texture header block. Then comes 15 color maps (shade tables)and 1 palette. Each is 256 * word for a total of 8192 bytes. The color maps go from dark to lighter shades with the [0..15] # 8 one being the palette.
Textures can share a set of palette/color maps , if the "Jump to "Palettes" entry is the same in the Texture header "A" then these textures share that set of 16 palettes.
Use a bit pattern of 5-6-5 b,g,r .
Unknown if there is a limit on the number of pals you can add, though file size would have to be a consideration if no pals were shared among textures.
Pals are written after the texture .
Palette XWA General ------------------ (256 * word)*16 // ea palette X 16 = 8192 bytes // pals use 5-6-5 blue,green,red bit pattern |
Face Data Header
This block contains information for the faces in the mesh that called it.
Face Data Header ------------------ 0 1 0 0 NumFaces // Number of Faces being declared Offset to Longint // Face data immediately follows the longint Edges // unique edge count for faces in this header FaceVerts[0..NumFaces-1] // vertex index FaceEdges[0..NumFaces-1] // edge index (no list) FaceTXVX[0..NumFaces-1] // texture vertex index FaceVxN[0..NumFaces-1] // vertex normal index FaceNorms[0..NumFaces-1] // Face Normals FaceText[0..NumFaces-1] // Face Texturing Info (software vectors) |
Vertices: Each face declares four groups of four vertex references (longints). The first group is the references to the geometry vertices (3 Block).
Edges The second group is edges numbers.Ea edge has a unique number in this group of faces,Ea pair of vertices that share an edge will have the same number. New numbers per Face Header
TX CoordinatesThe third group is references to the texture vertex list.
Vertex Normals The fourth group is referenced to the vertex normal list .
All references are Longints. If a reference is FFFFFFFF (-1), then it should be ignored, and that face should be assumed to have only 3 vertices. Each face will take 64 bytes. Faces are either a triangle or a quad.
Normals: Each face has three floats (i,j,k) representing its normalized vector. Each face then has 12 Bytes.
Texturing: Used by the software rendering engine. Six floats for each
face (24 bytes). These are 2 vectors.Direction and magnitude are significant.
1. the cross product of the two must be the face normal (not unit length,
but same direction as the face normal) or the texture exhibits weird
"out-of-plane" effects.
2. The vectors are set to the "across-top" dx,dy,dz
and the "down side" dx,dy,dz. In the case of a rectangular face the vector
magnitudes (lengths) will equal the side lengths. Which side the face is viewed
from in calculating this doesn't seem to matter.
3. The two vectors position
the texture in 3-D space and also set the scale of the texture - the texture is
basically stretched in space to fit the vectors.
XWA If the face is a Triangle, Edge,Vxn,and Txvx may not necessarily also be limited to 3 numbers, in fact they can be mixed between quad numbers and tri.