计算机图形学OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理,用法 .(转)

单位矩阵  对角线上都是1,其余元素皆为0的矩阵。

在矩阵的乘法中,有一种矩阵起着特殊的作用,如同数的乘法中的1,我们称这种矩阵为单位矩阵.

它是个方阵,除左上角到右下角的对角线(称为主对角线)上的元素均为1以外全都为0.

OpenGL中的坐标用齐次坐标表示,即(x,y,z)表示成(x‘,y‘,z‘,h),其中x=x‘/h; y=y‘/h; z=z‘/h. 通常h取1. 比如空间中的点(2,3,4),在OpenGL中将表示成(2,3,4,1). 齐次坐标表示方式适合于矩阵运算,也很方便地表示了无穷远的点,比如(1,0,0,0)就表示x轴上无穷远的点,因为1/0是无穷大,这里约定0/0=0.

接着要说点矩阵(线性代数)的知识。OpenGL里面的平移、旋转、缩放等变换均是线性变换,用矩阵相乘来表示。以平移变换为例,请见官方对glTranslatef函数的说明。假设有点(3,3,3),如果把该点沿x轴移动2单位,沿y轴移动3单位,沿z轴移动4单位,那么该点会是(3+2, 3+3, 4+4) = (5,6,7). 用矩阵表示是:

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

左边的矩阵称为平移变换矩阵,若把2、3、4换成x、y、z,则用它乘以一个齐次坐标表示的向量,就可以将该向量平移(x,y,z). 旋转变换和缩放变换都像平移变换一样可用一个矩阵来表示。这里可以不用理会这些矩阵长什么样,只需清楚它们乘以一个齐次坐标表示的向量,就可以使该向量发生需要的变换。

把平移变换矩阵记为T(x,y,z),旋转变换矩阵记为R(x,y,z,s),表示绕向量(x,y,z)旋转s角度;把向量记为X。这里只需要知道它们是 矩阵就行了,现在要把一个点X,如(3,3,3,1),移动(2,2,2)单位,再绕y轴旋转30度角,用矩阵表示即 R(0,1,0,30)*T(2,2,2)*X,可以理解为离X最近的矩阵最先作用。理解这个顺序很重要,这样,所有变换都可以用一串矩阵的相乘来表示, 计算机里面也确实是这么做的。

介绍完基本的数学知识,下面说OpenGL的作用机制。OpenGL有个变换矩阵堆栈,堆栈就像子弹夹一样,先进的后出。OpenGL中的每个向量,在被定义之后进入到OpenGL世界中,都必须先乘以这个变换矩阵堆栈的栈顶变换矩阵。如下图所示:

理解完上面的知识,再来理解glLoadIdentity、glTranslatef、glRotatef这些函数干了什么就容易多了。这些函数就是对这个堆栈的操作:

  • glTranslatef:将T(x,y,z)右乘与堆栈的栈顶变换矩阵。右乘的解释,假设目前栈顶变换矩阵为M,那么就相当于把M修改为M*T.
  • glRotatef :将R(x,y,z,s)右乘与堆栈的栈顶变换矩阵。
  • glLoadIdentity:将堆栈的栈顶变换矩阵设置成单位矩阵。
  • glPushMatrix:将堆栈的栈顶变换矩阵复制一份,然后Push到堆栈中。所谓Push,就像塞子弹一样把一个矩阵压入到堆栈中,此时,栈顶就是这个新的矩阵了,注意定义的向量都是和栈顶变换矩阵作用的。
  • glPopMatrix:将堆栈的栈顶变换矩阵Pop出来。

该讲的讲完了,下面出几道题目练习下吧。

1、OpenGL代码是:glLoadIdentity(); glTranslate3f(4,5,1); glRotate3f(0,1,0,90); glVertex3f(1,1,1); 请问此时栈顶变换矩阵是什么?(1,1,1)这个点到了OpenGL世界中的点是什么?

答:栈顶变换矩阵是T(4,5,1)*R(0,1,0,90),(1,1,1)到OpenGL世界中的坐标是T(4,5,1)*R(0,1,0,90)*(1,1,1).

2、解释为什么使用glPushMatrix和glPopMatrix的组合可以隔离这两个函数中的变换,使之不影响后面的点?

答:glPushMatrix新压入的变换矩阵是复制了原来的栈顶变换矩阵,所以它继承了之前的变换,此后执行glTranslatef、 glRotatef这些函数时,修改的是栈顶变换矩阵,在glPopMatrix之前的点都将受到栈顶变换矩阵的作用,之后用glPopMatrix,把 栈顶变换矩阵Pop掉,此时的栈顶变换矩阵又还原成原来的那个栈顶变换矩阵。

3、为什么有时候glTranslate3f和glRotate3f能颠倒有时候又不能?

