美文网首页
OpenGL-18-变换与矩阵堆栈

OpenGL-18-变换与矩阵堆栈

作者: 宇宙那么大丶 | 来源:发表于2020-08-05 20:55 被阅读0次

    一、变换

    1、OpenGL中的变换

    图片.png

    2、视图变换

    • 视图变换是应⽤到场景中的第⼀种变换, 它⽤来确定场景中的有利位置,在默认情况下, 透视投影中位于原点(0,0,0),并沿着 z 轴负⽅向进⾏观察 (向显示器内部”看过去”).
    • 当观察者点位于原点(0,0,0) 时,就像在透视投影中⼀样.
    • 视图变换将观察者放在你希望的任何位置.并允许在任何⽅向上观察场景, 确定视图变换就像在场景中放置观察者并让它指向某⼀个⽅向;
    • 从⼤局上考虑, 在应⽤任何其他模型变换之前, 必须先应⽤视图变换. 这样做是因为, 对于视觉坐标系⽽⾔, 视图变换移动了当前的⼯作的坐标系; 后续的变化都会基于新调整的坐标系进⾏.

    3、模型变换

    模型变换: ⽤于操纵模型与其中某特定变换。这些变换将对象通过旋转、缩放、平移等操作移动到需要的位置。

    image.png
    • 注意:模型变换不满足交换律。意思就是先旋转再平移 和 先平移再旋转的结果是不一样的。
    image.png
    • 两种看待模型变换的⽅式:移动观察者、移动物体
    image.png

    API:
    平移

    //参数:结果,在X轴上平移多少,在Y轴上平移多少,在Z轴上平移多少
    void m3dTranslationMatrix44(M3DMatrix44f m, floata x, float y, float z);
    

    旋转

    //参数:这里是弧度(需要把角度转成弧度),围绕X/Y/Z旋转,围绕谁转写1,相反写0
    //这个API是有返回结果呢
    m3dRotationMatrix44(m3dDegToRad(45.0), floata x, float y, float z);
    

    缩放

    //参数:结果,围绕X/Y/Z进行缩放。如果写-1,就是整体翻转
    void m3dScaleMatrix44(M3DMatrix44f m, floata xScale, float yScale, float zScale);
    

    综合变换

    //结果,第一个变换,第二个变换。相乘
    void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b);
    

    二、矩阵堆栈

    1、基础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);
    

    2、压栈和出栈及过程分析

    压栈

    //将当前矩阵压⼊堆栈(栈顶矩阵copy ⼀份到栈顶) 
    void GLMatrixStack::PushMatrix(void); 
    

    压栈一个矩阵

    //将M3DMatrix44f 矩阵对象压⼊当前矩阵堆栈
    void PushMatrix(const M3DMatrix44f mMatrix); 
    
    • PushMatrix不仅仅可以传一个矩阵,也可以传GLFame 对象
      压栈一个GLFame 对象
    //将GLFame 对象压⼊矩阵对象
    void PushMatrix(GLFame &frame); 
    

    出栈

    //出栈(出栈指的是移除顶部的矩阵对象)
    void GLMatrixStack::PopMatrix(void);
    

    过程分析:

    • LoadIdentity后会在栈顶压入一个单元矩阵
    • 如果PushMatrix空的话,会copy一下栈顶的单元矩阵,在压入栈顶
    • 如果PushMatrix一个矩阵,就直接把这个矩阵压入栈顶
    • 后面的变化操作,就使用MultMatrix,与栈顶的单元矩阵进行相乘
    image.png

    参考之前的文章:观察方式与MV矩阵堆栈关系

    3、放射变换

    直接对当前矩阵堆栈进行变换操作

    //旋转
    //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);
    

    举例:

    modelViewMatrix.PushMatrix();
    //围绕Y轴翻转 
    modelViewMatrix.Scale(1.0f, -1.0f, 1.0f);
    //沿着Y轴偏移一下
    modelViewMatrix.Translate(0.0f, 0.8f, 0.0f);
    modelViewMatrix.PopMatrix();
    

    4、GLFrame的API

    对GLFrame对象,例如观察者对象,进行操作

    class GLFrame 
     { 
     protected: 
             M3DVector3f vOrigin; // Where am I? 
             M3DVector3f vForward; // Where am I going? 
             M3DVector3f vUp; // Which way is up? 
    }
    
    
    cameraFrame.SetOrigin(float x, float y, float z)
    cameraFrame.SetUpVector(float x, float y, float z)
    cameraFrame.SetForwardVector(float x, float y, float z)
    
    //将堆栈的顶部压⼊任何矩阵
    void GLMatrixStack::LoadMatrix(GLFrame &frame); 
    
    
    //矩阵乘以矩阵堆栈顶部的矩阵。相乘结果存储在堆栈的顶部
    void GLMatrixStack::MultMatrix(GLFrame &frame); 
    
    
    //将当前的矩阵压栈
    void GLMatrixStack::PushMatrix(GLFrame &frame);
    

    相关文章

      网友评论

          本文标题:OpenGL-18-变换与矩阵堆栈

          本文链接:https://www.haomeiwen.com/subject/rpourktx.html