Each animation of an MD5 model is its own .md5anim file, and scripted
camera moves are .md5camera files. Both use the same text tokens as the
mesh file: white space between tokens, quoted
names, // and /* */ comments, and vectors in parentheses.
This page follows the loaders in the Doom 3 source code (Anim.cpp and
Camera.cpp).
Animation header
| Keyword | Value | Meaning |
|---|---|---|
MD5Version | integer | Always 10 |
commandline | string | Exporter options; ignored |
numFrames | integer | Frames, at least 1 |
numJoints | integer | Joints, at least 1; matched to the mesh’s joints by name |
frameRate | integer | Frames per second |
numAnimatedComponents | integer | Values in each frame block, 0 to 6 × numJoints |
Hierarchy
hierarchy {, one line per joint, }:
"name" parent flags startIndex
| Field | Type | Meaning |
|---|---|---|
| name | string | Joint name |
| parent | integer | Parent joint, which must come earlier, or −1. Only the first joint may be a root |
| flags | integer | Which of the joint’s six values the frames change; only the six bits below are allowed |
| startIndex | integer | Position in each frame block of the joint’s first changing value |
Flags
| Bit | Value | Name | Value replaced |
|---|---|---|---|
| 0 | 1 | ANIM_TX | Position x |
| 1 | 2 | ANIM_TY | Position y |
| 2 | 4 | ANIM_TZ | Position z |
| 3 | 8 | ANIM_QX | Orientation x |
| 4 | 16 | ANIM_QY | Orientation y |
| 5 | 32 | ANIM_QZ | Orientation z |
A joint with flags 63 changes all six; one with 0 keeps its base frame throughout.
Bounds
bounds {, then one line per frame, ( minx miny minz ) ( maxx maxy
maxz ), then }: a box around the model in each frame.
Base frame
baseframe {, then one line per joint, ( x y z ) ( qx qy qz ),
then }. These are the joint’s position and orientation relative to its
parent (unlike the mesh file, where joints are in model space). As in the mesh file,
w is not stored and Doom 3 takes w = √|1 − qx² − qy² − qz²|.
Frames
For each frame, in order from 0: frame, the frame number (which must
equal its position), {, exactly numAnimatedComponents floats,
and }.
To rebuild joint j in a frame, start from its base frame values. Then, with
k = the joint’s startIndex, go through the flags in the order
x, y, z, qx, qy, qz: for each flag that is set, replace that value with the frame’s
value number k, and add 1 to k. Compute w, then combine each joint
with its parent’s result to get model space, and use those joints to compute the
vertices as on the mesh page.
Worked example: with the hierarchy line "head" 1 56 10, flags 56 =
8 + 16 + 32, so only the three orientation values change, and they are values 10, 11
and 12 of each frame block. The position stays at the base frame’s.
Camera files
An .md5camera file moves the game’s camera for cut scenes.
| Keyword | Value | Meaning |
|---|---|---|
MD5Version | integer | Always 10 |
commandline | string | Exporter options; ignored |
numFrames | integer | Frames, at least 1 |
frameRate | integer | Frames per second, at least 1 |
numCuts | integer | Cuts, 0 to numFrames |
cuts { … } | integers | The frames, from 1 to numFrames − 1, at which the camera jumps instead of moving smoothly from the frame before |
camera { … } | one line per frame | ( x y z ) ( qx qy qz ) fov: position, orientation without w, and horizontal field of view in degrees |