坐标变换

坐标变换和OpenGL矩阵

       一、理解坐标变换

       变换允许我们移动、旋转和操作3D世界中的实体。变换的一项功能就是可以将3D坐标系投影到一个2D屏幕上;而它的另一项功能平移、旋转和缩放的理论基础。虽然这些变换表面上好像是直接对物体进行的改变,但事实上变换所改变的是被变换物体的坐标系。例如,当旋转了一个模型的坐标系,在绘制模型时,就好像模型被旋转了。相似的,当将一个模型从坐标原点平移到距离原点100个距离单位的一点,在绘制时,模型就感觉离开了视点100个距离单位。

       绘制3D场景时,顶点在最终被绘制到屏幕上之前,要经过三种类型的变换:

       (1)视图变换。设定视点位置。

       (2)模型变换。在场景种移动物体。

       (3)投影变换。定义视体和剪裁平面。

       另外还有一个附加的变换叫视区变换,它被用来将3D场景的2D投影映射到计算机屏幕的窗口中去。不把视区变换归为顶点将要经过的变换,是因为视区变换其实是与绘制窗口更有关系。此外,还将讨论另一种变换:模型视图变换。它可以被认为是视图变换和模型变换的合并。

       在实际中实现这些变换时,必须按照严格的顺序来执行。视图变换必须在模型变换之前进行,投影变换和视区变换可以在绘制之前的任何时候进行。

       顶点数据(x,y,z,w)->模型视图矩阵->眼坐标->投影矩阵->裁剪坐标->透视分割->归一化设备坐标->视区变换窗->窗口坐标(x,y)。

       1、视点和眼坐标

       对于OpenGL中的变换和观察,最重要的概念之一就是视点坐标系或者叫做眼坐标系。眼坐标系其实就是笛卡尔坐标系在视点上的应用。在OpenGL中,默认的视点始终朝向z轴的负方向。

       无论进行何种变换,眼坐标系始终保持不变。例如,旋转一个物体时,其实是在相应于眼坐标系旋转物体的局部坐标系。如果要将一个三角形逆时针旋转45度,就应该将三角形的局部坐标系逆时针旋转45度。

       理解眼坐标对于掌握OpenGL变换是很重要的。我们将要讨论3D世界中如何通过改变当前坐标来任意的变换物体。



2、视图变换

       视图变换是最先应用于场景的变换,用来定位和定向视点。正如已经讨论过的,视点的默认方向是指向z轴的负方向。而其位置位于原点(0,0,0)。可以通过平移和旋转命令来改变视点的位置和指向,这实际上就是在进行视图变换操作。

       要记住视图变换必须在其他任何变换之前完成。这是因为这一变换相对于眼坐标系改变了当前的坐标系。任何其他的变换操作都是基于这个修改过的当前坐标系来进行的。

       那么如何进行视图变换呢?首先,必须清理当前矩阵。这可以通过glLoadIdentity()函数命令来完成,其函数定义如下所示:

       void glLoadIdentity(void);

       此函数将当前矩阵设置为单位矩阵,这一步是必须的,因为绝大多数的变换命令都是要操作当前矩阵并为其设置各自的值。如果没有此步骤,就可能引起意想不到的结果,因此必须记住清理矩阵。

       初始化当前矩阵之后,就可以用几种不同的方法来生成视图矩阵。一种方法就是让视图矩阵等于单位矩阵。这样就会应用视点默认的位置和方向,视点位于原点,指向z轴的负方向。其他的方法如下所示:

       (1)使用gluLookAt()函数指定一条延伸自视点的视线。此函数封装了一系列平移和旋转命令。

       (2)使用平移和旋转模型变换命令,即glTranslate*()和glRotate*()函数,此方法就是相对于一个静止的视点来移动3D世界中的物体。

       (3)定制自己的坐标系,使用平移和旋转创建自己的视点轨迹(例如,为视点绕某一物体旋转的场景定制极坐标系)。

       gluLookAt()函数的使用

       因为我们还未讨论过模型变换,就先介绍下gluLookAt()函数,其定义如下所示:

       void gluLookAt(GLdouble eyex, GLdoubleeyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdoubleupx, GLdouble upy, GLdouble upz);

       可以使用此函数定义视点的位置和方向。最前面的三个参数(eyex,eyey,eyez)用以指定视点的位置。值(0,0,0)自然就是指原点。紧接着的三个参数(centerx,centery,centerz)定义视点的指向,也叫做视线。一般此组参数是指当前所观察场景的中央点的坐标值。最后的三个参数(upx,upy,upz)表示一个矢量,标识哪一个方向是上方。



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值