欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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);