基于OpenGL投影总矩阵变换的探讨与实现

合集下载

实验3OpenGL几何变换

实验3OpenGL几何变换

实验3OpenGL⼏何变换1.实验⽬的:理解掌握⼀个OpenGL程序平移、旋转、缩放变换的⽅法。

2.实验内容:(1)阅读实验原理,运⾏⽰范实验代码,掌握OpenGL程序平移、旋转、缩放变换的⽅法;(2)根据⽰范代码,尝试完成实验作业;3.实验原理:(1)OpenGL下的⼏何变换在OpenGL的核⼼库中,每⼀种⼏何变换都有⼀个独⽴的函数,所有变换都在三维空间中定义。

平移矩阵构造函数为glTranslate<f,d>(tx, ty, tz),作⽤是把当前矩阵和⼀个表⽰移动物体的矩阵相乘。

tx, ty,tz指定这个移动物体的矩阵,它们可以是任意的实数值,后缀为f(单精度浮点float)或d(双精度浮点double),对于⼆维应⽤来说,tz=0.0。

旋转矩阵构造函数为glRotate<f,d>(theta, vx, vy, vz),作⽤是把当前矩阵和⼀个表⽰旋转物体的矩阵相乘。

theta, vx, vy, vz指定这个旋转物体的矩阵,物体将绕着(0,0,0)到(x,y,z)的直线以逆时针旋转,参数theta表⽰旋转的⾓度。

向量v=(vx, vy,vz)的分量可以是任意的实数值,该向量⽤于定义通过坐标原点的旋转轴的⽅向,后缀为f(单精度浮点float)或d(双精度浮点double),对于⼆维旋转来说,vx=0.0,vy=0.0,vz=1.0。

缩放矩阵构造函数为glScale<f,d>(sx, sy, sz),作⽤是把当前矩阵和⼀个表⽰缩放物体的矩阵相乘。

sx, sy,sz指定这个缩放物体的矩阵,分别表⽰在x,y,z⽅向上的缩放⽐例,它们可以是任意的实数值,当缩放参数为负值时,该函数为反射矩阵,缩放相对于原点进⾏,后缀为f(单精度浮点float)或d(双精度浮点double)。

注意这⾥都是说“把当前矩阵和⼀个表⽰移动<旋转, 缩放>物体的矩阵相乘”,⽽不是直接说“这个函数就是旋转”或者“这个函数就是移动”,这是有原因的,马上就会讲到。

OpenGL矩阵操作

OpenGL矩阵操作

OpenGL矩阵操作OpenGL的矩阵变换操作方法一、借助OpenGL的矩阵堆栈,保存各个物体的矩阵变换火柴棍案例glMatrixMode(GL_PROJECTION);glMatrixMode(GL_MODELVIEW); 将当前变换矩阵设置为模型视图变换矩阵。

glPushMatrix,glPopMatrix—压入和弹出当前矩阵堆栈glGet(GL_MAX_MODELVIEW_STACK_DEPTH);glGet(GL_MAX_PROJECTION_STACK_DEPTH);来获取模型视图矩阵堆栈和投影矩阵堆栈的最大堆栈深度。

一般情况下(在Windows平台上),模型视图的最大堆栈深度是32,而投影堆栈的最大深度是2。

二、自己保存各个物体的空间变换矩阵float M[4][4]; //其中M[j,i]表示矩阵M的第j行,第i列的数据。

float M[16]; //也可以创建一个一维数组无论是2维数组还是一维数组,都是按照列优先的顺序保存的。

如图所示1. 读取矩阵堆栈glGetFloatv(GL_MODELVIEW_MATRIX, M);glGetFloatv(GL_PROJECTION_MATRIX, M);2. 设置矩阵堆栈,用于描画glLoadIdentity(); //加载4*4单位矩阵;glLoadMatrix{fd}(*m); //加载指定4*4矩阵m;glMultiMatrix{fd}(*m); //当前矩阵右乘*m;< 图形变换>1. 几何变换:平移、缩放、旋转2. 齐次坐标:用n+1维向量表示n维向量,比如,(wx,wy,wz,w)表示(x,y,z)。

通常,令w=1,用来进行复合几何变换。

3. 坐标变换:根据图形在一个坐标系下的坐标求其在另一坐标系下的坐标。

4. 3D空间通过投影,可以在2D屏幕上显示。

同时,在投影面上定义一个窗口。

只有窗口内的图形才显示。

在屏幕上定义一个矩形视区,然后,从窗口到视区进行一一映射。

OpenGL矩阵与变换

OpenGL矩阵与变换

OpenGL矩阵与变换学习OpenGL的过程中,最令人难以理解的就是变换这一部分内容(或许是因为我天性愚钝的原因吧,我感觉这一块内容特别令我匪夷所思,有时候半天也想不通,如果是这样的话,看来我就要继续修炼了,呵呵),因为涉及到矩阵运算,而且OpenGL的变换似乎不总是按照我们想象的那样进行,这就需要理解OpenGL的变换机制以及矩阵运算的细节。

这里记录一些我在学习这些内容时的心得,可能有些不准确或者是错误的,请大家批评指正,互相学习!OpenGL中的变换操作是通过矩阵运算进行的,OpenGL中的矩阵又分为当前矩阵和变换矩阵,当前矩阵存放着当前模型或者是绘图区状态的信息。

变换矩阵是用来执行模型的平移、旋转、缩放以及透视等变换操作的矩阵,这种操作通过将变化矩阵与当前矩阵相乘生成新的当前矩阵来实现,生成新的当前矩阵从而生成新变换之后的新的模型以及新的视图变换状态。

总结一下:当前矩阵用来表示模型坐标,当前视图状态变换矩阵是通过某种的运算生成的,用于同当前矩阵相乘以生成新的变换后的当前矩阵的矩阵,下面将详细讨论变换矩阵的生成方法。

2、变换矩阵的生成方法a、函数法。

OpenGL为我们提供了简单的变换矩阵生成方法,使我们不必关心矩阵的具体构造方法,我们只需要关心我们究竟想让我们绘制的模型或者我们的模型所在的场景视图做何种变换。

那么当我们想要进行某种变换时,只需要调用相关的函数,并为函数传递适当的参数,便可以完成相应的变换,即构造相应的变换矩阵并乘于当前矩阵,生成新的当前矩阵。

只不过更直观的函数调用被我们看到了,而OpenGL 设计者们为了避免不必要的麻烦而为我们定义了封装好的函数避免了我们理解矩阵的困难。

毕竟不是所有人都善于矩阵运算!不是所有人都系统的学习过线性代数的相关课程!举例说明:一些常用的变换函数:glTranslatef(GLfloat x,GLfloat y,GLfloat z)、glRotatef(GLfloat angle,GLfloat x,GLfloat y,GLfloat z)、glScalef(GLfloat x,GLfloat y,GLfloat z)以上三个函数都是模型视图变换函数,因为变换函数对于矩阵的操作都是相似的,并且对于模型视图变换函数的讨论相对简单且同样便于理解变换函数与变换矩阵的关系,故不再讨论视图变换矩阵。

投影矩阵的推导

投影矩阵的推导

投影矩阵的推导(OpenGL D3D)OpenGL矩阵推导——模型视图变化在三维编程中,模型视图变换是从三维世界到二维屏幕中一个很重要的变换,但是这个变换往往很多人都不太理解,要么是事而非。

而这方面的文章不是太少就是讲的太浅没有真正的理解模型视图变换,本人在这个过程中曾经走过很多歪路,不过好在最终在自己的不懈努力下终于降伏了这只猛虎。

