OpenGL之向量、矩阵介绍

GLTools库中有一个组件叫Math3d,其中包含了大量好用的OpenGL一致的3D数学和数据类型。虽然我们不必亲自进行所有矩阵和向量的操作,但是我们得知道它们是什么以及如何运用它们。
像我们开发中用到的图形变换,就涉及到了矩阵/向量的计算。例如CAAnimation实现的仿射变换,就用到了OpenGL渲染技术。

向量

在3D笛卡尔坐标系里,一个顶点就是xyz坐标空间里的一个位置。而在空间中给定的一个位置,恰恰是有一个单独的xyz定义的,这就是向量。数学思维里,一个顶点就是一个向量

单位向量

例如在X轴上的向量(1,0,0),其长度为1,我们称长度为1的向量为单位向量
向量的长度(模)的计算公式是:


= |xyz|
把一个不是单位向量的向量缩放到1的过程,叫做标准化,也叫单位化向量。
单位化向量的计算公式
(x/|xyz|,y/|xyz|,z/|xyz|),使用一个非零向量除以它的模,就得到方向相同的单位向量。

math3d库中,有两个数据类型可以表示一个三维或者四维向量。
M3DVeoctor3f表示三维向量(x,y,z)
M3DVeoctor4f表示四维向量(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;
声明一个四维向量并初始化一个四维向量
M3DVector4f vVector = {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个单位向量点乘将得到一个标量,表示两个向量之间的夹角。(也就是夹角的cos值,[-1,1]之间)

math3d提供的点乘API:

  • float m3dDotProduct3(const M3DVector3f u, const M3DVector3f v):获得2个向量之间的点乘结果,即余弦值 = cosα
  • float m3dGetAngleBetweenVector3(const M3DVector3f u, const M3DVector3f v):获取2个向量之间夹⻆的弧度值,即α = arccos(余弦值)

叉乘

向量之间叉乘是业务开发中比较常用的。2个向量叉乘得到另外一个向量,会与原来2个向量定义的平面垂直,也就是平面的法线。



math3d中叉乘API:

  • void m3dCrossProduct3(M3DVector3f result, const M3DVector3f u, const M3DVector3f v):2个向量之间的叉乘结果得到一个新的向量。

矩阵Matrix

假设我们想求得空间中一个点(x,y,z),围绕任意位置旋转一定角度后的新位置,可以通过矩阵计算。
新位置x不只与原来的x、旋转参数有关,还和y、z坐标有关。
只有一行或一列的矩阵,也可以称为向量。
在其他编程标准中,许多矩阵库定义一个矩阵时,使用二维数组。而在OpenGL的约定中,更多倾向使用一维数组。原因是:OpenGL使用的是column-Major(以列为主)矩阵排序的约定,这个在数学中叫转置矩阵。



这两个矩阵的内容是一样的。第一个矩阵读取数据的顺序是{A0,A1,A2,A3,A4...A15},第二个矩阵读取的顺序是{A0,A4,A8,A12,A1...A15}.
这16个值表示空间中一个特定的位置,这4列中每一列都是由4个元素组成的向量。如果将一个对象所有的顶点向量乘以这个矩阵,就能让整个对象变换到空间中给定的位置和方向。
列向量进行了特殊的标注,矩阵的最后一行都是0,只有最后一个元素为1。


4 * 4矩阵

1. 单元矩阵
有三种初始化方式:

GLFloat m[] = {
             1,0,0,0,        //X
             0,1,0,0,        //Y
             0,0,1,0,        //Z
             0,0,0,1         //Translation
}

M3DMatrix44f m = {
             1,0,0,0,        //X
             0,1,0,0,        //Y
             0,0,1,0,        //Z
             0,0,0,1         //Translation
}

void m3dLoadIdentity44f(M3DMatrix44f m);

叉乘规则

  • 将一个向量叉乘单元矩阵,就相当于一个向量 X 1,不会发生任何改变;
  • 两个矩阵相乘,前一个矩阵的列数必须等于后一个矩阵的行数,否则不符合矩阵规则。


顶点向量的变换计算

1.线性代数角度
为了便于书写,都是从左到右计算的。从数学角度上由于顶点是行向量,要满足矩阵相乘的规定条件(即 前一个矩阵列数等于后一个矩阵行数),必须将mvp矩阵(模型矩阵、视图矩阵、投影矩阵)放在右边,属于右乘。
公式:
变换后顶点向量 = V_local * M_model * M_view * M_pro
变换后顶点向量 = 顶点 * 模型矩阵 * 观察矩阵 * 投影矩阵


线性代数角度

2.OpenGL角度
OpenGL中的矩阵是以列优先,所以顶点以列向量的方式表示,从OpenGL角度上由于顶点是列向量,要满足矩阵相乘的条件,顶点向量需要向左乘变换矩阵,之后mvp矩阵的顺序颠倒为pvm,才能保证相乘结果一致(因为矩阵叉乘不满足交换律)。称为左乘。


OpenGL角度

可以从OpenGL矩阵堆栈中矩阵相乘源码分析

  • 主要分为3步:
  1. 从栈顶获取栈顶矩阵,复制到mTemp
  2. 将栈顶矩阵 mTemp 左乘 mMatrix
  3. 将结果放回栈顶空间里
  • 矩阵堆栈变化代码段:


    矩阵堆栈变化代码段
矩阵堆栈变化流程图
  • 在顶点着色器中的代码段:


    顶点着色器中的代码段
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 向量:向量就是在3D笛卡尔坐标中的一个顶点。单位向量就是长度为1的向量、 标量:标量是一个只有数值大小 没有方向,...
    简单的孤寂阅读 2,748评论 0 0
  • 向量与矩阵的应用场景和相关方法 向量 向量:(也称为欧几里得向量、几何向量、矢量),指具有大小(magnitude...
    泽泽伐木类阅读 326评论 0 1
  • 向量 单位向量 标量:只有大小,例如:1,2,3...向量:既有大小又有方向。单位向量:向量长度(向量的模)为1的...
    凯歌948阅读 435评论 0 0
  • 一、 向量 1.1 什么是向量 在 3D 笛卡尔坐标系,基本上⼀个顶点就是XYZ 坐标空间上的⼀个位置,⽽在空间中...
    HardCabbage阅读 243评论 0 0
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,865评论 16 22

友情链接更多精彩内容