OpenGL之矩阵的基本变换和矩阵堆栈

矩阵的基本变换

基本变换的解析说明
变换 说明
视图变换 指定观察者位置
模型变换 在场景中移动物体
模型视图 描述视图/模型变换的⼆元性(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);

完整代码传送门

OpenGL之利用矩阵的平移、旋转、综合变换等实现矩阵的移动

猜你喜欢

转载自blog.csdn.net/Forever_wj/article/details/107394019