Wolfenstein: Enemy Territory

Custom Model Depot Yard

MDM MDX unofficial specification

Here is the data structure of mdm and mdx which I am using in the tool. but there is no guarantee to ensure this document saying truth. So use these info at your own risk.

Player model in ET

Each character used in ET is assigned in characters of pak0.pk3. There are some files to define a character, they refer what class it is, what mesh it uses, what animation group it uses, what mesh it uses when it is undressed, what model its head is.

The mdm is a mesh data file for player models. mdm includes the surfaces and tags. The surface is a geometric data of model or polygon data. Skinning the surfaces with textures, the model appears in ET. The tag is a position info to attach another model to this model. The tag has its position and degree at each frame.

The mdx is a animation data file which contains bone structure and frames. The bone is a skeltal model data. Each bone has its length and its parent bone. The frame is a 3D-position data of the bones. one of the mdx frames have slightly different bone position compared with the previous frame. Thus a series of those frame will make an animation of a action. Ordinarily the mdx has several(or massive) number of animations in it.

A combination of mdm and mdx makes the polygons live, act, be a player.

This system is extremely good for sharing the animations which are used by the similar models. For example, ET only has one mdx( precisely there are more but they are a little ) to be used by the player models, 5 classes of allies and axis team. If we need to create the animation data for each model as like RtCW, The file size will be more bigger and memory requirements will be higher.

However the combination of mdm and mdx is valid when they have the same bone structure. This means that we must create new mdx if we make a non-humanlike model or a small or tall person. I myself think that separating the model data into a set of meshes, tags and bone structure and frames is better if we want to make a small or large human model.

MDM Data Structure

[MDM]
  |
  |--[MDM HEADER]
  |
  |--[Surface]
  |     |
  |     |--[Header]
  |     |--[Vertex]
  |     |--[Triangle]
  |     |--[Collapsemap]
  |     |--[Bone Reference]
  |     :
  |
  |--[Tag]
  |    :
  |
  |--[EOF]


[MDX]
  |
  |--[MDX HEADER]
  |
  |--[Frame]
  |     |
  |     |--[Frame State]
  |     |--[Compressed Bone Frame]
  |     :
  |
  |--[Bone]
  |    :
  |
  |--[EOF]

Detail Data Structure

Here is a data specifications of mdm and mdx. Repeatly I say, they are not guaranteed to be right.

MDM HEADER

MDM HEADER is the header section of mdm. There are information of version, location, Level of Detail, number and offset of the surfaces and tags and so on.
MDM HEADER
NameType and SizeDescription
MDM Identificationchar * 4Magic Number. It should be 'MDMW'.
MDM Versionint32 * 1mdm version. It should be 3.
MDM Namechar * 64Name and virtual path to this mdm.
LoD Biasfloat * 1These are coeffcients of Level of Detail.
LoD Scalefloat * 1
Number of Surfacesint32 * 1Number of surfaces this mdm has.
Offset to Surfacesint32 * 1Offset to the address of the surfaces from this header. Header size is fixed then this value also fixed.
Number of Tagsint32 * 1Number of tags this mdm has.
Offset to Tagsint32 * 1Offset to the address of the tags from this header.
Offset to EoFint32 * 1Offset to EoF of this mdm. Otherwords this mdm file size.

Surface

Surface is a mesh data which will be seen as a part of the player model in ET. Generally a mdm has several surfaces. They are almost separated upper and lower parts, also hands and torso. Example:
MDM SURFACE HEADER
NameType and SizeDescription
Surface Identificationint32 * 1ID or version of surface. It should be 0x00000009.
Surface Namechar * 64Name of this surface. Generally it refers what part it is. Such as u_body, l_legs.
Shader Namechar * 64Name and virtual path of the shader to apply this surface. The ET mdm has nothing here. The skin file defines what shader this surface uses.
Shader Indexint32 * 1?? I dont know what this means. However this is always 0.
LoD Minimumint32 * 1This determines the maximum LoD effect on this surface.
Offset to MDM Headerint32 * 1Offset to MDM Header from this surface address. always negative value.
Number of Verticesint32 * 1Number of vertices this surface has.
Offset to Verticesint32 * 1Offset to the address of the vertices data from the head of surface data.
Number of Trianglesint32 * 1Number of triagles(polygons) which consist of this surface.
Offset to Trianglesint32 * 1Offset to the address of the triangles data from the head of surface.
Offset to Collapsemapint32 * 1Offset to the address of the collapsemap. The collapsemap is the list of triangle indices in order to apply LoD. This list indicates the triangle(or vertex?) will be omitted in that order.
Number of Reference Bonesint32 * 1Number of the bones which are used when this surface will be rendered with calculating its vertices.
Offset to Reference Bonesint32 * 1Offset to the address of the reference bone list.
Offset to Next Surfaceint32 * 1Offset to the next surface or this surface data size.
NameType and SizeDescription

MDM SURAFCE VERTEX is a vertex data of this surface.

MDM SURFACE VERTEX
NameType and SizeDescription
Vertex Normalized Vectorfloat * 3Normalized vector of this vertex. Maybe used for lightening effect.
Texture Coordinatesfloat * 2UV coordinates of the texture image. 3 vertices will cut an triangle image which their potisions are refered by this uv coords from the texture. This value is standardized so ranges from 0 to 1.
Number of Bone Weightsint32 * 1Number of the bone weights which will affect this vertex.

