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] | |--[MDM HEADER] | |--[Surface] | | | |--[Header] | |--[Vertex] | |--[Triangle] | |--[Collapsemap] | |--[Bone Reference] | : | |--[Tag] | : | |--[EOF] [MDX] | |--[MDX HEADER] | |--[Frame] | | | |--[Frame State] | |--[Compressed Bone Frame] | : | |--[Bone] | : | |--[EOF]
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 | ||
Name | Type and Size | Description |
MDM Identification | char * 4 | Magic Number. It should be 'MDMW'. |
MDM Version | int32 * 1 | mdm version. It should be 3. |
MDM Name | char * 64 | Name and virtual path to this mdm. |
LoD Bias | float * 1 | These are coeffcients of Level of Detail. |
LoD Scale | float * 1 | |
Number of Surfaces | int32 * 1 | Number of surfaces this mdm has. |
Offset to Surfaces | int32 * 1 | Offset to the address of the surfaces from this header. Header size is fixed then this value also fixed. |
Number of Tags | int32 * 1 | Number of tags this mdm has. |
Offset to Tags | int32 * 1 | Offset to the address of the tags from this header. |
Offset to EoF | int32 * 1 | Offset 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 | ||
Name | Type and Size | Description |
Surface Identification | int32 * 1 | ID or version of surface. It should be 0x00000009. |
Surface Name | char * 64 | Name of this surface. Generally it refers what part it is. Such as u_body, l_legs. |
Shader Name | char * 64 | Name 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 Index | int32 * 1 | ?? I dont know what this means. However this is always 0. |
LoD Minimum | int32 * 1 | This determines the maximum LoD effect on this surface. |
Offset to MDM Header | int32 * 1 | Offset to MDM Header from this surface address. always negative value. |
Number of Vertices | int32 * 1 | Number of vertices this surface has. |
Offset to Vertices | int32 * 1 | Offset to the address of the vertices data from the head of surface data. |
Number of Triangles | int32 * 1 | Number of triagles(polygons) which consist of this surface. |
Offset to Triangles | int32 * 1 | Offset to the address of the triangles data from the head of surface. |
Offset to Collapsemap | int32 * 1 | Offset 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 Bones | int32 * 1 | Number of the bones which are used when this surface will be rendered with calculating its vertices. |
Offset to Reference Bones | int32 * 1 | Offset to the address of the reference bone list. |
Offset to Next Surface | int32 * 1 | Offset to the next surface or this surface data size. |
Name | Type and Size | Description |
MDM SURAFCE VERTEX is a vertex data of this surface.
MDM SURFACE VERTEX | ||
Name | Type and Size | Description |
Vertex Normalized Vector | float * 3 | Normalized vector of this vertex. Maybe used for lightening effect. |
Texture Coordinates | float * 2 | UV 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 Weights | int32 * 1 | Number 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 | ||
Name | Type and Size | Description |
Bone Index | int32 * 1 | Index number of the bone which affect the vertex. |
Weight | float * 1 | A coefficient how much this bone affects the vertex position. A summation of this value must be 1. |
Position Vector | float * 3 | The 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 | ||
Name | Type and Size | Description |
Vertex Indices | int32 * 3 | 3 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 | ||
Name | Type and Size | Description |
Tag Name | char * 64 | Name of this tag. |
Rotation Matrix | float * 9 | A 3*3 rotation matrix to calculate another model's pose or angles. |
Attach Bone Index | int32 * 1 | Index of the bone which this tag is attached to. |
Position Vector | float * 3 | The position vector of tag when attached bone is treated as an origin. |
Number of Reference Bones | int32 * 1 | The 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 Bones | int32 * 1 | The relative offset to the Reference Bones data from the head of this tag data. |
Offset to Next Tag | int32 * 1 | Offset to the next tag data or this tag data size. |
Reference Bone List | int32 * Number of Reference Bones | Index 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 | ||
Name | Type and Size | Description |
MDX Identification | char * 4 | ID of mdx, it should be 'MDXW'. |
MDX Version | int32 * 1 | MDX version, should be 2 for now. |
MDX Name | char * 4 | Name and virtual path of this mdx. |
Number of Frames | int32 * 1 | Number of the frames this mdx has. |
Number of Bones | int32 * 1 | Number of the bones this mdx has. |
Offset to Frames | int32 * 1 | Offset to the address of frames from the header. |
Offset to Bones | int32 * 1 | Offset to the address of bones from the header. |
Torso Parent Bone Index | int32 * 1 | Bone Index to be a torso parent. |
Offset to EoF | int32 * 1 | Offset 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 | ||
Name | Type and Size | Description |
Bounding Box Vector 1 | float * 3 | The 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 2 | float * 3 | |
Local Origin | float *3 | The origin position which is used at this frame. |
Bounding Sphere Radius | float * 1 | Another Bounding area, sphere type. Used for the explosion damage etc. |
Parent of Root Bone | Tfloat * 3 | The 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 | ||
Name | Type and Size | Description |
Angle(Pitch) | int16 * 1 | These are used to calculate the rotation matrix of this bone. |
Angle(Yaw) | int16 * 1 | |
Angle(Roll) | Type and Size | |
(unused?) | int16 * 1 | Maybe this is inserted to make an unit of Compressed Bone Frame has 32bit order. |
Offset Angle(Pitch) | int16 * 1 | This 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 | ||
Name | Type and Size | Description |
Bone Name | char * 64 | Name of this boen. |
Index of Parent Bone | int32 * 1 | Index of the parent bone to calculate this bone position. |
Torso Weight | float * 1 | Coeeficient how much this bone tends to be like torso. |
Parent Distance | float * 1 | Distance from this bone's parent. |
Flag(?) | int32 * 1 | If 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. |
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.