OpenGL之视图变换与全局坐标系统学习笔记

夕加加 2011-04-20

8:19---9:00

总结与计划

[OPENGL学习]

[视图和模型变换]

对变换进行的思考

模型变换

视图变换

[投影变换]

透视投影

正投影

视景体裁剪

[视口变换]

视口变换

变换深度坐标

视图变换

时间:

9:34---10:23

其是操作相机.

其包括:相机的位置,方向

其在程序当中的实现为:

移动与旋转两个操作.

在OPENGL当中,对于相机或物体的操作,其均是使用相同的函数.使用相机的模型矩阵.

那怎么样区分哪些是对于相机的操作,哪些是对地物体的操作呢.

扩展:

OPENGL变换,其是属性OPENGLAPP的四大模块当中的:显示模块.

初始模块

显示模块

用户操作模块

结束模块

初始模块:

本地窗口地创建,OPENGL环境的建立,对象的创建

显示模块:

其是场景的建立,包括:相机位置的确定,相机视野大小的确定(投影).

对象在空间当中的位置与方向.

用户操作模块:

响应业务事件,事件处理.

结束模块:

资源释放

==>OPENGL其是一个界面的显示工具,我们在写APP的时候,要去将界面与业务逻辑分层.以便于移植,如:将要使用DX,那也很方便的.

位置:其是由X,Y,Z所确定的,其的改变是通过translatef来进行的.

方向:其是描述相机的朝向,在一个3D空间当中,对象的朝向,其是怎么样描述的,怎么样表达的,怎么样操作的.

[注意:]

在3D空间,我们首先要明白的第一件事:其是使用什么坐标系.

1.相机的坐标系

2.相机的默认位置:原点

3.相机的默认方向 : Z轴的负方向

其分成三个部分来讲解:

1. 基本的模型变换函数 ,用于视图变换,与其的意思

2. 工具函数库:gluLookAt()其定义一条视线,其是封装了一系列的旋转和移动操作.

3. 创建自己的工具函数,对于旋转和移动的封装.其的背景与作用

[1. 基本的模型变换函数]

在OPENGL当中,对于相机(观察点)的变换操作,其是使用模型变换函数来完成的.

1. 要知道哪些是对于相机的操作,哪些是对于物体的操作

2. 对于相机的操作,其本质是对于物体的反操作,如:相机向Z轴的原点向正方向移动5,相当于物体在Z轴的原点向负方便移动5.

小规则:在默认情况下,操作相机向前移动,就是沿Z轴的负方向移动.如果旋转了相机那意思就不同,为什么呢,哪一点.

更简单点:相机不动,而物体动,在显示模块当中,其均是操作物化.

例子:

使用相机与物体之间距离5个单位,其是使用

glTranslatef(0.0,0.0,-5.0);

其的解释:

1. 将场景当中的物体沿Z轴移动-5个单位

2. 将相机沿Z轴移动+5个单位

现在假设我们要从侧面观察物体.

背景:

相机与物体其均在原点.

分析:

观察+从侧面

观察:

因为相机与物体均原点,所以要移动相机或物体--> 3DAPP当中的显示模块其应该是要包括移动操作语句.

从侧面:

其是要旋转相机或物体,

编程实现:

我们要先写移动,还是先写旋转呢,语句的次序不同,其的效果也是不同的.

因为矩阵的乘法没的交换律A*B!=B*A

我们应该是先旋转后移动.

在编写代码的时候,要先写移动后写旋转.其原因还是因为矩阵乘法不满足交换律.

这种思考问题的方式很麻烦的.(其是以全局固定坐标系统)

我们应该改变一种问题的思考方式.

局部移动坐标系统:

其的好处:逻辑次序与编写代码的次序相同.

关键:

局部+ 移动 +坐标系统

坐标系统是什么:

局部:其是相对于哪一个

移动:其是谁移动呢.

其就为什么可以很逻辑次序与编写代码的次序相同.

-->

本质:

OPENGL其的本质不变的.

矩阵的相乘不满足交换律也是不变的.

能够改变的:

思考问题的逻辑次序

我们使用全局固定坐标思考问题的逻辑次序与编写代码的次序相反.

局部移动坐标系统,

局部+移动+坐标系统

此坐标系统与全局固定坐标系统,初始相同.

其为什么是局部,为什么是移动呢.

局部:其是描述物体的,而全局固定坐标系统,其是描述场景的.

考虑把物体以及它的局部坐标系统移离原点===>体现了局部移动坐标系统当中的移动特点

然后,根据经过移动的坐标系统调用旋转函数.

注意:

全局固定坐标系统与局部移动坐标系统,其在旋转的参照点不同.

前者:

总是根据全局原点进行的

后者:

根据局部坐标系统的原点进行.而此原点是会变化的.

关键:

在默认情况下,向前就是没Z轴的负方向,

默认情况:

相机与物体均是在原点处且没有旋转

一般情况:

其是要考虑是否旋转了物体或相机.,结果虽然还是移动,但其表现的效果是不同的,其可能不是沿着Z轴方向旋转而是成一定的角度方

向移动.

小结:

全局固定坐标系统与局部移动坐标系统,其的本质是相同的,只是其的思考的方式不同而矣.

其在OPENGL的表现是一样的.OPENGL其还是以矩阵相乘的方式进行的.

[使用工具函数gluLookAt()]

在前面的学习当中,我们知道了怎么样思考移动,旋转对象,与使用OPENGL编程实现,

不管是全局固定坐标系统还是局部移动坐标系统,

其的本质还是:glTranslatef,glRotatef.

为了确定一个对象在3D空间当中的位置与方向,我们要使用glTranslatef,glRotatef

我们能否将此操作过程封装起来,留出的接口: 接口参数,在哪里,朝向,

