美文网首页iOS视觉
十三 OpenGL中的向量和矩阵

十三 OpenGL中的向量和矩阵

作者: 王俏 | 来源:发表于2020-08-05 08:38 被阅读0次

    1 向量

    1.1 向量的定义

    坐标系中的一个坐标(x,y,z),即从坐标原点(0,0,0)指向(x,y,z)的一个向量,包含方向和模(到坐标原点的距离)

    向量的模|xyz|的计算公式:

    image

    如下图:

    image

    向量(x0,y0,0)的模是

    image

    而(x0,y0,0)与(x0,y0,z0)连线垂直于z=0平面,所以(x0,y0,z0)的长度为

    image

    1.2 单位向量

    模为1的向量

    1.3 向量的标准化

    (x,y,z) ---> (x/|xyz|,y/|xyz|,z/|xyz|)

    image

    注意: 零向量不能被标准化,数学上没意义:除数为0,几何上也没有意义:零向量没有方向

    1.4 零向量

    大小为0,没有方向

    1.5 负向量

    与原向量大小相等,方向相反

    1.6 标量与向量的乘法

    向量的每个元素*标量后组成的向量,几何意义是:缩放向量的长度,当标量为-1时,是翻转

    image

    注意:

    • 标量和向量相乘时,不需要写乘法。将2个量挨着写即表示相乘(常将标量写在左边)
    • 标量与向量的乘法和除法优先级高于加法和减法
    • 标量不能除以向量,并且向量不能除以另一个向量
    • 负向量能被认为乘法的特殊情况,乘以标量-1

    1.7 向量的加法和减法:加减法的两个向量维度必须相同

    对应分量相加/相减

    a+b几何意义:平移向量,使向量a的头连接向量b的尾,接着从a的尾向b的头画一个向量
    a-b:是向量a和b的尾向连,从b的头画一个向量指向a的头。a-b的模是a,b两点之间的距离
    注意:向量不能与标量或者维度不同的向量相加减;向量加法满足交换律a+b = b+a,当a=b时a-b = b-a

    1.8 向量的点乘

    点乘的含义是:两个向量的夹角的余弦值(前提是相乘的两个向量均为单位向量)
    A · B = |A|·|B|·cos<A,B>

    image

    1.9 向量的叉乘

    两个向量叉乘,得到一个新向量C,与原来的两个向量垂直的向量。

    叉乘,也叫向量的外积、向量积。

    |向量C|=|向量A✖向量B|=|A||B|sin<A,B>

    向量C的方向与A,B所在的平面垂直,且方向要用“右手法则”判断(用右手的四指先表示向量A的方向,然后手指朝着手心的方向摆动到向量B的方向,大拇指所指的方向就是向量C的方向)

    注:向量的叉乘不满足交换律,因为A✖B=-B✖A;乘法在加减法之前计算; 当点乘和叉乘在一起时, 叉乘优先计算;任意向量与自身叉乘等于零向量

    给定 2 个向量量 v 和 n . 能将 v 分解成 2 个向量: V1 和 V2; 它们分别平行于和垂直于 n; 并且满⾜足 v = v1 + v2; 一般平行向量 V2 为 v 在 n 上的投影

    image

    V2 平⾏于 n ,可求解:


    image

    V1 = V -V2

    2 矩阵 float m[]=[A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15]

    2.1 行优先矩阵排序,即行矩阵

    image

    2.2 列优先矩阵排序,即列矩阵

    image

    注意: 列矩阵是矩阵的最后一行都为0,只有最后一个元素为1

    2.3 单元矩阵

    GLFloat m[] = { 1,0,0,0,
                    0,1,0,0,
                    0,0,1,0,
                    0,0,0,1}
    

    对角线为1,其他位置为0 的矩阵
    一个向量 * 单元矩阵 不会发生变化

    2.4 矩阵相乘

    A ✖ B 计算的前提条件是: A的列数 = B的行数

    3 OpenGL中的矩阵和向量

    OpenGL中向量和矩阵都倾向于采用一维数组表示

    3.1 向量的声明和定义,计算

    • 三维向量/四维向量的声明
    typedef float M3DVector3f[3]; 
    typedef float M3DVector4f[4];
    
    
    • 定义第一个三维向量
    M3DVector3f vVector;
    
    • 定义一个四维向量并初始化
    M3DVector4f vVertex = {0,0,1,1};
    
    • 向量的点乘
    float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
    
    • 获取2个向量之间夹⻆的弧度值
    float m3dGetAngleBetweenVector3(const M3DVector3f u,const
    M3DVector3f v);
    
    • 向量的叉乘 result = u ✖ v
    void m3dCrossProduct3(M3DVector3f result,const M3DVector3f  u ,const M3DVector3f v);
    

    3.2 矩阵的声明,定义和计算

    三维矩阵/四维矩阵的声明

    typedef float M3DMatrix33f[9];
    typedef float M3DMatrix44f[16]
    

    单元矩阵的三种定义方式

    • 方式1:
    GLFloat m[] = { 1,0,0,0,
                    0,1,0,0,
                    0,0,1,0,
                    0,0,0,1}
    
    • 方式2 :
    M3DMatrix44f m = { 1,0,0,0,
                        0,1,0,0,
                        0,0,1,0,
                        0,0,0,1}
    
    • 方式3 :
    void m3dLoadIdentity44f(M3DMatrix44f m);
    

    3.2 顶点变换

    • 线性代数下的顶点变换为:

    变换后顶点向量 = V_local * M_model * M_view * M_pro

    变换后顶点向量 = 顶点 ✖ 模型矩阵 ✖ 观察矩阵 ✖ 投影矩阵;

    image

    注:图引自逻辑教育CC老师课件

    • OpenGL下的顶点变换为:

    变换顶点向量 = M_pro * M_view * M_model * V_local

    变换顶点向量 = 投影矩阵 ✖ 视图变换矩阵 ✖ 模型矩阵 ✖ 顶点

    3.3 矩阵的计算

    • 左乘

      MultMatrix(const M3DMatrix44f mMatrix)

      1). 从栈顶获取栈顶矩阵 复制到 mTemp

      2). 将栈顶矩阵 mTemp 左乘 mMatrix (mTemp ✖ mMatrix )

      3). 将结果放回栈顶空间⾥;

    image

    3.2 OpenGL中的矩阵变换

    • 视图变换:将观察者放在你希望的任何位置,并允许在任何方向上观察场景, 确定视图变换就像在场景中放置观察者并让它指向某⼀个方向观察,默认观察者位于(0,0,0)向Z轴负方向进行观察。在应用任何其他模型变换之前, 必须先应⽤视图变换

    • 模型变换:在场景中移动物体进行平移、旋转、缩放


      image
    • 模型视图变换:描述视图/模型变换的二元性

    • 投影:改变视景体⼤小和设置它的投影方式

    • 视⼝:伪变化,对窗口上最终输出进行缩放

    3.3 OpenGL中矩阵变换的使用

    • 平移

    将矩阵m 在x方向平移x0个单位,y方向平移y0个单位,z方向平移z0个单位后结果存放在m矩阵中。

    void m3dTranslationMatrix44(M3DMatrix44f m, floata x0, float y0, float z0);
    
    
    • 旋转

    围绕某一轴旋转一定弧度

    m3dRotationMatrix44(m3dDegToRad(45.0), floata x, float y, float z);
    
    • 缩放 :

    将矩阵m 在x方向缩放xScale倍,y方向缩放yScale倍,z方向缩放zScale倍后结果存放在m矩阵中。

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

    注意:xScale取值-1时,是围绕X轴翻转,
    yScale取值-1时,是围绕Y轴翻转,
    zScale取值-1时,是围绕Z轴翻转,

    • 综合变化: product = a ✖ b
    void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b);
    

    3.4 矩阵堆栈的使用 GLMatrixStack::GLMatrixStack(int iStackDepth = 64);

    • 在堆栈顶部载⼊⼀个单元矩阵
    void GLMatrixStack::LoadIdentity(void);
    
    image
    • 在堆栈顶部载⼊任何矩阵 参数:4*4矩阵
    void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);
    
    image
    • 矩阵乘以矩阵堆栈顶部矩阵,相乘结果存储到堆栈的顶部
    void GLMatrixStack::MultMatrix(const M3DMatrix44f);
    
    image
    • 获取矩阵堆栈顶部的值 GetMatrix 函数 为了适应GLShaderMananger的使用,或者获取顶部矩阵的副本
      const M3DMatrix44f & GLMatrixStack::GetMatrix(void);
    void GLMatrixStack::GetMatrix(M3DMatrix44f mMatrix);
    
    image
    • 将当前矩阵压入堆栈(栈顶矩阵copy一份到栈顶)
    void GLMatrixStack::PushMatrix(void);
    
    image

    将M3DMatrix44f 矩阵对象压入当前矩阵堆栈

    void PushMatrix(const M3DMatrix44f mMatrix);
    
    image
    • 将GLFame 对象压入矩阵对象
    void PushMatrix(GLFrame &frame);
    
    image
    • 出栈(出栈指的是移除顶部的矩阵对象) void
    GLMatrixStack::PopMatrix(void);
    
    image

    3.5 仿射变换

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

    3.6 GLFrame

    GLFrame和矩阵对应
    GLFrame定义:

    GLFrame
    {
        protected:
            M3DVector3f vOrigin;//x 
            M3DVector3f vForward; //z
            M3DVector3f vUp; //y
    }
    

    GLFrame操作也与矩阵相似:
    在矩阵堆栈中存储的是GLFrame对应的矩阵

    //将堆栈的顶部压⼊任何矩阵
    void GLMatrixStack::LoadMatrix(GLFrame &frame);
    //矩阵乘以矩阵堆栈顶部的矩阵。相乘结果存储在堆栈的顶部 void GLMatrixStack::MultMatrix(GLFrame &frame);
    //将当前的矩阵压栈
    void GLMatrixStack::PushMatrix(GLFrame &frame);
    

    照相机管理

    GetCameraMatrix这个函数⽤来检索条件适合的观察者矩阵,存入第一个参数中

    void GetCameraMatrix(M3DMatrix44f m,bool bRotationOnly = flase);
    
    image

    注:图引自逻辑教育CC老师课件

    相关文章

      网友评论

        本文标题:十三 OpenGL中的向量和矩阵

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