答:矩阵A乘以矩阵B未必等于矩阵B乘以矩阵A,当它们相等时,很多只是巧合。

在opengl中,函数glTranslatef的作用就是移动坐标原点。对应的3个参数对应着3个坐标轴。
如果你调用一次glTranslatef(1.0f,0.0f,0.0f)然后画一个小球,接着再调用次glTranslatef(0.0f,1.0f,0.0f)再画一个小球。

此时,两个小球中,一个在另外一个正右方。
所以,如果要使两个小球分别处于x、y轴,则需要在第二次画之前调用glLoadIdentity()函数,使坐标原点归位。
另外,此处的坐标系为右手坐标系。
切记切记。

2、glPushMatrix、glPopMatrix操作其实就相当于栈里的入栈和出栈。
许多人不明白的可能是入的是什么,出的又是什么。我也是自己反复做了下测试才懂的(利用无聊的web上机时间)。

例如你当前的坐标系原点在你电脑屏幕的左上方。现在你调用glPushMatrix,然后再调用一堆平移、旋转代码等等,然后再画图。那些平移和旋转都是基于坐上角为原点进行变化的。而且都会改变坐标的位置,经过了这些变化后,你的坐标肯定不再左上角了。

那如果想恢复怎么办呢?这时就调用glPopMatrix从栈里取出一个“状态”了,这个状态就是你调用glPushMatrix之前的那个状态。就如很多opengl的书上所讲:调用glPushMatrix其实就是把当前状态做一个副本放入堆栈之中。

glLoadIdentity()

将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作
1.X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。
2.OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。
3.中心左面的坐标值是负值,右面是正值。
  移向屏幕顶端是正值,移向屏幕底端是负值。
  移入屏幕深处是负值,移出屏幕则是正值。

glTranslatef(x, y, z)

沿着 X, Y 和 Z 轴移动。

注意在glTranslatef(x, y,
z)中,当您移动的时候,您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置。其作用就是将你绘点坐标的原点在当前原点的基础上平移一个(x,y,z)向量。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

glLoadIdentity();