Weight is a element to determine where the vertex is. The vetex potision is calculated by summation of the multiple of the weight and its position of each bone.

MDM SURFACE WEIGHT
NameType and SizeDescription
Bone Indexint32 * 1Index number of the bone which affect the vertex.
Weightfloat * 1A coefficient how much this bone affects the vertex position. A summation of this value must be 1.
Position Vectorfloat * 3The position vector of vertex when this bone is treated as an origin.

Triangle is combinations of 3 vertex indices to buld a polygon.

MDM SURFACE TRIANGLE
NameType and SizeDescription
Vertex Indicesint32 * 33 vertex indices to make a polygon.

Collapsemap data is not specified yet. Reference Bone data is the continuous number of the bone index. They are int32 and their amount is same as the number of Number of Reference Bones in Surface Header.

Tag

Tag is popular for Quake3-Engine-Based game modders. Tag is used to attach another model to this model. mds which has been used in RtCW has different tag data type. mds treat the tags as bones so the position of tag will be changed at each frame.
MDM TAG
NameType and SizeDescription
Tag Namechar * 64Name of this tag.
Rotation Matrixfloat * 9A 3*3 rotation matrix to calculate another model's pose or angles.
Attach Bone Indexint32 * 1Index of the bone which this tag is attached to.
Position Vectorfloat * 3The position vector of tag when attached bone is treated as an origin.
Number of Reference Bonesint32 * 1The number of bones to calculate the tag's parent bone position. Ther are from a root bone to the previous bone of the attached to.
Offset to Reference Bonesint32 * 1The relative offset to the Reference Bones data from the head of this tag data.
Offset to Next Tagint32 * 1Offset to the next tag data or this tag data size.
Reference Bone Listint32 * Number of Reference BonesIndex list of the Reference Bones.

MDX HEADER

MDX Header refers the version, numbers and offset of the frame and bone structure of this mdx.

MDX HEADER
NameType and SizeDescription
MDX Identificationchar * 4ID of mdx, it should be 'MDXW'.
MDX Versionint32 * 1MDX version, should be 2 for now.
MDX Namechar * 4Name and virtual path of this mdx.
Number of Framesint32 * 1Number of the frames this mdx has.
Number of Bonesint32 * 1Number of the bones this mdx has.
Offset to Framesint32 * 1Offset to the address of frames from the header.
Offset to Bonesint32 * 1Offset to the address of bones from the header.
Torso Parent Bone Indexint32 * 1Bone Index to be a torso parent.
Offset to EoFint32 * 1Offset to EoF of mdx otherwords size of this mdx.

MDX FRAME

Frame is a state of the skeltal model at a moment. It can be the scene of firing Panzer, or dying by the head shot, or Nazi salutling. There are 2 sections in Frame, Frame State and Compressed Bone Frame. Frame State refers the bounding box of this model at this frame and a base position which will be used as the parent bone by the root bone. Compressed Bone Frame is the bone position data at this frame. "Compressed" means that each data is not 32bit, but 16bit.

MDX FRAME STATE
NameType and SizeDescription
Bounding Box Vector 1float * 3The relation of 1 and 2 is diagonal. The box area created by using vector 1 and 2 to the box diagonal positions is called Bounding Box. The Bounding Box is used for checking collision or hitting box or trigger entity and so on.
Bounding Box Vector 2float * 3
Local Originfloat *3The origin position which is used at this frame.
Bounding Sphere Radiusfloat * 1Another Bounding area, sphere type. Used for the explosion damage etc.
Parent of Root Bone Tfloat * 3The position used by calculatin of the root bone position.

The Compressed Bone Frame follows after Frame State. It will repeat same times as the number of bones.

MDX COMPRESSED BONE FRAME
NameType and SizeDescription
Angle(Pitch)int16 * 1These are used to calculate the rotation matrix of this bone.
Angle(Yaw)int16 * 1
Angle(Roll)Type and Size
(unused?)int16 * 1Maybe this is inserted to make an unit of Compressed Bone Frame has 32bit order.
Offset Angle(Pitch)int16 * 1This is used to calculate where is this tag.
Offset Angle(Yaw)int16 * 1

To know the bone position, you have to summation the vectors which are calcurated by using ( Parent Distance, 0 , 0 ) as a start vector, rotating it with Offset Angles.

To convert angles to radian, just do this: Radian = 2 * 3.14 * Angle / 65536.0

MDX BONE

Bone Structure is like a puppet. A puppet has joints and fixed-length bones. Bones in ET is so. The meshed are attached around the bones. If a bone moves, mesh moves. If a bone is rotated, mesh is rotated as well.

MDX BONE
NameType and SizeDescription
Bone Namechar * 64Name of this boen.
Index of Parent Boneint32 * 1Index of the parent bone to calculate this bone position.
Torso Weightfloat * 1Coeeficient how much this bone tends to be like torso.
Parent Distancefloat * 1Distance from this bone's parent.
Flag(?)int32 * 1If this bone is a tag, this value is 1 or not, 0. but in ET there is no longer tags as bones, this is always 0.

References and Thanks

http://mojo.gmaxsupport.com/Articles/MDSFileFormat.html

Chris Cookson speced the mds, and this is extremely helpful for ET modder as well. Thanks that great documents.