美文网首页
OpenGL在矩阵的应用变换

OpenGL在矩阵的应用变换

作者: 东旭39 | 来源:发表于2020-07-16 23:01 被阅读0次

    OpenGL的常用的库会封装了数学公式,

    向量

    在 3D 笛卡尔坐标系,⼀个顶点就是XYZ 坐标空间上的⼀个位置。⽽在空间中给定的⼀个位置恰恰是由⼀个单独的 XYZ 定义的. ⽽这样的 XYZ 就是向量。
    在 X轴上的向量 (1,0,0). 向量⻓度为1,称为⻓度为1的向量为单位向量.
    向量⻓度(向量的模)计算公式:


    向量长度

    如果⼀个向量不是单位向量, ⽽我们把它缩放到1。这个过程叫做标准化。将⼀个向量进⾏标准化就是将它的缩为1,也叫做单位化向量

    OpenGL如何定义向量

    • M3DVector3f表示⼀个三维向量(x,y,z)
    • M3DVector4f表示⼀个四维向量(x,y,z,w)
      一般w坐标设为1.0。x,y,z值通过除以w,来进⾏缩放。
    //三维向量/四维向量的声明 , 本质是float类型的一唯数组
    typedef float M3DVector3f[3];
    typedef float M3DVector4f[4];
    //声明⼀个三维向量 M3DVector3f:类型 vVector:变量名
    M3DVector3f vVector;
    //声明⼀个四维向量并初始化⼀个四维向量
    M3DVector4f vVertex = {0,0,1,1};
    //声明⼀个三分量顶点数组,例如⽣成⼀个三⻆形
    M3DVector3f vVerts[] = {
          -0.5f,0.0f,0.0f,
          0.5f,0.0f,0.0f,
          0.0f,0.5f,0.0f
    };
    

    向量点乘

    向量点乘表示两个向量相应元素的乘积的和
    (x,y,z)* (a,b,c) = x * a + y * b + z * c
    向量A(x,y,z)、B(a,b,c),向量A * 向量 B = |A||B|Cos(θ),|A|表示向量的模,θ表示向量A和向量B的夹角。
    使⽤⼀个⾮零向量除以它的模(向量的⻓度), 就可以得到⽅向相同的单位向量。

    math3d 库中提供了关于点乘的API
    //1.m3dDotProduct3 函数获得2个向量之间的点乘结果;
    float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
    //2.m3dGetAngleBetweenVector3 即可获取2个向量之间夹⻆的弧度值;
     float m3dGetAngleBetweenVector3(const M3DVector3f u,const 
    M3DVector3f v);
    

    向量叉乘

    2个向量之间叉乘就可以得到另外⼀个向量,新的向量会与原来2个向量定义的平⾯垂直。同时进⾏叉乘,不必为单位向量。
    (x,y,z)* (a,b,c) = (x * a , y * b , z * c)

    math3d 库中提供了关于叉乘的API
    //1.m3dCrossProduct3 函数获得2个向量之间的叉乘结果得到⼀个新的向量
    void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const 
    M3DVector3f v); 
    

    矩阵

    空间中的正方形进行平移、旋转、缩放,需要对正方体中的每个顶点进行空间变化,通过矩阵可以很方便的进行计算。

    opengl中使用列向量为主的排序


    截屏2020-07-16 21.59.01.png

    如果将图形中的顶点向量乘以这个矩阵,就能让整个图形变换到空间中给定的位置和⽅向。
    单元矩阵 Matrix

    //单元矩阵初始化⽅式①
    GLFloat m[] = {
    1,0,0,0, //X Column
    0,1,0,0, //Y Column
    0,0,1,0, //Z Column
    0,0,0,1 // Translation
    }
    // 单元矩阵初始化⽅式 ②
    M3DMatrix44f m = {
    1,0,0,0, //X Column
    0,1,0,0, //Y Column
    0,0,1,0, //Z Column
    0,0,0,1 // Translation
    }
    //单元矩阵初始化⽅式③
    void m3dLoadIdentity44f(M3DMatrix44f m); 
    

    矩阵相乘不满足交换律,所有左乘和右乘是不同的。
    OpengGL中,矩阵先进行平移、然后旋转与矩阵先旋转、然后平移得到最终的图形是不一样的。


    截屏2020-07-16 22.08.39.png

    opengl在进行投影变换时,要经过 model->view-> projection变换。
    在线性代数中,顶点进行变换时。


    截屏2020-07-16 22.27.35.png

    但openGL是列矩阵为主的排序。所以实际上opengl是先将projection矩阵、view矩阵、model矩阵依次放入栈中。

    变换顶点向量 = projection * view * model * local
    变换顶点向量 = 投影矩阵 ✖ 视图变换矩阵 ✖ 模型矩阵 ✖ 顶点


    截屏2020-07-16 22.11.15.png

    OpenGL的GLMatrixStack矩阵堆栈有个MultMatrix方法,用于矩阵左侧

        inline void MultMatrix(const M3DMatrix44f mMatrix) {
                M3DMatrix44f mTemp;
                m3dCopyMatrix44(mTemp, pStack[stackPointer]);
                m3dMatrixMultiply44(pStack[stackPointer], mTemp, mMatrix);
        }
                
    
    1. 从栈顶获取栈顶矩阵 复制到 mTemp
    2. 将栈顶矩阵 mTemp 左乘 mMatrix
    3. 将结果放回栈顶空间⾥;

    视图变换

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

    平移

    void m3dTranslationMatrix44(M3DMatrix44f m, floata x, float y, float z);
    

    旋转

    m3dRotationMatrix44(m3dDegToRad(45.0), floata x, float y, float z);
    

    缩放

    void m3dScaleMatrix44(M3DMatrix44f m, floata xScale, float yScale, float zScale);
    

    综合变换

    void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b);
    

    相关文章

      网友评论

          本文标题:OpenGL在矩阵的应用变换

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