本章我们不去介绍一些新的运动、物理学或渲染图形的方法。我要给大家介绍的是矩阵
(Matrix),它给我们提供了一个新的可选方案。
图形的变换上也很常用。您也许可以回想到 beginGradientFill 方法就是使用矩阵来设置位
置,大小以及旋转比例的。
Flash 中内置的矩阵。我很庆幸现在为止还没有一处提到 Keanu Reeves [译注:基努-里维斯,
尤指电影《黑客帝国》-- The Matrix] 的电影。看看我还能坚持多久。
图 18-1 一个 3×3 矩阵,一个 1×3 矩阵,一个 3×1 矩阵
用的变量里面通常要用行列的值作为脚标。例如,如果图 18-1 中的 3×3 矩阵叫做 M,
那么 M2,3 就等于 6,因为它指向第二行,第三列。
个大的矩阵。 我们可以用一个单元保存某一列的和,用另一个单元格将这个总和乘以一个分
数,等等。我们看到这样的矩阵应该非常有用。
矩阵运算
做什么以及如何生成都有各自的规则。
的细节,使用的整个矩阵的几乎都是一些随机的数字。我们学习这些规则,但是不知道为什
么要做这些事情或所得的结果代表什么。就像在玩把数字排列成漂亮形状的游戏。
绍一些数值矩阵开始,然后描述如何做矩阵乘法。
矩阵加法
将它视为一个 1×3 的矩阵:
现在假设要将这个点在空间中移动,或叫做点的平移。我们需要知道每个轴上移动多远。这
时可以将它放入一个转换矩阵(translation matrix)中。它又是一个 1×3 的矩阵:
这里 dx, dy, dz 是每个轴移动的距离。现在我们要想办法将转换矩阵加到点矩阵上面。这就
是矩阵加法,
和的矩阵。很明显,要让两个矩阵相加,它们的大小都应该是相同的。转换方法如下:
获得的矩阵可以叫做 x1, y1, z1,转换之后包含了该点的新坐标。让我们用实数来试一下。
假设点在 x, y, z 轴上的位置分别为 100, 50, 75,要让它们分别移动 -10, 20, -35。则应该是
这样的:
因此,当进行加法运算时,所得该点的新坐标就是 90, 70, 40。非常简单,不是吗?大家也
许已经注意到了速度间的相互关系,
平交易嘛。
理大于 3×1 的矩阵加法,但是我会给大家这样一个抽象的例子:
数使用在矩阵 3D 引擎中。
矩阵乘法
在本书中我们实际上不会用到 3D 缩放,因为例子中的点缩放,影片也没有 3D 的“厚度”,
因此只有二维的缩放。当然,大家可以建立一个可缩放整个 3D 立体模型的更为复杂的引
擎。这就需要写一些根据新的影片大小改变 3D 点的函数。这些已经超出了我们讨论的范
围,但是由于缩放是非常简单的,并且使用矩阵乘法很容易实现,因此我将带大家看一下这
个例子。
使用矩阵进行缩放
轴分量的大小。当然可以建立一个 3×1 的矩阵:
我们知道 w, h, d 代表宽度(width),高度(height)和深度(depth)。下面需要缩放这个矩
阵:
这里 sx, sy, sz 是对应轴上的缩放比例。它们都将是分数或小数,1.0 为 100%,2.0 为
200%,0.5 为 50%,等等。稍后大家会看到为什么矩阵是用这种形式分布的。
相同。只要符合这个标准,第一个矩阵可以有任意多个行,第二个矩阵可以有任意多个列。
本例中,由于第一个矩阵有三列(w, h, d),因此缩放矩阵就有三行。那么它们如何进行乘
法运算呢?让我们来看一下这个模式:
矩阵的计算结果如下:
删除所有等于 0 的数:
非常有合乎逻辑,因为我们是用宽度 (x 轴分量) 乘以 x 缩放系数,高度乘以 y 缩放系数,
深度乘以 z 缩放系数。但是,我们究竟在做什么呢?那些所有等于 0 的数都像被遮盖上了,
因此让我们将这个模式抽象得更清晰一点。
现在可以看到该模式的结果为:
我们将第一个矩阵的第一行(u, v, w)与第二个矩阵每行的第一个元素相乘。将它们加起来
就得到了结果的第一行的第一个元素。在第二个矩阵的第二列(b, e, h)中使用相同的方法
就得到了第二列的结果。
就得到了这个 3×2 的矩阵:
现在让我们看一些实际中用到的矩阵乘法 —— 坐标旋转。希望通过这个缩放的例子会让它
看起来更加清晰。
使用矩阵进行坐标旋转
首先,要挖出我们的 3D 点矩阵:
它保存了该点所有的坐标。当然,还要有一个旋转矩阵。我们可以在三个轴的任意一轴上进
行旋转。我们将分别创建每种旋转的矩阵。先从 x 轴旋转矩阵开始:
这里有一些正余弦值, “sin 和 cos 是什么?”很明显,这就是我们要旋转的角度的正余弦
值。如果让这个点旋转 45 度,则这两个值就是 45 的正弦和余弦值。
使用弧度制)现在,我们让该矩阵与一个 3D 点的矩阵相乘,看一下结果。
由此得到:
整理后结果如下:
这句话用 ActionScript 大略可以翻译成:
回忆一下第十章,在讨论坐标旋转时,我们会看到这实际上就是 x 轴的坐标旋转。不要惊
讶,矩阵数学只是观察和组织各种公式和方程的不同方法。至此,要创建一个 y 轴旋转的
矩阵就非常容易了:
最后,z 轴的旋转为:
这是一个很好的尝试,用 x, y, z 的矩阵乘以每个旋转矩阵的单位,证明所得到的结果与第
十章的坐标旋转公式完全相同。
编写矩阵
的 RotateXY.as 进行重新转换。这个类中有 rotateX 和 rotateY 两个方法, 用以实现 3D 坐
标旋转。我们要让它们以矩阵的方式工作。
建一个给定角度的 x 旋转矩阵。这个矩阵将使用数组的形式表示。最后使用 matrixMultiply
函数让两个矩阵相乘,当然还需要创建这个函数!相乘后的矩阵还要用另一个数组进行保存,
因为我们需要将这些数值再存回小球的 x, y, z 坐标中。下面是新版的方法:
private function rotateX(ball:Ball3D, angleX:Number):void {
}
下面是矩阵乘法的函数:
private function matrixMultiply(matrixA:Array, matrixB:Array):Array {
}
现在,
用在每个例子中的函数。大家也可以使用 for 循环创建出更为动态的可处理任何大小的矩
阵函数,但是现在我要让代码保持简洁。
只需要创建一个 y 旋转矩阵来代替 x 旋转矩阵即可。
private function rotateY(ball:Ball3D, angleY:Number):void {
}
就是这样。大家也可以创建一个 rotateZ 函数,由于我们的例子中实际上不需要用到它,所
以我将它作为练习留给大家完成。
2 中,我发现非矩阵版本的运行得更为流畅一些。原因是我们为 3D 旋转和缩放执行了非
常大量的数学运算。当我们使用矩阵数学进行计算时,会产生额外的计算。在进行矩阵乘法
时,我们实际是做了四次乘以零的操作,并将这四个结果与其它数值相加。这八次数学运算
实际上没有任何作用。将这些操作乘以 50 个对象,每帧旋转二次,每帧就多做了 800 次
额外计算!这两个版本在 AS 3 中的运行时看不出任何的不同,这就是 Flash CS3 与 AS 3
强大的证明。但是,当加入的物体越来越多时,我们就要为这些巨大的计算量付出代价。我
给大家的这些代码都非常基本的。你也许可以使它更加优化一些,让性能得到提升。
介绍。在 3D 中使用矩阵是一个很好的引子,因为这样可以让大家看到它们是如何与已知
公式相关联的。同样,矩阵在其它语言的 3D 制作中应用得非常之广泛,而且比我们现在
的 ActionScript 更为有效。在这些语言中,只需付出一点点 CPU 就可以得到矩阵所带来
的组织良好的代码。如果大家试图在 Flash 以外的其它软件中进行 3D 动画编程,那么就
一定要使用到矩阵。还是那句话,谁知道 Flash 播放器几年后会成为什么样?终会有一天,
所有的这些技术都能与 Flash 完美地结合。
Matrix 类
实上,我们有一个内置矩阵类。浏览一下 Flash 帮助文档中的 flash.geom.Matrix 类,就会
发现那里写得非常清楚详细。如果本章前面内容您都能理解,那么要掌握这些材料就一定没
问题。文档写得非常好,我就不再浪费空间将这些内容重复一遍了,但是我会给大家一个快
速的总结并举出两个例子。
影片剪辑,文本类等)都有名为 transform (转换)的属性。这是 flash.geom.Transform 类的
一个实例,它还包含有另一个名为 matrix 的属性。如果我们创建一个 Matrix 类的实例,
并把它赋给显示对象的 transform.matrix 属性,那么它将会改变这个对象的形状、大小或位
置。我们马上会看到一些具体的例子。
基本来说 Matrix 类的矩阵是一个 3×3 的矩阵,形式如下:
其中 u, v, w 内部自动被设置为 0, 0, 1。而且它们是不可改变的,因此不需要管它们。(更
为具体的解释请参见帮助文档)我们使用下述语法来创建一个新的 Matrix:
那么这些字母是什么意思呢?tx 和 ty 非常简单。它们通过改变矩阵来控制显示对象的 x
和 y 轴。而 a, b, c, d 有些难度,因为它们都相互依赖。如果设置 b 和 c 为 0,就可以使
用 a 和 d,在 x 和 y 轴上缩放一个对象。如果设置 a 和 d 为 1,就可以使用 b 和 c,
分别在 y 和 x 轴上倾斜一个对象。
在本例中,设置如下:
当然, 我们可以看到这里包含了一个旋转矩阵,它确实可以旋转一个物体。自然本例中的 cos
和 sin 代表我们想要旋转的某个角度的正弦和余弦值(弧度制)让我们试验一下这个例子。
enterFrame 处理函数,所有的动作都加在其中:
package {
}
这里有一个 angle 变量,每帧都会增加。代码求出了角度的正弦和余弦值并将它们赋给新
的矩阵对象,以这种方式指定 rotation。我同时还设置了平移,根据舞台的宽度和高度把影
片放置到中心。新的矩阵被赋给了影片的 transform.matrix 属性。测试该影片就得到了一个
旋转的正方形。
rotation 没有问题,这是一个更为简单的解决方法。但是,也许在一些处理多个角度、弧度、
正弦、余弦的例子中,相比将一切转换回角度制并改变 rotation 值而言,像这样的矩阵赋
值确实要简单很多。
轴上进行拉伸以便使一个部分走一条路, 另一个部分走另一条路。
子。字母顶部的部分向右倾斜,而底部的部分向左倾斜。这是 Flash 中一个众所周知的一
个难点,但是使用 Matrix 类将会惊人地简单。如同我前面所说,设置矩阵的 a 和 d 为 1。
属性 b 是 y 轴倾斜的值,属性 c 控制 x 轴的倾斜值。让我们先来试一下 x 倾斜。在
SkewX.as 中,我几乎使用了与前一个例子完全相同的设置,只不过改变了 onEnterFrame 方
法中矩阵的创建。
private function onEnterFrame(event:Event):void {
}
这里相对于鼠标的 x 坐标创建了一个 skewX 变量,以舞台的中心为偏移量。然后将它乘
以 .01 让倾斜的值处于可控范围,并将此值赋给矩阵。
Matrix 类一切都变得可能,如果你知道有谁在试图做这样的事,那么就把上述代码拿给他
们看,等着看他们开始流口水吧!如果您亲自测试了这段代码,那么肯定已经知道我的意思
了。
图 18-2 影片在 x 轴上的倾斜
在 SkewXY 中,我在 y 轴上做了同样的事情:
private function onEnterFrame(event:Event):void {
}
从图 18-3 中可以看到影片在两个轴上的倾斜
图 18-3 影片在两个轴上的倾斜
如此简单就能实现这样的效果的确让人惊喜。如果您不确定这种效果能用在哪里,那么我告
诉您,倾斜效果在伪 3D 效果中使用得非常频繁。当我们在上个例子中移动鼠标时,如果
这个图形正在倾斜并旋转,那么大家已经可以看到了它是如何显示出透视来的。这不是特别
精确的 3D,但是它可以用在一些非常棒的效果中。在网上有一些这方面的教程,告诉我们
如何使用倾斜实现这种伪 3D 效果。Matrix 的使用也许会将代码缩短一半。
这 些 并 不 是 AS 3 唯 一 使 用 矩 阵 的 地 方 。 大 家 还 应 该 看 看 ColorMatrixFilter ,
这些不同的制图 API 填充和渐变的方法,以及 flash.geom.Transform 类。
ConvolutionFilter,
所以说矩阵的应用非常广泛!
PS:矩阵 flash.geom.Transform 类现在已经用的非常广泛了,这里虽然介绍的很简单,但是前面
分析的很透彻,相信刚接触的朋友也能很容易看懂的……
(如果要转载请注明出处http://blog.sina.com.cn/jooi,谢谢)