OpenGL--- (七)OpenGL基础变化与矩阵堆栈
基础变化
视图变换
- 视图变换是应用在场景中的第一种变换,通过物体/观察者在Z轴上的移动,确定场景中利于观察者的位置。
- 默认情况下,透视投影中的观察者位置处于原点(0,0,0),并沿着z轴负方向看向屏幕里面。
- 视图变换将观察者放在你希望的任意位置,并允许在任何方向上观察场景。确定视图变换就像在场景中放置观察者并让它指向某一个方向。
- 截取自<OpenGL 超级宝典 第5版>:从大局上考虑,在应用任何其他模型变换之前,必须先应用视图变换。这样做是因为:对于视觉坐标系而言,视图变换移动了当前的工作的坐标系,后续的变化都会基于新的坐标系完成。
模型变换
-
模型变换其实就是物体通过平移、旋转、缩放的操作,将物体移动到你想要的位置的一个过程。
平移:物体沿着给定的轴进行移动
平移
旋转:物体围绕给定的坐标轴进行旋转
旋转
缩放:根据物体大小进行了放大/缩小的操作
缩放
模型变换中,两个变换的顺序是不能交换的,交换后的矩阵相乘结果是不一致的,如下图,交换平移和旋转的顺序,得到的结果完全不一致当缩放的X/Y/Z参数传值-1时,可以实现物体围绕某一个轴翻转
物体翻转的实现不仅可以通过旋转实现,还可以通过缩放实现
造成这种情况的根本原因:矩形相乘采用的是矩形的叉乘,而矩形叉乘是不满足交换率的。
另外,在模型变换过程中,有两种观察方式:
- 移动观察者 即 观察者动,物体不动
-
移动坐标系 即 观察者不动,物体动
与3种模型变换相对应的OpenGL方法,如图所示:
方法
投影
透视投影:
屏幕上物体与实物的比例是 < 1:1的,且有远小近大的效果。
OpenGL中对应的设置API:
void SetPerspective(float fFov, float fAspect, float fNear, float fFar)
正投影:
屏幕上物体与实物比例是 = 1:1的,都是一样大的效果。
OpenGL中对应的设置API:
void SetOrthographic(GLfloat xMin, GLfloat xMax, GLfloat yMin, GLfloat yMax, GLfloat zMin, GLfloat zMax)
矩形堆栈
使用原因:
程序全局只有一个矩形堆栈,但是需要绘制的图形有多种,即变化有很多种,每个图形所需的变换矩阵不同,如果想两个图形的操作互不影响,需要一个矩阵状态去保存空白的状态。
矩阵堆栈
矩阵堆栈是由GLMatrixStack类创建的,其特性是先进后出,根据矩阵类的源码可知,矩阵堆栈中最大只能放64个状态
矩阵对阵中除了可以放M3DMatrix44f矩阵外,还可以放GLFRame,其实就是比矩阵多做了一步,需要通过GLFRame的get方法方法获得矩阵,放入堆栈中
矩阵堆栈相关API如下图所示:
矩阵堆栈中关于入栈、相乘、出栈的流程
- 原始矩阵堆栈中,拷贝一份栈顶矩阵,压入栈顶。
- 当有变换操作时,将变换操作的矩阵与矩阵堆栈栈顶相乘,将其结果覆盖栈顶矩阵。
- 如果还有其他矩阵入栈,则继续相乘。
- 当没有矩阵需要push,即图形绘制完成后,需要pop栈顶矩阵。
用了几个push,就需要pop几个矩阵,push与pop是一一对相应的
最终的矩阵堆栈仍然是最初时的矩阵堆栈
仿射变换
矩形堆栈中有平移、旋转、缩放三个模型变换相对应的仿射变换,可以不用通过模型变换,而是直接通过矩形堆栈的API实现这3种变换,如下:角色帧
-
主要用来表示物体及观察者所处的位置,有3个参数:
1、vOrigin:当前所处的位置,默认是(0,0,0),处于原点
2、vForward:即将要去的位置,默认是(0,0,-1),朝向-z轴方向
3、vUp:朝向哪,默认是(0,1,0),朝向+y轴方向
除了矩阵,GLFrame对象也可以直接压入矩阵堆栈,主要涉及以下3个方法:
- 加载到堆栈栈顶
void GLMatrixStack::LoadMatrix(GLFrame &frame);
- 与堆栈栈顶相乘,将结果覆盖栈顶矩阵 void
GLMatrixStack::MultMatrix(GLFrame &frame);
- 堆栈栈顶出栈
void GLMatrixStack::PushMatrix(GLFrame &frame);