矩阵数学( 三 )


1 0 0
x y z
*
0 cos sin
0 -sin cos
由此得到:
(x*1 + y*0 + z*0) (x*0 + y*cos - z*sin) (x*0 + y*sin + z*cos)
整理后结果如下:
(x) (y*cos - z*sin) (z*cos + y*sin)
这句话用大略可以翻译成:
x = x;
y = Math.cos(angle) * y - Math.sin(angle) * z;
z = Math.cos(angle) * z + Math.sin(angle) * y;
回忆一下第十章,在讨论坐标旋转时,我们会看到这实际上就是 x 轴的坐标旋转 。不要惊讶,矩阵数学只是观察和组织各种公式和方程的不同方法 。至此,要创建一个 y 轴旋转的矩阵就非常容易了:
cos 0 sin
0 1 0
-sin 0 cos
最后,z 轴的旋转为:
cos sin 0
-sin cos 0
0 0 1
这是一个很好的尝试,用 x, y, z 的矩阵乘以每个旋转矩阵的单位,证明所得到的结果与第十章的坐标旋转公式完全相同 。
编写矩阵
OK,现在大家已经有了足够的基础将这些知识转换为代码了 。下面,我们对第十五章的 .as 进行重新转换 。这个类中有和两个方法,用以实现 3D 坐标旋转 。我们要让它们以矩阵的方式工作 。
从函数开始 。它会用到小球的 x, y, z 坐标,将它们放入 1×3 矩阵,然后创建一个给定角度的 x 旋转矩阵 。这个矩阵将使用数组的形式表示 。最后使用函数让两个矩阵相乘,当然还需要创建这个函数!相乘后的矩阵还要用另一个数组进行保存,因为我们需要将这些数值再存回小球的 x, y, z 坐标中 。下面是新版的方法:
(ball:, :):void {
var :Array = [ball.xpos, ball.ypos, ball.zpos];
var sin: = Math.sin();
var cos: = Math.cos();
var :Array = new Array();
[0] = [1, 0, 0];
[1] = [0, cos, sin];
[2] = [0, -sin, cos];
var :Array = (, );
ball.xpos = [0];
ball.ypos = [1];
ball.zpos = [2];
}
下面是矩阵乘法的函数:
(:Array, :Array):Array {
var :Array = new Array();
[0] = [0] * [0][0] +
[1] * [1][0] +
[2] * [2][0];
[1] = [0] * [0][1] +
[1] * [1][1] +
[2] * [2][1];
[2] = [0] * [0][2] +
[1] * [1][2] +
[2] * [2][2];
;
}
现在,这个矩阵乘法的函数是手工写出的一个 1×3 和 3×3 矩阵的乘法,这就是我们后面用在每个例子中的函数 。大家也可以使用 for 循环创建出更为动态的可处理任何大小的矩阵函数,但是现在我要让代码保持简洁 。

矩阵数学

文章插图
最后创建函数 。如果你了解函数,那么这个函数应该非常显而易见了 。只需要创建一个 y 旋转矩阵来代替 x 旋转矩阵即可 。
(ball:, :):void {
var :Array = [ball.xpos, ball.ypos, ball.zpos];
var sin: = Math.sin();
var cos: = Math.cos();
var :Array = new Array();
[0] = [ cos, 0, sin];
[1] = [ 0, 1, 0];
[2] = [-sin, 0, cos];
var :Array = (, );
ball.xpos = [0];
ball.ypos = [1];
ball.zpos = [2];
}
就是这样 。大家也可以创建一个函数,由于我们的例子中实际上不需要用到它,所以我将它作为练习留给大家完成 。
现在,运行一下 .as,与第十五章的版本相比,它们看上去实际是一样的 。在 AS 2 中,我发现非矩阵版本的运行得更为流畅一些 。原因是我们为 3D 旋转和缩放执行了非常大量的数学运算 。当我们使用矩阵数学进行计算时,会产生额外的计算 。在进行矩阵乘法时,我们实际是做了四次乘以零的操作,并将这四个结果与其它数值相加 。这八次数学运算实际上没有任何作用 。将这些操作乘以 50 个对象,每帧旋转二次,每帧就多做了 800 次额外计算!这两个版本在 AS 3 中的运行时看不出任何的不同,这就是 Flash CS3 与 AS 3 强大的证明 。但是,当加入的物体越来越多时,我们就要为这些巨大的计算量付出代价 。我给大家的这些代码都非常基本的 。你也许可以使它更加优化一些,让性能得到提升 。