www.xbdev.net
xbdev - software development
Sunday May 11, 2025
Home | Contact | Support | 3D File Formats The bits and bytes... | 3D File Formats The bits and bytes...
>>
     
 

3D File Formats

The bits and bytes...

 



Animating MD2 - Quake 2 File Format

Author bkenwright@xbdev.net


For some people who are new to the principle of animation and key frames I'll have to just outline the very basics of how it all works, then you can expand on this and learn more.

The animations (frames) can be interpolated using the standard linear interpolation equation: p(t) = p(0) + t( p1 - p0 ).

• t - The current time with 0 being the start and 1 being the end.
• p(t) - The result of the equation with time t.
• p0 - The starting position.
• p1 - The ending position.

Now I want you to write this out on a piece of paper a 100 times... until you know it like the back on your hand, as this is how nearly all animating is done in games... there are a couple of fancier methods but they are very similar in principle to the above one.


/***************************************************************************/
/*                                                                         */
/* File: md2_v1.cpp                                                        */
/* Author: bkenwright@xbdev.net                                            */
/* Date: 10-11-2002                                                        */
/*                                                                         */
/***************************************************************************/

#include <windows.h>
#include <stdio.h>

void abc(char *str)
{
    
FILE *fp fopen("output.txt""a+");
    
fprintf(fp"%s\n"str);
    
fclose(fp);
}

char buff[500];

struct stMd2Header
{
    
int magic;            // The magic number used to identify the file.
    
int version;        // The file version number (must be 8).
    
int skinWidth;        // The width in pixels of our image.
    
int skinHeight;        // The height in pixels of our image.
    
int frameSize;        // The size in bytes the frames are.
    
int numSkins;        // The number of skins associated with the model.
    
int numVertices;    // The number of vertices.
    
int numTexCoords;    // The number of texture coordinates.
    
int numTriangles;    // The number of faces (polygons).
    
int numGlCommands;    // The number of gl commands.
    
int numFrames;        // The number of animated frames.
    
int offsetSkins;    // The offset in the file for the skin data.
    
int offsetTexCoords;// The offset in the file for the texture data.
    
int offsetTriangles;// The offset in the file for the face data.
    
int offsetFrames;    // The offset in the file for the frames data.
    
int offsetGlCommands;// The offset in the file for the gl commands data.
    
int offsetEnd;        // The end of the file offset.
};
stMd2Header Md2Header;

// Some structures to hold or read in data in.
struct stSkins
{
    
char skinName[64];
};

struct stTexCoords
{
    
short uv;
};

struct stTriangles
{
    
float vertex[3];
    
float normal[3];
};

struct stVerts
{
    
byte vertex[3]; // an index reference into the location of our vertexs
    
byte lightNormalIndex// in index into which tex coords to use.
};
struct stFrames
{
    
float scale[3];
    
float translate[3];
    
char strFrameName[16];
    
stVerts *pVerts;
};


int _stdcall WinMain(HINSTANCE hinstanceHINSTANCE nchar *kint l)
{
    
FILE *fopen("pac3D.md2""rb");
    
fread(&Md2Header1sizeof(Md2Header), f);

    
// Allocate memory for our data so we can read it in.
    
stSkinspSkins        = new stSkinsMd2Header.numSkins ];
    
stTexCoordspTexCoords = new stTexCoordsMd2Header.numTexCoords ];
    
stTrianglespTriangles = new stTrianglesMd2Header.numTriangles ];
    
stFramespFrames = new stFramesMd2Header.numFrames ];

    
// -1- Seek to the start of our skins name data and read it in.
    
fseek(fMd2Header.offsetSkinsSEEK_SET);
    
fread(pSkinssizeof(stSkins), Md2Header.numSkinsf);

    
// -2- Seek to the start of our Texture Coord data and read it in.
    
fseek(fMd2Header.offsetTexCoordsSEEK_SET);
    
fread(pTexCoordssizeof(stTexCoords), Md2Header.numTexCoordsf);

    
// -3- Seek to the start of the Triangle(e.g. Faces) data and read that in.
    
fseek(fMd2Header.offsetTrianglesSEEK_SET);
    
fread(pTrianglessizeof(stTriangles), Md2Header.numTrianglesf);

    
// -4- Finally lets read in "one" of the frames, the first one.!
    
fseek(fMd2Header.offsetFramesSEEK_SET);
    
pFrames[0].pVerts = new stVertsMd2Header.numVertices ];
    
fread(pFrames1Md2Header.frameSizef);
    
    
// CONVERSION!  A few things before we can use our read in values,
    // for some reason the Z and Y need to be swapped, as Z is facing up
    // and Y is facing into the screen.
    // Also our texture coordinates values are between 0 and 256, we just
    // divide them all by 256 which makes them between 0 and 1.

    // Swap Z<->Y
    
