假设在空间有⼀个点,这个点使⽤x、y、z 描述它的位置,此时让其围绕任意位置旋转⼀定⻆度后,我们需要知道这个点的新的位置,此时我们就需要通过进⾏计算了。
为什么需要新的点位置就需要矩阵计算呢?
因为新的位置的x不单纯与原来的x有关系,而且还和旋转的参数有关,甚⾄于y和z坐标有关;矩阵只有⼀⾏或者⼀列都是合理的,只有⼀⾏或者⼀列数字可以称为向量,也可以称为矩阵
;
OpenGL
中矩阵声明:
//三维矩阵/四维矩阵的声明
typedef float M3DMatrix33f[9];// 3x3矩阵
typedef float M3DMatrix44f[16];// 4x4矩阵
值得一提的是,在其它很多编程语言中习惯使用二维数组来定义矩阵。但在OpenGL
中,更偏向于使用一维数组来定义矩阵。 这样做的原因是:OpenGL
使⽤的是 Column-Major
(以列为主)矩阵排序的约定。
矩阵分类
-
行优先矩阵:一行一行读取
-
列优先矩阵:一列一列读取
-
两者的关系为:行优先矩阵经过转置即可的到列优先矩阵
image
这 16 个值表示空间中⼀个特定的位置,这4列中,每⼀列都是有4个元素组成的向量。
如果将⼀个对象所有的顶点向量乘以这个矩阵,就能让整个对象变换到空间中给定的位置和方向。
单元矩阵初始化方式
// 方式一:
GLFoat 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);
将一个向量乘以 单元矩阵
等于向量本身。
矩阵的点乘
image1.矩阵可以进行点乘的前提:两个矩阵的行列数相等
2.矩阵A · 矩阵B = 矩阵C
规则: 矩阵A的第一个元素与矩阵B的第一个元素的乘积 = 矩阵C的第一个元素
矩阵的叉乘
image 矩阵相乘1.矩阵可以进行叉乘的前提:第一个矩阵的列数 = 第二个矩阵的行数
2.矩阵A X 矩阵B = 矩阵C
规则:矩阵A第一行与矩阵B第一列对应元素乘积的综合 = 矩阵C的第一个元素
⚠️注意:A * B
的前提条件是矩阵 A
的列数 == 矩阵B
的行数
⚠️注意:A * B != B * A
(不能调换位置)
以线性代数⻆度理解矩阵相乘
image1.数学中为了方便计算,都是以行矩阵为标准,从左到右的顺序进行计算,所以在数学中,顶点将以行向量的方式表示
2.从数学角度理解mvp矩阵的计算,由于顶点是行向量,要满足矩阵相乘的规定条件(即 叉乘的前提),必须将mvp矩阵放在右边,属于右乘
顶点向量 = V_local * M_model * M_view * M_pro
顶点向量 = 顶点 * 模型矩阵 * 观察矩阵 * 投影矩阵
以OpenGL角度理解矩阵相乘
image1.OpenGL中的矩阵规定是以列为主,所以顶点以列向量的方式表示
2.从OpenGL角度理解mvp矩阵的计算,由于顶点是列向量,如果项进行矩阵规则,就需要满足矩阵相乘的条件,需要将mvp矩阵的顺序颠倒为pvm,且放在列向量的左边,属于左乘
变换顶点向量 = M_pro * M_view * M_model * V_local
变换顶点向量 = 投影矩阵 ✖ 视图变换矩阵 ✖ 模型矩阵 ✖ 顶点
OpenGL 左乘源码
// OpenGL 源码
inline void MultMatrix(const M3DMatrix44f mMatrix) {
M3DMatrix44f mTemp;
m3dCopyMatrix44(mTemp, pStack[stackPointer]);
m3dMatrixMultiply44(pStack[stackPointer], mTemp, mMatrix);
}
1.从栈顶获取栈顶矩阵,复制到mTemp
2.将栈顶矩阵 mTemp 左乘 mMatrix
3.将结果放回栈顶,覆盖栈顶矩阵
网友评论