www.xbdev.net xbdev - software development
Friday March 22, 2019
home | about | contact | Donations

     
 

3D File Formats

The bits and bytes...

 

MD3 Format - Give him a gun...
Author bkenwright@xbdev.net

When ....

 

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;
}
//---------------------------------------------------------------------------

 

 

 
 Visitor: 9534626  { 209.237.238.175 } Copyright (c) 2002-2017 xbdev.net - All rights reserved.
Designated tutorial and software are the property of their respective owners.