旋转:

在这一课里,我将教会你如何旋转三角形和四边形。左图中的三角形沿Y轴旋转,四边形沿着X轴旋转。

上一课中我教给您三角形和四边形的着色。这一课我将教您如何将这些彩色对象绕着坐标轴旋转。
其实只需在上节课的代码上增加几行就可以了。下面我将整个例程重写一遍。方便您知道增加了什么,修改了什么。
我们增加两个变量来控制这两个对象的旋转。这两个变量加在程序的开始处其他变量的后面( bool fullscreen=TRUE;下面的两行)。它们是浮点类型的变量,使得我们能够非常精确地旋转对象。浮点数包含小数位置,这意味着我们无需使用1、2、3...的角度。你会发现浮点数是OpenGL编程的基础。新变量中叫做 rtri 的用来旋转三角形, rquad 旋转四边形。

GLfloat        rtri;                        // 用于三角形的角度

GLfloat        rquad;                        // 用于四边形的角度

接着我们修改DrawGLScene()的代码。
下面这段代码与上一课的相同。

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(Angle,Xvector,Yvector,Zvector)负责让对象绕某个轴旋转。这个命令有很多用处。 Angle 通常是个变量代表对象转过的角度。 Xvector , Yvector 和 Zvector 三个参数则共同决定旋转轴的方向。比如(1,0,0)所描述的矢量经过X坐标轴的1个单位处并且方向向右。(-1,0,0)所描述的矢量经过X坐标轴的1个单位处,但方向向左。
D. Michael Traub:提供了对 Xvector , Yvector 和 Zvector 的上述解释。
为了更好的理解X, Y 和 Z的旋转,我举些例子...

X轴-您正在使用一台台锯。锯片中心的轴从左至右摆放(就像OpenGL中的X轴)。尖利的锯齿绕着X轴狂转,看起来要么向上转,要么向下转。取决于锯片开始转时的方向。这与我们在OpenGL中绕着X轴旋转什么的情形是一样的。(译者注:这会儿您要把脸蛋凑向显示器的话,保准被锯开了花 ^-^。)

Y轴-假设您正处于一个巨大的龙卷风中心,龙卷风的中心从地面指向天空(就像OpenGL中的Y轴)。垃圾和碎片围着Y轴从左向右或是从右向左狂转不止。这与我们在OpenGL中绕着Y轴旋转什么的情形是一样的。

Z轴-您从正前方看着一台风扇。风扇的中心正好朝着您(就像OpenGL中的Z轴)。风扇的叶片绕着Z轴顺时针或逆时针狂转。这与我们在OpenGL中绕着Z轴旋转什么的情形是一样的。

下面的一行代码中,如果rtri等于7,我们将三角形绕着Y轴从左向右旋转7 。您也可以改变参数的值,让三角形绕着X和Y轴同时旋转。

    glRotatef(rtri,0.0f,1.0f,0.0f);                // 绕Y轴旋转三角形

下面的代码没有变化。在屏幕的左面画了一个彩色渐变三角形,并绕着Y轴从左向右旋转。

    glBegin(GL_TRIANGLES);                    // 绘制三角形

        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, 0.0f);            // 左下

        glColor3f(0.0f,0.0f,1.0f);            // 设置当前色为蓝色

        glVertex3f( 1.0f,-1.0f, 0.0f);            // 右下

    glEnd();                        // 三角形绘制结束

您会注意下面的代码中我们增加了另一个glLoadIdentity()调用。目的是为了重置模型观察矩阵。如果我们没有重置,直接调用glTranslate的话,会出现意料之外的结果。因为坐标轴已经旋转了,很可能没有朝着您所希望的方向。所以我们本来想要左右移动对象的,就可能变成上下移动了,取决于您将坐标轴旋转了多少角度。试试将glLoadIdentity() 注释掉之后,会出现什么结果。

重置模型观察矩阵之后,X,Y,Z轴都以复位,我们调用glTranslate。您会注意到这次我们只向右一了1.5单位,而不是上节课的3.0单位。因为我们重置场景的时候,焦点又回到了场景的中心(0.0处)。这样就只需向右移1.5单位就够了。 当我们移到新位置后,绕X轴旋转四边形。正方形将上下转动。

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

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

    glRotatef(rquad,1.0f,0.0f,0.0f);            //  绕X轴旋转四边形

下一段代码保持不变。在屏幕的右侧画一个蓝色的正方形

    glColor3f(0.5f,0.5f,1.0f);                // 一次性将当前色设置为蓝色

    glBegin(GL_QUADS);                    // 绘制正方形

        glVertex3f(-1.0f, 1.0f, 0.0f);            // 左上

        glVertex3f( 1.0f, 1.0f, 0.0f);            // 右上

        glVertex3f( 1.0f,-1.0f, 0.0f);            // 左下

        glVertex3f(-1.0f,-1.0f, 0.0f);            // 右下

    glEnd();                        // 正方形绘制结束

下两行是新增的。倘若把 rtri 和 rquad 想象为容器,那么在程序的开始我们创建了容器( GLfloat rtri , 和 GLfloat rquad )。当容器创建之后,里面是空的。下面的第一行代码是向容器中添加0.2。因此每次当我们运行完前面的代码后,都会在这里使 rtri 容器中的值增长0.2。后面一行将 rquad 容器中的值减少0.15。同样每次当我们运行完前面的代码后,都会在这里使 rquad 容器中的值下跌0.15。下跌最终会导致对象旋转的方向和增长的方向相反。

尝试改变下面代码中的+和-,来体会对象旋转的方向是如何改变的。并试着将0.2改成1.0。这个数字越大,物体就转的越快,这个数字越小,物体转的就越慢。

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

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

    return TRUE;                        // 继续运行
}

