在前面一章里,尽管图形能够在三维空间旋转,但看起来还是不像三维图形。因此,要生成真正三维的图形,必须将二维图形进行组合、建模,组成三维图形。如同QUAKE中的人物,也是由很多多边形或三角形构成表面,再进行各种处理,当组成人物全部外表面的多边形和三角形同时协调的运动时,看起来就像一个真正的人在运动了。
建立一个人物的模型比较复杂一些,我们先从简单的开始。
首先利用四个三角形和一个四边形组合起来建立一个四棱锥,为了便于识别,每个面采用不同的颜色。整个四棱锥的创建在DrawPyramid()中实现。
void DrawPyramid()
{
glBegin(GL_TRIANGLES);
//第一个三角形,红色
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
//第二个三角形,也从棱锥的顶点开始,设置为绿色
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, 0.0f, 1.0f);
//第三个三角形,设置为蓝色
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
glVertex3f(-1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
//第四个三角形,设置为黄色
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
glEnd();
//棱椎下面的四边形/正方形,采用混合颜色
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f); //红色
glVertex3f(1.0f, 0.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f); //绿色
glVertex3f(-1.0f, 0.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f); //蓝色
glVertex3f(-1.0f, 0.0f, -1.0f);
glColor3f(1.0f, 1.0f, 0.0f); //黄色
glVertex3f(1.0f, 0.0f, -1.0f);
glEnd();
}
无论在哪里,立方体都是最典型的三维物体。接下来,我们创建一个立方体。为了简便起见,所有的表面全部用纯色,不使用混合颜色。绘制多个四边形时,可以每一个四边形一对glBegin~glEnd。也可以在一对glBegin~glEnd中绘制全部的四边形,每四个定点定义了一个四边形。如果绘制n个四边形,则需要4n个顶点。其中4i-3,4i-2,4i-1,4i四个顶点定义的是第i个四边形。立方体的六个面则需要24个顶点。
void DrawCube()
{
glBegin(GL_QUADS); // 开始绘制立方体
glColor3f(0.0f,1.0f,0.0f); // 顶面采用蓝色
glVertex3f( 1.0f, 1.0f,-1.0f); // 四边形的右上顶点
glVertex3f(-1.0f, 1.0f,-1.0f); // 四边形的左上顶点
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的左下顶点
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的右下顶点
glColor3f(1.0f,0.5f,0.0f); // 底面采用成黄色
glVertex3f( 1.0f,-1.0f, 1.0f); // 四边形的右上顶点
glVertex3f(-1.0f,-1.0f, 1.0f); // 四边形的左上顶点
glVertex3f(-1.0f,-1.0f,-1.0f); // 四边形的左下顶点
glVertex3f( 1.0f,-1.0f,-1.0f); // 四边形的右下顶点
glColor3f(1.0f,0.0f,0.0f); // 前面,正对着我们的面采用红色
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的右上顶点
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的左上顶点
glVertex3f(-1.0f,-1.0f, 1.0f); // 四边形的左下顶点
glVertex3f( 1.0f,-1.0f, 1.0f); // 四边形的右下顶点
glColor3f(1.0f,1.0f,0.0f); // 后面,背对着我们的面,采用黄色
glVertex3f( 1.0f,-1.0f,-1.0f); // 四边形的右上顶点
glVertex3f(-1.0f,-1.0f,-1.0f); // 四边形的左上顶点
glVertex3f(-1.0f, 1.0f,-1.0f); // 四边形的左下顶点
glVertex3f( 1.0f, 1.0f,-1.0f); // 四边形的右下顶点
glColor3f(0.0f,0.0f,1.0f); // 左面采用蓝色
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的右上顶点
glVertex3f(-1.0f, 1.0f,-1.0f); // 四边形的左上顶点
glVertex3f(-1.0f,-1.0f,-1.0f); // 四边形的左下顶点
glVertex3f(-1.0f,-1.0f, 1.0f); // 四边形的右下顶点
glColor3f(1.0f,0.0f,1.0f); // 右面采用紫色
glVertex3f( 1.0f, 1.0f,-1.0f); // 四边形的右上顶点
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的左上顶点
glVertex3f( 1.0f,-1.0f, 1.0f); // 四边形的左下顶点
glVertex3f( 1.0f,-1.0f,-1.0f); // 四边形的右下顶点
glEnd(); // 立方体绘制结束
}
为了降低场景变化的速度,使我们能够仔细观察程序的运行效果,在glMain()中,增加了Sleep(100)语句,即每次渲染延迟100毫秒。glTranslatef(1.0f, 0.0f, float(-12+10*sin(i)))不停变换四棱锥在Z轴的距离,看起来四棱锥像是被弹簧拉伸一样。glRotatef(angle,1.0f,1.0f,1.0f)使四棱锥和立方体都沿X、Y、Z轴旋转。
void glMain()
{
Sleep(100); //暂停100毫秒
static int angle = 0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
static int i;
glLoadIdentity(); //加载单位矩阵
glTranslatef(1.0f, 0.0f, float(-12+10*sin(i))); // 变换物体离观察者的距离
i++;
glRotatef(angle,1.0f,1.0f,1.0f); // 在XYZ轴上旋转棱锥
DrawPyramid();
glLoadIdentity(); //加载单位矩阵
glTranslatef(-2.5f,0.0f,-8.0f); // 把立方体放在屏幕的左侧
glRotatef(angle,1.0f,1.0f,1.0f); // 在XYZ轴上旋转立方体
DrawCube();
angle++;
SwapBuffers(hDC);
}
图4-1 简单三维模型