单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,OpenGL,图形编程,武汉纺织大学数学与计算机学院,授课教师:陈永强 教授,3.OpenGL二维观看与三维变换,3.1二维观看,3.2三维变换,3,3.1OpenGL二维观看,实现二维观看的步骤:,指定矩阵堆栈,指定裁剪窗口,指定视区,4,指定矩阵堆栈,指定当前操作的是投影矩阵堆栈,glMatrixModeGL_PROJECTION;,初始化,即指定当前操作的矩阵堆栈的栈顶元素为单位矩阵。,glLoadIdentity;,5,指定裁剪窗口,定义二维裁剪窗口,gluOtho2D(xwmin,xwmax,ywmin,ywmax,);,其中,双精度浮点数,xwmin,xwmax,ywmin,ywmax,分别对应裁剪窗口的左、右、下、上四条边界。,默认的裁剪窗口,四条边界分别为,wxl,=-1.0,wxr,=1.0,wyt=-1.0,wyb=1.0,。,6,指定视区,指定视区,glViewPortxvmin,yvmin,vpWidth,vpHeighht;,xvmin和yvmin指定了对应于屏幕上显示窗口中的矩形视区的左下角坐标,单位为像素。,整型值vpWidth和vpHeighht则指定了视区的宽度和高度。,默认的视区大小和位置与显示窗口保持全都。,3.1OpenGL二维观看,例子,教材,【,程序,6-2】,8,变换种类,模型视图矩阵,矩阵操作,矩阵堆栈,投影变换,剪切变换,3.2OpenGL,中的变换,9,视图变换:指定观看者或摄影机的位置;,模型变换:在场景中移动对象;,模型视图变换:描述视图变换与模型变换的对偶性;,投影变换:对视见空间进展修剪和转变大小;,视见区变换:对窗口的最终输出进展缩放;,变换种类,10,视图变换:指定观看者或摄影机的位置;,视图变换是第一个应用到场景上的变换。它用于确定场景的有利位置。默认状况下,观看点位于原点,顺着z轴的负向看。视图变换使你可以将观看点放置在任何期望的位置上,从任何方向进展观看。确定视图变换相当于在场景中放置一部摄像机并确定其指向。,在工作时间表上,必需先指定视图变换再指定其他任何变换。,变换种类,11,模型变换:在场景中移动对象;,模型变换用于处理模型和模型内的特定对象。这些变换把对象移动到适宜的位置,旋转它们,并对它们进展缩放。模型变换实际上就是几何变换。,变换种类,12,模型视图变换:描述视图变换与模型变换的对偶性;,从内部效果和它们对场景最终外观的效果来说,视图变换和模型变换是一样的,把这两者分开完全是为了程序员的便利,向后移动对象和向前移动参考系之间并没有本质差异。术语“模型视图”表示你可以把这类变换视为模型变换或视图变换,但实际上并无区分,因此称它为模型视图变换。,变换种类,13,投影变换:对视见空间进展修剪和转变大小;,投影变换应用到最终的模型视图方向。投影实际上定义了视见空间并建立了修剪平面。更明确一些,投影变换指定已完成场景如何转换成屏幕上的最终图象。常用的投影变换包括 正投影和透视投影。,变换种类,14,视见区变换:对窗口的最终输出进展缩放;,把场景的一个二维投影映射到屏幕上某处的窗口。这个到物理窗口坐标的映射是最终完成的一项变换,它称为视见区变换。,变换种类,15,在计算机图形学中,全部的变换都是通过矩阵乘法来实现的,立刻物体顶点构成的齐次坐标矩阵乘以三维变换矩阵就得到了变换后的物体顶点的齐次坐标矩阵,这样只要求出物体的三维变换矩阵,就可以得到变换后的物体。,在OpenGL中,对象的坐标变换也通过矩阵来实现的虽然并不愿定要自己定义矩阵。通常,在OpenGL中使用了两个重要的矩阵:模型视图矩阵和投影矩阵,其中模型视图矩阵用于物体的模型视图变换,投影矩阵用于投影变换。,变换种类,16,有了模型视图矩阵和投影矩阵,在OpenGL中从未加工的顶点数据到屏幕坐标的过程就包括如下步骤:,1.将顶点坐标转换为标准化齐次坐标矩阵;,2.将顶点的标准化齐次坐标矩阵乘以模型视图矩阵,生成变换后的顶点齐次坐标矩阵;,3.将变换后的顶点齐次坐标矩阵乘以投影矩阵,生成修剪坐标矩阵,这样就有效地排解了视见空间之外的全部数据。,4.由修剪坐标除以w坐标,得到规格化的设备坐标。留意,在变换过程中,模型视图矩阵和投影视图矩阵都有可能转变坐标的 w 值。,5.坐标三元组被视见区变换影射到一个2D平面。这也是一个矩阵变换,但在OpenGL中不能直接指定或修改它,系统会依据指定给 glViewport 的值在内部设置它。,变换种类,17,模型视图矩阵用于指定场景的视图变换和几何变换,模型视图矩阵是一个44的矩阵,它代表了用来放置和定位对象的经过变换的坐标系。,在计算机图形学中,物体进展的几何变换可以分解成多个根本几何变换,而三维几何变换矩阵是多个根本几何变换矩阵相乘的结果。,OpenGL供给了一些函数用于把任意矩阵设置成当前操作的矩阵模型视图矩阵或投影矩阵。,模型视图矩阵,18,glfloat m=1.0f,0.0f,3.0f,0.0f,0.0f,1.0f,0.0f,1.0f,0.0f,0.0f,1.0f,1.0f,0.0f,0.0f,0.0f,1.0f,;,glMatrixMode(GL_MODELVIEW);,glLoadMatrixf(m);,这段程序中,先声明白一个数组来保存 44 矩阵的值,留意这里矩阵按列优先挨次保存,这意味着先从上往下遍历每一列;,然后使用glLoadMatrix函数将定义的矩阵设置为当前操作的矩阵。,模型视图矩阵,19,假设需要执行变换,即把定义的矩阵乘到模型视图矩阵中。,可以使用函数 glMultmatrix,其函数原型如下:,void glMultMatrixfd(const TYPE*m);,参数 m 为一个以列优先挨次保存16个连续值的数组。,模型视图矩阵,20,平移,旋转,比例,模型视图矩阵,21,平移,void glTranslatefd(TYPE x,TYPE y,TYPE z);,参数,x,y,z,就是目标分别沿三个轴的正向平移的偏移量。这个函数用这三个偏移量生成的矩阵完成乘法。,当参数是,(0.0,0.0,0.0),时,生成的矩阵是单位矩阵,此时对物体没有影响。,模型视图矩阵,22,旋转,void glRotatefd(TYPE angle,,,TYPE x,,,TYPE y,,,TYPE z),;,函数中第一个参数是表示目标沿从原点到指定点,(x,y,z),的方向矢量逆时针旋转的角度,后三个参数则是指定旋转方向矢量的坐标。这个函数表示用这四个参数生成的矩阵完成乘法。,当角度参数是,0.0,时,表示对物体没有影响。,模型视图矩阵,23,比例,void glScalefd(TYPE x,TYPE y,TYPE z);,三个参数值就是目标分别沿三个轴向缩放的比例因子。这个函数用这三个比例因子生成的矩阵完成乘法。,这个函数能完成沿相应的轴对目标进展拉伸、压缩和反射三项功能。,当参数是(1.0,1.0,1.0)时,对物体没有影响。,当其中某个参数为负值时,表示将对目标进展相应轴的反射变换,且这个参数不为1.0,则还要进展相应轴的缩放变换。,最好不要令三个参数值都为零,这将导致目标沿三轴都缩为零。,模型视图矩阵,模型视图矩阵,视图变换函数定义观看坐标系,void gluLookAtGLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz;,视点位置:eyex,eyey,eyez),参考点位置:centerx,centery,centerz),向上矢量方向:(upx,upy,upz),模型视图矩阵,例子,红皮书,cube.c,model.c,26,矩阵操作,矩阵堆栈选择,glMatrixMode(GLenum,mode),;,参数,mode,用于确定将哪个矩阵堆栈用于矩阵操作。,GL_MODELVIEW:,模型视图矩阵堆栈,GL_PROJECTION:,投影矩阵堆栈,GL_TEXTURE:,纹理矩阵堆栈,27,矩阵操作,通过上述的高级矩阵函数,可以很便利地实现变换。,问题:在调用函数时,修改的是当前的模型视图矩阵。新的矩阵随后将成为当前的模型视图矩阵并影响此后绘制的图形。这样模型视图矩阵函数在调用时,就会造成效果的积存。,28,矩阵操作,效果积存,一段代码:,/沿 x 轴正向移动 10 个单位,glTranslatef(10.0f,0.0f,0.0f);,glutSolidSphere(1.0f,15,15);,/沿 y 轴正向移动 10 个单位,glTranslatef(0.0f,10.0f,0.0f);,glutSolidSphere(1.0f);,这段代码绘制了两个球,第一个绘制的球的球心沿x轴正向移动了10个单位,而其次球不仅沿y轴正向移动10个单位,也沿x轴正向移动10个单位。这就是效果积存。,矩阵操作,单位矩阵,glTranslatef(10.0f,0.0f,0.0f);,glutSolidSphere(1.0f,15,15);,glTranslatef(0.0f,10.0f,0.0f);,glutSolidSphere(1.0f,15,15);,想要其次个球只沿 y 轴正向移动 10 个单位,一种简洁的方法是把模型矩阵复位,即通过给模型视图矩阵加载上单位矩阵来复位原点。,glMatrixMode(GL_MODELVIEW);,glLoadIdentity();,30,矩阵堆栈,实际上,在创立、装入、相乘模型变换和投影变换矩阵时,都已用到堆栈操作。,一般说来,矩阵堆栈常用于构造具有继承性的模型,即由一些简洁目标构成简洁模型。而在构造简洁模型时,常常需要保存中间的变化状态,以便在进展一些变换后能够恢复。,31,矩阵堆栈,OpenGL为模型视图矩阵和投影矩阵各维护着一个“矩阵堆栈”,可以把当前矩阵压到堆栈中保存它,然后对当前矩阵进展修改。把矩阵弹出堆栈即可恢复。使用的函数如下:,void glPushMatrix(void);,void glPopMatrix(void);,32,矩阵堆栈,函数 glPushMatrix 用于将当前矩阵压入当前矩阵堆栈,常用于保存当前变换矩阵。,函数 glPopMatrix 用于将最终一个最顶上的矩阵弹出当前矩阵堆栈,常用于恢复当前变换矩阵原先的状态,假设曾经调用 glPushMatrix 把它保存起来的话。,33,矩阵堆栈,堆栈是有深度的,假设超出了堆栈深度或当堆栈为空时试图弹出一个矩阵值,都会发生错误。,可以用下面的函数猎取堆栈深度的最大值:,glGet(GL_MAX_MODELVIEW_STACK_DEPTH);,glGet(GL_MAX_PROJECTION_STACK_DEPTH);,34,投影变换,OpenGL中只供给了两种投影方式,一种是平行投影正射投影,另一种是透视投影。在投影变换之前必需指定当前处理的是投影变换矩阵:,glMatrixMode(GL_PROJECTION);glLoadIdentity;,35,投影变换,平行投影,视景体是一个矩形的平行管道,也就是一个长方体,其特点是无论物体距离相机多远,投影后的物体大小尺寸不变。,OpenGL,中平行投影函数共有两个:,glOrtho,gluOrtho2D,36,投影变换,void glOrtho(GLdouble left,GLdouble right,,GLdouble bottom,GLdouble top,,GLdouble near,GLdouble far);,函数的操作是创立一个正射投影矩阵,并且用这个矩阵乘以当前矩阵。,近裁剪平面是一个