MD3 file format specs


The file structure of the md3 files, as far as we know at this time:

Last Updated October8 1999

!!Warning!!
This document is very technical!
It is assumed that you, the reader, have knowledge of programming C and have basic knowledge of 3d.


Please note that:

Char is a 8bit integer variable type
Short is a 16bit integer variable type
Int is a 32bit integer variable type
Float is a 32bit floating point variable-type
Vec2 is float[2]
Vec3 is float[3]
Mat3x3 is float[3][3]
TexVec is a texture vector or texture u/v coordinate

First start off with the header of the md3 file.

MD3_HEADER:

char ID[4];         //id of file, always "IDP3" 
int  Version;       //i suspect this is a version 
//number, always 15
char FileName[68]; //sometimes left Blank... //65 chars, 32bit aligned ==
//68 chars int BoneFrame_num; //number of BoneFrames int Tag_num; //number of 'tags' per BoneFrame int Mesh_num; //number of meshes/skins
int MaxSkin_num; //maximum number of unique skins
//used in md3 file int HeaderLength; //always equal to the length of
//this header
int Tag_Start; //starting position of //tag-structures
int Tag_End; //ending position of
//tag-structures/starting
//position of mesh-structures int FileSize; //size of file

comments:
If Tag_Start is the same as Tag_End then there are no tags.

Tag_Num is sometimes 0, this is alright it means that there are no tags...
i'm not sure what Tags are used for, altough there is a clear connection
with boneframe, together they're probably used for bone based animations
(where you rotate meshes around eachother to create animations)
.

 

After the header comes a list of tags, if available.
The ammount of tags is the header variable Tag_num times the header variable BoneFrame_num.
So it is highly probably that tags have something to do with boneframes and that objects
can have 0 to n tags 'attached' to them.
Note: We call them 'Tags' because the name in tag usually starts with "tag_".

TAG:

char Name[64];    //name of 'tag' as it's usually 
//called in the md3 files try to
//see it as a sub-mesh/seperate
//mesh-part. //sometimes this 64 string may
//contain some garbage, but
//i've been told this is because //some tools leave garbage in
//those strings, but they ARE
//strings...
Vec3 Postition; //relative position of tag Vec3x3 Rotation; //the direction the tag is facing relative to the rest of the model

comments:
fairly obvious i think, the name is the name of the tag.
"position" is the relative position and "rotation" is the relative rotation to the rest of the model.

After the tags come the 'boneframes', frames in the bone animation.
The number of meshframes is usually identical to this number or simply 1.
The header variable BoneFrame_num holds the ammount of BoneFrame..

BONEFRAME:

//unverified: 
float  Mins[3];
float  Maxs[3];
float  Position[3];
float  scale;
char Creator[16]; //i think this is the
//"creator" name.. //but i'm only guessing.

comments:
Mins, Maxs, and position are very likely to be correct, scale is just a guess.
If you divide the max
imum and minimum xyz values of all the vertices from each meshframe you get
the exact values as mins and maxs..
Position is the exact center of mins and maxs, most of the time anyway.

Creator is very probably just the name of the program or file of which it (the boneframe?) was created..
sometimes it's "(from ASE)" sometimes it's the name of a .3ds file.

 

After the objects in the file are the mesh-headers.
The header variable
Mesh_num holds the ammount of Meshes..
Note that a mesh consists out of the mesh-header, the skins, the triangles, the texture u/v coordinates and finally the vertices.
Each mesh contains that data, and the next mesh will only start after the triangles, meshes etc. of the previous mesh.
To my suprise there are .md3 files that don't have any meshes in them! This is something we need to look into.

MESH:

char ID[4];          //id, must be IDP3 
char Name[68];       //name of mesh 
                     //65 chars, 
//32 bit aligned == 68 chars int MeshFrame_num; //number of meshframes //in mesh int Skin_num; //number of skins in mesh int Vertex_num; //number of vertices int Triangle_num; //number of Triangles int Triangle_Start; //starting position of //Triangle data, relative
//to start of Mesh_Header int HeaderSize; //size of header int TexVec_Start; //starting position of
//texvector data, relative
//to start of Mesh_Header int Vertex_Start; //starting position of
//vertex data,relative
//to start of Mesh_Header int MeshSize; //size of mesh

comments:
Meshframe_num is the number of quake1/quake2 type frames in the mesh.
(these frames work on a morph like way, the vertices are moved from one position to another instead of rotated around eachother like in bone-based-animations)
Skin_num is the number of skins in the md3 file..
These skins are animated.
Triangle_Start, TexVec_Start & Vertex_Start are the number of bytes in the file from the start of the mesh header to the start of the triangle, texvec and vertex data (in that order).

 

After the Mesh header come the skin structures used by the mesh.
The mesh header variable
Skin_num holds the ammount of skins..

SKIN:

char Name[68]; //name of skin used by mesh
               //65 chars, 
//32 bit aligned == 68 chars

comments:
Name holds the name of the texture, relative to the baseq3 path.
Q3 has a peculiar way of handling textures..
The scripts in the /script directory in the baseq3 directory contain scripts that hold information about how some surfaces are drawn and animate (and out of how many layers it consist etc.)
Now the strange thing is, if you remove the ".tga" at the end of the skin, and that name is used in the script files, than that scripted surface is used.
If it isn't mentioned in the script files then the filename is used to load the
tga file.


After the Skins come the triangles.
The mesh header variable
Triangle_num holds the ammount of triangles..

TRIANGLE

int  Triangle[3]; //vertex 1,2,3 of triangle
              

comments:
This is the simplest of structures.
A triangle has 3 points which make up the triangle, each point is a vertex and the three ints that the triangle has point to those vertices.
So you have a list of vertices, for example you have a list of 28 vertices and the triangle uses 3 of them: vertex 1, vertex 14 and vertex 7.
Then the ints contain 1, 14 and 7.

 

After the triangle data come the texture u/v coordinates of each vertex. The mesh header variable Vertex_num holds the ammount of u/v coordinates and vertices..
You have an U/V coordinate per vertex.

TEXTURE U/V COORDINATES:

Vec2  TexVec; //Texture U/V coordinates of vertex 
           

comments:
U/V coordinates are basically the X/Y coordinates on the texture.
This is used by the triangles to know which part of the skin to display.

 

After the texture u/v coordinates come the vertices.
The mesh header variable
Vertex_num holds the ammount of vertices per frame, and the mesh header variable MeshFrame_num contains the ammount of frames in the mesh.
So you have
MeshFrame_num times Vertex_num vertices.

VERTICES:
             
//!!!important!!! signed!
signed short Vec[3]; //vertex X/Y/Z coordinate unsigned char EnvTex[2]; //enviromental mapping texture coordinates
comments:
Vec contains the 3d xyz coordinates of the vertices that form the model.EnvTex contains the texture coordinates for the enviromental mapping.
Why does md3 have a second set of texture coordinates?
Because:
1.
these texture coordinates need to be interpolated when the model changes shape,
2. these texture coordinates are different from the normal texture coordinates but still both need to be used (with shaders you can have multi-layered surfaces, one could be an enviromental map, an other could be a transparent texture)