矩阵全解析
矩阵作为三维中基础的基础,在此作一个全解析。
列优先和行优先
数组的元素可以存储在列优先布局或行优先布局中。
对于存储在列优先布局中的数组,列的元素在内存中是连续的。
内存的连续性有助于利用CPU缓存,提高访问效率,这对性能来说有很重要的影响。
在webgl中数据的存储和传输通常是以列优先(Column-Major)的方式进行的。这是因为WebGL的设计受到了OpenGL的影响,而OpenGL使用的是列优先存储方式。
计算机内存中的数组存储
计算机内存以一维数组的形式存储数据。例如,当您声明 3×3 矩阵时,软件会将此矩阵存储为包含九个元素的一维数组。默认情况下,webgl 以列优先数组布局存储这些元素。每列的元素在内存中是连续的。
以如下矩阵 A 为例:
A =
1 2 3
4 5 6
7 8 9
默认情况下,矩阵 A
在内存中的排列方式如下所示:
1 4 7 2 5 8 3 6 9
在行优先数组布局中,编程语言将行元素连续存储在内存中。在行优先布局中,数组的元素存储为:
1 2 3 4 5 6 7 8 9
同时,在JavaScript中数组是行优先的。
布局在THREEJS中的表现
在threejs使用中具体表现在设置数组时是行优先的,但是内部处理是列优先的。
const m = new THREE.Matrix4()
m.set(
1, 0, 0, 10, // x
0, 1, 0, 2, // y
0, 0, 1, 3, // z
0, 0, 0, 1 // w
)
打印elements数据发现是列优先存储的
[
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
10,
2,
3,
1
]
矩阵与矩阵的基本运算
加减
两个矩阵相加减,即它们相同位置的元素相加减。
只有对于两个行数、列数分别相等的矩阵(即同型矩阵),加减法运算才有意义,即加减运算是可行的.
同时,加减运算满足交换律和结合律
乘法
- 矩阵相乘的主要条件时第一个矩阵的列数等于第二个矩阵的行数。
- 如果将”n“x”k“的矩阵乘以”k“x”m“大小,您将得到一个新的”n“x”m“
- 矩阵乘法不适用交换律,n x k和k x n是完全不同的两个结果
矩阵A:
A1 A2 A3
1 0 2
0 1 2
6 3 1
0 2 4
矩阵B:
B1
2
-8
7
最终会得到一个4X1的矩阵。
计算过程:
c11 = 1 x 2 + 0 x (-8) + 2 x 7 = 16
c21 = 0 x 2 + 1 x (-8) + 2 x 7 = 6
c31 = 6 x 2 + 3 x (-8) + 1 x 7 = -5
c41 = 0 x 2 + 2 x (-8) + 4 x 7 = 12
结果为:
[
16
6
-5
12
]
再来一个例子:
2x2矩阵A=[2,1,4,3] 2x2矩阵B=[1,2,1,0] 结果矩阵c = AxB = [3,4,7,8]
计算思路为:
c11 = a[11]*b[11] + a[12]*b[21]
c12 = a[11]*b[12] + a[12]*b[22]
c21 = a[21]*b[11] + a[22] *b[21]
c22 = a[21]*b[12] + a[22]*b[22]
验证计算结果可以使用这个网站: https://matrix.reshish.com/zh/multiplication.php
求逆
有矩阵A,存在
$$ A \times A^{-1} = I $$
其中I是标准矩阵,那么说$$ A^{-1} $$ 是 $$ A $$ 的逆。首先,只有方形矩阵( 行列相等 )才有逆。
2x2矩阵求逆
$$ \left[ \begin{matrix} a & b\\ c & d\\ \end{matrix} \right]^{-1} = \frac{1}{ad-bc} \times \left[\begin{matrix} d & -b \\ -c & a \end{matrix}\right] $$
3x3矩阵求行列式
$$ \left[ \begin{matrix} m11 & m12 & m13 \\ m21 & m22 & m23 \\ m31 & m32 & m33 \end{matrix}\right] $$
以上矩阵的行列式等于
$$ m11(m22 \times m33 - m32 \times m23) - m12(m21 \times m33 - m23 \times m31) + m13(m21 \times m32 - m22 \times m31) $$
查看3x3矩阵行列式计算: http://www.euclideanspace.com/maths/algebra/matrix/functions/...
3x3矩阵求逆
首先根据上面公式求行列式det, 如果det等于0,那么不存在逆矩阵
对3x3矩阵每个元素的代数余子式得到的矩阵的转置矩阵$$ A $$ 除以 det
例子:求以下矩阵的逆
$$ \left[ \begin{matrix} 1 & 2 & 3 \\ 2 & 1 & 4 \\ 5 & 6 & 2 \end{matrix}\right] $$
步骤流程如下:
- 计算det
$$ det = 1\times(1\times2-4\times6)-2(2\times2-4\times5)+3(2\times6-5\times1) = 31 $$
- 因为det不等于0,所以继续以下流程
对矩阵每个元素都用当前位置的代数余子式代替
$$ \left[ \begin{matrix} -22 & 16 & 7 \\ 14 & -13 & 4 \\ 5 & 2 & -3 \end{matrix}\right] $$
对第三步的矩阵进行转置
$$ \left[ \begin{matrix} -22 & 14 & 5 \\ 16 & -13 & 2 \\ 7 & 4 & -3 \end{matrix}\right] $$
对矩阵的每个元素都除以det就是最后的结果
$$ \left[ \begin{matrix} -0.7096774193548387 & 0.45161290322580644 & 0.16129032258064516 \\ 0.5161290322580645 &-0.41935483870967744 &0.06451612903225806\\ 0.22580645161290322 & 0.12903225806451613 & -0.0967741935483871 \end{matrix}\right ] $$
矩阵应用变换
设定矩阵为( 中括号内为数组中的下标 )
x1[0] | y1[4] | z1[8] | w1[12] |
---|---|---|---|
x2[1] | y2[5] | z2[9] | w2[13] |
x3[2] | y3[6] | z3[10] | w3[14] |
x4[3] | y4[7] | z4[11] | w4[15] |
当一个vec4点p应用一个矩阵A时,相当于是A*p, 也就是一个4x4矩阵和一个4x1的矩阵相乘 所以向量p的最终结果为
p.x = x1*p.x + y1*p.y + z1*p.z + w1*p.w
p.y = x2*p.x + y2*p.y + z2*p.z + w2*p.w
p.z = x3*p.x + y3*p.y + z3*p.z + w3*p.w
p.w = x4*p.x + y4*p.y + z4*p.z + w4*p.w
vec3应用矩阵的结果
在笛卡尔坐标系中,会使用xyz表示一个坐标,为了增加缩放这个维度人为的添加一个新的分量w, 也就是说在笛卡尔坐标系中一个点表示为(x,y,z,w), 其中最终的x = x/w, y= y/w, z = z/w, 称为齐次坐标
所以一个vec3应用矩阵后的结果为:
p.x = ( x1*p.x + y1*p.y + z1*p.z ) * w
p.y = (x2*p.x + y2*p.y + z2*p.z) * w
p.z = ( x3*p.x + y3*p.y + z3*p.z ) * w
w = 1 / ( x4*p.x + y4*p.y + z4*p.z + w4 )
vec3应用缩放矩阵
如果是每个维度都缩放同一个系数,那么根据上面的公式( p.x, p.y, p.z的获取式子 ),存在两种方案:
- 直接设置w4=1 / 缩放系数,例如:扩大2倍, w4 = 0.5 , 缩小3倍, w4 = 3
- 分别设置xyz为对应系数, 例如扩大2倍,x1 = 2, y2 = 2, z3 = 2
如果每个维度缩放的系数不一样,那么只有方案二可用,由此可见比较统一的方法是第二种。
得出缩放矩阵为:
$$ \left[ \begin{matrix} scalex & 0 & 0 & 0\\ 0 & scaley & 0 & 0\\ 0 & 0 & scalez & 0\\ 0 & 0 & 0 & 1 \end{matrix}\right] $$
vec3 应用平移矩阵
$$ \left[ \begin{matrix} 1 & 0 & 0 & x\\ 0 & 1 & 0 & y\\ 0 & 0 & 1 & z\\ 0 & 0 & 0 & 1 \end{matrix}\right] $$
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。