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;						// 继续运行

}

这一课又结束了。到这里您应该已经较好的掌握了在3D空间创建对象的方法。必须将OpenGL屏幕想象成一张很大的画纸,后面还带着许多透明的层。差不多就是个由大量的点组成的立方体。这些点从左至右、从上至下、从前到后的布满了这个立方体。如果您能想象的出在屏幕的深度方向,应该在设计新3D对象时没有任何问题。

效果截图:

     

(11)nehe教程5---3D空间的更多相关文章

  1. NeHe OpenGL教程 第五课:3D空间

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

  2. Direct3D 11 Tutorial 4: 3D Spaces_Direct3D 11 教程4:3D空间

    概述 在上一个教程中,我们在应用程序窗口的中心成功渲染了一个三角形. 我们没有太注意我们在顶点缓冲区中拾取的顶点位置. 在本教程中,我们将深入研究3D位置和转换的细节. 本教程的结果将是渲染到屏幕的3 ...

  3. iOS 11开发教程(五)iOS11模拟器介绍二

    iOS 11开发教程(五)iOS11模拟器介绍二 3.iOS11模拟器中设置语言 对于不同国家的人来说,使用到的语言是不一样的.一般情况下iOS11模拟器默认使用的English(英语).对于英文不好 ...

  4. 第05课 OpenGL 3D空间

    3D空间: 我们使用多边形和四边形创建3D物体,在这一课里,我们把三角形变为立体的金子塔形状,把四边形变为立方体. 在上节课的内容上作些扩展,我们现在开始生成真正的3D对象,而不是象前两节课中那样3D ...

  5. WordPress搬家教程:换空间与换域名

    WordPress搬家教程:换空间与换域名 由于本人博客空间8月份已到期,便新购一个虚拟主机想进行WordPress搬家,于是特意在网上查了些WordPress搬家教程,进行了综合总结,并结合这次实操 ...

  6. 《zw版·Halcon-delphi系列原创教程》 3d汽车模型自动区域分割

    <zw版·Halcon-delphi系列原创教程> 3d汽车模型自动区域分割 目前,图像分析,在3D设计,机器视觉方面拥有很广.这个Halcon脚本是3d汽车模型自动区域分割,很简单才20 ...

  7. iOS 11开发教程(二十二)iOS11应用视图实现按钮的响应(2)

    iOS 11开发教程(二十二)iOS11应用视图实现按钮的响应(2) 此时,当用户轻拍按钮后,一个叫tapButton()的方法就会被触发. 注意:以上这一种方式是动作声明和关联一起进行的,还有一种先 ...

  8. iOS 11开发教程(二十一)iOS11应用视图美化按钮之实现按钮的响应(1)

    iOS 11开发教程(二十一)iOS11应用视图美化按钮之实现按钮的响应(1) 按钮主要是实现用户交互的,即实现响应.按钮实现响应的方式可以根据添加按钮的不同分为两种:一种是编辑界面添加按钮实现的响应 ...

  9. iOS 11开发教程(二十)iOS11应用视图美化按钮之设置按钮的状态

    iOS 11开发教程(二十)iOS11应用视图美化按钮之设置按钮的状态 在示例2-2中,设置按钮的标题和颜色时,需要对按钮的状态进行设置,表示按钮在某一状态下的标题和标题颜色是什么样子.例如,UICo ...

随机推荐

  1. Android中修改状态栏的颜色和我们App的风格一致

    其实也没什么东西,就是一个主题,下面看代码: <resources> <!-- Base application theme. --> <style name=" ...

  2. random_names随机名字生成

    // 先从txt文件中获取姓和名数组 - (void)getNames{ NSString *resourcePath1 = [[NSBundle mainBundle] pathForResourc ...

  3. centos下安装nagios

    摘要Nagios是一款开源的免费网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等. Nagios是一款开源的免费网络监视工具,能有效监控Wind ...

  4. Objective-C中Block语法、Block使用以及通过Block实现数组排序

    Block:语法块,本质上是匿名函数(没有名称的函数) 标准C里面没有Block,C语言的后期扩展版本,加入了匿名函数 在C++.JS.Swift等语言有类似语法,叫做闭包 Block语法和C语言里的 ...

  5. OC中类的扩展介绍

    对OC类的扩展总结如下: 共有4个: 1.子类 subClass 作用:可以使用类的继承来增添父类的变量和方法. 写法:在.h文件中 @interface Student : Person 2.分类 ...

  6. 如何配置DNS服务器(局域网——域名指向某个IP地址)

    单击“开始”,指向“管理工具”,然后单击“DNS”,打开 DNS 管理器.   如有必要,向管理单元添加适用的服务器,然后连接该服务器.在控制台树中,单击适用的 DNS 服务器.   在“操作”菜单上 ...

  7. Xcode 添加代码块

    我们经常会定义一些retain的property,而且大概每次我们都会像这样写: @property (nonatomic, retain) Type *name;  每次都要老老实实的把“@prop ...

  8. 从Java的角度理解前端框架,nodejs,reactjs,angularjs,requirejs,seajs

    [前端神秘的面纱] 对后端开发来说,前端是神秘的, 眼花缭乱的技术,繁多的框架, 如果你还停留在前端等于只用jquery做开发,那么你out了, 本文从Java的角度简述下目前前端流行的一些框架. 水 ...

  9. 关于ASCII、GB231、GBK、UTF-8/UTF8、ANSI、unicode的学习笔记

    继续上次的学习内容,写一些自己学习的笔记吧!总是觉得没有笔记的学习总是不那么踏实,我承认自己是个记忆力很差的人,特别羡慕那些可以把自己学过的东西记得很牢靠的人.哎!可惜我不是,那只能做出来点东西,就算 ...

  10. hdu 4858 项目管理 图的分块

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4858 我们建造了一个大项目!这个项目有n个节点,用很多边连接起来,并且这个项目是连通的!两个节点间可能 ...