OpenGL中的变换

转载 2012年03月29日 20:50:49
 OpenGL变换包括计算机图形学中最基本的三维变换,即几何变换、投影变换、裁剪变换、视口变换。实际上,从三维空间到二维平面,就如同用相机拍照一样,通常都要经历以下几个步骤(括号内表示的是相应的图形学概念):
  第一步,将相机置于三角架上,让它对准三维景物(视点变换,Viewing Transformation)。
  第二步,将三维物体放在适当的位置(模型变换,Modeling Transformation)。
  第三步,选择相机镜头并调焦,使三维物体投影在二维胶片上(投影变换,Projection Transformation)。
  第四步,决定二维像片的大小(视口变换,Viewport Transformation)。
  这样,一个三维空间里的物体就可以用相应的二维平面物体表示了,也就能在二维的电脑屏幕上正确显示了。

1. 几何变换

    视点变换和模型变换本质上都是一回事,即图形学中的几何变换。只是视点变换一般只有平移和旋转,没有比例变换。当视点进行平移或旋转时,视点坐标系中的物体就相当于在世界坐标系中作反方向的平移或旋转。因此,从某种意义上讲,二者可以统一,只是各自出发点不一样而已。

      视点变换是在视点坐标系中进行的。视点坐标系于一般的物体所在的世界坐标系不同,它遵循左手法则,即左手大拇指指向Z正轴,与之垂直的四个手指指向X正轴,四指弯曲90度的方向是Y正轴。而世界坐标系遵循右手法则的。当矩阵初始化glLoadIdentity()后,调用glTranslatef()作视点变换。通常相机位置缺省值同场景中的物体一样,都在原点处,而且相机初始方向都指向Z负轴。这里相机移走后,仍然对准立方体。如果相机需要指向另一方向,则调用glRotatef()可以改变。

      模型变换是在世界坐标系中进行的。在这个坐标系中,可以对物体实施平移glTranslatef()、旋转glRotatef()和放大缩小glScalef()。     

1)平移
  平移变换函数:void glTranslate{fd}(TYPE x,TYPE y,TYPE z)

  三个函数参数就是目标分别沿三个轴向平移的偏移量。

2)旋转
  旋转变换函数:void glRotate{fd}(TYPE angle,TYPE x,TYPE y,TYPE z)

  函数中第一个参数是表示目标沿从点(x, y, z)到原点的方向逆时针旋转的角度,后三个参数是旋转的方向点坐标。

3)缩放和反射变换函数如下:

  void glScale{fd}(TYPE x,TYPE y,TYPE z)

  三个函数参数值就是目标分别沿三个轴向缩放的比例因子。这个函数表示用这三个比例因子生成的矩阵乘以当前矩阵。这个函数能完成沿相应的轴对目标进行拉伸、压缩和反射三项功能。当参数是(1.0, 1.0, 1.0)时,表示对函数glScale*()操作是单位矩阵,也就是对物体没有影响。当其中某个参数为负值时,表示将对目标进行相应轴的反射变换,且这个参数不为1.0,则还要进行相应轴的缩放变换。

2. 投影变换

      投影变换是一种很关键的图形变换,OpenGL中只提供了两种投影方式,一种是正射投影,另一种是透视投影。不管是调用哪种投影函数,为了避免不必要的变换,其前面必须加上以下两句:
  glMAtrixMode(GL_PROJECTION);
  glLoadIdentity();
  事实上,投影变换的目的就是定义一个视景体,使得视景体外多余的部分裁剪掉,最终图像只是视景体内的有关部分。

1)正射投影(Orthographic Projection)
  正射投影,又叫平行投影。这种投影的视景体是一个矩形的平行管道,也就是一个长方体,如图8-9所示。正射投影的最大一个特点是无论物体距离相机多远,投影后的物体大小尺寸不变。

i  void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,
      GLdouble near,GLdouble far)
