哈... 最近正着手进行Android 3D游戏... 有些心得会陆续在后面陆续与大家分享.....

首先看看構成MD2的幾種基本結構

typedef struct
{
float X,Y,Z;
}tVector;

這個相信不用多說,凡是3D遊戲編程必然會有的一個結構--矢量;

typedef struct
{
float U;
float V;
}tTexCoord;

typedef struct
{
short U;
short V;
}tUVIndex;

這兩個幾乎一樣的結構,存儲了一個頂點的紋理座標--UV座標;不同之處在於一個是用於讀取MD2的,另一個是放入內存的,因此數據類型不一樣;

typedef struct
{
unsigned short MeshIndex[3];
unsigned short UVIndex[3];
}tMesh;

這個結構表示了一個多邊形,因為MD2是由Triangle構成的,所以每個多邊形需要有三個頂點.而tMesh結構僅僅存放了頂點和UV座標的索引,即需要時再到頂點列表(tVector * VertexList)和UV列表(tTexCoord * UV)查詢;

typedef struct
{
unsigned char Vertex[3];
unsigned char NormalIndex;
}tFramePoint;

這是一個頂點的結構,類似tVector;不同的是數據類型並不是float,unsigned char應該是MD2的規範,讀取時應用這種格式;

MD2模型是有動畫的,當然也就有關鍵幀了.MD2模型應該有一個總的頂點列表,存放所有幀的所有頂點,每一幀的頂點數和多邊形數都是一樣的.每一幀中都有一個頂點列表首地址,各幀的頂點列表內,頂點的順序都是相同的,因此多邊形列表(TriangleIndex)隻需要一個,當要顯示不同幀時,隻需要改變頂點列表的首地址即可顯示;UV列表也是一樣的道理;

typedef struct
{
float Scale[3];
float Translate[3];
char Name[16];
tFramePoint pFramePoint[1];
}tFrame;

這就是一幀的結構了,可以看到pFramePoint[1]即是幀內頂點列表的首地址;而Scale和Translate則用於拉伸移動變換,載入MD2文件時應當先載入一幀,再根據pFramePoint[J],Scale和Translate的關係把幀內每一個頂點數據存放到總的頂點列表內;

typedef struct
{
tTexTypes TextureType;
int Width;
int Height;
long int ScaleWidth;
long int ScaleHeight;
unsigned int TexIde;
unsigned char * Data;
unsigned char * Palette;
}tTexture;

紋理貼圖結構;重點理解的是TexIde與Data,使用gluBuild2DMidmaps()函數進行貼圖的載入;

typedef struct
{
int NumFrames;
int NumVertices;
int NumTriangles;
int NumUV;
int FrameSize;
int TexWidth,TexHeight;
int CurrentFrame;
int NextFrame;
float Interpol;
tMesh * TriIndex;
tTexCoord * UV;
tVector * VertexList;
tTexture * ModelTexture;
}tModelData;

這就是MD2文件的結構了,一開始需要重點理解的是tMesh * TriIndex,tTexCoord * UV,tVector * VertexList和tTexture * ModelTexture這四個結構:TriIndex即多邊形列表,存放了一幀的所有頂點的空間座標索引和UV座標索引,當繪製某個頂點,如第J個頂點,則根據索引值,向幀內頂點列表和UV列表查詢該點信息:

{

....

tVector * VertexList=new tVector[NumFrames*NumVertices];//為頂點列表分配內存空間;

tFrame * Frame=(tFrame *)&Buffer[OffsetFrame+FrameSize*KeyFrame];//填充某幀的結構;

.....

tVector * TmpVertexList=(tVector *)&VertexList[NumVertices*KeyFrame];

glBegin(0X0004)//0X0004是OpenGL的TRIANGLE模式

for(int J=0;J<NumTriangles;J++)

{

glTexCoord2fv((GLfloat *)&UV[TriIndex[J].UVIndex[2]]);

glVertex3fv((GLfloat *)&TmpVertexList[TriIndex[J].MeshIndex[2]]);

glTexCoord2fv((GLfloat *)&UV[TriIndex[J].UVIndex[1]]);

glVertex3fv((GLfloat *)&TmpVertexList[TriIndex[J].MeshIndex[1]]);

glTexCoord2fv((GLfloat *)&UV[TriIndex[J].UVIndex[0]]);

glVertex3fv((GLfloat *)&TmpVertexList[TriIndex[J].MeshIndex[0]]);

}

glEnd();

}

更多相关文章

  1. 转:android下拉列表框 spinner
  2. Android(安卓)-- 系统结构 /system/ 目录下文件夹功能说明
  3. Realm简单使用
  4. 滁州学院首页获取新闻列表
  5. Android图片加载后变小
  6. Android对话形式的列表
  7. android权限列表
  8. Android之ListView
  9. android音乐播放器例子及其源码分析

随机推荐

  1. Sql Server里删除数据表中重复记录的例子
  2. SQL Server的事务操作隔离模式介绍
  3. 在SQL Server中迁移数据的几种方法
  4. 浅谈Transact-SQL
  5. 深入浅出解析mssql在高频,高并发访问时键
  6. 浅析SQL语句中GROUP BY的用法
  7. 生成300个不同的随机数的SQL语句
  8. sql中循环处理当前行数据和上一行数据相
  9. SQL SERVER先判断视图是否存在然后再创建
  10. SQL语句中含有乘号报错的处理办法