本人就以自己的理解,通过矩阵推导过程一步一步来了解模型视图变化,最后通过两个OpenGl的程序来进一步理解模型视图矩阵。

先从一个基本的模型视图—透视投影变换讲起。

透射投影是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical View Volume 以下简称CVV)中,待裁剪完毕后进行透视除法的行为。

透视投影变换是令很多刚刚进入3D图形领域的开发人员感到迷惑乃至神秘的一个图形技术。

其中的理解困难在于步骤繁琐,对一些基础知识过分依赖,一旦对它们中的任何地方感到陌生,立刻导致理解停止不前。

主流的3D APIs 都把透射投影的具体细节进行了封装,从而只需一个函数便可生成一个透射投影矩阵比如gluPerspective(),使得我们不需要了解其算法便可实现三维到二维的转化,然而实事是,一些三维图形或游戏开发人员遇到一些视图矩阵的问题往往会不知所措,比如视景体裁剪。

以下部分内容是从别处那转过来的,主要感谢Twinsen和一个叫丁欧南的高中生。

透视投影变换是在齐次坐标下进行的,而齐次坐标本身就是一个令人迷惑的概念,这里我们先把它理解清楚。

齐次坐标对于一个向量v以及基oabc,可以找到一组坐标(v1,v2,v3),使得v = v1 a + v2 b + v3 c (1)而对于一个点p,则可以找到一组坐标(p1,p2,p3),使得p–o = p1 a + p2 b + p3 c (2)从上面对向量和点的表达,我们可以看出为了在坐标系中表示一个点(如p),我们把点的位置看作是对这个基的原点o所进行的一个位移,即一个向量——p –o(有的书中把这样的向量叫做位置向量——起始于坐标原点的特殊向量),我们在表达这个向量的同时用等价的方式表达出了点p:p = o + p1 a + p2 b + p3 c (3)(1)(3)是坐标系下表达一个向量和点的不同表达方式。

OpenGL完全教程 第四章 矩阵变换

OpenGL完全教程 第四章 矩阵变换

OpenGL完全教程 第四章 矩阵变换作者:何咏 日期:2006-2-3 20:52:21 点击:3468如需转载本文,请声明作者及出处。

第四章 矩阵变换通过前三章的学习,我们知道了如何使用OpenGL在3D空间中绘制基本图元,并把使用图元组成模型。

然而,在我们绘制完一个物体或一个场景之后,我们总希望从多个角度观察这个物体,或者在场景中走动。

这时,我们需要OpenGL的另一个功能:变换。

OpenGL为我们提供了许多方面和类型的变换。

你可以对投影方式进行变换,也可以对物体/模型 进行变换。

你可以改变自己的位置和方向,也可以改变物体的大小和角度。

学习本章内容,你将了解:•OpenGL中变换的种类•使用矩阵描述一个变换•基本变换•定义和使用自己的变换4.1 OpenGL中的变换变换(Transform),可以使3D空间中的物体投影到2D平面上。

使用变换,你可以移动、旋转、缩放甚至弯曲一个物体。

然而变换并没有直接修改顶点数据,取而代之,变换修改了坐标系。

如果旋转一个坐标系,然后再在 旋转后的坐标系里绘图,绘制后的图形就好像被旋转了。

在基本OpenGL渲染流程中,将进行以下变换:视图变换 :用于指定观察者的位置和方向;模型视图变换:移动和变换场景中的模型;投影变换 :对视见空间进行裁剪和扭曲;视见区变换:对最终输出进行缩放。

4.1.1 视图变换在一个场景中,我们希望改变观察者的位置和观察角度。

用于改变观察者方位和角度的变换,就是视图变换。

默认情况下(没有执行任何变换时),观察者位于点(0,0,0),且视线朝着-Z方向。

也就是说,只有在z<0的地方绘图,才有可能被观察到。

4.1.2 模型视图变换此变换用于移动和旋转场景中的物体。

使用模型视图变换完全可以代替视图变换。

道理是很简单的:比如你想使用视图变换将观察者向-Z轴移动10个单位,此时场景中所有的物体都向+Z轴移动了10个单位。

这跟你直接使用模型视图变换将场景中所有物体向+Z方向移动10个单位的效果是完全一样的。

图形学实验报告 OpenGL中的变换

图形学实验报告 OpenGL中的变换

《计算机图形学基础》实验6 OpenGL中的变换一、实验目的及要求1.理解OpenGL中的各种变换的实现原理;2.掌握OpenGL中模型视图矩阵的操作方法。

3.掌握OpenGL中投影变换的实现方法。

二、实验环境主要是软件开发环境VC 6.0三、实验内容1、分子动画示例2、深度测试示例四、实验结果1、分子动画五、程序代码1.分子动画#include <gl/glut.h>void Initial(){glEnable(GL_DEPTH_TEST); // 启用深度测试glClearColor(1.0f, 1.0f, 1.0f, 1.0f ); //背景为白色}void ChangeSize(int w, int h){if(h == 0) h = 1;glViewport(0, 0, w, h); // 设置视区尺寸glMatrixMode(GL_PROJECTION); // 指定当前操作投影矩阵堆栈glLoadIdentity(); // 重置投影矩阵GLfloat fAspect;fAspect = (float)w/(float)h; // 计算视区的宽高比gluPerspective(45.0, fAspect, 1.0, 500.0); // 指定透视投影的观察空间glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void Display(void){static float fElect1 = 0.0f; // 绕原子旋转的角度glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色和深度缓冲区glMatrixMode(GL_MODELVIEW); // 指定当前操作模型视图矩阵堆栈glLoadIdentity(); // 重置模型视图矩阵glTranslatef(0.0f, 0.0f, -250.0f); //将图形沿z轴负向移动glColor3f(1.0f, 0.0f, 0.0f);glutSolidSphere(12.0f, 15, 15); // 绘制红色的原子glColor3f(0.0f, 0.0f, 0.0f);glPushMatrix(); // 保存当前的模型视图矩阵glRotatef(fElect1, 0.0f, 1.0f, 0.0f); // 绕y轴旋转一定的角度glTranslatef(90.0f, 0.0f, 0.0f); // 平移一段距离glutSolidSphere(6.0f, 15, 15); // 画出第一个电子glPopMatrix(); // 恢复模型视图矩阵glPushMatrix(); // 保存当前的模型视图矩阵glRotatef(45.0f, 0.0f, 0.0f, 1.0f); //绕z轴旋转45°glRotatef(fElect1, 0.0f, 1.0f, 0.0f);glTranslatef(-70.0f, 0.0f, 0.0f);glutSolidSphere(6.0f, 15, 15); // 画出第二个电子glPopMatrix(); // 恢复模型视图矩阵glPushMatrix(); // 保存当前的模型视图矩阵glRotatef(-45.0f,0.0f, 0.0f, 1.0f); //绕z轴旋转-45°glRotatef(fElect1, 0.0f, 1.0f, 0.0f);glTranslatef(0.0f, 0.0f, 60.0f);glutSolidSphere(6.0f, 15, 15); // 画出第三个电子glPopMatrix();fElect1 += 10.0f; // 增加旋转步长,产生动画效果if(fElect1 > 360.0f) fElect1 = 10.0f;glutSwapBuffers();}void TimerFunc(int value){glutPostRedisplay();glutTimerFunc(100, TimerFunc, 1);}int main(int argc, char* argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);glutCreateWindow("分子动画示例");glutReshapeFunc(ChangeSize);glutDisplayFunc(Display);glutTimerFunc(500, TimerFunc, 1); //指定定时器回调函数Initial();glutMainLoop();return 0;}六、心得体会这次的分子动画实验比较有意思,就是对代码的理解性不是很高。

