MD2关键帧动画

本想用骨骼动画的,无奈.x格式的太过于复杂,而且游戏业里也不怎么用。
只是把它的原理弄明白一些了,但是,我弱小的意志在DirectX SDK那个1000多行的SkinedMesh例子面前顺利地崩溃了,心想,还是先从最基本的关键帧动画开始做吧-_-!


确定文件格式:md2(正好连找都不用找了,老师给了)

以下是我Copy的:

MD2文件格式简介


MD2Quake2中使用的模型文件格式,由于其比较简单,容易实现,所以应用很广,是一种经典的动画模型格式。该文件格式由2部分组成:一部分是文件头,包含了文件ID号、版本号和有关模型的各种数据的起始地址等;另一部分是文件的主体,包含了有关模型的各种数据,如顶点数据、纹理数据、法向量数据等。


MD2是基于关键帧动画的,关键帧插值的数学公式为:

                               p(t) = p(0) + t ( p1 - p0 )

其中:


t — 当前时间。0表示开始,1表示结束;


p(t) — 时间t 时方程的值;


p0 — 起始位置;


p1 — 结束位置。


MD2共有16个关键帧:

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

说白了,一个模型有16个动作,每个动作有很多帧组成,每帧由很多三角形组成一个网络,每个三角形由三个顶点组成,每个顶点由x,y,z三个坐标组成,每个……(再说就欠揍了)
那么怎么让它动呢?知道怎么放电影不?就是一帧帧地画就行了! 

这是我改写的类:

 

#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);
        
return false;
    }


    
return true;
}


void  XMD2Model::ReadMD2Data()
{
    fread(
&m_Md2Header, 1sizeof(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] = '
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值