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 maximum
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..
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)