#pragma once #include <iostream> #include <d3dx9.h> /**//***************************************************************************/ /**//**/ /**//* File: XMD2Model.h */ /**//* Author: bkenwright@screentoys.net */ /**//* Date: 10-11-2002 */ /**//**/ /**//***************************************************************************/ // This file holds our self contained .md2 (quake2) class for loading in and // displaying our .md2 file in directX3D. 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. }; // Some structures to hold or read in data in. struct stMd2Skins ...{ char skinName[64]; }; struct stMd2TexCoords ...{ short u, v; }; struct stMd2Triangles ...{ short vertexIndex[3]; short texIndex[3]; }; struct stMd2Vertices ...{ float vertex[3]; float normal[3]; }; struct stMd2Frames ...{ char name[16]; stMd2Vertices* pFinalVerts; }; // These two variables are declared in dxdraw.cpp thats why they have the // extern keyword in front of them. extern LPDIRECT3DDEVICE9 g_pd3dDevice; struct stKeyFrame ...{ int start; int end; char szName[16]; }; struct stKey ...{ int numKeys; stKeyFrame *pKey; }; // Our DirectX3D structure definition. struct my_vertex ...{ D3DXVECTOR3 m_vecPos; //位置 D3DCOLOR m_dwDiffuse; //颜色 D3DXVECTOR2 m_vecTex; //纹理坐标 }; /**//***************************************************************************/ /**//**/ /**//* The XMD2Model class, yup its name speaks for itself, it loads the 3D */ /**//* model data from the .md2 file and then we can access its public data */ /**//* variables to use the data. */ /**//**/ /**//***************************************************************************/ class XMD2Model ...{ public: XMD2Model()...{ m_vertex_description = (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); }; ~XMD2Model()...{}; public: bool ImportMD2(char* szFileName, char* szTexName); void Release(); void RenderFrame(); void Animate(UINT iAnimKey); protected: void ReadMD2Data(); void SetUpFrames(); void SetUpDX(); bool Timer(float* t); void SetDXVertices(UINT iAnimKey); FILE* m_fp; protected: stMd2Header m_Md2Header; stMd2Skins *m_pSkins; stMd2Triangles *m_pTriangles; stMd2TexCoords *m_pTexCoords; stMd2Frames *m_pFrames; protected: stKey m_Keys; int m_curFrame; int m_nextFrame; int m_curAnimKey; protected: float m_lastTime; float m_elapsedTime; protected:// dx variables UINT m_vertex_description; IDirect3DTexture9* m_pTexture; IDirect3DVertexBuffer9* m_vb; // vertex buffer }; #include "XMD2Model.h" /**//***************************************************************************/ /**//**/ /**//* The action implimentations of our XMD2Model class. */ /**//**/ /**//***************************************************************************/ bool XMD2Model::ImportMD2(char* szFileName, char* szTexName) ...{ m_fp = fopen(szFileName, "rb"); ReadMD2Data(); SetUpFrames(); SetUpDX(); fclose(m_fp); // Load or textures into our DX. // Use D3DX to create a texture from a file based image if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, szTexName, &m_pTexture ) ) ) ...{ MessageBox(NULL, "加载纹理失败!", NULL, MB_OK); returnfalse; } returntrue; } void XMD2Model::ReadMD2Data() ...{ fread(&m_Md2Header, 1, sizeof(m_Md2Header), m_fp); // Allocate memory for our data so we can read it in. m_pSkins =new stMd2Skins [ m_Md2Header.numSkins ]; m_pTexCoords =new stMd2TexCoords[ m_Md2Header.numTexCoords ]; m_pTriangles =new stMd2Triangles[ m_Md2Header.numTriangles ]; m_pFrames =new stMd2Frames [ m_Md2Header.numFrames ]; // -1- Seek to the start of our skins name data and read it in. fseek(m_fp, m_Md2Header.offsetSkins, SEEK_SET); fread(m_pSkins, sizeof(stMd2Skins), m_Md2Header.numSkins, m_fp); // -2- Seek to the start of our Texture Coord data and read it in. fseek(m_fp, m_Md2Header.offsetTexCoords, SEEK_SET); fread(m_pTexCoords, sizeof(stMd2TexCoords), m_Md2Header.numTexCoords, m_fp); // -3- Seek to the start of the Triangle(e.g. Faces) data and read that in. fseek(m_fp, m_Md2Header.offsetTriangles, SEEK_SET); fread(m_pTriangles, sizeof(stMd2Triangles), m_Md2Header.numTriangles, m_fp); // -4- Finally lets read in "one" of the frames, the first one.! struct stAliasVerts ...{ byte vertex[3]; // an index reference into the location of our vertexs byte lightNormalIndex; // in index into which tex coords to use. }; struct stAliasFrame ...{ float scale[3]; float translate[3]; char name[16]; stAliasVerts aliasVerts[1]; }; unsigned char largebuffer[50000]; stAliasFrame* pTempFrame = (stAliasFrame*) largebuffer; fseek(m_fp, m_Md2Header.offsetFrames, SEEK_SET); for(int iFrame=0; iFrame< m_Md2Header.numFrames; iFrame++) ...{ fread(pTempFrame, 1, m_Md2Header.frameSize, m_fp); // We have read in all the frame data here (into a temporyary!!..eeEKK).. m_pFrames[iFrame].pFinalVerts =new stMd2Vertices[ m_Md2Header.numVertices ]; strcpy( m_pFrames[iFrame].name, pTempFrame->name ); // 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=0; i< m_Md2Header.numVertices; i++) ...{ m_pFrames[iFrame].pFinalVerts[i].vertex[0] = pTempFrame->aliasVerts[i].vertex[0] * pTempFrame->scale[0] + pTempFrame->translate[0]; // x m_pFrames[iFrame].pFinalVerts[i].vertex[2] =-1*(pTempFrame->aliasVerts[i].vertex[1] * pTempFrame->scale[1] + pTempFrame->translate[1]); // z m_pFrames[iFrame].pFinalVerts[i].vertex[1] = pTempFrame->aliasVerts[i].vertex[2] * pTempFrame->scale[2] + pTempFrame->translate[2]; // y } } // Scale Textures. for (int j=0; j< m_Md2Header.numTexCoords; j++) ...{ // WARNING.. you can't put a decimal number into a short...e.g. // you can't put 0.1 into a unsigned short int, it will be changed to 0. /**//* m_pTexCoords[j].u = m_pTexCoords[j].u ;// 256; //float(m_Md2Header.skinWidth); m_pTexCoords[j].v = m_pTexCoords[j].v ;// 256; //float(m_Md2Header.skinHeight); */ } } void XMD2Model::SetUpFrames() ...{ //stand01, stand02... walk01 etc. //First lets see how many key frames there are.. e.g. walk, run, stand etc. m_Keys.numKeys =0; char strName[16] =...{0}; char strLastName[16] =...{0}; char strVeryFirstName[16] =...{0}; for(int iFrame=0; iFrame< m_Md2Header.numFrames; iFrame++) ...{ strcpy(strName, m_pFrames[iFrame].name); int stringLength = strlen( strName ); for(int i=0; i< stringLength; i++) ...{ // a:97 A:65 z:122 Z:90 if( (strName[i] <'A') || (strName[i] >'z' ) ) ...{ // Its an integer if we are here. strName[i] ='