最后换掉窗口模式下的标题内容

        // 重建 OpenGL 窗口

        if (!CreateGLWindow("NeHe's 旋转实例",640,480,16,fullscreen))

在这一课中,我试着尽量详细的解释如何让对象绕某个轴转动。改改代码,试着让对象绕着Z轴、X+Y轴或者所有三个轴来转动:)。如果您有什么意见或建议请给我EMAIL。如果您认为有什么不对或可以改进,请告诉我。我想做最好的OpenGL教程并对您的反馈感兴趣。

第04课 OpenGL 旋转的更多相关文章

  1. NeHe OpenGL教程 第四课:旋转

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

  2. ubuntu 16.04 上opengl 的安装以及例子程序编译执行

    因为最近在移植 Qt5.7 + opengl , 遇到了难以越过的山峰,没有办法,试着在 ubuntu 16.04上将 opengl 配置以下,记录: 安装相关的库: sudo apt-get ins ...

  3. HexoC++第04课 构造析构.md

    C++第04课 构造析构.mdhtml {overflow-x: initial !important;}#write, body { height: auto; } #write, #write h ...

  4. 第12课 OpenGL 显示列表

    显示列表: 想知道如何加速你的OpenGL程序么?这一课将告诉你如何使用OpenGL的显示列表,它通过预编译OpenGL命令来加速你的程序,并可以为你省去很多重复的代码. 这次我将教你如何使用显示列表 ...

  5. 第11课 OpenGL 飘动的旗帜

    飘动的旗帜: 这一课从第六课的代码开始,创建一个飘动的旗帜.我相信在这课结束的时候,你可以掌握纹理映射和混合操作. 大家好!对那些想知道我在这里作了些什么的朋友,您可以先按文章的末尾所列出的链接,下载 ...

  6. 第10课 OpenGL 3D世界

    加载3D世界,并在其中漫游: 在这一课中,你将学会如何加载3D世界,并在3D世界中漫游.这一课使用第一课的代码,当然在课程说明中我只介绍改变了代码. 这一课是由Lionel Brits (βtelge ...

  7. 第09课 OpenGL 移动图像

    3D空间中移动图像: 你想知道如何在3D空间中移动物体,你想知道如何在屏幕上绘制一个图像,而让图像的背景色变为透明,你希望有一个简单的动画.这一课将教会你所有的一切.前面的课程涵盖了基础的OpenGL ...

  8. 第07课 OpenGL 光照和键盘(2)

    下一段代码绘制贴图立方体.我只对新增的代码进行注解.如果您对没有注解的代码有疑问,回头看看第六课. int DrawGLScene(GLvoid) // 从这里开始进行所有的绘制 { glClear( ...

  9. 第07课 OpenGL 光照和键盘(1)

    光照和键盘控制: 在这一课里,我们将添加光照和键盘控制,它让程序看起来更美观. 这一课我会教您如何使用三种不同的纹理滤波方式.教您如何使用键盘来移动场景中的对象,还会教您在OpenGL场景中应用简单的 ...

随机推荐

  1. redis连接密码和指定数据库

    台服务器上都快开启200个redis实例了,看着就崩溃了.这么做无非就是想让不同类型的数据属于不同的应用程序而彼此分开. 那么,redis有没有什么方法使不同的应用程序数据彼此分开同时又存储在相同的实 ...

  2. IDEA - 2019中文版安装教程

    前言 个人安装备忘录 软件简介 IDEA 全称IntelliJ IDEA,是java语言开发的集成环境,在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE支持. ...

  3. Shell系列(20)- 字符截取命令cut

    前言 grep是按行提取:cut默认是通过制表符,按列提取,不能识别用空格作为分隔符 语法 cut [选项] [文件] 选项 -f :列号,截取哪几列数据,多个列号用逗号隔开:列与列之间默认用TAB制 ...

  4. sqlite3 import/export db sqlite 导入 导出 数据

    export: $ sqlite3 xxx.db3 > .output xxx.sql >.dump > .q import: $ sqlite3 xxx.db3 > .rea ...

  5. file_get_contents('php://input') 数据如何转换成数组

    前台表单页:demo01.html 后台:demo01.php 输出结果: 备注:若前台通过Ajax的post提交过来的是json数据,需要对json数据进行解析:$data = json_decod ...

  6. 鸿蒙内核源码分析(静态链接篇) | 完整小项目看透静态链接过程 | 百篇博客分析OpenHarmony源码 | v54.01

    百篇博客系列篇.本篇为: v54.xx 鸿蒙内核源码分析(静态链接篇) | 完整小项目看透静态链接过程 | 51.c.h.o 下图是一个可执行文件编译,链接的过程. 本篇将通过一个完整的小工程来阐述E ...

  7. P2611-[ZJOI2012]小蓝的好友【Treap,扫描线】

    正题 题目链接:https://www.luogu.com.cn/problem/P2611 题目大意 \(r*c\)的网格上有\(n\)个标记点,然后求有多少个矩形包含至少一个标记点. \(1\le ...

  8. 推荐一款 Python 微服务框架 - Nameko

    1. 前言 大家好,我是安果! 考虑到 Python 性能及效率性,Python Web 端一直不温不火,JAVA 和 Golang 的微服务生态一直很繁荣,也被广泛用于企业级应用开发当中 ​本篇文章 ...

  9. 请求既有multipartFile,也有实体的解决方案

    上回书我们说到,我们在发文件上传请求的时候,携带数据 this.fileData.append('trainName', this.dataModel.trainName); // 添加培训名称 然后 ...

  10. JVM类加载器的分类

    类加载器的分类 JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Defined ClassLoader). 从概念上来讲,自定 ...