1

矩阵全解析

矩阵作为三维中基础的基础,在此作一个全解析。

列优先和行优先

数组的元素可以存储在列优先布局或行优先布局中。

对于存储在列优先布局中的数组,列的元素在内存中是连续的。

内存的连续性有助于利用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
]

矩阵与矩阵的基本运算

加减

两个矩阵相加减,即它们相同位置的元素相加减。

只有对于两个行数、列数分别相等的矩阵(即同型矩阵),加减法运算才有意义,即加减运算是可行的.

同时,加减运算满足交换律和结合律

乘法

  1. 矩阵相乘的主要条件时第一个矩阵的列数等于第二个矩阵的行数。
  2. 如果将”n“x”k“的矩阵乘以”k“x”m“大小,您将得到一个新的”n“x”m“
  3. 矩阵乘法不适用交换律,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] $$

步骤流程如下:

  1. 计算det

$$ det = 1\times(1\times2-4\times6)-2(2\times2-4\times5)+3(2\times6-5\times1) = 31 $$

  1. 因为det不等于0,所以继续以下流程
  2. 对矩阵每个元素都用当前位置的代数余子式代替

    $$ \left[ \begin{matrix} -22 & 16 & 7 \\ 14 & -13 & 4 \\ 5 & 2 & -3 \end{matrix}\right] $$

  3. 对第三步的矩阵进行转置

    $$ \left[ \begin{matrix} -22 & 14 & 5 \\ 16 & -13 & 2 \\ 7 & 4 & -3 \end{matrix}\right] $$

  1. 对矩阵的每个元素都除以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的获取式子 ),存在两种方案:

  1. 直接设置w4=1 / 缩放系数,例如:扩大2倍, w4 = 0.5 , 缩小3倍, w4 = 3
  2. 分别设置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] $$

vec3 应用旋转矩阵


陈东民
2.1k 声望269 粉丝

坚持自我 纯粹的技术