美文网首页
OpenGL 中向量,矩阵的理解

OpenGL 中向量,矩阵的理解

作者: iOS_沧海一笑 | 来源:发表于2020-07-16 16:52 被阅读0次

    什么是向量?

    定义: 在 3D 笛卡尔坐标系, 基本上. 一个顶点就是XYZ 坐标空间上的一个位置. ⽽在空间中给定的一个位置恰恰是由一个单独的XYZ 定义的. 而这样的 XYZ 就是向量; 向量是有大小,有方向的。与标量不同,标量只有大小,没有方向

    image.png
    • 单位向量:在 X轴上的向量 (1,0,0). 向量⻓度为1. 我们称为长度为1的向量为单位向量. 向量的长度(向量的模)计算公式:

      image.png
    • 单位化向量:如果一个向量不是单位向量,而我们把它缩放到1,这个过程叫做标准化,将一个向量进行标准化就是将它的长度缩为1,也叫单位化向量

    OpenGL定义向量【math3d库】

    • math3d库,有2个数据类型,能够表示一个三维或者四维向量:

    M3DVector3f:可以表示一个三维向量(x, y, z)
    M3DVector4f:可以表示一个四维向量(x, y, z, w)
    在典型情况下,w坐标设为1.0。x,y,z值通过除以w,来进行缩放。而除以1.0则本质上不改变x,y,z值。

    • 三维向量,四维向量使用代码声明:
        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
         };
      

    向量点乘

    定义:向量可以进行加法,减法计算. 但是向量里有一个在开发中使用价值非常⾼的操作,叫做“点乘(dot product)” .点乘只能发生在2个向量之间进行;
    2个(三维向量)单元向量之间进行点乘运算将得到一个标量(不是三维向量,是一个标量,标量是只有大小,没有方向).它表示两个向量之间的夹⻆angle.

    向量进行点乘必须满足以下条件:

    • 前提条件:2个向量必须为单位向量
    • 动作:2个三维向量之间进行点乘
    • 结果:返回一个 [ -1, 1 ] 范围的值,这个值其实就是夹角anglecos值(余弦值)

    如何单位化向量?
    ( x / |xyz|, y / |xyz|, z / |xyz| );
    使⽤一个非零向量除以它的模(向量的长度), 就可以得到方向相同的单位向量;

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

    向量叉乘

    定义:向量之间的叉乘(cross product) 也是在业务开发里非常有用的一个计算方式; 2个向量之间叉乘就可以得到另外一个向量,新的向量会与原来2个向量定义的平面垂直. 同时进行叉乘,不必为单位向量;

    向量进行叉乘必须满足以下条件:

    • 前提: 2个普通向量
    • 动作: 向量与向量叉乘
    • 结果: 向量(垂直于原来2个向量定义的平面的向量)
    image.png
    • math3d 库中提供了了关于叉乘的API
    //1.m3dCrossProduct3 函数获得2个向量量之间的叉乘结果得到⼀一个新的向量量
      void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);
    

    什么是矩阵 Matrix ?

    假设, 在空间有一个点.使用 xyz 描述它的位置. 此时让其围绕任意位置旋转一定⻆度后. 我们需要知道这个点的新的位置. 此时需要通过矩阵进行计算; 为什么?因为新的位置的x 不单纯与原来的x还和旋转的参数有关. 甚至与y和z坐标有关;
    矩阵只有一行或者一列都是合理的. 只有一行或者一列数字可以称为向量. 也可以称为矩阵;

    //三维矩阵/四维矩阵的声明
    typedef float M3DMatrix33f[9];
    typedef float M3DMatrix44f[16];
    

    在其他编程标准中, 许多矩阵库定义一个矩阵时,使⽤用二维数组;OpenGL的约定⾥里,更多倾向使用 一维数组; 这样做的原因是: OpenGL 使用的是 Column-Major(以列为主)矩阵排序的约定;

    image.png

    一个4*4矩阵是如何在3D空间中表示一个位置和方向的列向量进行了特别的标注:矩阵的最后一行都为0,只有最后一个元素为1. 奥秘之处在于这 16 个值表示空间中一个特定的位置; 这4列中,每一列都是有4个元素组成的向量; 如果将一个对象所有的顶点向量 乘以这个矩阵,就能让整个对象变换到空间中给定的位置和方向;


    image.png
    • 单元矩阵的初始化方式
    //单元矩阵初始化方式1                       
    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
    }
    //单元矩阵初始化方式2
    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
    }
    //单元矩阵初始化方式2
    void m3dLoadIdentity44f(M3DMatrix44f m);
    

    将一个向量 ✖ 单元矩阵 ,就相当于一个向量✖1. 不会发生任何改变;


    image.png

    单元矩阵在 OpenGL 的维度,有以下公式:
    变换顶点向量 = M_pro * M_view * M_model * V_local
    变换顶点向量 = 投影矩阵 ✖ 视图变换矩阵 ✖ 模型矩阵 ✖ 顶点

    image.png
    • 矩阵左乘

      1. 从栈顶获取栈顶矩阵复制到 mTemp
      2. 将栈顶矩阵 mTemp 左乘 mMatrix
      3. 将结果放回栈顶空间里;
    image.png
    image.png

    相关文章

      网友评论

          本文标题:OpenGL 中向量,矩阵的理解

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