矩阵数学( 二 )


a b c j k l (a + j) (b + k) (c + l)
d e f + m n o = (d + m) (e + n) (f + o)
g h i p q r (g + p) (h + q) (i + r)
以上就是我们需要知道矩阵加法的一切 。在介绍了矩阵乘法之后,我将展示如何将现有的函数使用在矩阵 3D 引擎中 。
矩阵乘法
在 3D 转换中应用更为广泛的是矩阵乘法( ),常用于缩放与旋转 。在本书中我们实际上不会用到 3D 缩放,因为例子中的点缩放,影片也没有 3D 的“厚度”,因此只有二维的缩放 。当然,大家可以建立一个可缩放整个 3D 立体模型的更为复杂的引擎 。这就需要写一些根据新的影片大小改变 3D 点的函数 。这些已经超出了我们讨论的范围,但是由于缩放是非常简单的,并且使用矩阵乘法很容易实现,因此我将带大家看一下这个例子 。
使用矩阵进行缩放
首先,需要知道一个物体现有的宽度,高度和深度 —— 换句话讲,它是三个轴上每个轴分量的大小 。当然可以建立一个 3×1 的矩阵:
w h d
我们知道 w, h, d 代表宽度(width),高度()和深度(depth) 。下面需要缩放这个矩阵:
sx 0 0
0 sy 0
0 0 sz
这里 sx, sy, sz 是对应轴上的缩放比例 。它们都将是分数或小数,1.0 为 100%,2.0 为 200%,0.5 为 50%,等等 。稍后大家会看到为什么矩阵是用这种形式分布的 。
要知道,矩阵乘法是为了让两个矩阵相乘,第一个矩阵的列数必需与另一个矩阵的行数相同 。只要符合这个标准,第一个矩阵可以有任意多个行,第二个矩阵可以有任意多个列 。本例中,由于第一个矩阵有三列(w, h, d),因此缩放矩阵就有三行 。那么它们如何进行乘法运算呢?让我们来看一下这个模式:
sx 0 0
w h d
*
0 sy 0
0 0 sz
矩阵的计算结果如下:
(w*sx + h*0 + d*0) (w*0 + h*sy + d*0) (w*0 + h*0 + d*sz)
删除所有等于 0 的数:
(w*sx) (h*sy) (d*sz)
非常有合乎逻辑,因为我们是用宽度(x 轴分量)乘以 x 缩放系数,高度乘以 y 缩放系数,深度乘以 z 缩放系数 。但是,我们究竟在做什么呢?那些所有等于 0 的数都像被遮盖上了,因此让我们将这个模式抽象得更清晰一点 。
a b c
u v w
*
d e f
g h i
现在可以看到该模式的结果为:
(u*a + v*d + w*g) (u*b + v*e + w*h) (u*c + v*f + w*i)
我们将第一个矩阵的第一行(u, v, w)与第二个矩阵每行的第一个元素相乘 。将它们加起来就得到了结果的第一行的第一个元素 。在第二个矩阵的第二列(b, e, h)中使用相同的方法就得到了第二列的结果 。
如果第一个矩阵的行数大于 1,就要在第二行中重复上述动作,就会得到第二行的结果:
u v w
a b c
x y z
*
d e f
g h i
就得到了这个 3×2 的矩阵:
(u*a + v*d + w*g) (u*b + v*e + w*h) (u*c + v*f + w*i)
(x*a + y*d + z*g) (x*b + y*e + z*h) (x*c + y*f + z*i)
现在让我们看一些实际中用到的矩阵乘法 —— 坐标旋转 。希望通过这个缩放的例子会让它看起来更加清晰 。
使用矩阵进行坐标旋转
首先,要挖出我们的 3D 点矩阵:
x y z
它保存了该点所有的坐标 。当然,还要有一个旋转矩阵 。我们可以在三个轴的任意一轴上进行旋转 。我们将分别创建每种旋转的矩阵 。先从 x 轴旋转矩阵开始:
1 0 0
0 cos sin
0 -sin cos
这里有一些正余弦值,“sin 和 cos 是什么?”很明显,这就是我们要旋转的角度的正余弦值 。如果让这个点旋转 45 度,则这两个值就是 45 的正弦和余弦值 。(当然,在代码中要使用弧度制)现在,我们让该矩阵与一个 3D 点的矩阵相乘,看一下结果 。