转自【翻译】NeHe OpenGL 教程

前言

声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改。对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢。

第五课:3D空间

3D空间:

我们使用多边形和四边形创建3D物体,在这一课里,我们把三角形变为立体的金子塔形状,把四边形变为立方体。

在上节课的内容上作些扩展,我们现在开始生成真正的3D对象,而不是象前两节课中那样3D世界中的2D对象。我们给三角形增加一个左侧面,一个右侧面,一个后侧面来生成一个金字塔(四棱锥)。给正方形增加左、右、上、下及背面生成一个立方体。

我们混合金字塔上的颜色,创建一个平滑着色的对象。给立方体的每一面则来个不同的颜色。

int DrawGLScene(GLvoid)      // 此过程中包括所有的绘制代码

{

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕及深度缓存

 glLoadIdentity();     // 重置模型观察矩阵

 glTranslatef(-1.5f,0.0f,-6.0f);    // 左移 1.5 单位,并移入屏幕 6.0

glRotatef(rtri,0.0f,1.0f,0.0f);    // 绕Y轴旋转金字塔

glBegin(GL_TRIANGLES);     // 开始绘制金字塔的各个面

有些人可能早已在上节课中的代码上尝试自行创建3D对象了。但经常有人来信问我:"我的对象怎么不会绕着其自身的轴旋转?看起来总是在满屏乱转。"要让您的对象绕自身的轴旋转,您必须让对象的中心坐标总是(0.0f,0,0f,0,0f)。

下面的代码创建一个绕者其中心轴旋转的金字塔。金字塔的上顶点高出原点一个单位,底面中心低于原点一个单位。上顶点在底面的投影位于底面的中心。

注意所有的面-三角形都是逆时针次序绘制的。这点十分重要,在以后的课程中我会作出解释。现在,您只需明白要么都逆时针,要么都顺时针,但永远不要将两种次序混在一起,除非您有足够的理由必须这么做。

我们开始画金字塔的前侧面。因为所有的面都共享上顶点,我们将这点在所有的三角形中都设置为红色。底边上的两个顶点的颜色则是互斥的。前侧面的左下顶点是绿色的,右下顶点是蓝色的。这样相邻右侧面的左下顶点是蓝色的,右下顶点是绿色的。这样四边形的底面上的点的颜色都是间隔排列的。

glColor3f(1.0f,0.0f,0.0f);   // 红色

  glVertex3f( 0.0f, 1.0f, 0.0f);   // 三角形的上顶点 (前侧面)

  glColor3f(0.0f,1.0f,0.0f);   // 绿色

  glVertex3f(-1.0f,-1.0f, 1.0f);   // 三角形的左下顶点 (前侧面)

  glColor3f(0.0f,0.0f,1.0f);   // 蓝色

  glVertex3f( 1.0f,-1.0f, 1.0f);   // 三角形的右下顶点 (前侧面)

现在绘制右侧面。注意其底边上的两个顶点的X坐标位于中心右侧的一个单位处。顶点则位于Y轴上的一单位处,且Z坐标正好处于底边的两顶点的Z坐标中心。右侧面从上顶点开始向外侧倾斜至底边上。

这次的左下顶点用蓝色绘制,以保持与前侧面的右下顶点的一致。蓝色将从这个角向金字塔的前侧面和右侧面扩展并与其他颜色混合。

还应注意到后面的三个侧面和前侧面处于同一个glBegin(GL_TRIANGLES) 和
glEnd()语句中间。因为我们是通过三角形来构造这个金字塔的。OpenGL知道每三个点构成一个三角形。当它画完一个三角形之后,如果还有余下的点出现,它就以为新的三角形要开始绘制了。OpenGL在这里并不会将四点画成一个四边形,而是假定新的三角形开始了。所以千万不要无意中增加任何多余的点。 


  

  glColor3f(1.0f,0.0f,0.0f);   // 红色

  glVertex3f( 0.0f, 1.0f, 0.0f);   // 三角形的上顶点 (右侧面)

  glColor3f(0.0f,0.0f,1.0f);   // 蓝色

  glVertex3f( 1.0f,-1.0f, 1.0f);   // 三角形的左下顶点 (右侧面)

  glColor3f(0.0f,1.0f,0.0f);   // 绿色

  glVertex3f( 1.0f,-1.0f, -1.0f);   // 三角形的右下顶点 (右侧面)

现在是后侧面。再次切换颜色。左下顶点又回到绿色,因为后侧面与右侧面共享这个角。

glColor3f(1.0f,0.0f,0.0f);   // 红色

  glVertex3f( 0.0f, 1.0f, 0.0f);   // 三角形的上顶点 (后侧面)

  glColor3f(0.0f,1.0f,0.0f);   // 绿色

  glVertex3f( 1.0f,-1.0f, -1.0f);   // 三角形的左下顶点 (后侧面)

  glColor3f(0.0f,0.0f,1.0f);   // 蓝色

  glVertex3f(-1.0f,-1.0f, -1.0f);   // 三角形的右下顶点 (后侧面)

最后画左侧面。又要切换颜色。左下顶点是蓝色,与后侧面的右下顶点相同。右下顶点是蓝色,与前侧面的左下顶点相同。

到这里金字塔就画完了。因为金字塔只绕着Y轴旋转,我们永远都看不见底面,因而没有必要添加底面。如果您觉得有经验了,尝试增加底面(正方形),并将金字塔绕X轴旋转来看看您是否作对了。确保底面四个顶点的颜色与侧面的颜色相匹配。

glColor3f(1.0f,0.0f,0.0f);   // 红色

  glVertex3f( 0.0f, 1.0f, 0.0f);   // 三角形的上顶点 (左侧面)

  glColor3f(0.0f,0.0f,1.0f);   // 蓝色

  glVertex3f(-1.0f,-1.0f,-1.0f);   // 三角形的左下顶点 (左侧面)

  glColor3f(0.0f,1.0f,0.0f);   // 绿色

  glVertex3f(-1.0f,-1.0f, 1.0f);   // 三角形的右下顶点 (左侧面)

 glEnd();      // 金字塔绘制结束

画立方体

接下来开始画立方体。他由六个四边形组成。所有的四边形都以逆时针次序绘制。就是说先画右上角,然后左上角、左下角、最后右下角。您也许认为画立方体的背面的时候这个次序看起来好像顺时针,但别忘了我们从立方体的背后看背面的时候,与您现在所想的正好相反。(译者注:您是从立方体的外面来观察立方体的)。

注意到这次我们将立方体移地更远离屏幕了。因为立方体的大小要比金字塔大,同样移入6个单位时,立方体看起来要大的多。这是透视的缘故。越远的对象看起来越小 :) 。

