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.
This document does not cover the MD4 file format.
The MD3 format is presented here from a larger scope to smaller ones.
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-octet 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 |
---|---|---|
- | MD3_START | offset of MD3 object. Usually 0, but not guaranteed. |
S32 | IDENT | Magic number. As a string of 4 octets, reads "IDP3"; as unsigned little-endian 1367369843 (0x51806873); as unsigned big-endian 1936228433 (0x73688051). |
S32 | VERSION | MD3 version number, latest known is 15, but use the constant MD3_VERSION |
U8 * MAX_QPATH | NAME | MD3 name, usually its pathname in the PK3. ASCII character string, NUL-terminated (C-style). Current value of MAX_QPATH is 64. |
S32 | FLAGS | ??? |
S32 | NUM_FRAMES | Number of Frame objects, with a maximum of MD3_MAX_FRAMES. Current value of MD3_MAX_FRAMES is 1024. |
S32 | NUM_TAGS | Number of Tag objects, with a maximum of MD3_MAX_TAGS. Current value of MD3_MAX_TAGS is 16. |
S32 | NUM_SURFACES | Number of Surface objects, with a maximum of MD3_MAX_SURFACES. Current value of MD3_MAX_SURFACES is 32. |
S32 | NUM_SKINS | Number of Skin objects. I should note that I have not seen an MD3 using this particular field for anything; this appears to be an artifact from the Quake 2 MD2 format. Surface objects have their own Shader field. |
S32 | OFS_FRAMES | Relative offset from start of MD3 object where Frame objects start. The Frame objects are written sequentially, that is, when you read one Frame object, you do not need to seek() for the next object. |
S32 | OFS_TAGS | Relative offset from start of MD3 where Tag objects start. Similarly written sequentially. |
S32 | OFS_SURFACES | Relative offset from start of MD3 where Surface objects start. Again, written sequentially. |
S32 | OFS_EOF | Relative offset from start of MD3 to the end of the MD3 object. Note there is no offset for Skin objects. |
! | (Frame) | The array of Frame objects usually starts immediately afterwards, but OFS_FRAMES should be used. |
! | (Tag) | The array of Tag objects usually starts immediately after FRAMES, but OFS_TAGS should be used. |
! | (Surface) | The array of Surface objects usually start after TAGS, but OFS_SURFACES should be used. |
- | MD3_END | End of MD3 object. Should match MD3_START. |
Datatype | name/purpose | Description |
---|---|---|
VEC3 | MIN_BOUNDS | First corner of the bounding box. |
VEC3 | MAX_BOUNDS | Second corner of the bounding box. |
VEC3 | LOCAL_ORIGIN | Local origin, usually (0, 0, 0). |
F32 | RADIUS | Radius of bounding sphere. |
U8 * 16 | NAME | Name of Frame. ASCII character string, NUL-terminated (C-style). |
Datatype | name/purpose | Description |
---|---|---|
U8 * MAX_QPATH | NAME | Name of Tag object. ASCII character string, NUL-terminated (C-style). Current value of MAX_QPATH is 64. |
VEC3 | ORIGIN | Coordinates of Tag object. |
VEC3 * 3 | AXIS | Orientation of Tag object. (XXX: more descr) |
Datatype | name/purpose | Description |
---|---|---|
- | SURFACE_START | Offset relative to start of MD3 object. |
S32 | IDENT | Magic number. As a string of 4 octets, reads "IDP3"; as unsigned little-endian 1367369843 (0x51806873); as unsigned big-endian 1936228433 (0x73688051). |
U8 * MAX_QPATH | NAME | Name of Surface object. ASCII character string, NUL-terminated (C-style). Current value of MAX_QPATH is 64. |
S32 | FLAGS | flags? |
S32 | NUM_FRAMES | Number of animation frames. This should match NUM_FRAMES in the MD3 header. |
S32 | NUM_SHADERS | Number of Shader objects defined in this Surface, with a limit of MD3_MAX_SHADERS. Current value of MD3_MAX_SHADERS is 256. |
S32 | NUM_VERTS | Number of Vertex objects defined in this Surface, up to MD3_MAX_VERTS. Current value of MD3_MAX_VERTS is 4096. |
S32 | NUM_TRIANGLES | Number of Triangle objects defined in this Surface, maximum of MD3_MAX_TRIANGLES. Current value of MD3_MAX_TRIANGLES is 8192. |
S32 | OFS_TRIANGLES | Relative offset from SURFACE_START where the list of Triangle objects starts. |
S32 | OFS_SHADERS | Relative offset from SURFACE_START where the list of Shader objects starts. |
S32 | OFS_ST | Relative offset from SURFACE_START where the list of St objects (Texture Coordinates, S-T vertices) starts. |
S32 | OFS_XYZNORMAL | Relative offset from SURFACE_START where the list of Vertex objects (X-Y-Z-N vertices) starts. |
S32 | OFS_END | Relative offset from SURFACE_START to where the Surface object ends. |
! | (Shader) | List of Shader objects usually starts immediate after the Surface header, but use OFS_SHADERS (or rather, OFS_SHADERS+OFS_SURFACES for files). |
! | (Triangle) | List of Triangle objects usually starts immedately after the list of Shader objects, but use OFS_TRIANGLES (+ OFS_SURFACES). |
! | (St) | List of St objects usually starts immedately after the list of Triangle objects, but use OFS_ST (+ OFS_SURFACES). |
! | (XYZNormal) | List of Vertex objects usually starts immediate after the list of St objects, but use OFS_XYZNORMALS (+ OFS_SURFACES). The total number of objects is (NUM_FRAMES * NUM_VERTS). One set of NUM_VERTS Vertex objects describes the Surface in one frame of animation; the first NUM_VERTS Vertex objects describes the Surface in the first frame of animation, the second NUM_VERTEX Vertex objects describes the Surface in the second frame of animation, and so forth. |
- | SURFACE_END | End of Surface object. Should match OFS_END. |
Datatype | name/purpose | Description |
---|---|---|
U8 * MAX_QPATH | NAME | Pathname of shader in the PK3. ASCII character string, NUL-terminated (C-style). Current value of MAX_QPATH is 64. |
S32 | SHADER_INDEX | Shader index number. No idea how this is allocated, but presumably in sequential order of definiton. |
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?) |
(member of Surface) (St)
Datatype | name/purpose | Description |
---|---|---|
F32 * 2 | ST | S-T (U-V?) texture coordinate. I am a little fuzzy on the whole notion of texture coordinates. Values tend to stay within [0.0 .. 1.0], suggesting (0,0) is one corner of the shader/texture and (1,1) is the other far corner of the shader/texture, with values outside the range indicating wraparounds/repeats. Again, I am fuzzy on this notion. |
(member of Surface) (XYZNormal)
Datatype | name/purpose | Description |
---|---|---|
S16 | X | X-coordinate in left-handed 3-space, scaled down by factor MD3_XYZ_SCALE. Current value of MD3_XYZ_SCALE is (1.0/64). (multiply by MD3_XYZ_SCALE to obtain original coordinate value) |
S16 | Y | Y-coordinate in left-handed 3-space, scaled down by factor MD3_XYZ_SCALE. Current value of MD3_XYZ_SCALE is (1.0/64). (multiply by MD3_XYZ_SCALE to obtain original coordinate value) |
S16 | Z | Z-coordinate in left-handed 3-space, scaled down by factor MD3_XYZ_SCALE. Current value of MD3_XYZ_SCALE is (1.0/64). (multiply by MD3_XYZ_SCALE to obtain original coordinate value) |
S16 | NORMAL | Encoded normal vector. See Normals. |
Tags are volumeless vectors. Tags are primarily used in aligning separate MD3 objects in-game. For example, the Tag object in the railgun model is called 'tag_weapon', and the position (and rotation) of this Tag gets aligned with those of the Tag named 'tag_weapon' in the player model, dragging the rest of the railgun model over with the [railgun's] Tag object. The railgun model follows its Tag positions and rotations, which in turn follows the positions and rotations of the player model Tag object (most noticeable in taunt animation). Tags are also used to line up the torso with the legs, and the head with the torso, and so on.
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
lat (latitude) | lng (longitude) |
(Code in q3tools/common/mathlib.c:NormalToLatLong)
Two special vectors are the ones that point up and point down, as these values for z result in a singularity for acos.
The special case of straight-up is:
lng <- atan2 ( y / x) * 255 / (2 * pi)
lat <- acos ( z ) * 255 / (2 * pi)
lng <- lower 8 bits of lng
lat <- lower 8 bits of lat
normal <- (lat shift-left 8) binary-or (lng)
And the special case of straight down is:
normal <- 0
or, shorter:
lat <- 0
lng <- 128
normal <- (lat shift-left 8) binary-or (lng)
normal <- 32768
(Code in q3tools/q3map/misc_model.c:InsertMD3Model)
lat <- ((normal shift-right 8) binary-and 255) * (2 * pi
) / 255
lng <- (normal binary-and 255) * (2 * pi) / 255
x <- cos ( lat ) * sin ( lng )
y <- sin ( lat ) * sin ( lng )
z <- cos ( lng )
.md2 File Format Specification (local mirror: md2-schoenblum.html)