F-16 Thunderbird的飞机模型有3704个独立的三角形,通过Deep Exporation工具的索引模式编制后,共有1898个独立的顶点,2716个法线,2925个纹理坐标。
下面代码展示DrawBody函数,通过遍历索引来为每一个独立的三角形设置并发送纹理,法线和顶点坐标。
void DrawBody(void)
{
int iFace, iPoint;
glBegin(GL_TRIANGLES);
for(iFace = 0; iFace < 3074; iFace++) //遍历每一个三角形
for(iPoint = 0; iPoint < 3; iPoint++) //每一个顶点
{
//设置纹理
glTexCoord2fv(textures[face_indices[iFace][iPoint+6]]);
//设置法线
glNormal3fv(normals[face_indices[iFace][iPoint+3]]);
//设置顶点
glVertex3fv(vertices[face_indices[iFace][iPoint]]);
}
glEnd();
}
当你必须优化模型的存储空间时,这种方法是可以的。例如你在嵌入式中需要节省内存,或者在网络上传输时需要减少流量。但在实时应用中,这种方法的性能非常差,因为每一次都向OpenGL发送一个顶点数据,函数调用的次数也特别多。
显而易见的加速这些代码执行的速度就是使用显示列表的方式。我们把这些代码放到显示列表中。
glNewList(bodyList, GL_COMPILE);
DrawBody();
glEndList();
….
glCallList(bodyList);
下面我们来对比一下显示列表的方式和顶点索引数组的方式。
首先计算一下这些经过包装过的顶点数据的所需要的内存。
// Thunderbird body
extern short face_indicies[3704][9];
extern GLfloat vertices [1898][3];
extern GLfloat normals [2716][3];
extern GLfloat textures [2925][2];
其中face_indicies包含了顶点,法线,和纹理的索引 short face_indicies[3704][9] = {{6,8,7 ,0,1,2 ,0,1,2 }, {6,9,8 ,0,3,1 ,0,3,1 }, {10,8,11 ,4,1,5 ,4,1,5 }....}
face_indicies 需要 3074*9*sizeof(short), 55332字节.类似地计算出vertices要22776字节,normals 32592字节。textures 23400字节。总计134100 约130KB.
在显示列表中,我们需要把这些数据拷贝一份到显示列表(显示列表中的命令和数据会经过优化后,放到命令缓冲区或者图形硬件中)我们没法计算显示列表具体使用多少内存,但可以对顶点的数据进行估算。每个三角形需要3个顶点,3个法线,2个纹理坐标,这些都是浮点数。假设sizeof(float)为4个字节。那么:
3704*3=11112个顶点。每个顶点包含3个成分(x,y,z)所以有11112*3=33336个浮点数值,同理法线有33336个浮点值,纹理坐标有22224个浮点值。把这些加起来再乘以4个字节为335,584个字节。那么加上之前的原始数据有469684个字节 约460kb,不到0.5M.但是我们有11,112个顶点数据需要经过OpenGL的变换管道,这里面包含了许多矩阵运算。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-25412-1.html
拿炮轰