The first 4 bytes will be "MDL7"
The next 44 bytes make up the header, that corresponds to the
MD7_HEADER struct definition
struct MD7_HEADER
{
char ident[4]; // "MDL7"
long version; // '0', 'sub'- version number;
long bones_num;
long groups_num;
long mdl7data_size; // this file size (head included), except entlump and medlump.
long entlump_size; // entity info size (not yet used, always 0)
long medlump_size; // size of data for MED in bytes
unsigned short md7_bone_stc_size;
unsigned short md7_skin_stc_size;
unsigned short md7_colorvalue_stc_size;
unsigned short md7_material_stc_size;
unsigned short md7_skinpoint_stc_size;
unsigned short md7_triangle_stc_size;
unsigned short md7_mainvertex_stc_size;
unsigned short md7_framevertex_stc_size;
unsigned short md7_bonetrans_stc_size;
unsigned short md7_frame_stc_size;
};
Bones data follows, the
following struct is repeated "bones_num" times:
struct MD7_BONE
{
unsigned short parent_index;
float x,y,z;
//ws, 12.05.2003: bone name mitspeichern...
char name[MAX_BONENAMESIZE];
};
Following the bones data is the groups data, which is really a lot of
stuff. This is repated "groups_num" times.
struct MD7_GROUP
{
unsigned char typ; // = '1' -> triangle based Mesh
long groupdata_size; // size of data for this group in bytes ( MD7_GROUP stc. included).
char name[16];
long numskins;
long num_stpts; // number of 2D skin vertices
long numtris;
long numverts;
long numframes;
};
Then follows skins, the number of which is defined by the "numskins"
field above.
struct MD7_SKIN
{
unsigned char typ; // 0,2,3,10,11,13 (wie vorher) oder 0x80 (1000 0000) oder 0xC0 (1100 0000)
long width;
long height;
char texture_name[16]; //Skin bzw. Texture oder Material Name
};
Once you read the type, you need to decode it because the structure is
followed by the raw skin data and mipmaps if they are included. I don't
know all the types, but they basically define the number of bpp (bits
per pixel) and whether mipmaps are included. Here are the types I've
ran into so far, and their bpp/mipmap setting.
Type
|
BPP
|
Mipmaps
|
2
|
2
|
No
|
3
|
2
|
No
|
4
|
3
|
No
|
5
|
4
|
No
|
10
|
2
|
Yes
|
11
|
2
|
Yes
|
12
|
3
|
Yes
|
13
|
4
|
Yes
|
To calculate the size of the data to read, simply multiply bpp * width
* height. If mipmaps are present, then their are 3 mipmaps that follow,
where the height and witdth are 1/2 the size of the previous image.
For example, if the original image is 256x256 and 3 bpp, the size would
be 196608 bytes.
The first mipmap would be 128x128, for a size of 49152 bytes.
The second mipmap would be 64x64, for a size of 12288 bytes.
The third mipmap would be 32x32, for a size of 3072 bytes.
There are material definitions that might be related to skins, but I
havent ran into any yet.
After the skins are the Skin Vertices, which use the following struct,
and there are "num_stpts" of them.
struct MD7_SKINPOINT
{
float s,t; // 0.0f - 1.0f
};
Then comes the Triangles, which use the following struct and there are
"numtris" of them.
struct MD7_TRIANGLE
{
unsigned short v_index[3]; // vertex index ( MD7_MAINVERTEX list)
unsigned short st_index[3]; // st index ( MD7_SKINPOINT list)
};
Then comes the Vertices, which use the following struct and there are
"numverts" of them.
struct MD7_MAINVERTEX
{
float x,y,z;
unsigned short bone_index;
//ws, 12.05.2003: vertex normal abspeichern
unsigned short normals162index; //float xn,yn,zn;
};
Then comes the Frames, which use the following struct, and there are
"numframes" of them.
struct MD7_FRAME
{
char frame_name[16];
long vertices_count; // length of vertices list
long transmatrix_count; // length of vertices list
};
Before the next frame, there are "vertices_count"
MD7_FRAMEVERTEX structs
followed by "transmatrix_count" MD7_BONETRANS structs.
struct MD7_FRAMEVERTEX
{
float x,y,z;
unsigned short vertindex; // the index of this vertex, 0.. MD7_GROUP::numverts - 1
//ws, 12.05.2003: vertex normal abspeichern
unsigned short normals162index; //float xn,yn,zn;
};
struct MD7_BONETRANS
{
float m [4*4]; // [4*3]
unsigned short bone_index; // the index of this vertex, 0.. MD7_HEADER::bones_num - 1
};
After the frames, is the "medlump" which has a size in bytes of
medlump_size from the header. Its data is opaque, to the best of my
knowledege.