for(int i=0iMd2Header.numVerticesi++)
    {
        
stVerts tempVert;
        
tempVert.vertex[1] = pFrames[0].pVerts[i].vertex[1]; // y
        
tempVert.vertex[2] = pFrames[0].pVerts[i].vertex[2]; // z

        
pFrames[0].pVerts[i].vertex[1] = tempVert.vertex[2]; // z->y
        
pFrames[0].pVerts[i].vertex[2] = tempVert.vertex[1]; // y->z
    
}

    
// Scale Textures.
    
for (int j=0jMd2Header.numTexCoordsj++)
    {
        
pTexCoords[j].pTexCoords[j].float(Md2Header.skinWidth);
        
pTexCoords[j].pTexCoords[j].float(Md2Header.skinHeight);
    }

    
// Now --Here-- is where we have all our data...if we wanted to could
    // convert of draw it here or something... but since we only wanted
    // to see how its extracted, we just clean up after ourselfs and exit.

    // Tidy up before exiting.
    
delete[] pFrames[0].pVerts;

    
delete[] pSkins;
    
delete[] pTexCoords;
    
delete[] pTriangles;
    
delete[] pFrames;
    
fclose(f);

    return 
1;
}

/***************************************************************************/
/*                                                                         */
/* Well at first it may look like a lot of code above, but in fact its     */
/* really simple once yo7u've gone over it once or twice, all it has done  */
/* is read in the main parts of the file... so that you have in essence,   */
/* extracted the 3D data which you can use to render you 3D model...       */
/* Only a single frame has been extracted, but we'll get to animation later*/
/*                                                                         */
/***************************************************************************/



The following shows the output dump for the key information from the MD2 file.

num keys16 
start
:0 end:39 name:stand 
start
:40 end:45 name:run 
start
:46 end:53 name:attack 
start
:54 end:65 name:pain 
start
:66 end:71 name:jump 
start
:72 end:83 name:flip 
start
:84 end:94 name:salute 
start
:95 end:111 name:taunt 
start
:112 end:122 name:wave 
start
:123 end:134 name:point 
start
:135 end:153 name:crstnd 
start
:154 end:159 name:crwalk 
start
:160 end:168 name:crattack 
start
:169 end:172 name:crpain 
start
:173 end:177 name:crdeath 
start
:178 end:197 name:death</p>

stand01 
stand02 
stand03 
stand04 
stand05 
stand06 
stand07 
stand08 
stand09 
stand10 
stand11 
stand12 
stand13 
stand14 
stand15 
stand16 
stand17 
stand18 
stand19 
stand20 
stand21 
stand22 
stand23 
stand24 
stand25 
stand26 
stand27 
stand28 
stand29 
stand30 
stand31 
stand32 
stand33 
stand34 
stand35 
stand36 
stand37 
stand38 
stand39 
stand40 
run1 
run2 
run3 
run4 
run5 
run6 
attack1 
attack2 
attack3 
attack4 
attack5 
attack6 
attack7 
attack8 
pain101 
pain102 
pain103 
pain104 
pain204 
pain203 
pain202 
pain201 
pain301 
pain302 
pain303 
pain304 
jump1 
jump2 
jump3 
jump4 
jump5 
jump6 
flip01 
flip02 
flip03 
flip04 
flip05 
flip06 
flip07 
flip08 
flip09 
flip10 
flip11 
flip12 
salute01 
salute02 
salute03 
salute04 
salute05 
salute06 
salute07 
salute08 
salute09 
salute10 
salute11 
taunt01 
taunt02 
taunt03 
taunt04 
taunt05 
taunt06 
taunt07 
taunt08 
taunt09 
taunt10 
taunt11 
taunt12 
taunt13 
taunt14 
taunt15 
taunt16 
taunt17 
wave01 
wave03 
wave04 
wave05 
wave06 
wave07 
wave08 
wave09 
wave10 
wave11 
wave12 
point01 
point02 
point03 
point04 
point05 
point06 
point07 
point08 
point09 
point10 
point11 
point12 
crstnd01 
crstnd02 
crstnd03 
crstnd04 
crstnd05 
crstnd06 
crstnd07 
crstnd08 
crstnd09 
crstnd10 
crstnd11 
crstnd12 
crstnd13 
crstnd14 
crstnd15 
crstnd16 
crstnd17 
crstnd18 
crstnd19 
crwalk1 
crwalk2 
crwalk3 
crwalk4 
crwalk5 
crwalk6 
crattack1 
crattack2 
crattack3 
crattack4 
crattack5 
crattack6 
crattack7 
crattack8 
crattack9 
crpain1 
crpain2 
crpain3 
crpain4 
crdeath2 
crdeath2 
crdeath3 
crdeath4 
crdeath5 
death11 
death12 
death13 
death14 
death15 
death16 
death21 
death22 
death23 
death24 
death25 
death26 
death31 
death32 
death33 
death34 
death35 
death36 
death37 
death38


 
Advert (Support Website)

 
 Visitor:
Copyright (c) 2002-2025 xbdev.net - All rights reserved.
Designated articles, tutorials and software are the property of their respective owners.