ii  void gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top)
它是一个特殊的正射投影函数,主要用于二维图像到二维屏幕上的投影。它的near和far缺省值分别为-1.0和1.0,所有二维物体的Z坐标都为0.0。因此它的裁剪面是一个左下角点为(left,bottom)、右上角点为(right,top)的矩形。

2)透视投影

 i  void glFrustum(GLdouble left,GLdouble Right,GLdouble bottom,GLdouble top,
      GLdouble near,GLdouble far);

 ii void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear, GLdouble zFar);
3. 视口变换
  在前面几节内容中已相继提到过视口变换,这一节将针对OpenGL来讲述视口变换的原理及其相关函数的用法。运用相机模拟方式,我们很容易理解视口变换就是类似于照片的放大与缩小。在计算机图形学中,它的定义是将经过几何变换、投影变换和裁剪变换后的物体显示于屏幕窗口内指定的区域内,这个区域通常为矩形,称为视口。
  glViewport(GLint x,GLint y,GLsizei width, GLsizei height);

注意:在实际应用中,视口的长宽比率总是等于视景体裁剪面的长宽比率。如果两个比率不相等,那么投影后的图像显示于视口内时会发生变形。另外,屏幕窗口的改变一般不明显影响视口的大小。因此,在调用这个函数时,最好实时检测窗口尺寸,及时修正视口的大小,保证视口内的图像能随窗口的变化而变化,且不变形。

在代码中视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投影变化的视口变化。

 

 

 视觉坐标系是一个左手坐标系,该坐标系是可以活动的。在初始态下,其原点及x,y轴分别与世界坐标系的原点及x,y轴重合,而z轴则正好相反,即为垂直屏幕面向内。

    

造型变换

    造型变换有三个基本的OpenGL命令:

    glTranslate*() 平移

    glRotate*() 旋转

    glScale*() 缩放

    OpenGL自动计算这三个命令的平移、旋转和缩放矩阵,这些命令的作用等价于调用glMultMatrix*(),参数设置为相应的矩阵。但前者比后者计算要快。

    void glTranslate*(TYPE x,TYPEy,TYPEz);

    该函数以平移矩阵乘当前矩阵。

   x,y,z指定沿世界坐标系xyz轴的平移量。

    void glRotate*(TYPE angle,TYPE x,TYPEy,TYPEz);

    该函数以旋转矩阵乘当前矩阵,其中:

    angle 指定旋转的角度(以度为单位)。

   x,y,z指定旋转轴向量的三个分量(该向量位于世界坐标系中)。

    void glScale*(TYPEx,TYPEy,TYPEz);

    该函数以缩放矩阵乘当前矩阵,xyz指定沿xyz轴的比例因子。

  • 视图变换

    视图变换改变视点的位置和方向,也就是改变视觉坐标系。在世界坐标系中,视点和物体的位置是一个相对的关系,对物体作一些平移、旋转变换,必定可以通过对视点作相应的平移、旋转变换来达到相同的视觉效果。完成视图变换可以有以下几种方法:

   (1).利用一个或几个造型变换命令(即glTranslate*()和glRotate*())。由于这些命令也是在GL_MODELVIEW状态下执行的,所以较难和那些造型变换命令区分开来,移动视点的变换和移动物体的变换很容易混淆。为了便于建立清晰的物体和场景模型,可以认为只有其中一个变换在起作用,比如认为只有模型变换的话,那么glTranslate*()和glRotate*()将统一被视为对物体的变换。

    (2).利用实用库函数gluLookAt()设置视觉坐标系。在实际的编程应用中,用户在完成场景的建模后,往往需要选择一个合适的视角或者不停地变换视角,以对场景作观察。实用库函数gluLookAt()就提供了这样的一个功能。

