OpenGL之矩阵的基本变换和矩阵堆栈
程序员文章站
2022-07-04 09:08:40
...
矩阵的基本变换
基本变换的解析说明
变换 | 说明 |
---|---|
视图变换 | 指定观察者位置 |
模型变换 | 在场景中移动物体 |
模型视图 | 描述视图/模型变换的⼆元性(2种看到模型转换的⽅式) |
投影 | 改变视景体⼤小和设置它的投影⽅式 |
视⼝ | 伪变化,对窗⼝上最终输出进⾏缩放 |
视图变换
- 视图变换是应⽤到场景中的第一种变换, 它⽤来确定场景中的有利位置,在默认情况下, 透视投影中位于原点(0,0,0),并沿着 z 轴负⽅向进行观察 (向显示器器内部“看过去”);
- 当观察者点位于原点(0,0,0) 时,就像在透视投影中⼀样;
- 从⼤局上考虑,在应⽤任何其他模型变换之前,必须先应⽤视图变换。这样做是因为, 对于视觉坐标系⽽言,视图变换移动了当前的工作的坐标系; 后续的变化都会基于新调整的坐标系进⾏。
模型变换
- 模型变换:用于操纵模型与其中某特定变换,这些变换将对象移动到需要的位置,通过旋转、缩放、平移。
- 在模型变换过程中,有两种观察方式:
移动观察者即观察者动,物体不动;
移动坐标系即观察者不动,物体动; - 模型变换-平移
/* 模型变换-平移
* 参数1:平移后的矩阵结果
* 参数2: x轴上的平移距离
* 参数3: y轴上的平移距离
* 参数4: z轴上的平移距离
*/
void m3dTranslationMatrix44(M3DMatrix44f m, floata x, float y, float z);
- 模型变换-旋转
/* 模型变换-旋转
* 参数1:旋转角度(弧度值)
* 参数2: 绕x轴旋转
* 参数3: 绕y轴旋转
* 参数4: 绕z轴旋转
*/
m3dRotationMatrix44(m3dDegToRad(45.0), floata x, float y, float z);
- 模型变换-缩放
/* 模型变换-缩放
* 参数1:缩放之后结果矩阵
* 参数2: x轴缩放比例
* 参数3: y轴缩放比例
* 参数4: z轴缩放比例
*/
void m3dScaleMatrix44(M3DMatrix44f m, floata xScale, float yScale, float zScale);
- 模型变换-综合变换
/* 模型变换-综合变换
* 参数1:矩阵相乘结果
* 参数2: 先变换的矩阵
* 参数3: 后变换的矩阵
*/
void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b);
投影变换
- 透视投影:屏幕上物体与实物的比例是 < 1:1的,且有远小近大的效果;
void SetPerspective(float fFov, float fAspect, float fNear, float fFar)
- 正投影:屏幕上物体与实物的比例是 = 1:1的,都是一样大的效果;
void SetOrthographic(GLfloat xMin, GLfloat xMax, GLfloat yMin, GLfloat yMax, GLfloat zMin, GLfloat zMax)
仿射变换
// Rotate 函数angle参数是传递的度数,⽽不是弧度
void MatrixStack::Rotate(GLfloat angle,GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Translate(GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Scale(GLfloat x,GLfloat y,GLfloat z);
角色帧
- 主要是用来表示物体及观察者所处的位置;
- 角色帧是一个用于代替对象在场景内变换矩阵的一个数据结构:包含空间中的一个位置,一个指向前方的向量,一个指向上方的向量,主要用于照相机对象的变换;
class GLFrame
{
protected:
M3DVector3f vOrigin; // Where am I?
M3DVector3f vForward; // Where am I going?
M3DVector3f vUp; // Which way is up?
}
- GLFrame
// 将堆栈的顶部压⼊任何矩阵
void GLMatrixStack::LoadMatrix(GLFrame &frame);
// 矩阵乘以矩阵堆栈顶部的矩阵,相乘结果存储在堆栈的顶部
void GLMatrixStack::MultMatrix(GLFrame &frame);
// 将当前的矩阵压栈
void GLMatrixStack::PushMatrix(GLFrame &frame);
- 照相机管理
// GLFrame函数,这个函数⽤来检索条件适合的观察者矩阵
void GetCameraMatrix(M3DMatrix44f m,bool bRotationOnly = flase);
矩阵堆栈
基本概念
- OpenGL 中的变换一般包括视图变换、模型变换、投影变换等,在每次变换后,OpenGL 会记住新的状态;
- 矩阵堆栈是由GLMatrixStack类创建的,其特性是先进后出,根据矩阵类的源码可知,矩阵堆栈中最大只能放64个状态;
- 矩阵对阵中除了可以放M3DMatrix44f矩阵外,还可以放GLFRame,就是比矩阵多做了一步,需要通过GLFRame的get方法方法获得矩阵,放入堆栈中;
- 矩阵push与pop是一一对相应的;
- 对于矩阵的操作都是对于矩阵栈的栈顶元素来操作的;当前矩阵就是矩阵栈的栈顶元素。
矩阵堆栈中关于入栈、相乘、出栈的流程:
- 原始矩阵堆栈中,拷贝一份栈顶矩阵,压入栈顶(PushMatrix());
- 当有变换操作时,将变换操作的矩阵与矩阵堆栈栈顶相乘,将其结果覆盖栈顶矩阵;
- 如果还有其他矩阵入栈,则继续相乘(MultMatrix()(变换、缩放、旋转));
- 当没有矩阵需要push,即图形绘制完成后,需要pop栈顶矩阵(PopMatrix()),恢复原始状态。
矩阵堆栈的使用
- GLMatrixStack:初始化时已经在堆栈中包含了单位矩阵;
- 载入单位矩阵:GLMatrixStack::LoadIdentity()
- 载入任何矩阵:GLMatrixStack::LoadMatrix(m)
- 任何矩阵乘以栈顶元素并压栈:GLMatrixStack::MultMatrix(m)
- 获取栈顶矩阵:
const M3DMatrix44f& GLMatrixStack::GetMatrix()
void GLMatrixStack::GetMatrix(m) - 压栈:复制当前矩阵(或指定矩阵),压入栈顶
GLMatrixStack::PushMatrix()
GLMatrixStack::PushMatrix(m)
GLMatrixStack::PushMatrix(frame) - 出栈:GLMatrixStack::PopMatrix()
- 栈顶变换:对当前栈顶矩阵进行变换
Rotate(angle,x,y,z)
Translate(x,y,z)
Scale(x,y,z)
矩阵堆栈的部分函数API说明
// 类型
GLMatrixStack::GLMatrixStack(int iStackDepth = 64);
// 在堆栈顶部载⼊一个单元矩阵
void GLMatrixStack::LoadIdentity(void);
// 在堆栈顶部载入任何矩阵 参数:4*4矩阵
void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);
// 矩阵乘以矩阵堆栈顶部矩阵,相乘结果存储到堆栈的顶部
void GLMatrixStack::MultMatrix(const M3DMatrix44f);
// 获取矩阵堆栈顶部的值 GetMatrix 函数
// 为了适应 GLShaderMananger 的使用,或者获取顶部矩阵的副本
const M3DMatrix44f & GLMatrixStack::GetMatrix(void)
void GLMatrixStack::GetMatrix(M3DMatrix44f mMatrix);
// 将当前矩阵压⼊堆栈(栈顶矩阵copy一份到栈顶)
void GLMatrixStack::PushMatrix(void);
// 将 M3DMatrix44f 矩阵对象压⼊当前矩阵堆栈
void PushMatrix(const M3DMatrix44f mMatrix);
// 将 GLFame 对象压⼊矩阵对象
void PushMatrix(GLFame &frame);
// 出栈(出栈指的是移除顶部的矩阵对象)
void GLMatrixStack::PopMatrix(void);