glLoadIdentity();

 glTranslatef(1.5f,0.0f,-7.0f);    // 先右移再移入屏幕

glRotatef(rquad,1.0f,1.0f,1.0f);   // 在XYZ轴上旋转立方体

glBegin(GL_QUADS);     // 开始绘制立方体

先画立方体的顶面。从中心上移一单位,注意Y坐标始终为一单位,表示这个四边形与Z轴平行。先画右上顶点,向右一单位,再屏幕向里一单位。然后左上顶点,向左一单位,再屏幕向里一单位。然后是靠近观察者的左下和右下顶点。就是屏幕往外一单位。

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);   // 四边形的右下顶点 (顶面)

底面的画法和顶面十分类似。只是Y坐标变成了-1。如果我们从立方体的下面来看立方体的话,您会注意到右上角离观察者最近,因此我们先画离观察者最近的顶点。然后是左上顶点最后才是屏幕里面的左下和右下顶点。

如果您真的不在乎绘制多边形的次序(顺时针或者逆时针)的话,您可以直接拷贝顶面的代码,将Y坐标从1改成 -1,也能够工作。但一旦您进入象纹理映射这样的领域时,忽略绘制次序会导致十分怪异的结果。

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);   // 四边形的右下顶点(底面)

接着画立方体的前面。保持Z坐标为一单位,前面正对着我们。

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);   // 四边形的右下顶点(前面)

立方体后面的绘制方法与前面类似。只是位于屏幕的里面。注意Z坐标现在保持 -1 不变。

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);   // 四边形的右下顶点(后面)

