现在的位置: 首页 > 综合 > 正文

OpenGL MD2模型显示

2013年10月15日 ⁄ 综合 ⁄ 共 2644字 ⁄ 字号 评论关闭

 发文章也慢了。3D果然比2D复杂些。

MD2是一系列“帧”组成的动画模型。读取模型的文件包括md2.h,md2.cpp。此外,纹理贴图也被封装成类class Texture,相关文件包括texture.h,texture.lib。md2.cpp代码量有900多行。没必要贴出来。为了读取和显示模型,作者封装了一个类class anmobj。
使用的相关函数:
md2_readModel 读取模型
md2_getAnimationCount 读取动作数量
md2_getAnimationFrames 读取指定动作的起始帧,结束帧
测试时没有正确显示贴图,类Texture没有源文件,也无法调试。我用下面这个函数指定贴图也可以。
void mytexture(UINT textur)
{
 glBindTexture  (GL_TEXTURE_2D, textur);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
再看class anmobj。重要的是md2模型的动画信息,即每个动作的动作名称,起始帧和结束帧。这个类封装了10个士兵的帧数据,坐标数据。条条大路通罗马,这些数据也可以放到其他地方。简化后的anmobj类,如下:
//动作
struct animation
{
 char name[16]; //动作名称
 int  start; //动作起始帧 
 int  end; //动作结束帧 
};
//md2接口
class anmobj
{
public:
 md2_model_t* model[2]; //两个MD2模型
 animation* anim[2]; //各个模型的动画数据
 int  size[2]; //动作数量
 
 //初始化模型
 void   getobj(CString na);
 //读取模型的动画信息
 animation*  animations (md2_model_t* model,int p);
 //绘制模型
 //入参 ID 坐标 帧
 void drawModel(int id,float x,float y,float z,int iframe);

};

void anmobj::getobj(CString na)//
{
 anim[0]=anim[1]=NULL; 
 
 if(model[0]!=NULL)
 {
  delete[] model[0];
  model[0]=NULL;
 }
 
 if(model[1]!=NULL)
 {
  delete[] model[1];
  model[1]=NULL;
 }
 
 model[0]   = md2_readModel(na+"tris.md2");
 
 model[1]   = md2_readModel(na+"weapon.md2");
 

 if(model[0]!=NULL)
 {
  size[0] = md2_getAnimationCount(model[0]);
  // 获取动作序列
  animations (model[0],0);//
 }

 if(model[1]!=NULL)
 {
  size[1] = md2_getAnimationCount(model[1]);
  animations (model[1],1);
 }

}

animation* anmobj::animations (md2_model_t* model,int p)

 if (size[p] == 0)
  return 0;//

 if(anim[p]!=NULL)
  delete[] anim[p];//
 
 anim[p] = new animation[size[p]];//
 //设置该模型的所有动画信息
 for (int i=0; i<size[p]; i++)//
 {
  //得到动画名称
  strcpy (anim[p][i].name,md2_getAnimationName(model,i));//
  //得到动画起始结束帧
  md2_getAnimationFrames(model,i,&anim[p][i].start,&anim[p][i].end);//

 }
 return 0;//
}

//不包含贴图代码
void anmobj::drawModel(int id,float x,float y,float z,int iframe)
{
 glPushAttrib(GL_CURRENT_BIT);
 glPushMatrix();

 glTranslatef(x,y,z);
 //旋转
 glRotatef(-180,0,1,0);
 //缩小
 glScaled(.06f,.06f,.06f);

 //role
 if(model[0]!=NULL && model[0]->header.numFrames>iframe)
 {
  md2_drawModel (model[0],iframe,0,0);
 }
 //weapon
 if(model[1]!=NULL && model[1]->header.numFrames>iframe)
 { 
  md2_drawModel (model[1],iframe,0,0);
 }

 glPopMatrix();
 glPopAttrib();
}

以下是士兵模型的动画数据:
[动作名称 起始帧 结束帧]
stand : 0 , 39
run : 40 , 45
attak : 46 , 53
pain1 : 54 , 57
pain2 : 58 , 61
pain3 : 62 , 65
jump : 66 , 71
......
death1 : 178 , 183
death2 : 184 , 189
death3 : 190 , 197
这些数据可以通过打印anim[0]得到,也可以通过anim[1]看到武器模型的帧信息,如下:
stand : 0 , 39
run : 40 , 45
attak : 46 , 53
pain1 : 54 , 57
pain2 : 58 , 61
......
注意,武器只有173帧(0至172)。

 

感谢《学OPENGL编3D游戏》课件(来自www.gameres.com

 

 

抱歉!评论已关闭.