zoukankan      html  css  js  c++  java
  • OpenGL 六

    关于矩阵和向量的相关知识,可能学过后几乎遗忘了干净,或是没有学过,但并不影响我们对相关API的使用。当然基础知识的理解会帮助我们弄明白和更好的进行OpenGL的开发工作。

    GLTools库中的Math3d,其中包含了大量的OpenGL 3D数学的数据类型,矩阵、向量的计算等等 API。

    一、向量

    1、何为向量

    3D笛卡尔坐标系中,一个顶点就是 XYZ 坐标空间上的一个点的位置。XYZ 就是一个向量,数学思维中一个顶点就是一个向量。

    向量长度为1 的称为单位向量。向量长度 = 2√(x+ y+ z2)  即:向量的模。

    把一个非单位向量缩放到 1 的过程,称为标准化。也叫做单位化向量。 -- 保留向量的方向

    1.1、声明向量

    M3DVector3f() -- 3维向量 (x,y,z)

    M3DVector4f() -- 4维向量 (x,y,z,w) -- w: 缩放值,不缩放为:1

    // 三维向量/四维向量的声明
    typedef float M3DVector3f[3];
    typedef float M3DVector4f[4];
    // 声明一个三维向量 
    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
    }

    2、向量的点乘(dot product)

    两个向量之间可以进行加、减计算,使用率较高的是点乘,点乘只发生在两个向量之间。

    2个单位向量 点乘 得到 一个标量 --> 标量:没有方向,只有数值 -->  一个 [-1,1] 的值,这个值其实就是两个向量间夹⻆的 cos 值 -- 余弦值。

    如何求2个普通向量的夹角呢?单位化向量 --> x,y,z 分别 ➗ 向量的模(x/|xyz|, y/|xyz|, z/|xyz|) --> 与此普通向量方向相同的单位向量。

    2.1、向量的点乘

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

    3、向量的叉乘(cross product)

    2个向量v1、v2叉乘可得到一个向量v3,向量v3垂直于向量v1、v2 --> 法线 --> 游戏场景中

    叉乘不满足交换律,因为向量是有方向的,交换叉乘方向会不同。

    3.1、向量的叉乘

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

    二、矩阵(Matrix)

     为什么使用矩阵?

    我们对一个物体进行移动旋转等操作时,物体的每个点都需要进行相应的移动旋转,简单的图形的平移可以对每个点进行x,y,z的计算,但是当物体移动很复杂,顶点又很多时,我们对每个点进行计算操作再赋值的工作量很大且易出错,更何况有旋转时我们不一定精确知道角度,此时,矩阵就解决了我们的这个问题。

     

    矩阵一行 or 一列都是合理的,其也可以称为向量。

    1、矩阵的声明

    // 三维矩阵/四维矩阵的声明
    typedef float M3DMatrix33f[9];
    typedef float M3DMatrix44f[16];
    在其他编程标准中, 许多矩阵库定义一个矩阵时使⽤的是二维数组;
    OpenGL 的约定里,更多倾向使⽤一维数组,这样做的原因是: OpenGL 使⽤的是 Column-Major (以列为主)矩阵排序的约定。 --> 列矩阵 == 转置矩阵(数学中的)

    列优先矩阵

    下图,这 16 个值表示空间中一个特定的位置,这4列中,每⼀列都是有4个元素组成的向量;

    如果无们要转动一个一个物体,那么将此物体所有的顶点向量 每一个顶点依次乘以一个矩阵,让此物体所有的顶点都应用 相同的变换,从而得到物体转动后 所在的空间中的 位置和⽅向。

     

    列向量的特别标注:矩阵的最后⼀行都为0,最后⼀个元素为0。 

    单元矩阵:

    // 单元矩阵初始化 ⽅式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 
    } 
    // 单元矩阵初始化 方式3
    void m3dLoadIdentity44f(M3DMatrix44f m); 

    2、矩阵的乘法

    线性代数角度计算:线性代数中,为便于书写,坐标的 计算顺序都是从左到右的方式进行的。

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

             顶点 * 模型矩阵 * 视图矩阵 * 投影矩阵  

    OpenGL的角度:因为OpenGL中的约定是列优先矩阵,所以计算如下:

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

             投影矩阵 * 视图变换矩阵 * 模型矩阵 * 顶点  

     

    矩阵的计算规则:左乘:代数中,用到两个矩阵相乘的时候,矩阵A×矩阵B,那么就称为 A左乘以B。

    三、OpenGL中的变换 

    1、视图变换

    2个视角的 视觉坐标系 

      

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

    2、模型变换

    ⽤于操纵模型与其中某特定变换。这些变换通过 旋转,缩放,平移 将对象移动到需要的位置。模型变换的平移旋转缩放的不同顺序结果是不同的。

    1.1 平移

    void m3dTranslationMatrix44(M3DMatrix44f m, floata x, float y, float z);// M3DMatrix44f m 平移的结果

    1.2 旋转

    m3dRotationMatrix44(m3dDegToRad(45.0), floata x, float y, float z);// 有返回值

    1.3 缩放

    void m3dScaleMatrix44(M3DMatrix44f m, floata xScale, float yScale, float zScale);// M3DMatrix44f m 缩放的结果

    1.4 综合变换 -- 既缩放也平移

    void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b); //M3DMatrix44f product放结果; const M3DMatrix44f a、b ,顺序不定,根据需求确定是 先平移还是先缩放。

    3、投影变换 

  • 相关阅读:
    HDU 2104 hide handkerchief
    HDU 1062 Text Reverse 字符串反转
    HDU 1049
    HDU 1096 A+B for Input-Output Practice (VIII)
    POJ 1017
    C/C++一些难为人知的小细节
    小刘同学的第十二篇博文
    小刘同学的第十一篇博文
    小刘同学的第十篇博文
    小刘同学的第九篇日记
  • 原文地址:https://www.cnblogs.com/zhangzhang-y/p/13344960.html
Copyright © 2011-2022 走看看