QfG5: model format

Even if it looks like I’m not doing anything, that is not completely true. I’m still figuring out various bits of the engine, trying to make a whole picture of its workings. In either case, here’s a bit more of documentation.

Models seem to come in two flavours, distinguished by the first 4 bytes: MIRT (common format) and 8XOV (used in about a dozen of files; the format is almost the same but texture-related fields are absent). Animation files also use the same IDs but with a different format and there 8XOV files are more common than MIRT ones.

Each MDL file begins with the following header:

  • 4 bytes—ID (MIRT/8XOV);
  • 32-bit int—header size;
  • 32-bit int—model ID;
  • 16 bytes—ASCIIZ model name;
  • 32-bit int—number of meshes in the file;
  • 32-bit int—number of textures in the file (MIRT only);
  • 32-bit int—unknown;
  • 1024 bytes—palette in ABGR format;
  • 32-bit int—offset to texture data (MIRT only);
  • Nx32-bit ints—offsets to the each mesh data.

Mesh data has the following header:

  • 16-byte ASCIIZ part name;
  • 20×32-bit floats—unknown;
  • 32-bit int—number of vertices;
  • 32-bit int—number of texture vertices;
  • 32-bit int—number of triangles;
  • 32-bit int—offset to the vertices data (from the mesh data start, should be 0x7C);
  • 32-bit int—offset to the texture vertices data;
  • 32-bit int—offset to the face (triangle) data;
  • 32-bit int—offset to some unknown data.

Vertices data are triplets of 32-bit floats. Texture vertices are pairs of 32-bit floats. Face data consists of a triplet of 32-bit ints with vertex indices, a triplet of 32-bit texture vertex indices, a 32-bit int texture number and a triplet of 32-bit floats with unknown values. Unknown data consists of quads of signed 32-bit integers (with the same number as the vertices) where the last element seems to be always zero.

Texture data is stored in the following format: first there is an array of 32-bit ints with an offset to the start of each texture (e.g. for single texture this offset will be 4), followed by texture header (32-bit float texture width, 32-bit float texture height, 32-bit int width power of two factor, 32-bit int height power of two factor, 32-bit int width mask and 32-bit int height mask) and texture data (palette indices for each pixel) for each of the textures.
E.g. for 128×64 texture the header values will be 128.0, 64.0, 7, 6, 127, 63.

While I’m yet to render it myself, I’ve written a small tool to covert data into Wavefront .obj format that various 3D viewers understand. Here’s a rendered part of 063.MDL as an example:

Beside the head, the model file also contains meshes for: body, tail, up and lower arms (both right and left), hands, shins, feet—13 objects in total. All using parts of the same 512×256 texture.

Leave a Reply