工具函数gluLookAt其就是为了这一个目标所产生的.

显示模块的全局思路:

构建场景

布置适合地观察点

gluLookAt其就是来布置观察点的.其说明了相机的位置,相机瞄准的参考点,并且提示哪个方向是朝上(说明是正立看,还是倒

立看)

方向其是由向量来表示,向量其是由点来表示的.

向量是有大小和方向的.所以朝向应该是由向量来表达.

注意:

voidgluLookAt(GLdoubleeyex,GLdoubleeyey,GLdoubleeyez,

GLdoublecenterx,GLdoublecentery,GLdoublecenterz.

GLdoubleupx,GLdoubleupy,GLdoubleupz);

我们通过EYE(X,Y,Z)来指定了观察点,瞄准点,朝向.

gluLookAt 其内部是会通过glTranslatef,glRotatef,或自定义矩阵然后调用glMultMatrixf,不管是哪些方案其均是影响

MODELMatrixf( 模型矩阵)

其哪些参数是说明:

相机的位置( 相机位于哪一点)

相机的朝向( 相机旋转了多少)

eye 其是说明相机的位置

center其是说明相机的朝向,也是瞄准着哪个方向看,

具体怎么样的移动,旋转其均是由gluLookAt来计算出来的.

void

gluLookAtf(GLfloateyex,GLfloateyey,GLfloateyez,GLfloatcenterx,

GLfloatcentery,GLfloatcenterz,GLfloatupx,GLfloatupy,GLfloatupz)

{

GLfloatforward[3],side[3],up[3];//向量的表示

GLfloatm[4][4];//变换矩阵

/*

其是计算观察点与参考点之间的向量 (forward向量)

*/

forward[0]=centerx-eyex;

forward[1]=centery-eyey;

forward[2]=centerz-eyez;

/*

其是规范化foward向量,也就是算出单位向量(说明方向)

*/

normalizef(forward);

up[0]=upx;

up[1]=upy;

up[2]=upz;

crossf(forward,up,side);

normalizef(side);

crossf(side,forward,up);

__identf(&m[0][0]);

m[0][0]=side[0];

m[1][0]=side[1];

m[2][0]=side[2];

m[0][1]=up[0];

m[1][1]=up[1];

m[2][1]=up[2];

m[0][2]=-forward[0];

m[1][2]=-forward[1];

m[2][2]=-forward[2];

glMultMatrixf(&m[0][0]);//之前的所有操作均是为确定怎么样旋转

glTranslatef(-eyex,-eyey,-eyez);

}

==>gluLookAt

其主要包括两个方面: 旋转,平移.

关键:

1.旋转的向量确定,(沿着哪个向量旋转,以什么角度旋转)

2.其是先旋转后平移.(如果先平移后旋转,那就可以相机永远在哪一个轴上)

向量

在编程当中,向量其主要是用到了向量的几何性质.

所以向量的方向,

所以向量相乘是:坐标值的相乘,而没有角度.这些均是很关键的

投影变换

其是OPENGL当中的四大模块当中的显示模块的内容,

其是属于显示模块当中的变换部分.

其的主要功能是:确定相机的视野.

我们自己生活在一个3D空间当中,当我们固定在一个空间当中的时候,我们所能到的东西范围是有限的.两只眼睛比一只眼睛所能观察到的东西都

一些的.

我们是看到一个空间当中的一部分.如果想观察到空间当中的其它部分,我们就要转身或旋转脑袋.

在OPENGL当中,其是怎么样表达一个相机的视野空间的呢.

定义好了视野空间,其又是怎么样将3D变换到2D屏幕上显示的呢.

其包括两个方面的内容:

1.视野空间的定义

2.视野空间当中的3D物体怎么样投影到2D屏幕上面.(可以想象成直接忽视视野空间当中的对象的Z值)

==>投影变换其就是来解决这一部知识的.

注意:

变换的本质:

顶点与矩阵相乘.不同的变换,其只是矩阵的值不相同而矣.所以当我们看到一个变换的时候,要知道其是操作什么样的矩

阵,其的矩阵值是多少.

如:视图模型矩阵其的操作GL_MODELVIEW

投影变换其所操作的矩阵是:GL_PROJECTION

在OPENGL当中,我们要去知道,此变换函数其是操作哪一个矩阵.是:GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE.当中的哪一

个.其是通过glMatrixMode(...)来指定的.

但这三个矩阵其均是使用当前矩阵来进行相乘.所以为了避免之前的影响,我们会去使用glLoadIdentity().来将当前矩阵设置为单位

矩阵

[3.3.1透视投影]

其的特点是:与我们人眼所观察到物体对象是不一样的.远处的东西看小些,近处的东西看大些,但没有不清楚的功能.

透视投影流程:

1.设置矩阵模型为GL_PROJECTION

2.将当前矩阵设置为单位矩阵

3.设置视景体,glFrustum

4.根据glFrustum的参数计算出一个矩阵.

5.其与当前矩阵,

6.其结果会保存在GL_PROJECTION矩阵当中.

7.3D空间到2D屏幕上显示的时候,顶点其就会与此矩阵相乘.

注意:

平截头.其是由裁剪平面所组成的.其包括4个侧面,顶面,底面.

裁剪平面与矩阵之间是什么关系呢.

工具函数:

gluPerspective其是定义成一个视景体.

glFrustum其函数参数是指定近侧裁剪平面的两个角.

gluPerspective其的参数是指定:y方向上视野的角度和纵横比(X/Y).

本文转载于:http://www.cnblogs.com/pengxinglove/archive/2010/12/31/1923371.html

相关推荐

Tokyo0 / 0评论 2014-12-15

bingxuelengmei / 0评论 2014-12-04