md2文件格式
md2文件头 |
纹理数据 |
纹理坐标数据 |
三角形数据 |
所有关键帧数据 |
1. md2文件头
2. struct SMD2Header
3. {
4. s32 magic; // four character code "IDP2"
5. s32 version; // must be 8
6. s32 skinWidth; // width of the texture 纹理宽
7. s32 skinHeight; // height of the texture 纹理高
8. s32 frameSize; // size in bytes of an animation frame 每个关键帧的大小
9. s32 numSkins; // number of textures 多少幅纹理
10. s32 numVertices; // total number of vertices 顶点个数
11. s32 numTexcoords; // number of vertices with texture coords 多少个纹理坐标
12. s32 numTriangles; // number of triangles 三角形个数
13. s32 numGlCommands; // number of opengl commands (triangle strip or triangle fan) opengl命令的个数
14. s32 numFrames; // animation keyframe count 关键帧个数
15. s32 offsetSkins; // offset in bytes to 64 character skin names 纹理数据偏移量
16. s32 offsetTexcoords; // offset in bytes to texture coordinate list 纹理坐标数据的偏移
17. s32 offsetTriangles; // offset in bytes to triangle list 三角形数据偏移量
18. s32 offsetFrames; // offset in bytes to frame list 关键帧数据偏移量
19. s32 offsetGlCommands;// offset in bytes to opengl commands
20. s32 offsetEnd; // offset in bytes to end of file
21. }
typedef __int32 s32;
2.纹理数据
3.纹理坐标数据
struct SMD2TextureCoordinate
{
s16 s;
s16 t;
}
typedef __int16 s16;
SMD2TextureCoordinate[header.numTexcoords];
纹理坐标数据其实就是一个坐标数据表,其他地方要用到纹理坐标其实是通过下标来查找到的!这里的纹理坐标还不是真正的纹理坐标。还需通过公式:
X = (s+0.5) *(1.0f/(header.skinWidth));
Y = (t+0.5) *(1.0f/(header.skinHeight));
4.三角形数据
struct SMD2Triangle
{
u16 vertexIndices[3];
u16 textureIndices[3];
} PACK_STRUCT;
typedef unsigned __int16 u16;
verterIndices顶点坐标在顶点数据表里的下标!顶点数据表存储在关键帧数据当中!!
textureIndices纹理坐标在纹理坐标数据表中的下标!这里纹理坐标数据表就是3介绍的纹理坐标数据!
5.关键帧数据
struct SMD2Frame
{
f32 scale[3]; // first scale the vertex position
f32 translate[3]; // then translate the position
c8 name[16]; // the name of the animation that this key belongs to
SMD2Vertex vertices[1]; // vertex 1 of SMD2Header.numVertices
} PACK_STRUCT;
struct SMD2Vertex
{
u8 vertex[3]; // [0] = X, [1] = Z, [2] = Y
u8 lightNormalIndex; // index in the normal table
} PACK_STRUCT;
u8 buffer[MD2_MAX_VERTS*4+128];
SMD2Frame* frame = (SMD2Frame*)buffer;
const s32 MD2_MAX_VERTS = 2048;
1.先介绍SMD2Vertex结构,vertex为点坐标,lightNormalIndex为点法线数据索引,点法线最终是通过一个公式求出来的:
target->Normal = (NormalTable[second->NormalIdx] - NormalTable[first->NormalIdx]) * div
+ NormalTable[first->NormalIdx];
core::vector3df* NormalTable = (core::vector3df*)&Q2_VERTEX_NORMAL_TABLE;
Q2_VERTEX_NORMAL_TABLE这个是一张常量表!
2.介绍SMD2Frame结构,scale[3];这个为放缩倍数,translate[3];为平移量!所以有公式可以求出最终的点:
X = vertices[n].verter[0]*sele[0]+translate[0];
Y = vertices[n].verter[1]*sele[1]+translate[1];
Z = vertices[n].verter[2]*sele[2]+translate[2];
name[16]为该帧的动画名称。
SMD2Vertex vertices[1] 为该帧所有点的首指针。
u8 buffer[MD2_MAX_VERTS*4+128];
SMD2Frame* frame = (SMD2Frame*)buffer;
由于frame长度大小不固定,因为帧的点数不固定,因为这样才用SMD2Vertex vertices[1]来存储首指针。而文件是以最大数量存储的所以这里使用了MD2_MAX_VERTS,它的值为2048,乘以4表示SMD2Vertex结构的长度为4。