OpenGL学习脚印:投影矩阵的推导

OpenGL学习脚印:投影矩阵的推导

OpenGL学习脚印:投影矩阵的推导OpenGL学习脚印: 投影矩阵的推导写在前面本节内容翻译和整理自songho的博客《OpenGL Projection Matrix》内容,以供自己和初学者熟悉投影矩阵推导过程。

通过本节,你可以了解到:•投影矩阵计算的阶段•透视投影和正交投影的矩阵推导本节的要点就在于: 阅读时,自己拿笔推导一遍。

1.概览计算机屏幕是2维的,OpenGL渲染的3D场景必须以2D形式的图像投影到屏幕上。

GL_PROJECTION 矩阵就是用来设置投影变换的。

首先,它将所有顶点从眼坐标(照相机坐标)转换到裁剪坐标系下。

然后,这些裁剪坐标通过透视除法,即除以裁剪坐标中w分量,转换到归一化设备坐标系(NDC)。

一个由视锥裁剪的三角形因此,我们要记住,裁剪(视锥剔除frustum culling)和NDC转换都集成到了GL_PROJECTION 矩阵。

接下来的部分描述了怎么样通过left, right, bottom, top, near and far 这6个界限参数来构造投影矩阵。

注意:视锥剔除是在裁剪坐标系中进行的,并且恰好在透视除法之前进行。

裁剪坐标xc, yc 和 zc 通过与wc比较来进行测试。

如果某个坐标值比Wc小或者比Wc大,那么这个顶点将被丢弃。

然后,OpenGL会重新在裁剪进行的地方构造多边形的边缘。

补充内容:实际上,眼坐标系下坐标在乘以投影矩阵后,裁剪测试和透视除法都是由GPU来执行的。

而后面这两个过程处理的裁剪坐标系数据都是由投影矩阵变换的。

1. 裁剪测试也即视锥剔除-Wc < Xc,Yc,Zc < Wc2. NDC透视除法Xn = Xc / Wc Yn = Yc / Wc Zn = Zc / Wc这里需要注意的是,我们在构造16个参数的投影矩阵的同时,不仅要考虑到裁剪,还要考虑到透视除法的过程。

这样,最终的NDC坐标才会满足:-1 < Xn,Yn,Zn < 12.透视投影在透视投影中,在眼坐标下截头椎体(a truncated pyramid frustum)内的3D点被映射到NDC下一个立方体中;x坐标从[l,r]映射到[-1,1],y坐标从[b,t]映射到[-1,1],z坐标从[n,f]映射到[-1,1]。

Win32 OpenGL编程(9) 投影变换

Win32 OpenGL编程(9) 投影变换

Win32 OpenGL编程(9) 投影变换收藏Win32 OpenGL编程(9) 投影变换write by 九天雁翎(JTianLing) -- /vagrxie讨论新闻组及文件提要在前文(系列文章(7),以下简称XO7,系列其他文章类似)中的照相机比喻中提到了4种3D变换,如下:1.确定照相机的位置的过程对应于“视图变换”(Viewing Transformations)2.确定物体位置的过程对应于“模型变换”(Modeling Transformations)3.确定照相机放大倍数的过程对应于“投影变换”(Projection Transformations)4.确定照片大小的过程对应于“视口变换”(Viewport Transformations)XO7中我们讲的是第一种变换视图变换,即改变观察者本身的位置,视角等的变换效果,XO8中讲的是第二种变换模型变换,本文开始继续按顺序讲解下一个3D 变换过程,投影变换。

正投影投影变换的过程就像是照相机选镜头的过程,目的是确定视野,其实说起来投影一词,我在学习工程制图的时候就接触过了,不知道大家是否学过这门课程,工程制图就是一种将三维空间的事物设想投影在二维空间中,然后画下来,工程中应用非常广泛,那时候学的那些剖面图什么的,也是累死我了-_-!OpenGL 就可以模拟这样的过程,并且名字和工程制图中的名字是一样的,叫正投影。

OpenGL以glOrtho来指定一个正交平行的矩形,屏幕上显示的就是此物体在此矩形的正面的投影。

在XO2中用过的gluOrtho2D实际上是此函数的一个去掉Z 轴坐标的简化版,而glOrtho包括的参数 nearVal,farVal表示此矩形的前,后两面,超出此矩形范围的图形将会被裁掉。

《OpenGL Programming Guide》:glOrtho — multiply the current matrix with an orthographic matrixC Specificationvoid glOrtho( GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble nearVal,GLdouble farVal);Parametersleft, rightSpecify the coordinates for the left and right vertical clipping planes.bottom, topSpecify the coordinates for the bottom and top horizontal clipping planes.nearVal, farValSpecify the distances to the nearer and farther depth clipping planes.These values are negative if the plane is to be behind the viewer.用此函数,通过调整nearVal与farVal我们可以实现类似工程制图中的剖面的效果,见下例:GLfloat gfNear = 1.0;//这里进行所有的绘图工作void SceneShow(GLvoid){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(-1.0, 1.0, -1.0, 1.0, gfNear, -1.0);glPushMatrix();DrawSmoothColorPyramid(0.5);glPopMatrix();glFlush();}///////////////////////////////////////////////////////////int Game_Main(void *parms = NULL, int num_parms = 0){DWORD dwStartTime;dwStartTime = GetTickCount();// this is the main loop of the game, do all your processing // here// for now test if user is hitting ESC and send WM_CLOSEif (KEYDOWN(VK_ESCAPE))SendMessage(ghWnd,WM_CLOSE,0,0);if (KEYDOWN(VK_UP)){gfNear -= 0.01;}if (KEYDOWN(VK_DOWN)){gfNear += 0.01;}SceneShow();// 控制帧率while(GetTickCount() - dwStartTime < TIME_IN_FRAME){Sleep(1);}// return success or failure or your own return code herereturn(1);} // end Game_Main以下就是当nearVal为0.8时的效果,也就是说,Z轴坐标大于0.8的,一律被截掉了,在工程制图中,我们老师常将,此时假设在此用一刀将物体切掉。

详解OpenGL的坐标系、投影和几何变换

详解OpenGL的坐标系、投影和几何变换

详解OpenGL的坐标系、投影和几何变换作者:charlee 按:我也是在迷茫中走过来的,初学OpenGL时,略微了解了一些有关变换的基本知识,但是却不知道具体的使用方法,因此经常需要在布置场景时反复调整各种参数。

当我终于有一天明白了它们的用法时,就觉得应该把这些心得体会写下来,让那些和我一样曾经迷茫过的人能够迅速地找到出路。

本文的读者对象为那些初学OpenGL,了解了一些坐标系、几何变换等基本知识,但是又不知道具体应该如何运用这些操作的人。

如果你对OpenGL一无所知,建议你先去学学OpenGL的基本知识。

1 坐标系OpenGL中使用的坐标系有两种,分别为世界坐标系和屏幕坐标系。

世界坐标系即OpenGL内部处理时使用的三维坐标系,而屏幕坐标系即为在计算机屏幕上绘图时使用的坐标系。

通常,OpenGL所使用的世界坐标系为右手型,如下图所示。

从计算机屏幕的角度来看,x轴正方向为屏幕从左向右,y轴正方向为屏幕从下向上,z轴正方向为屏幕从里向外。

