MD3 Format - Give Him a Gun...
Author bkenwright@xbdev.net
Let's examine the prevous demo - but now start attaching objects (like a gun) to the skeleton... what is a game character with out some sort of weapon? (or tool) :)
Output for the implementation in this part.
Download Source Code
md3.h
/***************************************************************************/
/* */
/* File: md3.h */
/* Author: bkenwright@xbdev.net */
/* URL: www.xbdev.net */
/* Date: 25-03-2006 (Easter) */
/* */
/***************************************************************************/
/*
Understanding the Quake3 MD3 File Format
*/
//---------------------------------------------------------------------------
#define SZ_MD3_LOWER_FILE "media\model\sarge\lower.md3"
#define SZ_MD3_LOWER_SKIN_FILE "media\model\sarge\lower_default.skin"
#define SZ_MD3_UPPER_FILE "media\model\sarge\upper.md3"
#define SZ_MD3_UPPER_SKIN_FILE "media\model\sarge\upper_default.skin"
#define SZ_MD3_HEAD_FILE "media\model\sarge\head.md3"
#define SZ_MD3_HEAD_SKIN_FILE "media\model\sarge\head_default.skin"
#define SZ_MD3_TEXTURE_PATH "media\model\sarge\"
#define SZ_MD3_ANIM_FILE "media\model\sarge\animation.cfg"
#define MAX_FILENAME_LENGTH 256
#define MAX_TEXTURES 20
//---------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h> //sprintf(...)
#include <string.h>
#pragma comment(lib, "D3d8.lib" ) //directX 8
#pragma comment(lib, "D3dx8.lib" )
#include <d3dx8.h>
//---------------------------------------------------------------------------
//Saving debug information to a log file
void abc(char *str)
{
/*
FILE *fp = fopen("output.txt", "a+");
fprintf(fp, "%s\n", str);
fclose(fp);
*/
}
//---------------------------------------------------------------------------
typedef unsigned int uint32;
typedef int int32;
typedef unsigned short int uint16;
typedef short int int16;
typedef float float32;
struct stMD3Header
{
char ID[4 ]; // ID of the file is always "IDP3"
int32 Version; // Version number, usually 15
char Filename[68 ]; // Filename, sometimes left blank
int32 numBoneFrames; // Number of BoneFrames
int32 numTags; // Number of 'tags' per BoneFrame
int32 numMeshes; // Number of Meshes/Skins in MaxSkin
int32 numMaxSkins; // Maximum number of unique skins
int32 ofsFrames; // Always equal to the length this header
int32 ofsTagStart; // Starting position of tag structures
int32 ofMeshSurfaces; // Ending position of tag structure
int32 ofEndOfFile; // Size of file
};
struct stBoneFrame
{
float32 mins[3 ];
float32 maxs[3 ];
float32 Position[3 ];
float32 Scale;
char Creator[16 ];
};
struct stAnim
{
int32 FirstFrame;
int32 numFrames;
int32 LoopingFrames;
int32 FPS;
};
struct stSkin
{
char Name[64 ];
int32 index;
};
struct stTag
{
char Name[64 ];
float32 Position[3 ];
float32 Rotation[3 ][3 ];
};
struct stTriangle
{
int32 Vertex[3 ];
};
struct stTexCoord
{
float32 Coord[2 ];
};
struct stVertex // = Record
{
int16 Vertex[3 ];
unsigned char Normal[2 ];
};
struct stMeshHeader
{
char ID[4 ];
char Name[64 ];
int32 flags;
int32 numMeshFrames;
int32 numSkins;
int32 numVertexes;
int32 numTriangles;
int32 ofsTriangles;
int32 ofsSkins;
int32 ofsTexVector;
int32 ofsVertex;
int32 ofsEndMeshSize;
};
struct stMesh
{
stMeshHeader MeshHeader;
stSkin* pSkins;
stTriangle* pTriangle;
stTexCoord* pTexCoord;
stVertex* pVertex;
int texID;
};
struct stM3DModel
{
char m_md3FileName[MAX_FILENAME_LENGTH];
stMD3Header m_md3Header;
stBoneFrame* m_pBoneFrame;
stTag* m_pTags;
stMesh* m_pMeshes;
int m_FPS;
int m_startFrame;
int m_endFrame;
int m_nextFrame;
int m_anim;
float m_poll;
//int m_animLower;
//int m_animUpper;
stM3DModel* m_pLinks[10 ];
int m_currentframe;
};
IDirect3DTexture8* pTextures[MAX_TEXTURES];
int g_NumLoadedTextures = 0 ;
//---------------------------------------------------------------------------
long filesize(FILE *stream)
{
long curpos, length;
curpos = ftell(stream);
fseek(stream, 0L, SEEK_END );
length = ftell(stream);
fseek(stream, curpos, SEEK_SET );
return length;
}
//---------------------------------------------------------------------------
enum
{
BOTH_DEATH1 = 0 ,
BOTH_DEAD1 = 1 ,
BOTH_DEATH2 = 2 ,
BOTH_DEAD2 = 3 ,
BOTH_DEATH3 = 4 ,
BOTH_DEAD3 = 5 ,
TORSO_GESTURE = 6 ,
TORSO_ATTACK = 7 ,
TORSO_ATTACK2 = 8 ,
TORSO_DROP = 9 ,
TORSO_RAISE = 10 ,
TORSO_STAND = 11 ,
TORSO_STAND2 = 12 ,
LEGS_WALKCR = 13 ,
LEGS_WALK = 14 ,
LEGS_RUN = 15 ,
LEGS_BACK = 16 ,
LEGS_SWIM = 17 ,
LEGS_JUMP = 18 ,
LEGS_LAND = 19 ,
LEGS_JUMPB = 20 ,
LEGS_LANDB = 21 ,
LEGS_IDLE = 22 ,
LEGS_IDLECR = 23 ,
LEGS_TURN = 24 ,
MAX_ANIMATIONS
};
//---------------------------------------------------------------------------
extern LPDIRECT3DDEVICE8 g_pD3DDevice;
extern LPD3DXMATRIXSTACK MatrixStack;
void DbgTriangle(IDirect3DDevice8 * pDevice,
D3DXVECTOR3& a, D3DXVECTOR3& b, D3DXVECTOR3& c,
DWORD colour)
{
struct TLVERTEX
{
float x,y,z;
DWORD col;
enum { FVF_TLVERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE};
};
pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
#if (0 ) // no lighting
pDevice->SetTextureStageState(0 ,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
pDevice->SetTextureStageState(0 ,D3DTSS_COLORARG1, D3DTA_DIFFUSE);
#else
g_pD3DDevice->SetTextureStageState(0 , D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pD3DDevice->SetTextureStageState(0 , D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pD3DDevice->SetTextureStageState(0 , D3DTSS_COLOROP, D3DTOP_MODULATE);
#endif
TLVERTEX Vertex[4 ] =
{
// x y z colour
{ a.x, a.y, a.z, colour },
{ b.x, b.y, b.z, colour },
{ c.x, c.y, c.z, colour }
};
#if (DIRECT3D_VERSION >= 0x0900 )
pDevice->SetFVF( TLVERTEX::FVF_TLVERTEX );
#else
pDevice->SetVertexShader( TLVERTEX::FVF_TLVERTEX );
#endif // DIRECT3D_VERSION
pDevice->SetTexture( 0 , NULL );
pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
pDevice->SetRenderState( D3DRS_FILLMODE,
D3DFILL_WIREFRAME );
HRESULT hr = pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 1 , Vertex, sizeof ( TLVERTEX ) );
//g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
}
//---------------------------------------------------------------------
extern void TexSquareA(IDirect3DDevice8 * pDevice,
D3DXVECTOR3 pos,
float w,
float h
);
class CMD3
{
public :
stM3DModel m_lower;
stM3DModel m_upper;
stM3DModel m_head;
stM3DModel m_gun;
stAnim m_Anim[26 ];
CMD3()
{
//m_startFrame = 0;
//m_endFrame = 0;
//m_currentframe = 0;
//poll = 0;
//m_lastUpdate = 0;
}
void Create(/* file names */ )
{
for (int i=0 ; i<MAX_TEXTURES; i++)
{
pTextures[i]=NULL ;
}
InitNormals();
LoadModel(&m_lower, SZ_MD3_LOWER_FILE);
LoadSkin (&m_lower, SZ_MD3_LOWER_SKIN_FILE);
LoadModel(&m_upper, SZ_MD3_UPPER_FILE);
LoadSkin (&m_upper, SZ_MD3_UPPER_SKIN_FILE);
LoadModel(&m_head, SZ_MD3_HEAD_FILE);
LoadSkin (&m_head, SZ_MD3_HEAD_SKIN_FILE);
LoadAnim (SZ_MD3_ANIM_FILE);
LoadModel(&m_gun, "media\model\railgun\railgun.md3" );
LoadSkin (&m_gun, "media\model\railgun\railgun.skin" );
SetAnim(TORSO_STAND);
SetAnim(LEGS_WALK);
memset(m_head.m_pLinks, 0 , sizeof (m_head.m_pLinks));
memset(m_upper.m_pLinks, 0 , sizeof (m_upper.m_pLinks));
memset(m_lower.m_pLinks, 0 , sizeof (m_lower.m_pLinks));
LinkModel(&m_lower, "tag_torso" , &m_upper);
LinkModel(&m_upper, "tag_head" , &m_head);
LinkModel(&m_upper, "tag_weapon" , &m_gun);
m_upper.m_currentframe = m_upper.m_startFrame;
m_head.m_currentframe = m_head.m_startFrame;
m_lower.m_currentframe = m_lower.m_startFrame;
m_upper.m_poll = 0 .0f;
m_head.m_poll = 0 .0f;
m_lower.m_poll = 0 .0f;
}
void Release()
{
ReleaseModel(&m_lower);
ReleaseModel(&m_upper);
ReleaseModel(&m_head);
ReleaseModel(&m_gun);
for (int i=0 ; i<MAX_TEXTURES; i++)
{
if (pTextures[i])
{
pTextures[i]->Release();
pTextures[i]=NULL ;
}
}
}
void Update(float time)
{
UpdateFrame(&m_lower, time);
UpdateFrame(&m_upper, time);
UpdateFrame(&m_head, time);
}
void Render()
{
D3DXMATRIX matCur, matNext;
D3DXMatrixIdentity(&matCur);
matNext = matCur;
DrawSkeleton(&m_lower, &matCur, &matNext);
DrawModel(&m_lower, &matCur, &matCur);
}
protected :
void LinkModel(stM3DModel* from, char * tagnameTo, stM3DModel* modelTo)
{
int numTags = from->m_md3Header.numTags;
stTag *pTags = from->m_pTags;
for (int i=0 ; i<numTags; i++)
{
if ( strcmp(pTags[i].Name, tagnameTo)==0 )
{
from->m_pLinks[i] = modelTo;
}
}
}
void UpdateFrame(stM3DModel* pMod, float time)
{
if (pMod->m_FPS>0 )
{
/*
float deltaFPS = time - (1.0f/pMod->m_FPS);
if ( deltaFPS < 0.0f )
{
_asm
{
int 13
};
}
pMod->m_poll += time + (time - 1.0f/pMod->m_FPS);
*/
pMod->m_poll += time;
}
else
{
pMod->m_poll += time;
}
if (pMod->m_poll > 1 .0f)
{
pMod->m_poll = 0 .0f;
pMod->m_currentframe = pMod->m_nextFrame;
pMod->m_nextFrame++;
if (pMod->m_nextFrame > pMod->m_endFrame)
{
pMod->m_nextFrame = pMod->m_startFrame;
}
}
}
void DrawSkeleton(stM3DModel* pMod, D3DXMATRIX* matCur, D3DXMATRIX* matNext)
{
DrawModel(pMod, matCur, matNext);
stM3DModel** pLinks = pMod->m_pLinks;
stMD3Header* pModHeader = &pMod->m_md3Header;
stTag* pTags = pMod->m_pTags;
int currentFrame = pMod->m_currentframe;
int nextFrame = pMod->m_nextFrame;
//int startFrame = pMod->m_startFrame;
for (int i=0 ; i<pModHeader->numTags; i++)
{
if (pLinks[i]==NULL )
{
continue ;
}
stM3DModel* childMod = pLinks[i];
//stMD3Header* pHeader = &childMod->m_md3Header;
//stTag* pTags = childMod->m_pTags;
float (*Rotation)[3 ];
Rotation = pTags[currentFrame * pModHeader->numTags + i].Rotation; //3x3 mat
float * Position = pTags[currentFrame * pModHeader->numTags + i].Position; //vector3
char * tagName = pTags[currentFrame * pModHeader->numTags + i].Name;
D3DXMATRIX m;
m(0 ,0 ) = Rotation[0 ][0 ];
m(0 ,1 ) = Rotation[0 ][1 ];
m(0 ,2 ) = Rotation[0 ][2 ];
m(0 ,3 ) = 0 ;
m(1 ,0 ) = Rotation[1 ][0 ];
m(1 ,1 ) = Rotation[1 ][1 ];
m(1 ,2 ) = Rotation[1 ][2 ];
m(1 ,3 ) = 0 ;
m(2 ,0 ) = Rotation[2 ][0 ];
m(2 ,1 ) = Rotation[2 ][1 ];
m(2 ,2 ) = Rotation[2 ][2 ];
m(2 ,3 ) = 0 ;
m(3 ,0 ) = Position[0 ];
m(3 ,1 ) = Position[1 ];
m(3 ,2 ) = Position[2 ];
m(3 ,3 ) = 1 ;
float (*RotationNext)[3 ] = pTags[nextFrame * pModHeader->numTags + i].Rotation; //3x3 mat
float * PositionNext = pTags[nextFrame * pModHeader->numTags + i].Position; //vector3
char * tagNameNext = pTags[nextFrame * pModHeader->numTags + i].Name;
D3DXMATRIX mNext;
mNext(0 ,0 ) = RotationNext[0 ][0 ];
mNext(0 ,1 ) = RotationNext[0 ][1 ];
mNext(0 ,2 ) = RotationNext[0 ][2 ];
mNext(0 ,3 ) = 0 ;
mNext(1 ,0 ) = RotationNext[1 ][0 ];
mNext(1 ,1 ) = RotationNext[1 ][1 ];
mNext(1 ,2 ) = RotationNext[1 ][2 ];
mNext(1 ,3 ) = 0 ;
mNext(2 ,0 ) = RotationNext[2 ][0 ];
mNext(2 ,1 ) = RotationNext[2 ][1 ];
mNext(2 ,2 ) = RotationNext[2 ][2 ];
mNext(2 ,3 ) = 0 ;
mNext(3 ,0 ) = PositionNext[0 ];
mNext(3 ,1 ) = PositionNext[1 ];
mNext(3 ,2 ) = PositionNext[2 ];
mNext(3 ,3 ) = 1 ;
//D3DXMATRIX world;
//g_pD3DDevice->GetTransform(D3DTS_WORLD, &world);
//D3DXMATRIX wrld = m * world;
//g_pD3DDevice->SetTransform(D3DTS_WORLD, &wrld);
m = m * (*matCur);
mNext = mNext * (*matNext);
DrawSkeleton(childMod, &m, &mNext);
//g_pD3DDevice->SetTransform(D3DTS_WORLD, &world);
}
}
void DrawModel(stM3DModel* pMod, D3DXMATRIX* matCur, D3DXMATRIX* matNext)
{
DrawModelInt(pMod, pMod->m_currentframe, pMod->m_nextFrame, matCur, matNext, pMod->m_poll);
}
IDirect3DVertexBuffer8* pVertexBuffer;
float aNorms[256 ][256 ][3 ];
void InitNormals()
{
for (int i=0 ; i<255 ; i++)
{
for (int j=0 ; j<255 ; j++)
{
float alpha =2 .0f*i*D3DX_PI/255 ;
float beta =2 .0f*j*D3DX_PI/255 ;
aNorms[i][j][0 ] = cosf(beta) * sinf(alpha);
aNorms[i][j][1 ] = sinf(beta) * sinf(alpha);
aNorms[i][j][2 ] = cosf(alpha);
}
}
}
void DrawModelInt(stM3DModel* pMod, const int currentFrame, const int nexFrame, D3DXMATRIX* matCur, D3DXMATRIX* matNext, float pol)
{
stMD3Header* pHeader = &pMod->m_md3Header;
stMesh* pMeshes = pMod->m_pMeshes;
struct TVERTEX
{
float x,y,z;
float nx,ny,nz;
float u,v;
enum { FVF_TVERTEX = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1};
};
#if (0 ) // no lighting
g_pD3DDevice->SetTextureStageState(0 ,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
g_pD3DDevice->SetTextureStageState(0 ,D3DTSS_COLORARG1, D3DTA_TEXTURE);
#else
g_pD3DDevice->SetTextureStageState(0 , D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pD3DDevice->SetTextureStageState(0 , D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pD3DDevice->SetTextureStageState(0 , D3DTSS_COLOROP, D3DTOP_MODULATE);
#endif
g_pD3DDevice->SetTexture(0 , NULL );
for (int k=0 ; k<pHeader->numMeshes; k++)
{
stMesh* currentMesh = &pMeshes[k];
//char* meshName = currentMesh->MeshHeader.Name;
if (currentMesh->texID>=0 )
{
g_pD3DDevice->SetTexture( 0 , pTextures[currentMesh->texID] );
}
int currentOffsetVertex = currentFrame * currentMesh->MeshHeader.numVertexes;
//interpolation
int nextCurrentOffsetVertex = nexFrame * currentMesh->MeshHeader.numVertexes;
int TriangleNum = currentMesh->MeshHeader.numTriangles;
//TVERTEX * pVertices = new TVERTEX[TriangleNum * 3];
pVertexBuffer = NULL ;
g_pD3DDevice->CreateVertexBuffer(TriangleNum*3 *sizeof (TVERTEX), D3DUSAGE_WRITEONLY, TVERTEX::FVF_TVERTEX ,D3DPOOL_DEFAULT, &pVertexBuffer);
TVERTEX* pVertices;
pVertexBuffer->Lock(0 , TriangleNum*3 *sizeof (TVERTEX), (BYTE**)&pVertices, 0 );
int indx = 0 ;
for (int i=0 ; i<TriangleNum; i++)
{
//D3DXVECTOR3 tri[3];
for (int j=0 ; j<3 ; j++)
{
int currentVertex = currentMesh->pTriangle[i].Vertex[j];
D3DXVECTOR3 vA;
vA.x = (currentMesh->pVertex[currentOffsetVertex + currentVertex].Vertex[0 ] / 64 .0f);
vA.y = (currentMesh->pVertex[currentOffsetVertex + currentVertex].Vertex[1 ] / 64 .0f);
vA.z = (currentMesh->pVertex[currentOffsetVertex + currentVertex].Vertex[2 ] / 64 .0f);
D3DXVECTOR3 nextVA;
nextVA.x = (currentMesh->pVertex[nextCurrentOffsetVertex + currentVertex].Vertex[0 ] / 64 .0f);
nextVA.y = (currentMesh->pVertex[nextCurrentOffsetVertex + currentVertex].Vertex[1 ] / 64 .0f);
nextVA.z = (currentMesh->pVertex[nextCurrentOffsetVertex + currentVertex].Vertex[2 ] / 64 .0f);
D3DXVec3TransformCoord(&vA, &vA, matCur);
D3DXVec3TransformCoord(&nextVA, &nextVA, matNext);
int normU, normV;
normU = currentMesh->pVertex[currentOffsetVertex + currentVertex].Normal[0 ];
normV = currentMesh->pVertex[currentOffsetVertex + currentVertex].Normal[1 ];
D3DXVECTOR3 norm;
norm[0 ] =aNorms[normU][normV][0 ];
norm[1 ] =aNorms[normU][normV][1 ];
norm[2 ] =aNorms[normU][normV][2 ];
normU = currentMesh->pVertex[nextCurrentOffsetVertex + currentVertex].Normal[0 ];
normV = currentMesh->pVertex[nextCurrentOffsetVertex + currentVertex].Normal[1 ];
D3DXVECTOR3 normNext;
normNext[0 ] =aNorms[normU][normV][0 ];
normNext[1 ] =aNorms[normU][normV][1 ];
normNext[2 ] =aNorms[normU][normV][2 ];
float u = currentMesh->pTexCoord[currentVertex].Coord[0 ];
float v = currentMesh->pTexCoord[currentVertex].Coord[1 ];
// Interplated value
float nx = norm[0 ] + pol * (normNext[0 ] - norm[0 ]);
float ny = norm[1 ] + pol * (normNext[1 ] - norm[1 ]);
float nz = norm[2 ] + pol * (normNext[2 ] - norm[2 ]);
float pA0 = vA[0 ] + pol * (nextVA[0 ] - vA[0 ]);
float pA1 = vA[1 ] + pol * (nextVA[1 ] - vA[1 ]);
float pA2 = vA[2 ] + pol * (nextVA[2 ] - vA[2 ]);
//tri[j].x = pA0;
//tri[j].y = pA1;
//tri[j].z = pA2;
pVertices[indx].x = pA0;
pVertices[indx].y = pA1;
pVertices[indx].z = pA2;
pVertices[indx].nx = nx;
pVertices[indx].ny = ny;
pVertices[indx].nz = nz;
pVertices[indx].u = u;
pVertices[indx].v = v;
indx++;
}
//DbgTriangle(g_pD3DDevice, tri[0], tri[1], tri[2], 0xff00ffff );
}
pVertexBuffer->Unlock();
g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
g_pD3DDevice->SetVertexShader(TVERTEX::FVF_TVERTEX);
g_pD3DDevice->SetStreamSource(0 , pVertexBuffer, sizeof (TVERTEX));
g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0 , TriangleNum);
pVertexBuffer->Release();
pVertexBuffer=NULL ;
/*
g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
g_pD3DDevice->SetVertexShader(TVERTEX::FVF_TVERTEX);
g_pD3DDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, TriangleNum, pVertices, sizeof( TVERTEX ) );
delete[] pVertices;
*/
}
}
bool SetAnim(int ani)
{
if ( ani>=0 && ani<=5 )
{
m_lower.m_FPS = m_Anim[ani].FPS;
m_upper.m_FPS = m_Anim[ani].FPS;
m_lower.m_startFrame =m_Anim[ani].FirstFrame;
m_upper.m_startFrame =m_Anim[ani].FirstFrame;
//m_upper.m_currentframe = m_upper.m_startFrame;
//m_lower.m_currentframe = m_lower.m_startFrame;
m_lower.m_endFrame =m_Anim[ani].FirstFrame + m_Anim[ani].numFrames;
m_upper.m_endFrame =m_Anim[ani].FirstFrame + m_Anim[ani].numFrames;
m_lower.m_anim =ani;
m_upper.m_anim =ani;
}
else if ( ani>=6 && ani<=12 )
{
m_upper.m_FPS =m_Anim[ani].FPS;
m_upper.m_nextFrame =m_Anim[ani].FirstFrame;
m_upper.m_startFrame =m_Anim[ani].FirstFrame;
m_upper.m_endFrame =m_Anim[ani].FirstFrame + m_Anim[ani].numFrames;
//m_upper.m_currentframe = m_upper.m_startFrame;
m_upper.m_anim =ani;
}
else if ( ani>=13 && ani<=24 )
{
m_lower.m_FPS =m_Anim[ani].FPS;
m_lower.m_nextFrame =m_Anim[ani].FirstFrame;
m_lower.m_startFrame =m_Anim[ani].FirstFrame;
m_lower.m_endFrame =m_Anim[ani].FirstFrame + m_Anim[ani].numFrames;
//m_lower.m_currentframe = m_lower.m_startFrame;
m_lower.m_anim =ani;
}
else
{
_asm
{
int 13 ;
}
}
return true;
}
bool LoadSkin(stM3DModel* pMod, const char * filename)
{
char buf[256 ];
char MeshName[256 ] = {0 };
char ImageName[256 ] = {0 };
FILE * fp = fopen(filename, "r" );
if (fp==NULL )
{
abc("unable to open file" );
return false;
}
//char firstWord[256];
char * val = NULL ;
int i = 0 ;
do
{
memset(MeshName, 0 , sizeof (MeshName));
val = fgets(buf,256 ,fp);
if (val==NULL )
{
break ;
}
//sscanf(buf, "%s", firstWord);
if (buf[ strlen(buf)-1 ] == '\n' )
{
buf[ strlen(buf)-1 ] = NULL ;
}
if (buf[ strlen(buf)-1 ] == ',' )
{
strcpy(MeshName, buf);
MeshName[ strlen(MeshName)-1 ] = NULL ;
}
if ( strncmp(buf, "tag_" , 4 )==0 ) // tags dont have skins
{
continue ;
}
char *pMeshNameEnd = strchr(buf, ',' );
int meshNameLen = (int )(pMeshNameEnd - buf);
strncpy(MeshName, buf, meshNameLen);
//char* pImageName = strstr(MeshName, ","); // get the full image and path name
//strcpy(ImageName, pImageName); // get name from last / (i.e only filename)
char * pName = strrchr(buf, '/' );
strcpy(ImageName, pName+1 );
for (int i=0 ; i<pMod->m_md3Header.numMeshes; i++)
{
stMesh * pMesh = &pMod->m_pMeshes[i];
if ( strcmp( pMesh->MeshHeader.Name, MeshName)==0 )
{
char TextureName[256 ];
strcpy(TextureName, SZ_MD3_TEXTURE_PATH);
strcat(TextureName, ImageName);
D3DXCreateTextureFromFile(g_pD3DDevice, TextureName, &pTextures[g_NumLoadedTextures]);
pMesh->texID = g_NumLoadedTextures;
g_NumLoadedTextures++;
}
}
// lose the starting /
} while (val);
return true;
}
bool LoadAnim(const char * filename)
{
char buf[256 ];
FILE * fp = fopen(filename, "r" );
if (fp==NULL )
{
abc("unable to open file" );
return false;
}
char firstWord[256 ];
char * val = NULL ;
int i = 0 ;
do
{
strcpy(firstWord, "//" );
val = fgets(buf,256 ,fp);
if (val==NULL )
{
break ;
}
sscanf(buf, "%s" , firstWord);
if (strcmp("sex" , firstWord)==NULL )
{
}
else if (strcmp("headoffset" , firstWord)==NULL )
{
}
else if (strcmp("footsteps" , firstWord)==NULL )
{
}
else if (strcmp("" , firstWord)==NULL )
{
}
else if (strcmp("//" , firstWord)==NULL )
{
}
else
{
char words[4 ][256 ];
sscanf(buf, "%s %s %s %s" , &words[0 ], &words[1 ], &words[2 ], &words[3 ]);
// Extract the values of FirstFrame, numFrames, LoopingFrames, FPS from the String
int FirstFrame = atoi(words[0 ]);
int numFrames = atoi(words[1 ]);
int loopingFrames = atoi(words[2 ]);
int FPS = atoi(words[3 ]);
m_Anim[i].FirstFrame = FirstFrame;
m_Anim[i].numFrames = numFrames;
m_Anim[i].LoopingFrames = loopingFrames;
m_Anim[i].FPS = FPS;
i++;
}
} while (val);
int skip = m_Anim[LEGS_WALKCR].FirstFrame - m_Anim[TORSO_GESTURE].FirstFrame;
for (int i=LEGS_WALKCR; i<MAX_ANIMATIONS; i++)
{
m_Anim[i].FirstFrame = m_Anim[i].FirstFrame - skip;
}
for (int i=0 ; i<MAX_ANIMATIONS; i++)
{
if (m_Anim[i].numFrames > 0 )
{
m_Anim[i].numFrames = m_Anim[i].numFrames - 1 ;
}
}
fclose(fp);
return true;
}
//-----------------------------------------------------------------------
//
// Loads model from a .md3 file
//
//-----------------------------------------------------------------------
bool LoadModel(stM3DModel* pMod, const char * filename)
{
char buf[256 ];
FILE * fp = fopen(filename, "rb" );
if (fp==NULL )
{
abc("unable to open file" );
return false;
}
// Lets get the size of this md3 file
int md3filesize = filesize(fp);
fseek(fp, 0L, SEEK_SET );
if (strlen(filename)>255 )
{
sprintf(buf, "filename is longer than %d" , MAX_FILENAME_LENGTH);
abc(buf);
return false;
}
// copy name
strcpy(pMod->m_md3FileName, filename);
sprintf(buf, "MD3 FileName: %s" , pMod->m_md3FileName);
abc(buf);
sprintf(buf, "FileSize: %d" , md3filesize);
abc(buf);
abc("\n~~MD3 Header~~\n" );
stMD3Header* pHeader = &pMod->m_md3Header;
// read header
fread(pHeader, 1 , sizeof (stMD3Header), fp);
/*
// log debug information to file
sprintf(buf, "ID %c%c%c%c", pHeader->ID[0], pHeader->ID[1], pHeader->ID[2], pHeader->ID[3]);
abc(buf);
sprintf(buf, "Version: %d", pHeader->Version);
abc(buf);
sprintf(buf, "FileName: %s", pHeader->Filename);
abc(buf);
sprintf(buf, "numBoneFrames: %d", pHeader->numBoneFrames);
abc(buf);
sprintf(buf, "numTags: %d", pHeader->numTags);
abc(buf);
sprintf(buf, "numMeshes: %d", pHeader->numMeshes);
abc(buf);
sprintf(buf, "numMaxSkins: %d", pHeader->numMaxSkins);
abc(buf);
sprintf(buf, "ofsFrames: %d", pHeader->ofsFrames);
abc(buf);
sprintf(buf, "ofsTagStart: %d", pHeader->ofsTagStart);
abc(buf);
sprintf(buf, "ofMeshSurfaces: %d", pHeader->ofMeshSurfaces);
abc(buf);
sprintf(buf, "ofEndOfFile (Filesize): %d", pHeader->ofEndOfFile);
abc(buf);
*/
if (strcmp("IDP3" , pHeader->ID)==NULL )
{
sprintf(buf, "Incorrect File Format 'Incorrect ID' ie. ('IDP3')" );
abc(buf);
}
// Allocate memory for all or bones/tags/etc
pMod->m_pBoneFrame = new stBoneFrame[pHeader->numBoneFrames];
pMod->m_pTags = new stTag[pHeader->numBoneFrames * pHeader->numTags];
pMod->m_pMeshes = new stMesh[pHeader->numMeshes];
stBoneFrame* pBoneFrame = pMod->m_pBoneFrame;
stTag* pTags = pMod->m_pTags;
stMesh* pMeshes = pMod->m_pMeshes;
// Lets seek to the start of the bone frames & read boneframe
fseek(fp, pHeader->ofsFrames, SEEK_SET );
fread(pBoneFrame, 1 , pHeader->numBoneFrames*sizeof (stBoneFrame), fp);
/*
sprintf(buf, "\n~~~~BoneFrames: %d~~~~~~", pHeader->numBoneFrames);
abc(buf);
for (int i=0; i<pHeader->numBoneFrames; i++)
{
abc("#");
sprintf(buf, "mins[%.1f,%.1f,%.1f]", m_pBoneFrame[i].mins[0], m_pBoneFrame[i].mins[1], m_pBoneFrame[i].mins[2]);
abc(buf);
sprintf(buf, "maxs[%.1f,%.1f,%.1f]", m_pBoneFrame[i].maxs[0], m_pBoneFrame[i].maxs[1], m_pBoneFrame[i].maxs[2]);
abc(buf);
sprintf(buf, "Position[%.1f,%.1f,%.1f]", m_pBoneFrame[i].Position[0], m_pBoneFrame[i].Position[1], m_pBoneFrame[i].Position[2]);
abc(buf);
sprintf(buf, "Scale[%.1f]", m_pBoneFrame[i].Scale);
abc(buf);
sprintf(buf, "Creator[%s]", m_pBoneFrame[i].Creator);
abc(buf);
}
*/
// Seek to start of tags and read them all in
fseek(fp, pHeader->ofsTagStart, SEEK_SET );
fread(pTags, 1 , pHeader->numBoneFrames * pHeader->numTags*sizeof (stTag), fp);
/*
sprintf(buf, "\n~~~~Tags: %d~~~~~~", pHeader->numTags);
abc(buf);
for (int i=0; i<m_md3Header.numTags; i++)
{
abc("#");
sprintf(buf, "Name[%s]", m_pTags[i].Name);
abc(buf);
sprintf(buf, "Position[%.1f,%.1f,%.1f]", m_pTags[i].Position[0], m_pTags[i].Position[1], m_pTags[i].Position[2]);
abc(buf);
sprintf(buf, "Rotation[%.1f,%.1f,%.1f][...][...]", m_pTags[i].Rotation[0][0], m_pTags[i].Rotation[0][1], m_pTags[i].Rotation[0][2]);
abc(buf);
}
*/
int meshOFS = pHeader->ofMeshSurfaces;
for (int j=0 ; j<pHeader->numMeshes; j++)
{
stMesh * pMesh = &pMeshes[j];
stMeshHeader * pMeshHeader = &(pMesh->MeshHeader);
fseek(fp, meshOFS, SEEK_SET );
// Seek to the start of the mesh data and read it all in
fread(pMeshHeader, 1 , sizeof (stMeshHeader), fp);
// Read in all the sub parts of the mesh data
{
fseek(fp, meshOFS + pMeshHeader->ofsTriangles, SEEK_SET );
pMesh->pTriangle = new stTriangle [pMeshHeader->numTriangles];
fread( pMesh->pTriangle, 1 , pMeshHeader->numTriangles * sizeof (stTriangle), fp);
fseek(fp, meshOFS + pMeshHeader->ofsSkins, SEEK_SET );
pMesh->pSkins = new stSkin [pMeshHeader->numSkins];
fread( pMesh->pSkins, 1 , pMeshHeader->numSkins * sizeof (stSkin), fp);
fseek(fp, meshOFS + pMeshHeader->ofsTexVector, SEEK_SET );
pMesh->pTexCoord = new stTexCoord [pMeshHeader->numVertexes];
fread( pMesh->pTexCoord, 1 , pMeshHeader->numVertexes * sizeof (stTexCoord), fp);
fseek(fp, meshOFS + pMeshHeader->ofsVertex, SEEK_SET );
pMesh->pVertex = new stVertex [pMeshHeader->numVertexes * pMeshHeader->numMeshFrames];
fread( pMesh->pVertex, 1 , pMeshHeader->numMeshFrames * pMeshHeader->numVertexes * sizeof (stVertex), fp);
pMesh->texID = -1 ;
}
meshOFS += pMeshHeader->ofsEndMeshSize;
}//End for meshes
/*
sprintf(buf, "\n~~~~Mesh Surfaces: %d~~~~~~", m_md3Header.numMeshes);
abc(buf);
for (int j=0; j<m_md3Header.numMeshes; j++)
{
abc("#");
stMesh * pMesh = &m_pMeshes[j];
stMeshHeader * pMeshHeader = &(pMesh->MeshHeader);
sprintf(buf, "ID [%c%c%c%c]", pMeshHeader->ID[0], pMeshHeader->ID[1], pMeshHeader->ID[2], pMeshHeader->ID[3]);
abc(buf);
sprintf(buf, "Name [%s]", pMeshHeader->Name);
abc(buf);
sprintf(buf, "flags [0x%.2X]", pMeshHeader->flags);
abc(buf);
sprintf(buf, "numMeshFrames [%d]", pMeshHeader->numMeshFrames);
abc(buf);
sprintf(buf, "numSkins [%d]", pMeshHeader->numSkins);
abc(buf);
sprintf(buf, "numVertexes [%d]", pMeshHeader->numVertexes);
abc(buf);
sprintf(buf, "numVertexes [%d]", pMeshHeader->numVertexes);
abc(buf);
sprintf(buf, "ofsTriangles [%d]", pMeshHeader->ofsTriangles);
abc(buf);
sprintf(buf, "ofsSkins [%d]", pMeshHeader->ofsSkins);
abc(buf);
sprintf(buf, "ofsTexVector [%d]", pMeshHeader->ofsTexVector);
abc(buf);
sprintf(buf, "ofsVertex [%d]", pMeshHeader->ofsVertex);
abc(buf);
sprintf(buf, "ofsEndMeshSize [%d]", pMeshHeader->ofsEndMeshSize);
abc(buf);
// Mesh Triangles
for (int i=0; i<pMeshHeader->numTriangles; i++)
{
stTriangle * pTri = &(pMesh->pTriangle[i]);
sprintf(buf, "Triangle [%d,%d,%d]", pTri->Vertex[0], pTri->Vertex[1], pTri->Vertex[2]);
abc(buf);
}
// Mesh Skins
for (int i=0; i<pMeshHeader->numSkins; i++)
{
stSkin * pSkin = &(pMesh->pSkins[i]);
sprintf(buf, "Skin:Name [%s]", pSkin->Name);
abc(buf);
sprintf(buf, "Skin:Index [%d]", pSkin->index);
abc(buf);
}
for (int i=0; i<pMeshHeader->numVertexes; i++)
{
stTexCoord * pTex = &(pMesh->pTexCoord[i]);
sprintf(buf, "TexCoord:Index [%.1f,%.1f]", pTex->Coord[0], pTex->Coord[1]);
abc(buf);
}
for (int i=0; i<pMeshHeader->numVertexes; i++)
{
stVertex* pVert = &(pMesh->pVertex[i]);
sprintf(buf, "Vertice:Vertex [%d,%d,%d]", pVert->Vertex[0], pVert->Vertex[1], pVert->Vertex[2]);
abc(buf);
}
}
*/
fclose(fp);
/*
for (int j=0; j<m_md3Header.numMeshes; j++)
{
stMesh * pMesh = &m_pMeshes[j];
delete[] pMesh->pSkins;
delete[] pMesh->pTexCoord;
delete[] pMesh->pTriangle;
delete[] pMesh->pVertex;
pMesh->pSkins = NULL;
pMesh->pTexCoord = NULL;
pMesh->pTriangle = NULL;
pMesh->pVertex = NULL;
}
delete[] m_pBoneFrame;
delete[] m_pTags;
delete[] m_pMeshes;
m_pBoneFrame = NULL;
m_pTags = NULL;
m_pMeshes = NULL;
*/
return true;
}// End LoadModel(..)
bool ReleaseModel(stM3DModel* pMod)
{
stMD3Header * pHeader = &pMod->m_md3Header;
stMesh * pMeshes = pMod->m_pMeshes;
for (int j=0 ; j<pHeader->numMeshes; j++)
{
stMesh * pMesh = &pMeshes[j];
delete[] pMesh->pSkins;
delete[] pMesh->pTexCoord;
delete[] pMesh->pTriangle;
delete[] pMesh->pVertex;
pMesh->pSkins = NULL ;
pMesh->pTexCoord = NULL ;
pMesh->pTriangle = NULL ;
pMesh->pVertex = NULL ;
}
stBoneFrame* pBoneFrame = pMod->m_pBoneFrame;
stTag* pTags = pMod->m_pTags;
stMesh *pMshes = pMod->m_pMeshes;
delete[] pBoneFrame;
delete[] pTags;
delete[] pMshes;
pBoneFrame = NULL ;
pTags = NULL ;
pMshes = NULL ;
return true;
}
};
main.cpp
/***************************************************************************/
/* */
/* File: main.cpp */
/* Author: bkenwright@xbdev.net */
/* URL: www.xbdev.net */
/* Date: 19-03-2006 (Easter) */
/* */
/***************************************************************************/
/*
Understanding the Quake3 MD3 File Format
*/
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h> //sprintf(...)
#include <string.h>
// These few lines are compiler directives that include the DirectX library's
// during linking. You could instead inside visual studio goto Project->
// settings menu and under the "Link" tabe add the necessary librarys instead.
#pragma comment(lib, "D3d8.lib" ) //directX 8
#pragma comment(lib, "D3dx8.lib" )
#include <d3dx8.h>
//---------------------------------------------------------------------------
#include "md3.h"
//---------------------------------------------------------------------------
LPDIRECT3D8 g_pD3D = NULL ;
LPDIRECT3DDEVICE8 g_pD3DDevice = NULL ;
static CMD3 md3;
LPD3DXMATRIXSTACK MatrixStack = NULL ;
void init(HWND hWnd)
{
//First of all, create the main D3D object. If it is created successfully we
//should get a pointer to an IDirect3D8 interface.
g_pD3D = Direct3DCreate8(D3D_SDK_VERSION);
//Get the current display mode
D3DDISPLAYMODE d3ddm;
g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
//Create a structure to hold the settings for our device
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof (d3dpp));
//Fill the structure.
//We want our program to be windowed, and set the back buffer to a format
//that matches our current display mode
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
//For depth buffering (e.g.) the z-buffer
d3dpp.BackBufferCount = 1 ;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.EnableAutoDepthStencil = TRUE;
//Create a Direct3D device.
g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESS SING, &d3dpp, &g_pD3DDevice);
/*
g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
g_pD3DDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pD3DDevice->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_DISABLE);
g_pD3DDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_LINEAR);
g_pD3DDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_LINEAR);
//Turn on back face culling. This is becuase we want to hide the back of our polygons
//g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
//Turn off lighting becuase we are specifying that our vertices have colour
g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
*/
//Turn on z-buffering
g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
g_pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
md3.Create();
}
void de_init()
{
md3.Release();
g_pD3DDevice->Release();
g_pD3DDevice = NULL ;
g_pD3D->Release();
g_pD3D = NULL ;
}
void set_camera()
{
// [1] D3DTS_VIEW
D3DXMATRIX v;
g_pD3DDevice->SetTransform(D3DTS_VIEW, D3DXMatrixLookAtLH(&v, &D3DXVECTOR3(0 ,0 ,-90 ),
&D3DXVECTOR3(0 ,0 ,0 ),
&D3DXVECTOR3(0 ,1 ,0 )));
// [2] D3DTS_PROJECTION
D3DXMATRIX p;
g_pD3DDevice->SetTransform( D3DTS_PROJECTION, D3DXMatrixPerspectiveFovLH( &p,
D3DX_PI/4 , 1 .0f, 1 .0f, 1000 .0f));
};
float g_zrot = 0 .0f;
void KeyBoard()
{
if ( GetKeyState(VK_LEFT) & 0x80 ) g_zrot-=0 .05f;
if ( GetKeyState(VK_RIGHT) & 0x80 ) g_zrot+=0 .05f;
}
void setmaterial()
{
D3DMATERIAL8 matMaterial;
D3DCOLORVALUE rgbaDiffuse = {1 .0 , 1 .0 , 1 .0 , 0 .0 }; //RGBA
D3DCOLORVALUE rgbaAmbient = {1 .0 , 1 .0 , 1 .0 , 0 .0 };
D3DCOLORVALUE rgbaSpecular = {0 .0 , 0 .0 , 0 .0 , 0 .0 };
// emissive is for a glow effect
D3DCOLORVALUE rgbaEmissive = {0 .0 , 0 .0 , 0 .0 , 0 .0 };
matMaterial.Diffuse = rgbaDiffuse;
matMaterial.Ambient = rgbaAmbient;
matMaterial.Specular = rgbaSpecular;
matMaterial.Emissive = rgbaEmissive;
matMaterial.Power = 100 .0f;
g_pD3DDevice->SetMaterial(&matMaterial);
}
void setlight()
{
//Set a light up?
D3DLIGHT8 d3dLight;
//Initialize the light structure.
ZeroMemory(&d3dLight, sizeof (D3DLIGHT8));
//Set up a white point light at (0, 0, -10).
d3dLight.Type = D3DLIGHT_POINT;
// Actual colour of the light. (e.g. white).
d3dLight.Diffuse.r = 1 .0f;
d3dLight.Diffuse.g = 1 .0f;
d3dLight.Diffuse.b = 1 .0f;
// Colour when no light hits the object.
d3dLight.Ambient.r = 0 .2f;
d3dLight.Ambient.g = 0 .2f;
d3dLight.Ambient.b = 0 .2f;
// Shiny effect.
d3dLight.Specular.r = 0 .0f;
d3dLight.Specular.g = 0 .0f;
d3dLight.Specular.b = 0 .0f;
d3dLight.Position.x = 0 .0f;
d3dLight.Position.y = 0 .0f;
d3dLight.Position.z = -5 .0f;
d3dLight.Attenuation0 = 1 .0f;
d3dLight.Attenuation1 = 0 .0f;
d3dLight.Attenuation2 = 0 .0f;
d3dLight.Range = 100 .0f;
g_pD3DDevice->SetLight(0 , &d3dLight);
g_pD3DDevice->LightEnable(0 ,TRUE);
//Turn on lighting
g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
g_pD3DDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(40 ,40 ,40 ));
}
// Well if we need to do any drawing or rendering triangles we can do it in here!
void Render()
{
if (!g_pD3DDevice)return ;
//Sleep(10);
KeyBoard();
set_camera();
setmaterial();
setlight();
// Some stuff to setup or graphics card!
//Turn off lighting becuase we are specifying that our vertices have colour
/*
g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
//g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
//g_pD3DDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_DIFFUSE);
g_pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
g_pD3DDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pD3DDevice->SetTexture( 0, NULL );
g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
*/
// Clear the back buffer to a blue color
g_pD3DDevice->Clear( 0 , NULL , D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0 ,0 ,255 ), 1 .0f, 0 );
g_pD3DDevice->BeginScene();
// Just to rotate our shape! See it rotate.
//static float angle = 0.0f;
//angle += 0.001f;
//~~~*~~~~ Create a matrix
//D3DXMATRIX mx;
//~~~*~~~~ Do somthing to our empty matrix.
//D3DXMatrixRotationY(&mx, angle ); // angle in radians...eg. 1 degree = PI/180
//~~~*~~~~ Use the matrix! No use having a matrix if we don't use it!
//g_pD3DDevice->SetTransform(D3DTS_WORLD, &mx);
D3DXMATRIX mm, mx, my, mz, tx;
D3DXMatrixTranslation(&tx, 0 , 0 , 50 );
D3DXMatrixRotationY(&my, 0 );
D3DXMatrixRotationZ(&mz, 3 .14f/1 .1f + g_zrot );
D3DXMatrixRotationX(&mx, -3 .14f/2 .0f );
mm = mz * my * mx * tx;
g_pD3DDevice->SetTransform(D3DTS_WORLD, &mm);
md3.Update(0 .01f);
md3.Render();
g_pD3DDevice->EndScene();
// After rendering the scene we display it.
g_pD3DDevice->Present( NULL , NULL , NULL , NULL );
}
void mainloop()
{
Render();
}
/***************************************************************************/
/* */
/* Handle all messages for the main window here */
/* */
/***************************************************************************/
long _stdcall MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_DESTROY)
{
// inside init.cpp we destroy any directx memory we allocated etc,
// tidy up before leaving.
// TIDY UP DIRECTX HERE BEFORE EXITING HERE!!!!!!!!!!!!!!!!!!!!!!!!!
de_init();
PostQuitMessage(0 );
}
return (long )DefWindowProc(hWnd, uMsg, wParam, lParam);
}
/***************************************************************************/
/* */
/* Program entry point. */
/* */
/***************************************************************************/
int _stdcall WinMain(HINSTANCE i, HINSTANCE, char * k, int )
{
MSG msg;
char szname[] = "DirectX3D - www.xbdev.net - Quake3 MD3" ;
WNDCLASSEX wc = { sizeof (WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL ), NULL , NULL , NULL , NULL ,
szname, NULL };
RegisterClassEx( &wc );
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW,
szname, szname,
WS_OVERLAPPEDWINDOW,//for fullscreen make into WS_POPUP
50 , 50 , 500 ,500 , //for full screen GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
GetDesktopWindow(), NULL , wc.hInstance, NULL );
// Initilise or directX code here!
// INIT OUR DIRECTX ONCE HERE AT THE START HERE!!!!!!!!!!!!!!!!!!!!!!!!!
init(hWnd);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
// Message loop. Note that this has been modified to allow
// us to execute if no messages are being processed.
while (1 )
{
if (PeekMessage(&msg, NULL , 0 , 0 , PM_NOREMOVE))
{
if (!GetMessage(&msg, NULL , 0 , 0 ))
break ;
DispatchMessage(&msg);
}
// Idle-time processing - call our loop function in game.cpp
// CALLING OUR DIRECTX CODE IN GAME.CPP FROM HERE!!!!!!!!!!!!!!!!!
mainloop();
}
return 0 ;
}
//---------------------------------------------------------------------------