MD2文件格式

来源:互联网 发布:painter mac教程 编辑:程序博客网 时间:2024/05/22 01:40

http://blog.csdn.net/hunter8777/article/details/6386499

 

MD2是一种3D模型网格存储文件格式,最早是由id Software公司为射击游戏Quake II创建的。

现今,很多游戏开发者借鉴于MD2文件格式的易用性来设计自己的模型文件。

本文来详细理解下MD2文件的结构。

 

参考内容《Focus On 3D Models》Chapter 3 Quake II's MD2 Models

 

 

一个MD2文件大致有以下内容

 

 

首先来看下MD2的文件头结构(Header)

[cpp] view plaincopyprint?
  1. struct SMD2Header  
  2. {  
  3.       int m_iMagicNum;  
  4.       int m_iVersion;  
  5.       int m_iSkinWidthPx;  
  6.       int m_iSkinHeightPx;  
  7.       int m_iFrameSize;  
  8.       int m_iNumSkins;  
  9.       int m_iNumVertices;  
  10.       int m_iNumTexCoords;  
  11.       int m_iNumTriangles;  
  12.       int m_iNumGLCommands;  
  13.       int m_iNumFrames;  
  14.       int m_iOffsetSkins;  
  15.       int m_iOffsetTexCoords;  
  16.       int m_iOffsetTriangles;  
  17.       int m_iOffsetFrames;  
  18.       int m_iOffsetGlCommands;  
  19.       int m_iFileSize;  
  20. };  

 

iMagicNum:文件魔数,MD2文件魔数值为IDP2,转换成整型表达为844121161

iVersion:版本号,MD2文件的版本值为8

iSkinWidthPx/iSkinHeightPx:表示纹理的宽和高。虽然不同纹理可以被导入,但每个MD2模型同一时间只能使用一张纹理。

iFrameSize:每个关键帧的字节数

iNumSkins:定义的纹理数量

iNumVertices:每帧的顶点数

iNumTexCoords:纹理坐标数,无须与顶点数相同

iNumTriangles:模型中的三角形个数

iNumGLCommands:OpenGL的命令,如绘制triangle fans和triangle strips。对于导入模型的过程,该参数不是必须的

iNumFrames:帧数。每帧存有动画某个时间步的所有顶点位置信息,即一帧是一个模型当前位置的快照

iOffsetSkins/iOffsetTexCoords/iOffsetTriangles/iOffsetFrames/iOffsetGlCommands:上述信息在文件中的偏移位置

iFileSize:文件总的大小

 

 

内存中存放每帧的数据结构(Frame)如下

[cpp] view plaincopyprint?
  1. struct SMD2Frame  
  2. {  
  3.    float m_fScale[3];  
  4.    float m_fTrans[3];  
  5.    char m_caName[16];  
  6.    SMD2Vert * m_pVertss  
  7.    SMD2Frame()  
  8.    {  
  9.       m_pVerts = 0;  
  10.    }  
  11.    ~SMD2Frame()  
  12.    {  
  13.       if(m_pVerts)  
  14.          delete [] m_pVerts;  
  15.    }  
  16. };  

 

fScale:三个维度上的缩放比例

fTrans:三个维度上的平移

caName:该帧的名字

pVertss:该帧定义的顶点数组

 

 

一般每个顶点结构(Vertices)在内存中简单如下

[cpp] view plaincopyprint?
  1. struct SMD2Vert  
  2. {  
  3.      float m_fVert[3];  
  4. };  

通常顶点结构不是以float存放的,为了节省空间,每一个维度位置信息被压缩至一个byte,在读取之后需要再乘以一个float-point的缩放值,才能得到float的xyz信息。

 

 

三角形面片(Triangles)信息如下

[cpp] view plaincopyprint?
  1. struct SMD2Tri  
  2. {  
  3.    unsigned short m_sVertIndices[3];  
  4.    unsigned short m_sTexIndices[3];  
  5. };  

 

在上述提及的文件头结构体中,iNumTriangles变量记录了模型所需的三角形面片数。

每个面片记录了顶点的索引值,同时还记录纹理坐标的索引,方便进行纹理的映射。

 

 

纹理结构(Texture Coordinates)与顶点类似

[cpp] view plaincopyprint?
  1. struct tMd2TexCoord  
  2. {  
  3.    short u, v;  
  4. };  

 

同样,使用short也是因为考虑空间压缩,需要通过乘以比例系数来获得float值。

 

 

绘制

在进行一帧绘制的时候,就获取当前需要绘制的frame,然后按照该帧定义的顶点集,遍历所有三角形面片的索引,进行绘制,代码片段如下:

[cpp] view plaincopyprint?
  1. glBegin(GL_TRIANGLES);  
  2. for(int i = 0; i < m_Head.m_iNumTriangles; i++)  
  3. {  
  4.    glVertex3fv(m_pFrames[frame].m_pVerts[m_pTriangles[i].m_sVertIndices[0]]);  
  5.    glVertex3fv(m_pFrames[frame].m_pVerts[m_pTriangles[i].m_sVertIndices[1]]);  
  6.    glVertex3fv(m_pFrames[frame].m_pVerts[m_pTriangles[i].m_sVertIndices[2]]);  
  7. }  
  8. glEnd();  

 

在处理动画绘制的时候,遍历每帧,对前后两帧的每个顶点进行线性插值,插值参数t一般与时间点有关。

 

 

小结

MD2是一种含有动画的3D网格模型文件,存放动画的方式是保存关键帧的所有顶点。

原创粉丝点击