MD3 is a model format used by the Quake 3 engine as well as its many mods. The format is used mostly for player models and non-structural geometry (non-static models) although it may be used for structural uses. Unlike modern formats, animations are not bone based but instead vertex based and are directly contained within the file.
File format
Data Type
Name
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
MD3 header
Data Type
Name
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 860898377 (0x33504449); as unsigned big-endian 1229213747 (0x49445033).
S32
VERSION
MD3 version number, latest known is 15, but use the constant MD3_VERSION.
U8 * 64
NAME
MD3 name, usually its pathname in the PK3. ASCII character string, NUL-terminated (C-style).
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. There is one set of tags per frame so the total number of tags to read is (NUM_TAGS * NUM_FRAMES).
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.
Frame
General properties of a single animation frame.
Data Type
Name
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)
Tag
An attachment point for another MD3 model.
Data Type
Name
Description
U8 * 64
NAME
Name of Tag object. ASCII character string, NUL-terminated (C-style).
VEC3
ORIGIN
Coordinates of Tag object.
VEC3 * 3
AXIS
3x3 rotation matrix associated with the Tag.
Surface
An animated triangle mesh.
Data Type
Name
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 860898377 (0x33504449); as unsigned big-endian 1229213747 (0x49445033).
U8 * 64
NAME
Name of Surface object. ASCII character string, NUL-terminated (C-style).
S32
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 (s-t texture coordinates) 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.
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.
Shader
Data Type
Name
Description
U8 * 64
NAME
Pathname of shader in the PK3. ASCII character string, NUL-terminated (C-style).
S32
SHADER_INDEX
Shader index number. No idea how this is allocated, but presumably in sequential order of definition.
Triangle
Data Type
Name
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. The triangles have clockwise winding.
TexCoord
Data Type
Name
Description
F32 * 2
ST
s and t texture coordinates, normalized to the range [0, 1]. Values outside the range indicate wraparounds/repeats. Unlike UV coordinates, the origin for texture coordinates is located in the upper left corner (similar to the coordinate system used for computer screens) whereas, in UV mapping, it is placed in the lower left corner. As such, the t value must be flipped to correspond with UV coordinates. See also Left-hand coordinates
Vertex
Data Type
Name
Description
S16 * 3
COORD
x, y, and z coordinates in left-handed 3-space, scaled down by factor 1.0/64. (Multiply by 1.0/64 to obtain original coordinate value.)
U8*2
NORMAL
Zenith and azimuth angles of normal vector. 255 corresponds to 2 pi. See spherical coordinates.
Normals
Encoding
The normal vector uses a spherical coordinate system. Since the normal vector is, by definition, a length of one, only the angles need to be recorded. Each angle is constrained between 0 - 255 to fit in one octet. A normal vector encodes into 16 bits.
(Code in q3tools/q3map/misc_model.c:InsertMD3Model)
lat <- zenith * (2 * pi ) / 255
lng <- azimuth * (2 * pi) / 255
x <- cos ( lat ) * sin ( lng )
y <- sin ( lat ) * sin ( lng )
z <- cos ( lng )