利用OPENGL可以绘制三维模型,在指定绘制模式的时候要通过指定光照,以及材质才能使物体看上去有三维的效果,否则,物体看上去就像是一张二维的图片一样。但是除了指定光照跟材质,还需要有一个非常重要的东西,那就是模型上顶点的法线。
一个曲面上的顶点的法线是指经过这一点并且与该点的切平面相垂直的那条直线。然而由于我们的三维模型是用顶点以及几个顶点(一般是三个)所组成的多边形来表示的(我们下面的描述都用三角形来表示),所以一个顶点可能同时属于N个相邻的三角形,每一个三角形有一个垂直它的法线向量,所以一个顶点的法线就可能有很多个。
在OPENGL绘制三角形的时候是通过指定三角形的三个三维顶点的坐标来实现的,如果在指定三个顶点的三维坐标的时候同时指定了该点的法线,那么绘制出来的模型看上去就有三维效果了。然而由于一个顶点的法线有可能有很多个,那么不同的法线指定方式,就会产生不同的绘制效果。
第一种:FLAT方式
FLAT指的是把三角形的三个顶点的发现向量都指定为该三角形所在平面的法线向量,绘制该三角形的代码如下:
glBegin(GL_TRIANGLES);
for (i = 0; i < group->numtriangles; i++) {
triangle = &T(group->triangles[i]);
glNormal3fv(&model->facetnorms[3 * triangle->findex]); //关键语句,将三个顶点的法线同时指定为三角面片的法线
glVertex3fv(&model->vertices[3 * triangle->vindices[0]]);
glVertex3fv(&model->vertices[3 * triangle->vindices[1]]);
glVertex3fv(&model->vertices[3 * triangle->vindices[2]]);
}
glEnd();
这种方式绘制出来的效果能清楚地看到模型上的三角面片,如下图所示:
第二种:SMOOTH方式
SMOOTH指的是对于某一个顶点V,把所有包含V的三角面片的法线相加,然后归一化,将结果作为顶点V的法线,绘制该三角形的代码如下:
glBegin(GL_TRIANGLES);
for (i = 0; i < group->numtriangles; i++) {
triangle = &T(group->triangles[i]);
glNormal3fv(&model->normals[3 * triangle->nindices[0]]); //关键语句:对于每个顶点指定一个法线
glVertex3fv(&model->vertices[3 * triangle->vindices[0]]);
glNormal3fv(&model->normals[3 * triangle->nindices[1]]);
glVertex3fv(&model->vertices[3 * triangle->vindices[1]]);
glNormal3fv(&model->normals[3 * triangle->nindices[2]]);
glVertex3fv(&model->vertices[3 * triangle->vindices[2]]);
}
glEnd();
这种方式绘制出来的模型的外观看上去是光滑的,如下图所示:
注意:要想在OPENGL里面以SMOOTH的方式绘制的话,就不能在OPENGL的初始化函数里面指定绘制方式为FLAT,即如下语句:
glShadeModel (GL_FLAT);