MDM/MDX is a successor of the MDS format.
Apart from a small difference in tags, the main difference is the seperation of animation data. While MDM specifies surface and tag data, the actual animation data is defined separately in an MDX file. MDM references this skeletal animation data for the purpose of reusing the same set of animations across several different meshes.
Name | Description |
---|---|
UINT8 | unsigned 8-bit integer |
INT16 | signed 16-bit integer |
UINT16 | unsigned 16-bit integer |
INT32 | signed 32-bit integer |
UINT32 | unsigned 32-bit integer |
F32 | 32-bit floating-point (IEEE-754) |
ASCII | 8-bit ASCII character |
(*) | Marks a list of objects of the same type. There can be multiple appearances of * inside those round brackets, for example (**) describes a list of lists. |
Name | Description | Type |
header | reference to MDMHeader object. | MDMHeader |
surfaces | list of MDMSurface objects, size=num_surfaces. | MDMSurface (*) |
tags | list of MDMTag objects, size=num_tags. | MDMTag (*) |
Notes:
Container object. References all MDM data.
Name | Description | Type |
ident | magic number, ASCII encoded, length 4, reads "MDMW". | 4*ASCII |
version | version number, latest known is 4. | UINT32 |
name | model name, usually its pathname, ASCII encoded, null-terminated, length 64. | 64*ASCII |
lod_scale | TODO | F32 |
lod_bias | TODO | F32 |
num_surfaces | number of surfaces. | UINT32 |
ofs_surfaces | file offset to field of surfaces. | UINT32 |
num_tags | number of tags. | UINT32 |
ofs_tags | file offset to field of tags. | UINT32 |
ofs_end | file offset to end of file. | UINT32 |
Notes:
General information about MDM data. Used mainly to navigate file data.
Name | Description | Type |
header | reference to MDMSurfaceHeader object. | MDMSurfaceHeader |
vertices | list of MDMVertex objects, size=num_vertices. | MDMVertex (*) |
triangles | list of MDMTriangle objects, size=num_triangles. | MDMTriangle (*) |
collapse_map | reference to MDMCollapseMap object. | MDMCollapseMap |
bone_refs | reference to MDMBoneRefs object. | MDMBoneRefs |
Notes:
Container object. References surface data.
Background:
Surfaces are described by geometry, level-of-detail and color data. A model can consist of multiple surfaces.
Name | Description | Type |
ident | magic number, ASCII encoded, length 4. | 4*ASCII |
name | surface name, ASCII encoded, null-terminated, length 64. | 64*ASCII |
shader | shader name, ASCII encoded, null-terminated, length 64. | 64*ASCII |
shader_index | used in-game only. | UINT32 |
min_lod | minimum amount of vertices for the surface or maximum amount of collapse operations during runtime. | UINT32 |
ofs_header | relative offset from this surface to start of file. This is a negative number. | UINT32 |
num_vertices | number of vertices. | UINT32 |
ofs_vertices | file offset to field of vertices. | UINT32 |
num_triangles | number of triangles. | UINT32 |
ofs_triangles | file offset to field of triangles. | UINT32 |
ofs_collapse_map | file offset to collapse map. | UINT32 |
num_bone_refs | number of bones this surface references. | UINT32 |
ofs_bone_refs | file offset to bone references. | UINT32 |
ofs_end | file offset to end of surface. | UINT32 |
Notes:
General information about a surface. Used mainly to navigate surface data.
normal | vertex normal coordinates. | 3*F32 |
tex_coords | u and v coordinates in UV-space as tuple. | 2*F32 |
num_weights | number of weights for this vertex. | UINT32 |
Notes:
Vertex location, normal and texture coordinates.
The number of weights usually does not exceed 3 (at least i have never seen any model with more).
Background:
Vertex normals manipulate the shading of a surface (for example smooth or flat).
Texture coordinate values refer to the process of UV-mapping.
Name | Description | Type |
bone_index | bone that exercises a weighted influence over the vertex location given as index into the list of bone_infos. | UINT32 |
bone_weight | amount of influence from the bone over the vertex location. | F32 |
location_offset | location coordinates given in bone space. TODO recheck with source code | 3*F32 |
Notes:
Weights are used to define a vertex location in conjunction with all other weights of a vertex. The weights and their offsets are specified in binding pose.
The sum of all weights for a vertex should always be equal to 1.
Name | Description | Type |
indices | indices into the list of vertices. The order defines in which direction the face normal is pointing. | 3*UINT32 |
Notes:
A triangle for a surface.
Name | Description | Type |
mappings | indices into the list of vertices for this surface, size=num_vertices. | num_vertices*UINT32 |
Notes:
The collapse map is used to render a surface with varying level of detail (LOD) dependent on view distance during runtime (progressive mesh algorithm).
Background:
The collapse map is a list of vertex indices pointing into the list of vertices for this surface. The value j at index i of the collapse map describes a collapse operation. This operation can be read as "vertex i is to be mapped/collapsed to vertex j".
A user will take a fully detailed mesh and gradually reduce vertex and triangle count at runtime by using the pre-calculated collapse map. For this, he first determines the amount of vertices the mesh should have. Then he applies the collapse operations starting from the end of the collapse map.
The particular method used was described by Stan Melax in a publication from November 1998, see "A Simple, Fast, and Effective Polygon Reduction Algorithm" for further details. A demo implementation can be found at: https://github.com/melax/sandbox/tree/master/bunnylod
Name | Description | Type |
bone_refs | indices into the list of bone_infos for this surface or tag, size=num_bone_refs. | num_bone_refs*UINT32 |
Notes:
Defines which bones a surface references. Probably used for optimization inside the engine. Needs to be hierarchically ordered.
Name | Description | Type |
name | tag name, ASCII encoded, null-terminated, length 64. | 64*ASCII |
orientation | orientation as rotation matrix in binding pose as tuple of floats given in parent bone space. Each sequence of 3 floats make up the coordinates of a basis vector. The first 3 floats make up the x basis vector, etc. | 3*3*F32 |
parent_bone | bone that controls the tags location and orientation. Given as index into the list of bone_infos (from the referenced MDX file). | UINT32 |
location_offset | location relative to its referenced bone as tuple of floats. The values are given in parent bone space. | 3*F32 |
num_bone_refs | number of bones this tag references. | UINT32 |
ofs_bone_refs | file offset to list of bone references. | UINT32 |
ofs_end | file offset to list of bone references. | UINT32 |
bone_refs | indices into the list of bone_infos (from the referenced MDX file) for this tag, size=num_bone_refs. | MDMBoneRefs |
Notes:
Frame independent tag information.
MDM tags are different from MDS tags in that their location and orientation values are stored in binding pose and with location offset to the parent bone. The orientation values therefore are fixed and controlled by the parent bone, whereas a bone in MDS is actually the tag and can be animated/oriented per frame.
Background:
Tags are used to attach external models to a model. Attachment means that the external models origin aligns itself with the models tag location and orientation. As the external model is parented to the tag (nested in tag space), any animation of the tag will also affect the external model.
Domain specific scripts tell the engine which external models to attach to a given tag. These scripts are either located in mapscript files (attachtotag command) or .skin files. Sometimes they are also hard coded.
An example use case is a hat model (defined separately) attached to a head model. This way, characters can be assembled with different looks without having to duplicate their model definitions. Tags therefore support reuse.
Another example use case is that of a tank turret model attached to a tank model. Instead of having a shooting animation (rotate turret left, shoot, rotate turret right) be recorded as vertex positions across several key-frames inside a single model, a tag can be used to control the shooting animation of a separated model. This safes memory, as the tags animation data most likely takes much less space compared to the animation data of the tank turret inside a single model.
However, reuse and memory savings are traded against loss in performance. Vertex positions of the external models have to be recalculated against the current frame tags location and orientation.
Name | Description | Type |
header | reference to MDXHeader object. | MDXHeader |
frames | list of MDXFrame objects, size=num_frames. | MDXFrame (*) |
bone_infos | list of MDXBoneInfo objects, size=num_bones. | MDXBoneInfo (*) |
Notes:
Container object. References all MDX data.
Name | Description | Type |
ident | magic number, ASCII encoded, length 4, reads "MDXW". | 4*ASCII |
version | version number, latest known is 4. | UINT32 |
name | model name, usually its pathname, ASCII encoded, null-terminated, length 64. | 64*ASCII |
num_frames | number of animation frames. | UINT32 |
num_bones | number of bones. | UINT32 |
ofs_frames | file offset to field of frames. | UINT32 |
ofs_bone_infos | file offset to field of bone infos. | UINT32 |
torso_parent_bone | TODO | UINT32 |
ofs_end | file offset to end of file. | UINT32 |
Notes:
General information about MDX data. Used mainly to navigate file data.
MDXFrame | ||
Name | Description | Type |
frame_info | reference to MDXFrameInfo object. | MDXFrameInfo |
bone_frames_compressed | list of MDXBoneFrameCompressed objects, size=num_bones. | MDXBoneFrameCompressed (*) |
Notes:
Container object. References bounding volume and bone animation data.
Name | Description | Type |
min_bound | location coordinates of min corner of minimum bounding box. | 3*F32 |
max_bound | location coordinates of max corner of minimum bounding box. | 3*F32 |
local_origin | TODO | 3*F32 |
radius | TODO | F32 |
root_bone_location | TODO | 3*F32 |
Notes:
Describes bounding volume information: axially aligned bounding box and bounding sphere. Additionally contains the root bone location.
Name | Description | Type |
orientation | orientation as euler angles in frame. Index 0 = pitch, index 1 = yaw, index 2 = roll. Index 3 is not used and contains a default value. | 4*INT16 |
location_dir | location in spherical coordinates. Index 0 = latitude, index 1 = longitude. | 2*INT16 |
Notes:
Bone location and orientation in a specific frame.
Bone orientation values are given as compressed 16-Bit integers. To convert this range to a range of floats, the given value is linearly mapped. For this, a hard coded scale value is used. The result is an angle in the range of [0, 360). To convert the angles to a rotation matrix, we first roll, then pitch, then yaw (intrinsic). TODO recheck signed integer to angle range
Bone location values are given as offset direction from a parent bone. Combined with the parent_dist value in the bone info field and the parent bones frame location, one can calculate the bones frame location. Linear mapping is done the same way as with the bone orientation values to get the angle values from the range of integer to the range of floats. To convert the angles to a direction vector, we first pitch (latitude), then yaw (longitude).
Name | Description | Type |
name | bone name, ASCII encoded, null-terminated, length 64. | 64*ASCII |
parent_bone | parent bone as index into the list of bone_infos. | UINT32 |
torso_weight | TODO | F32 |
parent_dist | distance to parent bone. | F32 |
flags | not used. | UINT32 |
Notes:
Frame independent bone information.