还剩两个面就完成了。您会注意到总有一个坐标保持不变。这一次换成了X坐标。因为我们在画左侧面。

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);   // 四边形的右下顶点(左面)

立方体的最后一个面了。X坐标保持为一单位。逆时针绘制。您愿意的话,留着这个面不画也可以,这样就是一个盒子:)

或者您要是有兴趣可以改变立方体所有顶点的色彩值,象金字塔那样混合颜色。您会看见一个非常漂亮的彩色立方体,各种颜色在它的各个表面流淌。

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();      // 立方体绘制结束

rtri+=0.2f;      // 增加三角形的旋转变量

 rquad-=0.15f;      // 减少四边形的旋转变量

 return TRUE;      // 继续运行

}

原文及其个版本源代码下载:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=05

NeHe OpenGL教程 第五课:3D空间的更多相关文章

  1. Android OpenGL教程-第五课【转】

    第五课 3D空间: 我们使用多边形和四边形创建3D物体,在这一课里,我们把三角形变为立体的金子塔形状,把四边形变为立方体. 先看看三角形的顶点变成啥了 private float[] mTriangl ...

  2. NeHe OpenGL教程 第十课:3D世界

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  3. NeHe OpenGL教程 第二十三课:球面映射

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. NeHe OpenGL教程 第二十七课:影子

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  5. NeHe OpenGL教程 第二十一课:线的游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. NeHe OpenGL教程 第十七课:2D图像文字

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. NeHe OpenGL教程 第七课:光照和键盘

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  8. NeHe OpenGL教程 第六课:纹理映射

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  9. NeHe OpenGL教程 第二十课:蒙板

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

随机推荐

  1. C 语言中 free() 函数简单分析

    又是一个睡不着的夜晚,现在是凌晨03:16,不知道是不是感冒的原因,头脑并不是清醒,但是就是睡不着.摸着黑打开电脑,洗了杯子抓了点茶叶,然后打开饮水机电源.舍友们都睡着了,我戴着耳机听着轻音乐,也能听 ...

  2. kuangbin_UnionFind A (POJ 2236)

    挺接近模板的一题 接受O操作的时候扫一遍 符合条件的merge进去 done #include <cstdio> #include <cstring> #include < ...

  3. c语言学习笔记

    为什么需要输出控制符: 1:  01组成的代码可以表示数据亦可以表示指令: 2:如果01组成的代码表示的是数据的话,那么同样的01代码组合以不同的输出格式输出就会有不同的输出结果.. %d   --- ...

  4. c++文件操作相关

    file operation API functions HANDLE CreateFile(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttr ...

  5. 用max-width来防止图片溢出---不兼容ie6-----将max-width设置成父元素的宽度,当图片过大时会换行,以及限制图片的宽度。但是如果使用table,仍然可能超出限制。

    img{ max-width:100%;  height:auto; } 如题.

  6. HTTPS-使用Fiddler抓取HTTPS数据包原理

    最近想尝试基于Fiddler的录制功能做一些接口的获取和处理工作,碰到的一个问题就是简单连接Fiddler只能抓取HTTP协议,关键的登录请求等HTTPS协议都没有捕捉到,所以想让Fiddler能够同 ...

  7. Linux-TCP/IP TIME_WAIT状态原理

    TIME_WAIT状态原理---------------------------- 通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态. 客户端主动关闭连接时,会发送最后一个a ...

  8. 谷歌 analytics.js 简要分析

    下面是部分翻译过的JS,看起来好看些.   (function () { function setHref(a, b) { return a.href = b; } function setName( ...

  9. web前端-面试经验总结

    这几次面试主要是冲着百度去的 面试1的主要问题: 笔试: 1.解释css盒子模型 2.常用选择器,以及优先级 3.B如何继承A 4.写一个闭包实例,有什么优点缺点 5.html5的心特性有哪些 6. ...

  10. html之texteara

    定义多行的文本输入控件,所有浏览器都支持,可容纳无限的文本,等宽的字体. 用css的height和width来设置其框框的大小是个很好的办法,其中的文本换行符为%OD/%OA(回车换行) html5中 ...