mdl file formats

Brian K. Martin (brian@phyast.pitt.edu)
Tue, 5 Mar 1996 10:41:05 -0500 (EST)

From: "Brian K. Martin" <brian@phyast.pitt.edu>
Message-Id: <199603051541.KAA10681@minerva.phyast.pitt.edu>
Subject: mdl file formats
To: quake-editing@nvg.unit.no (quake)
Date: Tue, 5 Mar 1996 10:41:05 -0500 (EST)

Hello, I have gotten tons of mail on the mdl format. So,
against some suggestions, I'm posting some stuff to help yunz
out. Note some info differs from the beta quake specs 3.0.

enjoy.

---------------------------------------------------------
MDL file format
(this is what I know so far)

These are the structs I use to read in file info:
// frame full of verticies
struct vframe{
unsigned char head[12];
unsigned char *v;
};
// file storage structure
struct MDL_FILE{
char filetype[4];
int version;
float xscale,yscale,zscale;
float xoffset,yoffset,zoffset;
float radius;
float f1,f2,f3;
unsigned num_items;
unsigned bitmapw;
unsigned bitmaph;
unsigned num_vertices;
unsigned num_triangles;
unsigned num_frames;
unsigned blank;
unsigned char *bitmap;
unsigned int *vertex;
unsigned int *triangle;
struct vframe *frame;
};

// how to read mdl file

void read_mdl(FILE *in)
{
int i,j,k;

fread(&mdl.filetype,4,1,in);
fread(&mdl.version,4,1,in);
fread(&mdl.xscale,4,1,in);
fread(&mdl.yscale,4,1,in);
fread(&mdl.zscale,4,1,in);
fread(&mdl.xoffset,4,1,in);
fread(&mdl.yoffset,4,1,in);
fread(&mdl.zoffset,4,1,in);
fread(&mdl.radius,4,1,in);
fread(&mdl.f1,4,1,in);
fread(&mdl.f2,4,1,in);
fread(&mdl.f3,4,1,in);
fread(&mdl.num_items,4,1,in);
fread(&mdl.bitmapw,4,1,in);
fread(&mdl.bitmaph,4,1,in);
fread(&mdl.num_vertices,4,1,in);
fread(&mdl.num_triangles,4,1,in);
fread(&mdl.num_frames,1,4,in);
fread(&mdl.blank,1,4,in);

mdl.bitmap = new (unsigned char)[mdl.bitmapw*mdl.bitmaph*mdl.num_items];

for(k=0;k<mdl.num_items;k++)
{
fseek(in,4,SEEK_CUR); // skip a blank word here

for(j=0;j<mdl.bitmaph;j++)
{
for(i=0;i<mdl.bitmapw;i++)
{
fread(mdl.bitmap+(i+mdl.bitmapw*(j+k*mdl.bitmaph)),1,1,in);
}
}
}

mdl.vertex = new (unsigned)[mdl.num_vertices*3];

for(i=0;i<mdl.num_vertices;i++)
{
// if the following is 1, you use the point for the front and back
fread(mdl.vertex+i*3,4,1,in);
// x pixel
fread(mdl.vertex+i*3+1,4,1,in);
// y pixel
fread(mdl.vertex+i*3+2,4,1,in);
}

mdl.triangle = new (unsigned)[mdl.num_triangles*4];

for(i=0;i<mdl.num_triangles;i++)
{
// clockwise/counter-clockwise flag (will need for culling and stuff)
fread(mdl.triangle+i*4,4,1,in);
// point #1
fread(mdl.triangle+i*4+1,4,1,in);
// point #2
fread(mdl.triangle+i*4+2,4,1,in);
// point #3
fread(mdl.triangle+i*4+3,4,1,in);

}

mdl.frame = new (struct vframe)[mdl.num_frames];

for(j=0; j<mdl.num_frames; j++)
{
//I don't know this header format yet
fread(mdl.frame[j].head,1,12,in);
mdl.frame[j].v = new (unsigned char)[mdl.num_vertices*4];

for(i=0;i<mdl.num_vertices;i++)
{
// x position
fread(mdl.frame[j].v+i*4 ,1,1,in);
// y position
fread(mdl.frame[j].v+i*4+1,1,1,in);
// z position
fread(mdl.frame[j].v+i*4+2,1,1,in);
// unknown, maybe a color value, prolly not a light value
fread(mdl.frame[j].v+i*4+3,1,1,in);
}
}

}

This is how I calculate the 3d points, it seems to work ok..

for frame=i
for vertex=j

x=mdl.xscale*(mdl.frame[i].v[j*4]+mdl.f1)+mdl.xoffset;
y=mdl.xscale*(mdl.frame[i].v[j*4+1]+mdl.f2)+mdl.yoffset;
z=mdl.xscale*(mdl.frame[i].v[j*4+2]+mdl.f3)+mdl.zoffset;

I'm sure if your a 3d programmer this is enough info to start.
Of course this stuff may be wrong, but it works. Also note
that some of this stuff differs from quake specs 3.0 (beta).

Later. brian martin