TesOtherMod:Shadowkey File Formats/Shadowkey Model Format

This is a description of the various model file formats used in Shadowkey.

Models.txt
This file is a text file containing one line per model entry in the format:

     [Index] [Unknown1] [Width] [Height] [Filename]

Fields are separated by one space.

:* Index -- The 0-based model index.
:* Unknown1 -- Either 0 or 2. Is 2 when the width/height fields are non-zero.
:* Width
:* Height -- Assumed to be a size of some sort, either texture or model size. Is usually a power of 2 but not always.


Models.idx
This file holds model offsets and sizes for the Models.huge file. All fields are Little Endian.

     dword NumModels
     struct {
         dword Offset
         dword Size
     } [NumModels]

:* Offset -- Start offset of the model in Models.huge from the start of the file.
:* Size -- Size bytes of the model in the Models.huge file.


Models.huge
This file is simply composed of concatenated model data (no header/footer or data between models). Use the Models.idx file to determine model offsets and sizes for reading.


Model Format
This is the format of individual models contained in the Models.huge file. All fields are Little Endian. It is composed of a short header followed by multiple variable length records.

     Header         // 14 bytes
     VertexData[]
     UVData[]
     FaceData[]
     TextureHeader  // 6 bytes
     TextureData[]
     Footer[]

Header
The model header is a short 14 byte record containing record counts:

     word Magic         // Always 7
     word NumAnimations // Assumed?
     word NumVertexes
     word NumUVs
     word NumFaces
     word Unknown1      // Doesn't seem to be used?
     word Unknown2      // Always 1

Vertex Data
The vertex data immediately follows the header data and is composed of word XYZ vertex coordinates. The size and number of vertexes can be calculated from:

     TotalVertexes = NumAnimations * NumVertexes
     ByteSize = NumAnimations * NumVertexes * 6

Note that a fair number of models only have 1 animation.

UV Texture Data
Immediately following the vertex data is assumed to be word UV texture coordinate data. The size of this section can be calculated from:

     ByteSize = NumUVs* 4

The values range from 0 to 65535 (confirmed, max value may depend on texture size?).

Face Data
Immediately following the UV data is the face data. The size of this section can be calculated from:

     ByteSize = NumFaces * 12

Each face record is 12 bytes composed of 6 word values representing a vertex index (0-based):

     word v[6]

Texture Header and Data
Immediately following the face data is a small texture header and the pixel texture data. The header has the format:

     word NumTextures
     word Width
     word Height

Following the header are the texture data in RGB values stored in word values (each color in 4 bits). Total size of the texture pixel data can be calculated form:

     ByteSize = NumTextures * Width * Height

Note that this doesn't use any information from the model header. The RGB value can be extracted from the word value by (not confirmed):

    byte r = ((Value & 0x00f)  > 4) + (Value & 0x0f0)
    byte b = ((Value & 0xf00) >> 8) + ((Value & 0xf00) >> 8)

The image might be stored from the bottom up (bottom line is first in the data).

Animation Data
After the texture data and at the end of the file is a small footer with animation data. It is composed of a record count followed by that many 6 byte records.

     word numAnims
     struct {
        word StartFrame
        word EndFrame
        word Speed
     } [numAnims]