而进行旋转操作时需要指定的角度θ的方向则由右手法则来决定,即右手握拳,大拇指直向某个坐标轴的正方向,那么其余四指指向的方向即为该坐标轴上的θ角的正方向(即θ角增加的方向),在上图中用圆弧形箭头标出。

2 投影将世界坐标系中的物体映射到屏幕坐标系上的方法称为投影。

投影的方式包括平行投影和透视投影两种。

平行投影的投影线相互平行,投影的结果与原物体的大小相等,因此广泛地应用于工程制图等方面。

透视投影的投影线相交于一点,因此投影的结果与原物体的实际大小并不一致,而是会近大远小。

因此透视投影更接近于真实世界的投影方式。

B 平行投影B透视投影xzy 02.1 平行投影OpenGL 中使用下面的函数来设置投影方式为平行投影。

glOrtho(xleft, xright, ybottom, ytop, znear, zfar); 各参数的含义如下图所示。

注意,只有位于立方体之内的物体才可见。

相机投影模型与OpenGL矩阵投影矩阵的设置

相机投影模型与OpenGL矩阵投影矩阵的设置

相机投影模型与OpenGL矩阵的设置摘要:本文描述相机的投影模型与OpenGL模型视图矩阵和投影矩阵的关系。

阅读完本文,读者能够根据相机的参数(内参和外参)设置OpenGL矩阵,使得OpenGL模拟出相机的成像效果。

相机投影模型:设空间点P3D={P x,P y,P z} ,其齐次坐标记为P3D̃={P x,P y,P z,1}。

旋转变换和平移变换均为3×3矩阵,分别记为R和T, R̃和T̃分别为它们的齐次形式。

