`
hereson3
  • 浏览: 162962 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

OpenGL坐标变换专题

阅读更多

OpenGL通过相机模拟、可以实现计算机图形学中最基本的三维变换,即几何变换、投影变换、裁剪变换、视口变换等,同时,OpenGL还实现了矩阵堆栈等。理解掌握了有关坐标变换的内容,就算真正走进了精彩地三维世界。

一、OpenGL中的三维物体的显示

(一)坐标系统

在现实世界中,所有的物体都具有三维特征,但计算机本身只能处理数字,显示二维的图形,将三维物体及二维数据联系在一起的唯一纽带就是坐标。

为了使被显示的三维物体数字化,要在被显示的物体所在的空间中定义一个坐标系。这个坐标系的长度单位和坐标轴的方向要适合对被显示物体的描述,这个坐标系称为世界坐标系。世界坐标系是始终固定不变的。

OpenGL还定义了局部坐标系的概念,所谓局部坐标系,也就是坐标系以物体的中心为坐标原点,物体的旋转或平移等操作都是围绕局部坐标系进行的,这 时,当物体模型进行旋转或平移等操作时,局部坐标系也执行相应的旋转或平移操作。需要注意的是,如果对物体模型进行缩放操作,则局部坐标系也要进行相应的 缩放,如果缩放比例在案各坐标轴上不同,那么再经过旋转操作后,局部坐标轴之间可能不再相互垂直。无论是在世界坐标系中进行转换还是在局部坐标系中进行转 换,程序代码是相同的,只是不同的坐标系考虑的转换方式不同罢了。

计算机对数字化的显示物体作了加工处理后,要在图形显示器上显示,这就要在图形显示器屏幕上定义一个二维直角坐标系,这个坐标系称为屏幕坐标系。这个坐标系坐标轴的方向通常取成平行于屏幕的边缘,坐标原点取在左下角,长度单位常取成一个象素。

(二)三维物体的相机模拟

为了说明在三维物体到二维图象之间,需要经过什么样的变换,我们引入了相机(Camera)模拟的方式,假定用相机来拍摄这个世界,那么在相机的取景器中,就存在人眼和现实世界之间的一个变换过程。

基于VC++的OpenGL编程讲座之坐标变换
图一、相机模拟OpenGL中的各种坐标变换


从三维物体到二维图象,就如同用相机拍照一样,通常都要经历以下几个步骤:

1、将相机置于三角架上,让它对准三维景物,它相当于OpenGL中调整视点的位置,即视点变换(Viewing Transformation)。

2、将三维物体放在场景中的适当位置,它相当于OpenGL中的模型变换(Modeling Transformation),即对模型进行旋转、平移和缩放。

3、选择相机镜头并调焦,使三维物体投影在二维胶片上,它相当于OpenGL中把三维模型投影到二维屏幕上的过程,即OpenGL的投影变换 (Projection Transformation),OpenGL中投影的方法有两种,即正射投影和透视投影。为了使显示的物体能以合适的位置、大小和方向显示出来,必须要 通过投影。有时为了突出图形的一部分,只把图形的某一部分显示出来,这时可以定义一个三维视景体(Viewing Volume)。正射投影时一般是一个长方体的视景体,透视投影时一般是一个棱台似的视景体。只有视景体内的物体能被投影在显示平面上,其他部分则不能。

4、冲洗底片,决定二维相片的大小,它相当与OpenGL中的视口变换(Viewport Transformation)(在屏幕窗口内可以定义一个矩形,称为视口(Viewport),视景体投影后的图形就在视口内显示)规定屏幕上显示场景的范围和尺寸。

通过上面的几个步骤,一个三维空间里的物体就可以用相应的二维平面物体表示了,也就能在二维的电脑屏幕上正确显示了。总的来说,三维物体的显示过程如下:

基于VC++的OpenGL编程讲座之坐标变换
图二、三维物体的显示过程

二、OpenGL中的几种变换

   OpenGL中的各种转换是通过矩阵运算实现的,具体的说,就是当发出一个转换命令时,该命令会生成一个4X4阶的转换矩阵(OpenGL中的物体坐标 一律采用齐次坐标,即(x, y, z, w),故所有变换矩阵都采用4X4矩阵),当前矩阵与这个转换矩阵相乘,从而生成新的当前矩阵。例如,对于顶点坐标v ,转换命令通常在顶点坐标命令之前发出,若当前矩阵为C,转换命令构成的矩阵为M,则发出转换命令后,生成的新的当前矩阵为CM,这个矩阵再乘以顶点坐标 v,从而构成新的顶点坐标CMv。上述过程说明,程序中绘制顶点前的最后一个变换命令最先作用于顶点之上。这同时也说明,OpenGL编程中,实际的变换 顺序与指定的顺序是相反的。

(一)视点变换

视点变换确定了场景中物体的视点位置和方向,就向上边提到的,它象是 在场景中放置了一架照相机,让相机对准要拍摄的物体。确省时,相机(即视点)定位在坐标系的原点(相机初始方向都指向Z负轴),它同物体模型的缺省位置是 一致的,显然,如果不进行视点变换,相机和物体是重叠在一起的。

执行视点变换的命令和执行模型转换的命令是相同的,想一想,在用相机 拍摄物体时,我们可以保持物体的位置不动,而将相机移离物体,这就相当于视点变换;另外,我们也可以保持相机的固定位置,将物体移离相机,这就相当于模型 转换。这样,在OpenGL中,以逆时针旋转物体就相当于以顺时针旋转相机。因此,我们必须把视点转换和模型转换结合在一起考虑,而对这两种转换单独进行 考虑是毫无意义的。
除了用模型转换命令执行视点转换之外,OpenGL实用库还提供了gluLookAt()函数,该函数有三个变量,分别定义了视点的位置、相机瞄准方向的参考点以及相机的向上方向。该函数的原型为:

void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble upx,GLdouble upy,GLdouble upz);


该函数定义了视点矩阵,并用该矩阵乘以当前矩阵。eyex,eyey,eyez定义了视点的位置;centerx、centery和centerz变量指定了参考点的位置,该点通常为相机所瞄准的场景中心轴线上的点;upx、upy、upz变量指定了向上向量的方向。

通常,视点转换操作在模型转换操作之前发出,以便模型转换先对物体发生作用。场景中物体的顶点经过模型转换之后移动到所希望的位置,然后再对场景进行视点定位等操作。模型转换和视点转换共同构成模型视景矩阵。

(二)模型变换

模型变换是在世界坐标系中进行的。缺省时,物体模型的中心定位在坐标系的中心处。OpenGL在这个坐标系中,有三个命令,可以模型变换。

1、模型平移

glTranslate{fd}(TYPE x,TYPE y,TYPE z);


该函数用指定的x,y,z值沿着x轴、y轴、z轴平移物体(或按照相同的量值移动局部坐标系)。

2、模型旋转

glRotate{fd}(TYPE angle,TYPE x,TYPE,y,TYPE z);


该函数中第一个变量angle制定模型旋转的角度,单位为度,后三个变量表示以原点(0,0,0)到点(x,y,z)的连线为轴线逆时针旋转物体。例如,glRotatef(45.0,0.0,0.0,1.0)的结果是绕z轴旋转45度。

3、模型缩放

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


该函数可以对物体沿着x,y,z轴分别进行放大缩小。函数中的三个参数分别是x、y、z轴方向的比例变换因子。缺省时都为1.0,即物体没变化。程序中物体Y轴比例为2.0,其余都为1.0,就是说将立方体变成长方体。

(三)投影变换

经过模型视景的转换后,场景中的物体放在了所希望的位置上,但由于显示器只能用二维图象显示三维物体,因此就要靠投影来降低维数(投影变换类似于选择相机的镜头)。

事实上,投影变换的目的就是定义一个视景体,使得视景体外多余的部分裁剪掉,最终进入图像的只是视景体内的有关部分。投影包括透视投影(Perspective Projection)和正视投影(Orthographic Projection)两种。

透视投影,符合人们心理习惯,即离视点近的物体大,离视点远的物体小,远到极点即为消失,成为灭点。它的视景体类似于一个顶部和底部都被进行切割过的棱椎,也就是棱台。这个投影通常用于动画、视觉仿真以及其它许多具有真实性反映的方面。

OpenGL透视投影函数有两个,其中函数glFrustum()的原型为:

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


它创建一个透视视景体。其操作是创建一个透视投影矩阵,并且用这个矩阵乘以当前矩阵。这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐 标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的Z负值,其左下角点和右上角点空 间坐标由函数根据透视投影原理自动生成。near和far表示离视点的远近,它们总为正值。该函数形成的视景体如图三所示。

基于VC++的OpenGL编程讲座之坐标变换(2)
图三、透视投影视景体


另一个透视函数是:

void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear, GLdouble zFar);


它也创建一个对称透视视景体,但它的参数定义于前面的不同,参数fovy定义视野在X-Z平面的角度,范围是[0.0, 180.0];参数aspect是投影平面宽度与高度的比率;参数zNear和Far分别是远近裁剪面沿Z负轴到视点的距离,它们总为正值。

基于VC++的OpenGL编程讲座之坐标变换(2)
图四、透视投影视景体


以上两个函数缺省时,视点都在原点,视线沿Z轴指向负方向。

正射投影,又叫平行投影。这种投影的视景体是一个矩形的平行管道,也就是一个长方体,如图五所示。正射投影的最大一个特点是无论物体距离相机多远,投影 后的物体大小尺寸不变。这种投影通常用在建筑蓝图绘制和计算机辅助设计等方面,这些行业要求投影后的物体尺寸及相互间的角度不变,以便施工或制造时物体比 例大小正确。

基于VC++的OpenGL编程讲座之坐标变换(2)
图五、正射投影视景体


OpenGL正射投影函数也有两个,一个函数是:

void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top, GLdouble near,GLdouble far)


它创建一个平行视景体。实际上这个函数的操作是创建一个正射投影矩阵,并且用这个矩阵乘以当前矩阵。其中近裁剪平面是一个矩形,矩形左下角点三维空间坐 标是(left,bottom,-near),右上角点是(right,top,-near);远裁剪平面也是一个矩形,左下角点空间坐标是 (left,bottom,-far),右上角点是(right,top,-far)。所有的near和far值同时为正或同时为负。如果没有其他变换, 正射投影的方向平行于Z轴,且视点朝向Z负轴。这意味着物体在视点前面时far和near都为负值,物体在视点后面时far和near都为正值。

另一个函数是:

void gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top)


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

(四)视口变换。

视口变换就是将视景体内投影的物体显示在二维的视口平面上。运用相机模拟方式,我们很容易理解视口变换就是类 似于照片的放大与缩小。在计算机图形学中,它的定义是将经过几何变换、投影变换和裁剪变换后的物体显示于屏幕窗口内指定的区域内,这个区域通常为矩形,称 为视口。OpenGL中相关函数是:

glViewport(GLint x,GLint y,GLsizei width, GLsizei height);


这个函数定义一个视口。函数参数(x, y)是视口在屏幕窗口坐标系中的左下角点坐标,参数width和height分别是视口的宽度和高度。缺省时,参数值即(0, 0, winWidth, winHeight) 指的是屏幕窗口的实际尺寸大小。所有这些值都是以象素为单位,全为整型数。

(5)裁剪变换

在OpenGL中,除了视景体定义的六个裁剪平面(上、下、左、右、前、后)外,用户还可自己再定义一个或多个附加裁剪平面,以去掉场景中无关的目标,如图六所示。

基于VC++的OpenGL编程讲座之坐标变换(3)
图六、附加裁剪平面


附加平面裁剪函数为:

1、void glClipPlane(GLenum plane,Const GLdouble *equation);

函数参数equation指向一个拥有四个系数值的数组,这四个系数分别是裁剪平面Ax+By+Cz+D=0的A、B、C、D值。因此,由这四个系数就能确定一个裁剪平面。参数plane是GL_CLIP_PLANEi(i=0,1,...),指定裁剪面号。

在调用附加裁剪函数之前,必须先启动glEnable(GL_CLIP_PLANEi),使得当前所定义的裁剪平面有效;当不再调用某个附加裁剪平面时,可用glDisable(GL_CLIP_PLANEi)关闭相应的附加裁剪功能。

下面这个例子不仅说明了附加裁剪函数的用法,而且调用了gluPerspective()透视投影函数,读者可以细细体会其中的用法。例程如下:

  #include "glos.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
void myinit(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK display(void);
void CALLBACK display(void)
{
GLdouble eqn[4] = {1.0, 0.0, 0.0, 0.0};
glClear(GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 0.0, 1.0);
glPushMatrix();
glTranslatef (0.0, 0.0, -5.0);
/* clip the left part of wire_sphere : x<0 */
glClipPlane (GL_CLIP_PLANE0, eqn);
glEnable (GL_CLIP_PLANE0);
glRotatef (-90.0, 1.0, 0.0, 0.0);
auxWireSphere(1.0);
glPopMatrix();
glFlush();
}
void myinit (void)
{
glShadeModel (GL_FLAT);
}
void CALLBACK myReshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
   gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
}
void main(void)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 500, 500);
auxInitWindow ("Arbitrary Clipping Planes");
myinit ();
auxReshapeFunc (myReshape);
auxMainLoop(display);
}

(六)矩阵栈的操作

在讲述矩阵栈之前,首先介绍两个基本OpenGL矩阵操作函数:

1、void glLoadMatrix{fd}(const TYPE *m)

设置当前矩阵中的元素值。函数参数*m是一个指向16个元素(m0, m1, ..., m15)的指针,这16个元素就是当前矩阵M中的元素,其排列方式如下:

M = | m0 m4 m8 m12 |
| m1 m5 m9 m13 |
| m2 m6 m10 m14 |
| m3 m7 m11 M15 |

2、void glMultMatrix{fd}(const TYPE *m)

用当前矩阵去乘*m所指定的矩阵,并将结果存放于*m中。当前矩阵可以是用glLoadMatrix() 指定的矩阵,也可以是其它矩阵变换函数的综合结果。

OpenGL的矩阵堆栈指的就是内存中专门用来存放矩阵数据的某块特殊区域。一般说来,矩阵堆栈常用于构造具有继承性的模型,即由一些简单目标构成的复 杂模型。矩阵堆栈对复杂模型运动过程中的多个变换操作之间的联系与独立十分有利。因为所有矩阵操作函数如glLoadMatrix()、 glMultMatrix()、glLoadIdentity()等只处理当前矩阵或堆栈顶部矩阵,这样堆栈中下面的其它矩阵就不受影响。堆栈操作函数有 以下两个:

·void glPushMatrix(void);

该函数表示将所有矩阵依次压入堆栈中,顶部矩阵是第二个矩阵的备份;压入的矩阵数不能太多,否则出错。

·void glPopMatrix(void);

该函数表示弹出堆栈顶部的矩阵,令原第二个矩阵成为顶部矩阵,接受当前操作,故原顶部矩阵被破坏;当堆栈中仅存一个矩阵时,不能进行弹出操作,否则出错。

分享到:
评论

相关推荐

    一些学习OpenGL的书籍

    顶点着色器主要负责处理顶点数据,如位置、颜色、纹理坐标等,它们经过变换、光照、投影等处理后,形成最终的片元。片段着色器则负责处理片元的颜色,影响最终像素的输出,包括纹理映射、光照计算等。在现代OpenGL中...

    OpenGL视图中绘制三维物体

    本专题将深入探讨如何在Visual C++ 2008环境下利用OpenGL库来实现三维物体的绘制。 首先,我们需要理解OpenGL的基本概念。OpenGL是一个跨语言、跨平台的编程接口,提供了一系列函数,用于生成和操作图形对象,如点...

    计算机图形学实验教程OpenGL版

    - 介绍了如何从文件中加载图像数据,并将其转换为OpenGL可以使用的格式。 - **1.6.3 LoadTexture() 创建纹理** - 详细说明了如何使用加载的图像数据创建OpenGL纹理对象。 - **1.6.4 在Initialize()里载入纹理** -...

    GLStudio:OpenGL基础入门

    博客教程基础知识章节完成情况√√√√√√√√√√√√ EGL ○坐标系统&图形变换○颜色混合○ √ GLSL语言基础○音视频相机开发专题完成情况√√√GPU图像专题完成情况基础流程框架梳理○视频的展示与处理○画幅...

    程序设计专题实验报告.doc

    【程序设计专题实验报告】 本实验报告主要涵盖了三个程序设计题目,旨在提升学生的程序设计能力,涉及的知识点广泛,包括图形界面设计、数值计算、文件处理、字符串操作、进制转换以及游戏逻辑实现。 首先,第一个...

    图形硬件开发Cg

    本专题的核心是结合OpenGL,一个广泛应用的图形库,来实现基于GPU的加速绘制。 OpenGL是一种跨平台的编程接口,用于渲染2D和3D图形。它允许程序员直接与GPU通信,执行图形渲染任务,如几何变换、光照处理和纹理映射...

    专题资料(2021-2022年)计算机图形学期末考试试卷C卷.doc

    5. **向量和坐标系**:向量在计算机图形学中用于表示方向和位置,齐次坐标提供了一种方便的扩展坐标系统,可以方便地进行变换操作。 6. **颜色理论**:理解颜色的三要素——色调、饱和度和亮度,以及它们如何在屏幕...

    图形学基础

    通过变换矩阵,我们可以将物体从世界坐标系转换到屏幕坐标系,以便于渲染。 接着,我们讨论颜色模型。RGB(红绿蓝)是最常见的颜色模型,用于数字图像表示。此外,还有CMYK(青、洋红、黄、黑)用于印刷,以及HSV...

    使用几何纹理映射快速地形渲染(英文)

    在3D建模软件或自定义的图形程序中,我们可以将高度图转换为3D网格,每个顶点都有其对应的纹理坐标。这些纹理坐标可以编码地形的高度,通过纹理混合技术来实现多样化的表面细节。 在渲染阶段,GPU使用这些纹理坐标...

    计算机图形学 课件下载

    - 这一章通常涉及坐标变换,包括平移、旋转、缩放和投影,以及矩阵在图形变换中的应用,比如齐次坐标和矩阵乘法在图形变换中的作用。 7. **第七章:曲线曲面生成** - "第七章曲线曲面生成.ppt"可能会讲解参数曲线...

    HTML5 3D地图旋转

    3. **加载模型(Geometry)**:将地理数据转化为3D模型,这可能涉及到将地理坐标转换为3D坐标系统。 4. **应用材质和纹理(Material & Texture)**:给3D模型添加颜色和纹理,使其看起来更真实。 5. **创建渲染器...

    行业-专项突破-图形专项+叶寒+(讲义+笔记).rar

    《行业-专项突破-图形专项+叶寒+(讲义+笔记)》是一个关于图形处理技术的专题学习资料,由知名讲师叶寒主讲。这个压缩包包含了一份讲义和笔记,是深入理解和掌握图形专项知识的重要参考资料。下面将详细阐述其中...

    Griphics实例

    在这个专题中,我们将深入探讨Griphics的基本概念、常用库、以及如何通过实例来提升图形处理技能。 1. **Griphics基本概念**: - **图形编程**:是计算机科学的一个分支,主要关注图像的生成、处理和交互。这包括...

    android粒子

    在OpenGL ES中,可以使用`glRotatef()`函数来应用旋转变换,或者使用矩阵操作来实现更复杂的旋转效果。在Android L中,还可以使用`ObjectAnimator`或`ValueAnimator`配合`PropertyValuesHolder`来实现平滑的旋转动画...

    三维游戏引擎开发-渲染

    开发者需要掌握OpenGL的管线原理,包括顶点坐标变换、裁剪、光照、投影等步骤。 5. **3D渲染技术**:包括模型加载、纹理映射、光照计算、视口变换、深度缓冲、帧缓冲对象(FBO)、混合模式等。这些技术共同作用,...

    中山大学计算机图形学课件

    这可能是一本计算机图形学教材的章节摘要,可能包括了图形学的基本概念、坐标系统、图元绘制、2D和3D变换、投影等核心知识点。学生可以通过阅读这些章节来构建完整的图形学知识体系。 3. **ch 5.pdf、ch 7.pdf、ch...

    iOS游戏应用源代码——joshvera-iPhone-Tetris-2dd7365.zip

    这些功能通常通过一系列算法实现,例如,方块的生成可能使用随机数生成器,方块的旋转可能涉及坐标变换,而消除行的判断则需要遍历并分析游戏盘面的状态。 此外,音效和音乐也是游戏体验的重要组成部分。iOS设备...

    精通Qt4编程(第二版)源代码

    \6.2 坐标系统与坐标变换 175 \6.2.1 坐标系统 175 \6.2.2 坐标变换 175 \6.3 用不同的字体 177 \6.4 绘图路径——QPainterPath 180 \6.5 QImage与QPixmap绘图设备 182 \6.5.1 QImage 182 \6.5.2 Pixmap 183 ...

    精通qt4编程(源代码)

    \6.2 坐标系统与坐标变换 175 \6.2.1 坐标系统 175 \6.2.2 坐标变换 175 \6.3 用不同的字体 177 \6.4 绘图路径——QPainterPath 180 \6.5 QImage与QPixmap绘图设备 182 \6.5.1 QImage 182 \6.5.2 Pixmap 183 \6.6 ...

    GIS程序设计实验源码打包

    实验一通常会介绍GIS的基本概念,包括地理坐标系统、投影变换等。源码可能涉及到读取和显示地图数据,比如使用GDAL/OGR库读取栅格和矢量数据。此外,还可能涉及基础的几何对象操作,如点、线、面的创建与查询。 2....

Global site tag (gtag.js) - Google Analytics