OpenGL--向量和矩阵

在我们OpenGL中涉及到图形变换的时候经常会运用到向量/矩阵的运算。今天我们就来了解下OpenGL中的向量、矩阵。

一、向量

1.标量和向量

  • 标量:只要大小,没有方向的量。
    比如:温度、质量、密度、长度等,标量的运算遵循代数的加减法则。
  • 向量/矢量:既有大小,也有方向的量。
    例如:加速度、位移、力、冲量、动量、电场强度、磁场强度,向量的运算并不遵循一般的代数法则,在相加减时它们遵从几何运算法则(平行四边形法则、三角形法则)。矢量常用带有箭头的直线段表示。线段的长度代表矢量大小,箭头代表矢量的方向。

2.向量的模:向量的长度或者大小即称为向量的模。

  • 空间向量(x,y,z),其中x,y,z分别是三轴上的坐标,模长是:

    image.png

  • 平面向量(x,y),模长是:

    image.png

  • 类似的n维向量的模:


    image.png

3.单位向量和向量单位化

  • 单位向量:即向量的长度为1.
  • 向量单位化:如果一个向量不是单位向量,可以通过单位化将其转化为单位向量,即 非零向量除以向量的模。
image

4.OpenGL中的向量:

OpenGLGLTools库中有⼀个组件叫Math3d,其中包含了大量好用的OpenGL⼀致的3D数学和数据类型。
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
};

5.向量的点乘和叉乘:

  • 点乘(dot product):

向量可以进行加法、减法计算. 但是向量里有⼀个在开发中使⽤价值⾮高的操作,叫做
“点乘(dot product)” 。点乘只能发⽣在2个向量之间进⾏。

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

点乘运算返回2个向量之间的夹角.png
OpenGL中向量的点乘:

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):

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

前提: 2个普通向量
动作: 向量与向量叉乘
结果: 向量(垂直于原来2个向量定义的平⾯的向量)

叉乘运算结果返回一个新的向量, 这个向量与原来2个向量垂直.png
OpenGL中的叉乘:

math3d库中提供了关于叉乘的API:

//.m3dCrossProduct3 函数获得2个向量之间的叉乘结果得到⼀一个新的向量
void m3dCrossProduct3(M3DVector3f result,const M3DVector3f  u ,const
    M3DVector3f v);

二、矩阵

在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数,最早来自于方程组及常数所构成的方阵。
OpenGL中,假设在空间有⼀个点.使⽤x,y,z描述它的位置。此时让其围绕任意位置旋转⼀定⻆度后,我们需要知道这个点的新的位置。此时需要通过矩阵进⾏计算。
因为新的位置的x不单纯与原来的x还和旋转的参数有关,甚⾄于yz坐标有关。
矩阵不仅可以有多行多列,只有一行一列也是可以的,只有一行或者一列的叫作向量,也可以叫作矩阵。

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

值得一提的是,在其它很多编程语言中习惯使用二维数组来定义矩阵。但在OpenGL中,更偏向于使用一维数组来定义矩阵。 这样做的原因是:OpenGL 使⽤的是 Column-Major(以列为主)矩阵排序的约定。

矩阵分类
  • 行优先矩阵:一行一行读取
  • 列优先矩阵:一列一列读取
  • 两者的关系为:行优先矩阵经过转置即可的到列优先矩阵


    image.png
image.png
  • OpenGL矩阵奥秘之处在于这 16 个值表示空间中⼀个特定的位置; 这4列中,每⼀列都是有4个元素组成的向量;
  • 如果将⼀个对象所有的顶点向量 乘以这个矩阵,就能让整个对象变换到空间中给定的位置和⽅向;
  • ⼀个4*4矩阵是如何在3D空间中表示⼀个位置和⽅向的列向量进⾏了特别的标注:
    矩阵的最后⼀⾏都为0,只有最后⼀个元素为1。
单位矩阵
  • 主对角线上数据都是1,其余元素都是0,即为单元矩阵
    单元矩阵的初始化方式:
//单元矩阵初始化⽅式①
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);
  • 向量 X 单元矩阵 = 向量 X 1,不会发生任何变化


    向量 X 单元矩阵.png
  • 向量与单元矩阵相乘的前提是:向量的列数 == 单元矩阵的行数


    单元矩阵 X 向量.png
理解OpenGL中的矩阵相乘
  • 数学角度:
    在线性代数数学的维度,为了便于书写. 所以坐标计算. 都是从左往右顺序,进⾏计算. 如下
    列公式:
    变换后顶点向量 = V_local * M_model * M_view * M_pro
    变换后顶点向量 = 顶点 ✖ 模型矩阵 ✖ 观察矩阵 ✖ 投影矩阵;
    从数学角度理解mvp矩阵的计算,由于顶点是行向量,要满足矩阵相乘的规定条件(即 叉乘的前提),必须将mvp矩阵放在右边,属于右乘

    数学角度.png

  • OpenGL角度
    在OpenGL 的维度. 如下列公式:
    变换顶点向量 = M_pro * M_view * M_model * V_local
    变换顶点向量 = 投影矩阵 ✖ 视图变换矩阵 ✖ 模型矩阵 ✖ 顶点

OpenGL中的矩阵规定是以列为主,所以顶点以列向量的方式表示
OpenGL角度理解mvp矩阵的计算,由于顶点是列向量,如果项进行矩阵规则,就需要满足矩阵相乘的条件,需要将mvp矩阵的顺序颠倒为pvm,且放在列向量的左边,属于左乘。

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

觉得不错记得点赞哦!听说看完点赞的人逢考必过,逢奖必中。ღ( ´・ᴗ・` )比心

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351