经过旋转和平移变换之后,新的点为P3D′={P x′,P y′,P z′}P3D′=RP3D+T将P3D′投影到2D平面的过程为(小孔成像模型,图形坐标左上角为原点,y轴朝下):{x=fP x′P z′+W2y=−fP y′P z′+H2其中,W和H分别为成像面的宽度和高度(即图像宽度和高度)。

OpenGL投影过程:OpenGL的投影过程为P normal3D=M proj×M model×P3D̃其中,P normal3D为规范化的3D点,它是一个齐次坐标,是4维向量。

M proj和M model分别为OpenGL的投影矩阵和模型视图矩阵,它们都为4*4的矩阵。

模型视图矩阵和摄像机外参相关,对应于R和T,投影矩阵和摄像机的内参相关。

如果给定摄像机的内参f(焦距)、W和H,外参RotX,RotY,RotZ,以及TransX,TransY,TransZ。

为了使OpenGL模拟相机成像结果,则应如下设置://清理背景glClearColor(0.0f, 0.0f, 1.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glEnable(GL_DEPTH_TEST);//设置内参//为什么这么设置,参见参考文献2//注意这里矩阵的排列是列优先排列glViewport(0, 0, W, H);//设置成像面大小glMatrixMode(GL_PROJECTION);GLdouble projection[16]; // Where The 16 Doubles Ofmemset(projection, 0, sizeof(GLdouble)*16);projection[0]= -2.0f*focalLength/W;projection[5]= 2.0f* focalLength /H;projection[10] = -(Far + Near)/(Far - Near);//Far 和 Near分别为远、近裁剪平面projection[11] = -1.0f; //这个固定要设为-1projection[14] = -2.0f*Far*Near / (Far - Near);glLoadMatrixd(projection);//保存投影矩阵//设置外参,注意OpenGL中矩阵乘法的顺序//按照RP+T模型//应该先设置Translation矩阵, 再设置Rotation矩阵glMatrixMode(GL_MODELVIEW);glLoadIdentity(); //reset modelview matrixgluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0);//把相机位置移到原点,朝向Z轴负方向glTranslatef(pTrans[0], pTrans[1], pTrans[2]);glRotatef(pRotRad[0]/3.1415926*180.0f, 1, 0, 0);glRotatef(pRotRad[1]/3.1415926*180.0f, 0, 1, 0);glRotatef(pRotRad[2]/3.1415926*180.0f, 0, 0, 1);说明:以上的远近裁剪平面是用于OpenGL做场景截取用,在此裁剪区域外的景物会被舍去。

OpenGL投影矩阵(ProjectionMatrix)构造方法

OpenGL投影矩阵(ProjectionMatrix)构造方法

OpenGL投影矩阵(ProjectionMatrix)构造⽅法(翻译,图⽚也来⾃)⼀、概述绝⼤部分计算机的显⽰器是⼆维的(a 2D surface)。

在OpenGL中⼀个3D场景需要被投影到屏幕上成为⼀个2D图像(image)。

这称为投影变换(参见或),需要⽤到投影矩阵(projection matrix)。

⾸先,投影矩阵会把所有顶点坐标从eye coordinates(观察空间,eye space或view space)变换到裁剪坐标(clip coordinated,属于裁剪空间,clip space)。

然后,这些裁剪坐标被变换到标准化设备坐标(normalized device coordinates, NDC,即坐标范围在-1到1之间),这⼀步是通过⽤⽤裁剪坐标的w_c分量除裁剪坐标实现的。

因此,我们要记住投影矩阵⼲了两件事: 裁剪clipping(即frustum culling,视景体剔除)和⽣成NDC。

下⽂会讲述如何根据6个参数(left, right, bottom, top, near和far边界值)来构建投影矩阵。

注意视景体剔出(也即clipping)是在裁剪坐标下完成的,是早于⽤w_c(即上⾯提到的w分量,c表⽰clipping)除裁剪坐标的(它会⽣成NDC)。

裁剪坐标x_c, y_c, z_c会与w_c进⾏⽐较。

如果裁剪坐标⽐-w_c⼩或者⽐w_c⼤,则丢弃这个顶点(vertex)。

即经裁剪后剩余的顶点的裁剪坐标满⾜:-w_c < x_c, y_c, z_c < w_c。

OpenGL会成发⽣裁剪的地⽅⽣成新的边,如下图1,⼀个三⾓形经裁后,成了⼀个梯形,两条红⾊的边就是裁剪后新⽣成的。

(图1. ⼀个被视体裁剪的三⾓形)⼀般常⽤的有透视投影和正交投影,相应地也就有两种投影矩阵。

⼆、透视投影(Perspective Projection)(图2. 透视投影中的视景体和标准化设备坐标NDC)在透视投影中,⼀个3D point是在⼀个截头锥体中(truncated pyramid frustum,上⾯图2左图,即⼀个棱台),会被映射到⼀个⽴⽅体(NDC坐标空间)中,x坐标范围从[1, r]变成了[-1, 1],y坐标范围从[b, t]变成了[-1, 1],z坐标从[-n, -f]变成了[-1, 1]。

[翻译转载]OpenGL投影矩阵(ProjectionMatrix)构造方法

[翻译转载]OpenGL投影矩阵(ProjectionMatrix)构造方法

视锥体的顶视图视锥体的侧视图[翻译转载]OpenGL 投影矩阵(ProjectionMatrix )构造⽅法OpenGL Projection Matrix原⽂地址:Overview电脑显⽰器是⼀个⼆维平⾯, ⽽OpenGL 渲染出来的场景却是三维的 , 所以必须要投影到⼆维的电脑屏幕上. 可以使⽤ GL_PROJCETION 来进⾏投影. ⾸先,它把顶点数据从 eye coordinates(视点坐标) 转换到 clip coordinates(裁剪坐标). 在将这些坐标除以w 坐标分量来转换到NDC(标准化设备坐标)上因此,我们应该清楚 裁剪(可视平截头体的裁剪) 和 NDC 的转换都包含在了 GL_PROJECTION 矩阵中了. 下⼀段将会说明如何通过l,r,b,t,n,f (左,右,下,上,近和远)这六个边界值来构建透视矩阵.注意 可视平截头体的裁剪(裁剪) 是在 clip coordinates(裁剪坐标) 中, 在除以 w c 前执⾏的.clip coordinates 的 x c ,y c ,z c 会通过 w c 来测试, 如果任何⼀个⼤于w c 或 ⼩于−w c , 那么这个顶点就会被丢弃.−w c <x c ,y c ,z c <w c当有丢弃时,OpenGL 将会重新构建多边形的边.⼀个被平截头体剪裁的三⾓形## Perspective Projection(透视投影)在透视投影中, truncated pyramid frustum (eye coordinates) (截锥体平截头体(视点坐标)) 中 三维的点呗映射到⼀个⽴⽅体(NDC); 三个坐标分量分别映射到[−1,1].x :[l ,r ]=>[−1,1],y :[b ,t ]=>[−1,1],z :[n ,f ]=>[−1,1]注意 eye coordinates 是定义在右⼿坐标中的, 但 NDC 是在左⼿坐标中的. 因此 源点摄像机在 eye space (视觉空间) 中看向 z 轴 负向 ⽽在 NDC 中 看向z 轴 正向. 由于glFrustum() 对由进到远只接受正值, 我们需要在构造 GL_PROJECTION 矩阵时 对他们取反.截锥体平截头体和标准化设备坐标在OpenGL 在, 在 eye space 中的三维点 会被投影到 near plane(projection plane) (近平⾯(投影平⾯)) 上, 下⾯这张图显⽰了如何将 p (x e ,y e ,z e ) 投影到 p (x p ,y p ,z p ) 上.把x_p 映射到x_n把y_p 映射到y_n在顶视图中,x e ,eye space 中的的x 坐标, 通过相似三⾓形的⽐值的映射到 x p ;x px e =−n z ex p =−n ∗x ez e =n ∗x e −z e 在侧视图中,y p 也是通过相似的⽅法计算出来的;y py e =−n z ey p =−n ∗y ez e =n ∗y e −z e 注意x p 和y p 都与z e 有关; 与−z e 成反⽐即除以−z e . 这是构造 GL_PROJECTION 矩阵的第⼀条线索. 在 eye coordinates 与 GL_PROJECTION 矩阵相乘完成变换后, clip coordinates 依然是 . 最终将其除以他的w 分量来得到NDC.(更多细节)x clipy clipz clip w clip =M projection ×x eye y eye z eye w eye ,x ndc y ndc z ndc =x clip /w clip y ndc /w clip z ndc /w clip因此,我们可以⽤ −z e 作为 clip coordinates 的 w 分量. 于是 GL_PROJECTION 矩阵的第四⾏变成了 (0,0,−1,0).\begin{pmatrix}x_{c}\\y_{c}\\ z_{c}\\w_{c}\end{pmatrix} = \begin{pmatrix} .& . & . & .\\ .& . & . &. \\ .& . & .&. \\ 0& 0 & -1 & 0 \end{pmatrix} \times \begin{pmatrix}x_{e}\\y_{e}\\z_{e}\\w_{e}\end{pmatrix}, \therefore w_c = -z_e 接下来,我们通过线性关系把 x_p,y_p 映射到 NDC 中的x_n,y_n 上; [l,r] => [-1,1] 和 [b,t] => [-1,1]x_n = \frac{1-(-1)}{r-l}*x_p + \beta 1 = \frac{2r}{r-l}+ \beta (⽤(r,1)代换(x_p,x_n))\beta = 1-\frac{2r}{r-l} = \frac{r-l}{r-l}-\frac{2r}{r-l} = \frac{r-l-2r}{r-l} = \frac{-r-l}{r-l} = -\frac{r+l}{r-l}\therefore x_n = \frac{2x_p}{r-l} - \frac{r+l}{r-l}y_n = \frac{1-(-1)}{t-b}*y_p + \beta1 = \frac{2t}{t-b}+ \beta (⽤(t,1)代换(y_p,y_n))\beta = 1-\frac{2t}{t-b} = \frac{t-b}{t-b}-\frac{2t}{t-b} = \frac{t-b-2t}{t-b} = \frac{-t-b}{t-b} = -\frac{t+b}{t-b}\therefore y_n = \frac{2y_p}{t-b} - \frac{t+b}{t-b}然后把x_p 和y_p 变量代换到上述式⼦中x_n = \frac{2x_p}{r-l}-\frac{r+l}{r-l} (x_p = \frac{nxe}{-z_e})x_n = \frac{2*\frac{nx_e}{-z_e}}{r-l} - \frac{r+l}{r-l}x_n = \frac{2n*x_e}{(r-l)(-z_e)} - \frac{r+l}{r-l}x_n = \frac{\frac{2n}{r-l}*x_e}{-z_e} - \frac{r+l}{r-l}x_n = \frac{\frac{2n}{r-l}*x_e}{-z_e} + \frac{\frac{r+l}{r-l}*z_e} {-z_e}x_n = (\frac{2n}{r-l}*x_e+\frac{r+l}{r-l}*z_e)/-z_e = x_c / -z_e同理可得y_n = (\frac{2n}{t-b}*y_e+\frac{t+b}{t-b}*z_e)/-z_e = y_c/-z_e注意我们使每个⽅程的两个项都除以-z_e 来表⽰perspective division(透视除法)(x_c/w_c,y_c/w_c ). ⽽且我们之前已经把w_c 设成了-z_e 了, 所以括号内的项已经是 clip coordinates 的 x_c 和y_c 了.于是得到了GL_PROJECTION 矩阵的前两⾏\begin{pmatrix}x_{c}\\y_{c}\\ z_{c}\\w_{c}\end{pmatrix} = \begin{pmatrix} \frac{2n}{r-l}& 0 & \frac{r+l}{r-l} & 0\\ 0& \frac{2n}{t-b} & \frac{t+b}{t-b} &0 \\ .& . & .&. \\ 0& 0 & -1 & 0\end{pmatrix} \times \begin{pmatrix}x_{e}\\y_{e}\\ z_{e}\\w_{e}\end{pmatrix}现在我们只剩GL_PROJECTION 矩阵的第三⾏需要解出了. 但解z_n 并不像其他坐标那样简单,因为 eye space 的z_e 总是被投影到近平⾯的-n 上. 但我们为了 clipping(裁剪)和depth test(深度测试)需要保证z 坐标的唯⼀性.,⽽且还要能够反投影(还原变换). 因为z 并不依赖于x 和y 坐标,我们借⽤w 分量 来找到 z_n 和z_e 之间的关系. 因此我们可以像下⾯这样来指定 GL_PROJECTION 矩阵的第三⾏.\begin{pmatrix}x_{c}\\y_{c}\\ z_{c}\\w_{c}\end{pmatrix} = \begin{pmatrix} \frac{2n}{r-l}& 0 & \frac{r+l}{r-l} & 0\\ 0& \frac{2n}{t-b} & \frac{t+b}{t-b} &0 \\ .& . & A&B \\ 0& 0 & -1 & 0\end{pmatrix} \times \begin{pmatrix}x_{e}\\y_{e}\\ z_{e}\\w_{e}\end{pmatrix}, z_n=z_c/w_c=\frac{Az_e+Bw_e}{-z_e}()()()()在 eye space中, w_e等于1. 因此等式变成z_n = \frac{Az_e+B}{-z_e}我们⽤(z_e,z_n)的关系来找到系数A和B;将(-n,-1)和(-f,1)回代到上式中\left\{\begin{matrix} \frac{-An+B}{n} = -1\\ \frac{-Af+B}{f} = 1 \end{matrix}\right. \rightarrow \left\{\begin{matrix} -An+B = -n \;(1)\\ -Af+B = f \;(2) \end{matrix}\right.重写等式(1);B=An-n \; (1')将B带⼊(2);-Af +(An-n) = f \; (2)$-(f-n)A = f + n A = -\frac{f+n}{f-n}$把A回代到(1)中;(\frac{f+n}{f-n})n + B = -n \; (1)B = -n - (\frac{f+n}{f-n})n = -(1+\frac{f+n}{f-n})n = -(\frac{f-n+f+n}{f-n})n = -\frac{2fn}{f-n}解出A和B后就可以得到Z_e和Z_n的关系;Z_n = \frac{-\frac{f+n}{f-n}z_e - \frac{2fn}{f-n}}{-z_e} \; (3)最终解出了整个 GL_PROJECTION 矩阵\begin{pmatrix} \frac{2n}{r-l}& 0 & \frac{r+l}{r-l} & 0\\ 0& \frac{2n}{t-b} & \frac{t+b}{t-b} &0 \\ 0& 0 & \frac{-{f+n}}{f-n}& \frac{-2fn}{f-n} \\ 0& 0 & -1 & 0 \end{pmatrix}这个投影是⼀种通⽤形式,如果可视平截头体是对称的,即r=-l 和 t=-b,可以对其化简\left\{\begin{matrix} r+l=0\\ r-l=2r \; (宽) \end{matrix}\right. , \left\{\begin{matrix} t+b=0 \\ t-b=2t \;(⾼) \end{matrix}\right.\begin{pmatrix} \frac{n}{r}& 0 & 0 & 0\\ 0& \frac{n}{t} & 0 &0 \\ 0& 0 & \frac{-{f+n}}{f-n}& \frac{-2fn}{f-n} \\ 0& 0 & -1 & 0 \end{pmatrix}在继续之前,请观察⼀下等式(3)中z_e和z_n的关系,你会发现他们并不是线性关系⽽是分式关系,这意味着在近平⾯会有⾮常⾼的精度⽽远平⾯的精度很低.如果[-n,-f]的范围很⼤,就会导致深度精度问题(z-fighting(深度冲突)); 在远平⾯z_e值⼩改动不会影响到z_n的值. 所以n和f的距离应该越⼩越好从⽽减少深度缓冲的精度问题.深度缓冲精度的⽐较Orthographic Projection(正射投影)为正射投影构造 GL_PROJECTION ⽐透视模式下的要简单的多正射视锥和标准化设备坐标(NDC)eye space 中所有的x_e,y_e和z_e分量都线性映射到 NDC. 我们只需要把长⽅体视锥缩放正⽅体,然后把它移动到原点. 让我们来通过线性关系来解出 GL_PROJECTION ⾥的元素吧.把x_e映射到x_nx_n = \frac{1-(-1)}{r-l}*x_e + \beta1 = \frac{2r}{r-l} + \beta \; (⽤(r,1)代换(x_e,x_n))\beta = 1 - \frac{2r}{r-l} = - \frac{r+l}{r-l}\therefore x_n = \frac{2}{r-l}*x_e - \frac{r+l}{r-l}把y_e映射到y_ny_n = \frac{1-(-1)}{t-b}*y_e + \beta1 = \frac{2t}{t-b} + \beta \; (⽤(t,1)代换(y_e,y_n))\beta = 1 - \frac{2t}{t-b} = - \frac{t+b}{t-b}\therefore y_n = \frac{2}{t-b}*y_e - \frac{t+b}{t-b}把z_e映射到z_nz_n = \frac{1-(-1)}{-f-(-n)}*z_e + \beta1 = \frac{2f}{f-n} + \beta \; (⽤(-f,1)代换(z_e,z_n))\beta = 1 - \frac{2f}{f-n} = - \frac{f+n}{f-n}\therefore z_n = \frac{-2}{f-n}*z_e - \frac{f+n}{f-n}由于在正射投影中不再需要w分量, GL_PROJECTION 矩阵的第四⾏保留成(0,0,0,1), 于是可以得到正射投影的 GL_PROJECTION\begin{pmatrix} \frac{2}{r-l}& 0 & 0 & -\frac{r+l}{r-l}\\ 0& \frac{2}{t-b} & 0 &-\frac{t+b}{t-b} \\ 0& 0 & \frac{-2}{f-n}& -\frac{f+n}{f-n} \\ 0& 0 & 0 & 1 \end{pmatrix}同样的,如果视锥是对称的,即r=-l 和 t=-b,可以对其化简\left\{\begin{matrix} r+l=0\\ r-l=2r \; (宽) \end{matrix}\right. , \left\{\begin{matrix} t+b=0 \\ t-b=2t \;(⾼) \end{matrix}\right.\begin{pmatrix} \frac{1}{r}& 0 & 0 & 0\\ 0& \frac{1}{t} & 0 &0 \\ 0& 0 & \frac{-{2}}{f-n}& -\frac{f+n}{f-n} \\ 0& 0 & 0 & 1 \end{pmatrix}Processing math: 26%。

OpenGLES矩阵变换及其数学原理详解(五)

OpenGLES矩阵变换及其数学原理详解(五)

OpenGLES矩阵变换及其数学原理详解(五)引⼦1. 向量刻画的是线性空间中的对象。

2. 矩阵刻画的是向量在线性空间中的运动(变换,跃迁),相似矩阵本质上就是同⼀个线性变换的不同的描述。

3. 在⼀个线性空间中,选定了⼀组基,对于任何⼀个线性变化都可以⽤⼀个确定的矩阵来描述4. 矩阵不仅可以作为线性变换的描述,⽽且可以作为⼀组基的描述,作为变换的矩阵,不但可以把线性空间中的⼀个点给变换到另⼀个点去,⽽且也能够把线性空间中的⼀个坐标系(基)表换到另⼀个坐标系(基)去。

5. 当我们谈到向量时,⼀定要指定它所在的坐标系才有意义,⽐如向量b=(1,2,3)实际上指的是在单位坐标系I下有⼀个向量的度量为b。

6. 就可以理解Ma=b就可以看成Ma=Ib,就是说在坐标系M中度量出来的向量a和在坐标系I⾥⾯度量出来的b实际上就是同⼀个向量。

7. 对于矩阵⽽⾔,他表⽰出来的那个坐标系也是由⼀组基(向量)组成的,同样存在这组基实在哪个坐标系下度量的问题。

对于矩阵M,将其理解成IM,即M中的那组向量是在I坐标系中得出的。

8. MxN本质是声明了⼀个在M坐标系中量出的另⼀个坐标系N,其中M本⾝是在I坐标系中度量出来的。

9. 对坐标系施加变换的⽅法,就是让表⽰那个坐标系的矩阵与表⽰那个变化的矩阵相乘。

因此我们来理解这样⼀个式⼦,ACb,AC为矩阵,b为⼀个向量b是⼀个向量,他是在I坐标系下度量的,a = Cb也就是在I坐标系下将向量b变换到向量b,d=ACb=Aa的含义就是继续在I 坐标系下将向量a变换到向量d。

即在同⼀个坐标系I下⾯进⾏了两次变换操作。

另⼀种理解⽅式是ACb=IACb,那么IAC三个矩阵相乘就表⽰了坐标系的变换,在I坐标系中度量处新的坐标系IA,再在IA坐标系下度量出IAC,然后这⾥最终的坐标系中的向量b和在1中在I坐标系中经过两次变换得到的向量是同⼀个向量。

上⾯的两种理解⽅式也揭⽰了对向量的变换和对坐标系的变换是等价的,这⼀点也可以通过后⾯旋转变换的图⽰中看出来。

关于OpenGL中模型视图投影视口变换的理解

关于OpenGL中模型视图投影视口变换的理解

关于OpenGL中模型视图投影视口变换的理解还是对于OpenGL中的各种变换理解的有些模糊,从网上看到了好多解释,现总结一下。

变换种类有:模型变换,视图变换,投影变换,视口变换以下的内容以红宝书中的cube.c程序作为讨论对象。

程序代码:#include <GL/glut.h>#include <stdlib.h>void init(void){glClearColor (0.0, 0.0, 0.0, 0.0);glShadeModel (GL_FLAT);}void display(void){glClear (GL_COLOR_BUFFER_BIT);glColor3f (1.0, 1.0, 1.0);glLoadIdentity (); /* clear the matrix *//* viewing transformation */gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);glScalef (1.0, 2.0, 1.0); /* modeling transformation */glutWireCube (1.0);glFlush ();}void reshape (int w, int h){glViewport (0, 0, (GLsizei) w, (GLsizei) h);glMatrixMode (GL_PROJECTION);glLoadIdentity ();glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);glMatrixMode (GL_MODELVIEW);}void keyboard(unsigned char key, int x, int y){switch (key) {case 27:exit(0);break;}}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);glutInitWindowSize (500, 500);glutInitWindowPosition (100, 100);glutCreateWindow (argv[0]);init ();glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutMainLoop();return 0;}先说明一下各种变换在代码中出现的顺序:在代码中,视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投影变换和视口变换。

opengl投影变换与逆变换

opengl投影变换与逆变换

opengl投影变换与逆变换⼀个新⼿都在问的:opengl中如何将2d窗⼝坐标转换为3d空间坐标。

以下是测试代码,需⽤到glm库。

#include <string>#include <cstdlib>#include <iostream>#include <glm/glm.hpp>#include <glm/ext.hpp>using namespace std;using namespace glm;void print(const vec4& v) {cout << v[0] << "" << v[1] << "" << v[2] << "" << v[3] << endl;}void print(const mat4& m) {print(glm::column(m, 0));print(glm::column(m, 1));print(glm::column(m, 2));print(glm::column(m, 3));}int main(int argc, char** argv) {//投影变换mat4 proj = glm::perspective(45.0f, 1.0f, 0.1f, 10.0f);{vec4 pos = vec4(3, 3, -9, 1);pos = proj*pos;print(pos);pos /= pos.w;print(pos);}cout<<endl;//投影逆变换{float x=0.5,y=0.5,z=-1;vec4 pos=vec4(x,y,z,1);mat4 invProj=glm::inverse(proj);pos=invProj*pos;print(pos);pos/=pos.w;print(pos);}return0;}⽂中忽略模型视图矩阵,就当相机固定在世界中⼼往负z轴⽅向观察。

D3D,OPENGL视点变换矩阵,投影矩阵(clip space)的推导过程

D3D,OPENGL视点变换矩阵,投影矩阵(clip space)的推导过程

D3D,OPENGL视点变换矩阵,投影矩阵(clip space)的推导过程此处推导D3D的变换矩阵(采用行向量,行主序存储,右乘矩阵),然后通过调整得出OPENGL中的变换矩阵1. 视点变换矩阵的推导。

根据给定的眼睛位置(position),朝向(orientation)来计算最终的视点变换矩阵。

投影矩阵的计算见Frustum类计算过程大致如下:设Q代表从世界空间坐标系到眼睛空间坐标系的变换矩阵,V代表一个点故VQ=VMT.其中T:从世界空间坐标系到眼睛空间坐标系的平移变换矩阵,M:从世界空间坐标系到眼睛空间坐标系的旋转变换矩阵。

则Q1-代表视点变换矩阵Q1-=MT1-= T1-M1-由于M是正交矩阵,故V=Q1-= T1-M T其中M=[Rx Ry Rz 0], T= [1 0 0 0][Ux Uy Uz 0] [0 1 0 0][Dx Dy Dz 0] [0 0 1 0 ][0 0 0 1] [Tx Ty Tz 1 ]故V=Q1-= [1 0 0 0] * [Rx Ux Dx 0][0 1 0 0] [Ry Uy Dy 0][0 0 1 0] [Rz Uz Dz 0][-Tx –Ty –Tz 1] [0 0 0 1]= [ Rx Ux Dx 0 ][ Ry Uy Dy 0 ][ Rz Uz Dz 0 ][ Wx Wy Wz 1 ]其中W = - Pos* M T对于OPENGL,则有:V=Q1-=M T T1-其中M=[Rx Ux -Dx 0][Ry Uy -Dy 0][Rz Uz -Dz 0][0 0 0 1]T= [1 0 0 Tx][ 0 1 0 Ty][0 0 1 Tz][0 0 0 1 ]故V=Q1 =[Rx Ry Rz Wx][Ux Uy Uz Wy][-Dx –Dy –Dz Wz][0 0 0 1]其中W = -M T* Pos2. 透视投影(perspective projection)矩阵的推导假设(X,Y,Z,1)为一个点,投影后的点为(Xp,Yp,Zp,1)则根据相似三角形原理,有:Xp/X=Yp/Y=N/Z所以:Xp=N*X/ZYp=N*Y/ZZp=N故投影变换可以表示为齐次坐标形式:(Xp,Yp,Zp,1)=(X,Y,Z,Z/N)对于X和Y :在进行上一步变换后,还要进一步做裁剪变换,即将投影后的坐标映射为[-1,1].即:(X*N/Z,Y*N/Z) : ([l,r],[b,t]) ([-1,1],[-1,1])即:(X*N/Z-l)/(r-l)=(s+1)/2由此可以得到:对于Z,变换稍微复杂一些。

OpenGL利用矩阵对模型进行变换

OpenGL利用矩阵对模型进行变换

OpenGL利用矩阵对模型进行变换本实例是利用矩阵对模型进行平移、缩放、旋转等变换,虽然实际应用中都有特定的方法,用起来很简单,但此矩阵算法是你理解opengl必须要学会的。

也是模型变换的原理。

//包含所需的glut头文件。

该头文件已经默认包含gl.h,和glu.h。

#include <glut.h>//还可以包含其他头文件#include<math.h> //数学函数的头文件#include <iostream>using namespace std;//定义顶点的个数#define VERTEX_NUM 3#define pi 3.14159265//二维坐标系中的一个点的表示方法typedef struct{GLfloat x;GLfloat y;GLfloat h;}vertex2D;//三角形的三个顶点的位置坐标float matrixT[3][3];vertex2D vOld[VERTEX_NUM] = {{50,50,1},{200,100,1},{150,300,1}};vertex2D vNew[VERTEX_NUM];//定义默认的窗口大小常量#define WINDOW_WIDTH 800#define WINDOW_HEIGHT 600//定义全局变量,随时保存窗口被改变后,当前窗口的大小GLsizei gWidth;GLsizei gHeight;//为了程序更加清晰,将在整个程序中只需要调用一次的//用于完成初始化工作的函数在此处调用。

void init(){//用于清屏的颜色rgba,在0--1之间的浮点数glClearColor(0.0, 0.0, 0.0, 0.0);//指定渲染模式:Flat(整个图元一个颜色), Smooth(光滑,插值)glShadeModel(GL_FLAT); //默认状态下就是光滑模式}//(1)当窗口的内容需要进行重绘时将要被调用的函数。

根据gluLookat求解ViewMatrix

根据gluLookat求解ViewMatrix

根据gluLookat求解ViewMatrix
如何根据OpenGL中的gluLookat函数求解 ViewMatrix矩阵。

视图坐标转换实际上就是把定点的坐标转换进眼睛(摄像机)坐标系中,这个操作与将眼睛转换到相应位置并设定朝向的操作相反。

来完成视图变换操作的矩阵V由两部分矩阵连乘形成的,一部分是朝向矩阵O,一部分是平移矩阵T,所以我们有:
V= OT;
朝向矩阵是由视线朝向D和眼睛的上方向U决定的,这两个方向向量叉乘得到向量C,向量C和向量D叉乘得到U‘,C,U,D(对应x,y,z),形成了眼睛坐标系的三个方向,它们属于右手坐标系,相关的公式如下:
c =
d x u,
u' = c x d,
将得到的三个变量相应的单位化,分别用这三个变量传到下面的矩阵中,就得到了转换需要的朝向矩阵O:
,注意向量d的各个分量都被取了原值的负值。

而平移矩阵,则是将眼睛移动操作的反操作,如果你有眼睛的位置,直接将眼睛的位置全取原值负值就OK了,但是需要注意的一点是,此时必须先把眼睛在世界坐标系中的位置通过上面刚求出来的矩阵转换为眼睛坐标系中的位置,然后再把眼睛位置取负值。

以上红字部分是十分重要的,大多数文档均未提及。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2 3 正等轴侧投影 , . 正二轴侧投 影具体 实现 正 等轴 侧图 : l r n lt ( . , . , 5 gT a s e 0000 一 . af
0 ;g Roae(5. , . , 0, . ) ) l ttf4 0 1 0 0. 0 0 ;
g Ro a e ( 3 2 0. 1 0, 0 ; l t t f 5, 0, . 0. ) 5. g S ae( . 1 0 1 0 ; lc lf1 0, . , . )
g Roae(2 . , . , . 0 0 ;lc lf l ttf 0 6 0 0 10, .)gS ae
(. , ., .) 10 10 10 ;
g u Wie b ( 2 ;g Orho 10, . lt rCu e0.) l t ( . 1
0 1 0, . , . , 0.) , . 10 15 2 0;
可 见 图 7, 8。 图
24 斜等轴侧投影 , 斜二轴侧投影 具体实现 斜等轴 侧图 : l r n lt ( . , . , 5 gT a s e 0 0 0 0 一 . af
2在 O eG 中的实现 pn L
绘 制投 影 的 函 数 具 体 实 现 如 下 : gl a sa e ( Tr n l tfTYPE x, d TYPE y, d TYPE, z ; 平移 函数 , d )/ / 3个参数 分别表示 X, Y Z轴 的平移 距离 / g Ro a e ( l t tfTYPE n l , a g e TYPE x, d T P y T E d ) / 旋 转函数 , Y E d , YP z ; } 4个参 数表示旋 转角度 a g e, y和 z轴 } n l X, / gS ae( PE S TYP y, lclfTY X, E s TYP Zi E S) / 缩放 函数 , X, 在 y和 Z 的缩 放 比例 / gu Wie b ( d u e sz )/ lt rCu eGL o bl ie; }正方 形 函数 /
1引言
投影 就 是将 n 维 的 点变 换 成 小于 n 维 的点 ,而 且 在 绝 大 多 数情 况 下 只 是 用 到 二 维 形 体 在 二维 平 面 上 的 投 影 ,因 此把 三维 物 体 变 为 二 维 图 形 表 示 的 过 程 为 投 影 变 换 ,投影 是如 下形 成的 :首先 在 三 维 李 间 中确 定 是 一 个 投 影 中 心 和 一 个 投 影 平 面 , 然 后 从 投 影 中 心 引 出 一 些 投 影 直 线 ,这 些 直 线 通 过 形 体 上 的 每 一 点 与 投 影 平 面 相 交 , 投影 平面 上 就形 成 了形 体的 投 影 , 在 在 很 多 参考 书 上 只 是给 出 一部 分 投 影 变 换 矩 阵 , 没 有 给 出投 影 图是 如 何 得 来 。 本 文 并 主要 通过 投 影 总 矩 阵 变 换 ,系统 地 对 平 面 几 何投 影 的 两 种 形 式 ,即 透 视 投 影 和 平 行 投影作 出 了矩阵 的推 导 , 以及利 用 Op n e GL 提供的 函数在 v s a + 6 0的环境下 实现 i lc + . u 投影 的绘制。
维普资讯
学 术 论 坛
基 于 OP GL投影总 矩阵 变换的探讨 与实现 e n
吴初汉 赵越
( 云南大学数学 系 昆 明 6 0 9 5 0 1) 摘 要 : 文主要对投 影总矩阵 变换 作 出 了 导 , 本 推 并通过投 影总矩 阵变换推 出了透视投 影和平行投 影的各种 类型的矩 阵变换 , 以及利 用 O e GI提供的函数在 v s a c pn iu l ++6 0环境下 实现 了各种 类型的投 影绘 制 . 关键词 :透视投 影 平行投 影 O e G 矩阵 绘制 pn 1 中图分类号 : P 9 T 31 文献标识码 :A 文章编 号 :1 7 — 9 x 2 0 ) 6c 1 0 4 0 8 ( 0 8 0 ( 一0 1 - 2 6 ) 8
gu W ie u e0 2 ; gOrh ( . , . lt r C b ( . ) l t o -1 0 1
0 一1 0 1 0, . , 0 0 ; , ., . 15 2 .)
0, 1 0, . , . , 0.) . 10 15 2 0{
正 二轴 侧 图 :gTr nltf0 0 0. , . l a sae( . , 0 一5
可 见 图 l 图 2, 3。 , 图
2 2 主视 图 , 侧视图 , 俯视 图投影具体 实现
主 视 图 : gTr n ltf0 0 0 0 5 0 ; l a sae( . , . , . )
g S ae( . , . , . ) lc lf1 0 2 0 3 0 ; glt ie b ( . g Orh ( . 1 u W r Cu e 0 2 l t o 一10, .
0 ; gRoae(9. , . , 0 0.) ) l ttf1 5 1 0 0. , 0 ;
侧视图 : gTr n ltf0 0 0 0 5 0 ; l a sae( . , . , .) gRoae(0 0 10 0 0 0.) 】 ttf9 . , . , . , 0 ; g ̄ke(. ,. , .)guWi C b (.t l q f10 20 30 ;lt r u e0 2 l e gOrh ( 10 10 一1 0 1 0 1 5 2 0 ; l t o . , . , . , . , . ,0.) 俯 视 图 : gTr n Itf0 0, . , 5.) l a sae( . 0 0 一 0 ; gRoa e(0 0 0. , 0 0.) l t tf9 . , 0 1 , 0 ; g ̄ ae( 02 0 30 ;lt rCu e0 2 l l 1 ,. , .)guWJ f e b(. gO t o 10 1 0 10 10 15 2 .) l rh ( . , . , . , . , . ,0 0 ;
0 g Roa e(0 0 10 0 0, . ) l ttf5 . , . , . 10 ; gu W ie b ( .) l r su ~1 0 lt rCu e 1 0 ;g F u t m( . ,
1. 0, 1. 1. 1. 2 0 0, 0, 5, 0.
可 见 图 4,图 5, 6。 图
相关文档
最新文档