void gluLookAt(GLdouble 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 指定视点向上的方向



   函数gluLookAt()的设置

    视点E、参考点C、视点向上的方向U实际上就是设定了一个视觉坐标系。这个视觉坐标系的原点是E,视线的方向(即z轴)是C-Ey轴方向就是视点向上的方向U,剩下的x轴方向就是向量((C-E)*U)。由于y轴和x轴是垂直的,所以也要求向量(C-U)和U互相垂直。这点在设置该函数参数时是必须注意的。

    (3).创建封装旋转和平移命令的实用函数。有些应用需要用简便方法指定视图变换的定制函数。例如,在飞机飞行中指定滚动、俯仰和航向旋转角,或对环绕对象运动的照相机指定一种利用极坐标的变换。

投影变换

    投影变换就是要确定一个取景体积,其作用有两个:

    1). 确定物体投影到屏幕的方式,即是透视投影还是正交投影。

    2). 确定从图象上裁剪掉哪些物体或物体的某些部分。

    投影变换包括透视投影和正交投影(平行投影)。

  • 透视投影

    透视投影的示意图如下,其取景体积是一个截头锥体,在这个体积内的物体投影到锥的顶点,用glFrustum()函数定义这个截头锥体,这个取景体积可以是不对称的,计算透视投影矩阵M,并乘以当前矩阵C,使C=CM

void glFrustum(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);

该函数以透视矩阵乘当前矩阵

left, right指定左右垂直裁剪面的坐标。

bottom,top指定底和顶水平裁剪面的坐标。

near,far指定近和远深度裁剪面的距离,两个距离一定是正的。



透视投影示意图

 

  • 正交投影

    正交投影的示意图见下:其取景体积是一个各面均为矩形的六面体,用glOrtho()函数创建正交平行的取景体积,计算正交平行取景体积矩阵M,并乘以当前矩阵C,使C=CM

    void glOrtho(Gldouble left,Gldouble right,Gldouble bottom,Gldouble top,Gldouble near,Gldouble far);

    该函数以正交投影矩阵乘当前矩阵。



      正交投影示意图

 

    对于二维情况,glu库函数提供glOrtho2D命令用于二维图象的投影:

    void gluOrtho2D(Gldouble left,Gldouble right,Gldouble bottom,Gldouble top);

    该函数创建一个二维投影矩阵M,裁剪平面是左下角坐标为(left,bottom)、右上角坐标为(right,top)的矩形。

    在通过视图造型矩阵和投影矩阵变换场景中对象的顶点后,任何位于取景体积外的顶点都被裁剪掉。除此之外,还可指定附加的任意位置的裁剪面,对场景中的物体作进一步的裁剪选择。

opengl复合变换

  • 2012年06月20日 11:24
  • 1KB
  • 下载

openGL 各种坐标矩阵变换

  • 2013年04月01日 12:35
  • 67KB
  • 下载

[OpenGL ES 03]3D变换:模型,视图,投影与Viewport

[OpenGL ES 03]3D变换:模型,视图,投影与Viewport 罗朝辉 (http://blog.csdn.net/kesalin) 本文遵循“署名-非商业用途-保持一致”创作公用协议 ...
  • kesalin
  • kesalin
  • 2012年12月06日 21:05
  • 30624

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

  • 2011年04月26日 16:49
  • 153KB
  • 下载

从零开始学习OpenGL ES之七 – 变换和矩阵

今天的主题是我一度谈之色变的。概念上讲,它是3D编程中最为困难的部分。   首先,你应该理解 3D 几何和笛卡尔坐标系他。你还应该理解由顶点构成的三角形组成的OpenGL虚拟世界的物体,各...

OpenGL视口变换

  • 2015年05月20日 13:51
  • 12.18MB
  • 下载

MFC Opengl 使用glm数学库进行空间坐标系矩阵变换

求一个空间坐标系的点在另一个坐标系中的点一直是比较麻烦的一件事情,最近做项目时,恰好需要实现这样一个功能,也是想了挺久,最后实现了点在不同空间坐标系中的转换。功能是通过矩阵进行实现的,数学库用的是gl...

OpenGL图形基本变换及拾取

  • 2014年09月19日 09:55
  • 15KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OpenGL中的变换
举报原因:
原因补充:

(最多只允许输入30个字)