MDC is a compressed version of the MD3 format.
The major difference between MDC and MD3 is compression of animation data. In MDC, the coordinates of vertices in each frame may be stored as 8-Bit offset values. MD3 always stores 16-Bit absolute values. The offset values are relative to a pre-calculated base frame. This allows MDC to have a compression rate of nearly 50% in good cases compared to MD3. Those rates are achieved when the models vertex coordinates do not travel large distances over several successive key frames. For models whose animated vertex coordinates change across great distances regularly, the rate of compression goes down, as more base frames are needed. In such a case MD3 might be the better choice, as it is more precise and faster to calculate. If the model is not animated, no compression is done and the format is identical to MD3 in terms of rendered result.
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. |
MDC | ||
Name | Description | Type |
header | reference to MDCHeader object. | MDCHeader |
frame_infos | list of MDCFrameInfo objects, size=num_frames. | MDCFrameInfo (*) |
tag_infos | list of MDCTagInfo objects, size=num_tags. | MDCTagInfo (*) |
tags | list of list objects, size=num_frames. Each nested list contains MDCFrameTag objects, size=num_tags. | MDCFrameTag (**) |
surfaces | list of MDCSurface objects, size=num_surfaces. | MDCSurface (*) |
Notes:
Container object. References to all MDC data.
Name | Description | Type |
ident | magic number, ASCII encoded, length 4, reads "IDPC". | 4*ASCII |
version | version number, latest known is 2. | UINT32 |
name | model name, usually its pathname, ASCII encoded, null-terminated, length 64. | 64*ASCII |
flags | not used. | UINT32 |
num_frames | number of animation frames. | UINT32 |
num_tags | number of tags. | UINT32 |
num_surfaces | number of surfaces. | UINT32 |
num_skins | not used. | UINT32 |
ofs_frame_infos | file offset to field of frame infos. | UINT32 |
ofs_tag_infos | file offset to field of tag infos. | UINT32 |
ofs_tags | file offset to field of tags. | UINT32 |
ofs_surfaces | file offset to field of surfaces. | UINT32 |
ofs_end | file offset to end of file. | UINT32 |
Notes:
General information about MDC data. Used mainly to navigate file 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 |
name | name of frame, ASCII encoded, null-terminated, length 16, does not seem to be used. | 16*ASCII |
Notes:
Describes bounding volume information: axially aligned bounding box and bounding sphere.
Name | Description | Type |
name | name of tag, ASCII encoded, null-terminated, length 64. | 64*ASCII |
Notes:
General information about a tag.
Name | Description | Type |
location | location coordinates in this frame. | 3*INT16 |
orientation | orientation as euler angles in frame. Index 0 = pitch, index 1 = yaw, index 2 = roll. | 3*INT16 |
Notes:
A tag in a specific frame.
To convert location and orientation values to float, a scale value is used.
Orientation values are given as euler angles. Inside file they are stored in order of pitch, yaw, roll. Rotation order is: first roll, then pitch, then yaw (XYZ, intrinsic).
Additionally, orientation values should be in range of [-32700, 32700], since the hardcoded scale value is 360/32700. TODO value ranges, normalized.
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 MDCSurfaceHeader object. | MDCSurfaceHeader |
triangles | list of MDCTriangle objects, size=num_triangles. | MDCTriangle (*) |
shaders | list of MDCShader objects, size=num_shaders. | MDCShader (*) |
tex_coords | list of MDCTexCoords objects, size=num_vertices. | MDCTexCoords (*) |
base_vertices | list of list objects, size=num_base_frames. Each nested list contains MDCBaseFrameVertex objects, size=num_vertices. | MDCBaseFrameVertex (**) |
comp_vertices | list of list objects, size=num_comp_frames. Each nested list contains MDCCompFrameVertex objects, size=num_vertices. | MDCCompFrameVertex (**) |
base_frame_indices | reference to MDCBaseFrameIndices object. | MDCBaseFrameIndices |
comp_frame_indices | reference to MDCCompFrameIndices object. | MDCCompFrameIndices |
Notes:
Container object. References surface data.
Background:
Surfaces are described by geometry, color and animation data. A model can consist of multiple surfaces.
Name | Description | Type |
ident | magic number, ASCII encoded, length 4, latest known is 7. | 4*ASCII |
name | surface name, ASCII encoded, null-terminated, length 64. | 64*ASCII |
flags | not used. | UINT32 |
num_comp_frames | number of compressed animation frames. | UINT32 |
num_base_frames | number of base animation frames. | UINT32 |
num_shaders | number of shaders. | UINT32 |
num_vertices | number of vertices. | UINT32 |
num_triangles | number of triangles. | UINT32 |
ofs_triangles | file offset to field of triangles. | UINT32 |
ofs_shaders | file offset to field of shaders. | UINT32 |
ofs_tex_coords | file offset to field of texture coordinates. | UINT32 |
ofs_base_vertices | file offset to field of base vertices. | UINT32 |
ofs_comp_vertices | file offset to field of compressed vertices. | UINT32 |
ofs_base_frame_indices | file offset to field of base vertex indices. | UINT32 |
ofs_comp_frame_indices | file offset to field of compressed vertex indices. | UINT32 |
ofs_end | file offset to end of surface. | UINT32 |
Notes:
General information about a surface. Used mainly to navigate surface data.
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 |
name | shader name, ASCII encoded, null-terminated, length 64. | 64*ASCII |
shader_index | used in-game only. | UINT32 |
Notes:
Shader for a surface. The name of the shader is a reference to either a shader inside a script file, or a path from top level directory to an texture image. Suffixes like .tga or .jpg can be omitted. Search order is: shader, .tga, .jpg. First found will be used.
Background:
Shaders manipulate surface properties. These properties define how the surface interacts with light sources present in a scene.
The term can be a bit confusing, since a shader in this context can either mean a script file (with references to texture images) or an texture image.
Name | Description | Type |
tex_coords | u and v coordinates in UV-space. | 2*F32 |
Notes:
Texture coordinates for a single vertex. UV coordinates are given so that u points right, and v points down. Each value should be in range of [0, 1]. Values outside this range are interpreted as repeating. Each vertex is mapped exactly once to UV-space. Therefore, seams will most likely cause an exporter to add additional vertices along the seam line to enforce bijection. UV-maps are stored once per surface.
Background:
The UV-map is used to color the surface with solid color from a 2D image. Texture coordinates make up UV-space.
Name | Description | Type |
---|---|---|
location | location coordinates in frame. | 3*INT16 |
normal | vertex normal in spherical coordinates. Index 0 = latitude, index 1 = longitude. | 2*UINT8 |
Notes:
Vertex location and normal in a base frame. Each key frame contains a list of vertex locations and normals. Base frames contain the base vertex values to which offset values from compressed frames are added. Base frame indices are encoded in the list of MDCBaseFrameIndices.
Vertex location values from file 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.
Vertex normals manipulate the shading of a surface (for example smooth or flat). They are given in spherical coordinates. Since the coordinates describe the direction of a normal, the radius value is omitted and only latitude and longitude values are given as unsigned 8-bit values from file. To convert them to cartesian space, the upwards vector is first rotated by the latitude value, then by the longitude value. Latitude range is within [0, 180] degrees. Longitude range is within [0, 360) degrees. To obtain the values in degrees, the given range of [0, 255] from file needs to be linearly mapped to [0, 360) degrees.
Name | Description | Type |
---|---|---|
location | location coordinates in frame. | 3*INT8 |
normal | vertex normal in spherical coordinates. Index 0 = latitude, index 1 = longitude. | UINT8 |
Notes:
Vertex location and normal in a compressed frame. Each key frame contains a list of vertex locations and normals. Compressed frames contain offset values which are added to their respective base frame. The base frame for a compressed frame is encoded in the list of MDCBaseFrameIndices.
Vertex location values from file are given as compressed 8-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.
Vertex normals manipulate the shading of a surface (for example smooth or flat). They are given as an index into a list of precalculated normals.
Name | Description | Type |
indices | indices into the list of base_vertices for this surface, size=num_frames. | num_frames*UINT16 |
Notes:
Indices into the list of base frame vertices.
Surfaces hold two seperate lists to store the vertex coordinates either as base or compressed. The indices are used to retrieve the index into the list of base frames for a specific frame.
Name | Description | Type |
indices | indices into the list of comp_vertices for this surface, size=num_frames. | num_frames*UINT16 |
Notes:
Indices into the list of compressed frame vertices.
Surfaces hold two seperate lists to store the vertex coordinates either as base or compressed. The indices are used to retrieve the index into the list of compressed frames for a specific frame. If a frame is not compressed, the retrieved value will be -1.