、曲面
在进行复杂物体建模时,使用的光滑曲线、曲面都是由一些线段和多边形逼近而成,并通过少数几个控制点对其进行描述。曲线的定义由glMap1*()函数完成:
void glMap1{fd}(GLenum target,TYPE u1,TYPE u2,GLint stride, GLint order,const TYPE *points);
参数target指出了控制顶点的意义以及在points参数中需要提供多少值;points指针可以指向控制点集、RGBA颜色值或是纹理坐标串等。参数u1和u2限定了变量U的取值范围,通常是从0变化到1;stride表示跨度(在每块存储区内浮点数或双精度数的个数,即两个控制点间的偏移量);最后的参数order为阶数,是次数加1,与控制点数一致。曲线定义后必须再glEnable()函数显式启动后才能起作用,其参数与target保持一致。在使用完毕后通过glDisable()函数将其关闭。曲线坐标可通过glEvalCoord1*()函数进行计算:
void glEvalCoord1{fd}[v](TYPE u);
该函数将产生曲线坐标值并将其绘制。参数u为定义域内的任意值,每调用一次将只产生一个坐标,此坐标值也是任意的。但目前较多采用的是定义均匀间隔曲线坐标值,依次调用glMapGrid1*()和glEvalMesh1()可以获得等间隔值。这两个函数分别用来定义一个一维网格和计算相应的坐标值。
曲面的构造可以是网格线和填充曲面形式,与曲线的构造很类似只是将其扩展为二维而已。下面给出曲面的定义函数:
void glMap2{fd}(GLenum target,TYPE u1,TYPE u2,GLint ustride,GLint uorder,TYPE v1,TYPE v2,GLint vstride,GLint vorder,TYPE points);
这里target的意义与在glMap1*()中的意义相同;(u1,u2),(v1,v2)是二维曲面坐标;其他参数如uorder,vorder,ustride和vstride等的定义都类似于在曲线中的定义;points为控制点坐标。对曲面任意一点的计算可通过函数
void glEvalCoord2{fd}[v](TYPE u,TYPE v);
来完成,通过在定义域内的曲线坐标值u,v来计算曲面内任意一点的世界坐标位置。对于曲面,也可以象曲线一样通过函数来定义均匀间隔的曲面坐标值:
void glMapGrid2{fd}(GLenum nu,TYPE u1,TYPE u2, GLenum nv,TYPE v1,TYPE v2);
void glEvalMesh2(GLenum mode,GLint p1,GLint p2,GLint q1,GLint q2);
第一个函数定义曲面参数空间均匀网格,从u1到u2分为等间隔nu步,从v1到v2分为等间隔nv步,然后由glEvalMesh2()将此网格应用到已经启动的曲面计算上。glEvalMesh2()的mode参数除了可以是GL_POINT和GL_LINE外,也可以是GL_FILL(生成填充空间曲面)。
Bezier曲面的绘制
下面给出一个通过定义曲面和均匀网格绘制一个具有光照和明暗处理效果的Bezier曲面(图1)的部分主要代码:
GLfloat ctrlpoints = {// 控制点坐标
{{-2.5, 1.5, 2.0}, {0.5, -1.5, 2.0},
{0.5, -1.5, -1.0}, {1.5, -1.5, 2.0}},
{{-1.5, -0.5, 1.0}, {0.5, 1.5, 2.0},
{0.5, 0.5, 1.0}, {1.5, -0.5, -1.0}},
{{-1.5, 0.5, 2.0}, {-1.5, 0.5, 1.0},
{0.5, 0.5, 3.0}, {1.5, -1.5, 1.5}},
{{-1.5, 1.5, -2.0}, {-0.5, 1.5, -2.0},
{0.5, 0.5, 1.0}, {1.5, 1.5, -1.0}}};
void Init()
{
glClearColor(0.0, 0.0, 0.0, 1.0); // 清屏
glEnable(GL_DEPTH_TEST); // 激活深度比较
glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12, 4, &ctrlpoints[0][0][0]);// 定义曲面
glEnable(GL_MAP2_VERTEX_3); // 启用曲面
glEnable(GL_AUTO_NORMAL); // 启用曲面法向向量计算
glEnable(GL_NORMALIZE); // 启用法向归一化
glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0); // 定义参数空间的均匀网格
GLfloat ambient = {0.4, 0.6, 0.2, 1.0}; // 初始化光照、材质的过程
GLfloat position = {0.0, 1.0, 3.0, 1.0};
GLfloat mat_diffuse = {0.8, 0