Notes on the MDX format - Mrkol/war3editor GitHub Wiki

The format

MDX is a binary model format. It is a recursive structure that consists of chunks and objects. A chunk is a block of data (bytes), that always starts with a 4 byte tag that represents it. A chunk's length may be varying. I will use the following terminology to speak of the format:

  • TBC abbreviation stands for "to be confirmed".
  • A chunk's total size is it's size from the start to the end, including the tag.
  • A chunk is called optional, if it might not be present at a stated location.
  • A chunk is called primary, if it's a part of the root MDLX chunk.
  • A chunk is called fixed, if it's length does not depend on it's contents and is always the same.
  • A chunk is called sized, if the 4 bytes after the tag encode a uint that represents this chunk's internal size in bytes.
  • A chunk's internal size is it's total size minus the 4 tag bytes and minus 4 size bytes, if the chunk is sized.
  • A chunk is called an array, if it's first 4 bytes represent the uint amount of objects of the same type, and afterwards there are exactly that amount of objects of the aforementioned type. In this case the amount of objects will be called the objective size.

An object is a logical block of data (bytes).

  • An object is called fixed, if it's length does not depend on it's contents and is always the same.
  • An object is called sized if it's first 4 bytes are it's inclusive size.
  • An object is called animateable if it can contain any of the track chunks (K*** tags).

The exact structure of the chunks and objects can be seen in the Editor.ModelRepresentation.Chunks/Objects namespaces, or here. From here on I will only consider the specifics of certain chunks and objects, not their binary representation.

MDLX — The model

The root chunk of the file is the MDLX chunk. It is not sized, not fixed and not optional. It's total size always equals the size of the whole file. The MDLX chunk might consist of the following chunks in arbitrary order, all of which are primary, optional and sized

  • VERS — Version (fixed)
  • MODL — Model info (probably fixed, TBC)
  • SEQS — Sequences
  • GLBS — Global sequences
  • TEXS — Textures
  • SNDS — Soundtracks
  • MTLS — Materials
  • GEOS — Geosets
  • GEOA — Geoset animations
  • BONE — Bones
  • LITE — Lights
  • HELP — Helpers
  • ATCH — Attachments
  • PIVT — Pivots
  • PREM — Particle emitters
  • PRE2 — Particle emitters2
  • RIBB — Ribbon emitters
  • EVTS — Events
  • CAMS — Cameras
  • CLID — Colliders

Nodes

A node is a "base" object that has several properties that are shared by other objects:

  • String name
  • Uint object id
  • Uint parent id
  • 4 bytes of various flags
  • Geoset animations (?) The flags:
  • 0x00000000: helper
  • 0x00000001: don't inherit translation
  • 0x00000002: don't inherit rotation
  • 0x00000004: don't inherit scaling
  • 0x00000008: billboarded
  • 0x00000010: billboarded lock x
  • 0x00000020: billboarded lock y
  • 0x00000040: billboarded lock z
  • 0x00000080: camera anchored
  • 0x00000100: bone
  • 0x00000200: light
  • 0x00000400 event object
  • 0x00000800: attachment
  • 0x00001000 particle emitter
  • 0x00002000: collision shape
  • 0x00004000: ribbon emitter
  • 0x00008000: if particle emitter: emitter uses mdl, if particle emitter 2: unshaded
  • 0x00010000: if particle emitter: emitter uses tga, if particle emitter 2: mitives far z
  • 0x00020000: line emitter
  • 0x00040000: unfogged
  • 0x00080000: model space
  • 0x00100000: xy quad

Bones

A bone is the basic unit of the skeletal animation system. It consists of

  • A node
  • An id of the geoset that's linked to this bone
  • An id of the geoset animation that's linked to it Further details needed.

Geosets

A geoset represents a mesh. It consists of

  • Vertices
  • Normals
  • Primitive groups' types
  • Primitive groups' sizes
  • Primitive groups indices (stored in order, in chunks of length PCNT[i] and of type PTYP[i])
  • Vertex groups
  • Group matrix counts
  • Matrix index array
  • A material id
  • Selection group???
  • Selection flags???
  • An extent and an array of extents???
  • UVs

Vertices are partitioned into groups. The vertex groups chunk (GNDX) maps each vertex to it's group. Each group is associated with at most 3 bones (TBC). Matrix index array (MATS) contains the groups' bone indices stored in order, counts of matrices being associated with groups are stored in-order in the group matrix counts chunk (MTGC). Obviously, each bone is associated with a single matrix.