glTranslatef(-1.5f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();

glLoadIdentity();
glTranslatef(0.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();

/////////////////////////////////////////////////////////////////////////////////////

程序的运行结果如下:

左边的三角形是第一步绘制的,可以看到该三角形绘制的坐标系,实际上是以(-1.5f,0.0f,-6.0f)为原点的。

第二个三角形绘制的时候,由于使用glLoadIdentity()使原点重新回到屏幕中心来,因此其原点位于屏幕的中心。

glRotatef(angle, x, y, z)
与glTranslatef(x, y, z)类似,glRotatef(angle, x, y, z)也是对坐标系进行操作。
旋转轴经过原点,方向为(x,y,z),旋转角度为angle,方向满足右手定则。
////////////////////////////////////////////////////////////////

glLoadIdentity();
glTranslatef(0.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();
////////////////////////////////////////////////////////////////

在未旋转的情况下如图所示:

////////////////////////////////////////////////////////////////

glLoadIdentity();
glRotatef(45,0.0f,0.0f,1.0f);
glTranslatef(0.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();
////////////////////////////////////////////////////////////////

绕Z轴正向旋转45度角,因为Z轴正方向由屏幕内指向屏幕外,由右手定则可知方向为逆时针转动。
由于直角顶点即为原点,因此将围绕直角逆时针旋转。

////////////////////////////////////////////////////////////////

glLoadIdentity();
glRotatef(45,0.0f,0.0f,1.0f);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f,0.0f, 0.0f);
glVertex3f(1.0f,0.0f, 0.0f);
glVertex3f(0.0f,1.0f, 0.0f);
glEnd();

时间: 2024-12-28 19:01:22

计算机图形学OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理,用法 .(转)的相关文章

[计算机图形学] OpenGL读取obj文件并显示其3D效果

? 读取三维网格模型(Wavefront OBJ文件) 无法向立方体:cube.obj 有法向兔子模型:bunny.obj 有法向有纹理八字模型:Eight.obj OBJ文件的格式可参考:http://www.cnblogs.com/youthlion/archive/2013/01/21/2870451.html ? 利用OpenGL显示该模型的绘制效果(全部) 顶点显示 线条显示 面片显示 ? 核心代码说说 1.下面的点.纹理.法向量.面用于构成一个PIC的类,PIC用于存储从OBJ文件中

OpenGL中glPushMatrix和glPopMatrix的原理

glPushMatrix.glPopMatrix操作事实上就相当于栈里的入栈和出栈. 很多人不明确的可能是入的是什么,出的又是什么. 比如你当前的坐标系原点在你电脑屏幕的左上方.如今你调用glPushMatrix,然后再调用一堆平移.旋转代码等等,然后再绘图.那些平移和旋转都是基于左上角为原点进行变化的.并且都会改变坐标的位置,经过了这些变化后,你的坐标肯定不再左上角了. 那假设想恢复怎么办呢?这时就调用glPopMatrix从栈里取出一个"状态"了,这个状态就是你调用glPushMa

计算机图形学(一) 视频显示设备_1_CRT原理

第 1 章 图形系统概述 如今.计算机图形学的作用与应用已经得到了广泛承认.大量的图形硬件和软件系统已经应用 到了差点儿全部的领域.通用计算机甚至很多手持计算器也已经普遍具备 二维及三维应用的图形功能 . 在个人计算机上也能够配用多种交互输入设备及图形软件包 .对于高性能应用.能够选择很多高级 的专用图形硬件系统和技术 .本章将探讨图形硬件和图形软件包的基本特性 . 1.1    视频显示设备 图形系统一般使用视频显示器作为其主要的输出设备. 大部分视频监视器的操作是基于标准的 阴极射线管 (c

OpenGL中摄像机矩阵的计算原理

熟悉OpenGL|ES的朋友,可能会经常设置摄像机的view矩阵,iOS中相对较好,已经封装了方向,只需要设置摄像机位置,目标点位置以及UP向量即可.下面先介绍下摄像机view矩阵的计算原理.此处假设知道摄像机位置eye,目标点位置target以及UP向量. 主要是u,v,w三个向量的计算: 1.w向量: (1)计算向量eyeToTarget = eye - target; (2)向量w 等于 向量eyeToTarget与向量UP的叉乘. 2.u向量:向量w与向量UP的叉乘 3.v向量:向量w与

【计算机图形学】OpenGL+VS2015相关类库配置

1 WiKi OpenGL一直是事实上的计算机图形学标准,截止2016年06月,OpenGL版本已经更新到4.5.不过DirectX发展迅速,大有OpenGL落后的态势,知乎上的该话题的讨论:https://www.zhihu.com/question/23241456.所以OpenGL为了追赶DirectX,推出 了glNext(Vulkan API),相关讨论https://www.zhihu.com/question/28039310. 2 相关资料 图形学的经典书籍是<Computer

OpenGL中平移、旋转、缩放矩阵堆栈操作

在OpenGL中,图元的几何变换均为线性变换,通过矩阵变换实现.OpenGL中的坐标用齐次坐标表示,即(x,y,z)表示成(x',y',z',h),其中x=x'/h; y=y'/h; z=z'/h. 通常h取1. 比如空间中的点(2,3,4),在OpenGL中将表示成(2,3,4,1). 齐次坐标表示方式适合于矩阵运算,也很方便地表示了无穷远的点,比如(1,0,0,0)就表示x轴上无穷远的点,因为1/0是无穷大,这里约定0/0=0. 例:点(1,1,1)将该向量平移变换(2,3,4)个单位,得到

3D计算机图形学零起点全攻略(转)

3D计算机图形学零起点全攻略 这篇文章不包含任何技术知识,但我的希望它能指明一条从零开始通往3D领域的成功之路.我将罗列我看过的相关经典书籍作为学习文献,阅读规则是每进入下个内容,我都会假设已经完成前面全部的文献研习内容.相信若能按照这条路走到最后,会有所进益. 完成整部分内容需要具备基础: 英语:CET4以上 数学:精通数字加减乘除法. 物理:基本力学. 计算机:了解电脑的基本知识,熟练使用Windows. 电脑配置: CPU:双核1.5以上 显卡:NVIDIA GeForce8400G MS

计算机图形学-mac系统下Xcode中OpenGL开发环境配置。

mac系统下Xcode中OpenGL开发环境配置. 这学期有计算机图形学的课程,需要用到OpenGL,最近着手开始配置开发环境了,老师上课给的安装包都是基于windows系统的.网上也是windows上配置的教程比较多,Mac版的比较少.我综合了几个教程并自己总结,实践成功.特来分享配置过程.希望能帮到大家! 介绍 OpenGL(Open Graphics Library)是定义了一个跨编程语言,跨平台的编程接口规格的专业的图形程序接口.它用于三维图像(二维亦可),是一个功能强大,与硬件无关,调

计算机图形学和OpenGL(二)坐标系和绘制点线函数

这节开始前我们先了解一下图元的概念.图形软件包中用来描述各种图形元素的函数称为图形输出原语,也称图元(primitive).而描述对象几何要素的输出图元一般称为几何图元.点和线是最简单的几何图元,本节就会简单介绍点和线段的绘制方法. 一.坐标系统. 坐标系统一般分为屏幕坐标和OpenGL中的绘图坐标. 在上一节中我们简单的写了个示例程序,程序中介绍了gluOrtho2D命令.我们可以利用该命令设定一个二维笛卡尔坐标系.该函数的四个变量制定的是显示图形x和y坐标范围.所以我们可以使用下面代码制定一