Document last updated 2011 Jul 11.
Much of the information was extracted from the header files provided in the Q3AToolsSource package from Id Software, Inc.
I make no claims as to the accuracy of the information provided within.
I have made attempts to be as accurate as possible, but the information herein is still provided "as-is".
I am not affiliated with Id Software, Inc., nor RSA Data Security, Inc.
Copyrights and trademarks are under the control of their respective holders.
The following information are educated guesses based on my experience with the MD3 format and Blender 3D modeller.
At this time, I don't know of any MD4 file that works in Quake 3.
MD4 is a newer 3D data format that appeared in Quake 3 (PR 1.29?).
MD4 uses "bones animation" (aka "skeletal animation", "skeletal deformation", ???), unlike the explicit vertex listings in MD3 (the 3D version of animated cels).
Potential advantages over MD3 include smaller data files and the potential for more complex animation.
Potential disadvantages include longer load time and/or requiring more processing power.
These particular disadvantages become a moot point with GHz consumer computers.
A separate file format is used to describe maps, the environment of the game: a source MAP file that compiles into a BSP file.
This document does not cover the MAP nor BSP file formats.
The MD4 file format from Id Software, Inc., should not be confused with Message Digest 4 algorithm from RSA Data Security, Inc., also called MD4.
One is a file format, the other is an algorithm ("math formula"), but they are, unfortunately, both called "MD4".
To add to the confusion, the Quake series uses the MD4 algorithm (slightly modified?) as a checksum algorithm for network error-checking and pak file integrity (including the MD4 files).
To clarify, this document covers the MD4 file format, not the MD4 algorithm.
This document does not cover the older MD3 file format.
The Quake series was developed and run on IA32 (x86) machines, using C.
The file format shows many remnants of x86-isms and C-isms (expected byte order, word sizes, data type names, etc.).
Some of these isms spill over into this document.
The MD4 format is presented here from a larger scope to smaller ones.
Disclaimer:
Introduction:
Datatype | name/purpose | Description |
---|---|---|
U8 | char | 8-bit unsigned octet (character). |
S16 | short | little-endian signed 16-bit integer. |
S32 | int | little-endian signed 32-bit integer. |
F32 | float | IEEE-754 32-bit floating-point. |
VEC3 | vec3_t | triplet of F32 in sequence (read 4 octets, make float, read 4, make float, read 4, make float), describing a 3-space vector. |
* | [] | indicates sequential repeat count (homogenous aggregation, array, vector), as in "U8 * 16" to mean a 16-character array (i.e. character string). |
- | file/array offset of which to make special note. | |
! | aggregate complex data that should be described elsewhere. |
Datatype | name/purpose | Description |
---|---|---|
- | MD4_START | offset of MD4 object. Usually 0, but not guaranteed. |
S32 | IDENT | Magic number. As a string of 4 char, reads "IDP4", as unsigned little-endian 1384147059 (0x52806873), as unsigned big endian 1936228434 (0x73688052). |
S32 | VERSION | MD4 version number, latest known is 1, but use the constant MD4_VERSION |
U8 * MAX_QPATH | NAME | MD4 name, usually its pathname in the PK3. ASCII character string, NUL-terminated (C-style). Current value of MAX_QPATH is 64. |
S32 | NUM_FRAMES | Number of Frame objects. Current value of MD3_MAX_FRAMES is 1024. |
S32 | NUM_BONES | Number of Bone objects. Current value of MD4_MAX_BONES is 128. |
S32 | OFS_FRAMES | Relative offset from start of MD4 object where Frame objects start. |
S32 | NUM_LODS | Number of LOD (Level of Detail) surfaces. Current value of MD3_MAX_LODS is 4. |
S32 | OFS_LODS | Relative offset from start of MD4 where LOD objects start. Written sequentially. |
S32 | OFS_EOF | Relative offset from start of MD4 of the end of the MD4 object. |
! | (Frame) | The array of Frame objects, use OFS_FRAMES. |
! | (LOD) | The array of LOD objects, use OFS_TAGS. |
- | MD4_END | End of MD4 object. Should match OFS_EOF. |
Datatype | name/purpose | Description |
---|---|---|
VEC3 | MIN_BOUNDS | First corner of the bounding box. The bounding box encloses all Surface objects for all LOD objects for this frame (that is, encloses the maximum possible volume occupied in this frame). |
VEC3 | MAX_BOUNDS | Second corner of the bounding box. |
VEC3 | LOCAL_ORIGIN | Midpoint of bounds, for bounding sphere (sphere cull?) |
F32 | RADIUS | Radius of bounding (culling?) sphere. |
U8 * 16 | NAME | Name of Frame. ASCII character string, NUL-terminated (C-style). |
! | (Bone) | List of Bone objects. Number of Bone object is determined by NUM_BONES in the MD4 header. This lists all the bones used in this animation frame, and lists their parameters (position/rotation) for this frame. |
Datatype | name/purpose | Description |
---|---|---|
VEC3 | LOC? | 3-space Cartesian coordinate? |
VEC3 | X_AXIS? | 3-space Cartesian vector for X axis? |
VEC3 | Y_AXIS? | 3-space Cartesian vector for Y axis? |
VEC3 | Z_AXIS? | 3-space Cartesian vector for Z axis? |
Datatype | name/purpose | Description |
---|---|---|
I32 | NUM_SURFACES | Number of Surface objects for this LOD object. Current value of MD3_MAX_SURFACES is 32. |
I32 | OFS_SURFACES | Offset of Surface object (XXX: relative to where?) |
I32 | OFS_END | Offset to end of LOD object (next LOD object follow) (XXX: what about final LOD?) |
! | (Surface) | List of Surface objects. |
Datatype | name/purpose | Description |
---|---|---|
- | SURFACE_START | Offset relative to start of MD4 object. |
S32 | IDENT | Magic number. As a string of 4 char, reads "IDP4", as unsigned little-endian 1384147059 (0x52806873), as unsigned big endian 1936228434 (0x73688052). |
U8 * MAX_QPATH | NAME | Name of Surface object. ASCII character string, NUL-terminated (C-style). Current value of MAX_QPATH is 64. |
U8 * MAX_QPATH | NAME | Name of shader to use. ASCII character string, NUL-terminated (C-style). Current value of MAX_QPATH is 64. |
I32 | SHADER_INDEX | Index number of shader. (XXX: how assigned?) |
I32 | OFS_HEADER | Offset of header? Relative to what? ID source states this is a negative number. |
I32 | NUM_VERTS | Number of Vertex objects for this Surface object. Current value of MD3_MAX_VERTS is 4096. |
I32 | OFS_VERTS | Offset of list of Vertex objects (XXX: relative to where?) |
I32 | NUM_TRIANGLES | Number of Triangle objects for this Surface object. Current value of MD3_MAX_TRIANGLES is 8192. |
I32 | OFS_TRIANGLES | Offset of list of Triangle objects (XXX: relatvie to where?) |
I32 | NUM_BONE_REFERENCES | Number of BoneReference objects. This allows the engine to look at only those bones which affect this Surface object, instead of calculating the effects of all Bone objects in the MD4 object. |
I32 | OFS_BONE_REFERENCES | Offset of list of BoneReference objects (XXX: relative to where?) |
I32 | OFS_END | Offset to end of MD4 object (XXX: relative to what?) |
! | (Triangle) | List of Triangle objects, use OFS_TRIANGLES |
! | (Vertex) | List of Vertex objects, use OFS_VERTS |
! | (BoneReference) | List of BoneReference objects, use OFS_BONE_REFERENCES |
- | SURFACE_END | End of Surface object. Should match OFS_END. |
(member of Surface)
BoneReference:
Datatype | name/purpose | Description |
---|---|---|
I32 | INDEX | Index into list of Bone objects. |
Datatype | name/purpose | Description |
---|---|---|
S32 * 3 | INDEXES | List of offset values into the list of Vertex objects that constitute the corners of the Triangle object. Vertex numbers are used instead of actual coordinates, as the coordinates are implicit in the Vertex object. (XXX: does order matter?) |
Datatype | name/purpose | Description |
---|---|---|
VEC3 | VERTEX | 3-space Cartesian coordinate, left-handed geometry. |
VEC3 | NORMAL | Cartesian normal vector, left-handed geometry. |
F32 * 2 | TEXCOORD | Texture coordinate on shader that corresponds to this vertex. |
I32 | NUM_WEIGHTS | Number of bones that influence this Vertex object, that is, number of Weight objects. |
! | (Weight) | List of Weight objects that influence this Vertex object. |
Datatype | name/purpose | Description |
---|---|---|
I32 | BONE_INDEX | Index into list of BoneReference objects. |
F32 | BONE_WIDHT | How much this BoneReference object influences the Vertex object, as a multiplier(?). |
First and foremost, the encoding of the normal vector is eliminated in favor of just using the Cartesian coordinates (yay, no crazy lat/lng calculations!).
Vertex coordinates are not scaled as in MD3, and are now full-blown floating-point values, not 16-bit integers.
LOD (Level Of Detail) sets are mashed into one MD4 object.
Only one shader may be associated with a Surface object. As a result, the list of shaders is eliminated (folded into the Surface object directly), and the texture coordinates are folded directly into the Vertex objects, instead of in a separate list of TexCoords [per shader].