opengl 坐标变换

20 篇文章 0 订阅

本系列教程是自己学习OpenGL时的一些笔记,分享出来希望对大家有所帮助。因为本人是学数学出身,内容侧重于理论推导。

 

1.  坐标变换序列

对于OpenGL来说,从物体的世界坐标系到显示器的屏幕坐标,需要经过四个变换阶段,如下图所示。

首先通过Model-View Matrix将Obect Coordinates变换为Eye Coordinates(以观察者为原点,观察方向为Z轴正方向所定义的坐标系),然后通过Projection Matrix将Eye Coordinates变换为Clip Coordinates(这一步是投影变换,定义了观察者所能看到的范围),接着通过Perspective Division将Clip Coordinates变换为Normalized Device Coordinates(这一步是对坐标进行标准化处理,一般自动完成),最后通过Viewport Transformation将Normalized Device Coordinates变换为Window Coordinates(将投影平面变换为显示器上的窗口坐标,这样就可以直接显示图形了)。

在计算机的内部,点采用齐次坐标的形式来表示。这样就可以把一个点的坐标变换表示为变换矩阵和点的坐标向量的乘法。例如,假设点P的坐标为(x, y, z, w)',变换矩阵为M,则变换后的点P'的坐标(x', y', z', w')' = M * (x, y, z, w)'。(注意:点的坐标一般用列向量表示,v'表示向量v的转置。)

 

2.  指定后序矩阵的类型

void glMatrixMode (GLenum mode);
mode可以取GL_MODELVIEW,GL_PROJECTION和GL_TEXTURE中的一个,它们是定义在头文件GL.h中的三个宏命令。
/* MatrixMode */
#define GL_MODELVIEW                      0x1700
#define GL_PROJECTION                      0x1701
#define GL_TEXTURE                             0x1702
GL_MODELVIEW表示后序的矩阵变换都是对Model-View矩阵的修改,GL_PROJECTION表示后序的矩阵变换都是对Projection矩阵矩阵的修改,GL_TEXURE表示后序的矩阵变换都是对纹理变换矩阵的修改(本文不详细讨论这种类型的变换,在纹理变换部分会有说明)。
OpenGL针对这三种类型的变换提供了三个矩阵变换栈,栈顶的矩阵为当前类型的变换矩阵。同时,OpenGL提供了下面两个函数来对栈进行操作。
void glPushMatrix (void);
void glPopMatrix(void);
glPushMatrix函数对当前栈顶矩阵进行复制,然后压入栈;glPopMatrix函数将当前栈顶元素弹出。如假设当前矩阵栈为ABC,执行glPushMatrix后变为AABC,执行其它矩阵变换后变为DABC,执行glPopMatrix后恢复为ABC。巧妙利用矩阵栈可以实现复杂的动画效果。
GL_MODELVIEW类型的矩阵栈的深度至少为32,其它两种类型的深度至少为2。具体可用以下命令来查询。
// 查询不同类型矩阵栈所支持的最大深度
int maxModelViewStackDepth, maxProjectionStackDepth, maxTextureStackDepth;
glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &maxModelViewStackDepth);
glGetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, &maxProjectionStackDepth);
glGetIntegerv(GL_MAX_TEXTURE_STACK_DEPTH, &maxTextureStackDepth);
 
// 查询不同类型矩阵栈的当前深度
int curModelViewStackDepth, curProjectionStackDepth, curTextureStackDepth;
glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &curModelViewStackDepth);
glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &curProjectionStackDepth);
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &curTextureStackDepth);
 
3.  模型-视图变换(Model-View Transformation)
OpenGL提供了以下函数来指定模型-视图变换。
(1) void glLoadIdentity (void);
将当前变换矩阵设置为单位矩阵。该函数也可以用于其它两种类型的变换,效果相同。
(2) void glLoadMatrixf(const GLfloat *m);  glLoadMatrixd (const GLdouble *m);
将当前变换矩阵设置为矩阵m,m是一个包含16个元素的数组,按列排序形成4*4变换矩阵。该函数也可以用于其它两种类型的变换,效果相同。
(3) glMultMatrixf (const GLfloat *m);  glMultMatrixd (const GLdouble *m);
将当前变换矩阵乘以矩阵m,m是一个包含16个元素的数组,按列排序形成4*4变换矩阵。该函数也可以用于其它两种类型的变换,效果相同。如下图所示,C为变换前的矩阵,M为输入的变换矩阵,C'为变换后的矩阵。

(4) void glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);

          void glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);

对模型按照指定的旋转轴逆时针旋转一定角度,也就是将当前变换矩阵乘以一个旋转矩阵。angle表示旋转角度,(x, y, z)表示旋转轴(以原点为起点,以(x, y, z)为终点的向量)。可按照以下步骤来构造该旋转矩阵。

第一种方法是OpenGL官方文档上给出的公式。

第二种方法是Rodriguez公式,这两种表示方式是完全等价的。

(5) void glTranslated (GLdouble x, GLdouble y, GLdouble z);

          void glTranslatef (GLfloat x, GLfloat y, GLfloat z);

对模型按照指定的偏移量进行平移,也就是将当前变换矩阵乘以一个旋转矩阵。x,y和z表示各个坐标方向的偏移量。平移矩阵具体形式如下。

(6) void glScaled (GLdouble x, GLdouble y, GLdouble z);

          void glScalef (GLfloat x, GLfloat y, GLfloat z);

对模型按照指定的因子进行缩放,也就是将当前变换矩阵乘以一个缩放矩阵。x,y和z表示各个坐标方向的缩放因子。缩放矩阵具体形式如下。

 

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

指定观察者坐标系,可将Object Coordinates变换为Eye Coordinates。该函数定义在glu.h文件中。

该函数所完成的功能等价于下面两条语句。

glMultMatrixd(M);

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

其中,矩阵M的定义如下所示。

 

4.  投影变换(Projection Transformation)  

投影变换包括透视投影和正交投影,OpenGL提供如下函数来实现投影变换。

(1) void glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);

定义了透视投影矩阵P,将点(left, bottom, -zNear, 1)变换为(-zNear, -zNear, -zNear, zNear),将点(right, top, -zNear, 1)变换为(-zNear, -zNear, -zNear, zNear)。投影矩阵P的具体形式如下。

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

定义了一种对称透视投影四棱锥,是glFrustum的一种特殊类型。

 

(3) void glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdoublezNear, GLdouble zFar);

定义了三维平行投影矩阵P,将点(left, bottom, -zNear, 1) 变换为(-1, -1, -1, 1) ,将点(right, top, -zNear, 1) 变换为(1, 1, -1, 1)。投影矩阵P的具体形式如下。

 

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

定义了二维平行投影,是glOrtho的一种特殊类型,即默认zNear = -1, zFar = 1。

 

5.  透视除法(Perspective Division)

对投影坐标做归一化处理,由OpenGL内部自动完成,没有提供用可供操作的函数。

 

6.  视口变换(Viewport Transformation)

将标准化的设备坐标转化为显示器上的窗口坐标,OpenGL提供了glViewport函数完成该功能。

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

z坐标分量主要用来做深度对比,即判断一个物体是否被另一个物体遮挡。zNear默认为0,zFar默认为1,也可以通过函数glDepthRange来指定。

void glDepthRange (GLclampd zNear, GLclampd zFar); 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值