执行复杂的 3D 转换

Flash Player 10 和更高版本,Adobe AIR 1.5 和更高版本

使用 Matrix3D 类可以转换坐标空间内的 3D 点,也可以将 3D 点从一个坐标空间映射到另一个坐标空间。

不需要理解矩阵运算就可以使用 Matrix3D 类。大多数常见的转换操作都可以通过该类的方法进行处理。您不必担心如何显式设置或计算矩阵中每个元素的值。

将显示对象的 z 属性设置为数值后,可以使用该显示对象的 Transform 对象的 Matrix3D 属性来检索显示对象的转换矩阵:

var leafMatrix:Matrix3D = this.transform.matrix3D;

您可以用 Matrix3D 对象的方法对显示对象执行平移、旋转、缩放和透视投影。

使用 Vector3D 类及其 xyz 属性可管理 3D 点。该类还可以表示具有方向和大小的物理空间矢量。通过 Vector3D 类的方法,可以执行有关空间矢量的常见计算,例如加法、点积和叉积计算。

注: Vector3D 类与 ActionScript Vector 类无关。Vector3D 类包含的属性和方法用于定义和操作 3D 点,而 Vector 类则支持类型对象数组。

创建 Matrix3D 对象

有三种主要的创建或检索 Matrix3D 对象的方式:

  1. 使用 Matrix3D() 构造函数方法实例化新的矩阵。Matrix3D() 构造函数使用包含 16 个数值的 Vector 对象,并将每个值分别放入一个矩阵单元格中。例如:

    var rotateMatrix:Matrix3D = new Matrix3D(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1);
  2. 设置显示对象的 z 属性的值。然后,从该对象的 transform.matrix3D 属性检索转换矩阵。

  3. 通过获取根显示对象的 perspectiveProjection.matrix3D 属性的值,检索用于控制舞台上 3D 对象的显示的 Matrix3D 对象。

应用多种 3D 转换

通过 Matrix3D 对象,可以一次应用多种 3D 转换。例如,如果要旋转、缩放然后移动立方体,可以对立方体的每个点分别应用这三种转换。但是,还有一种高效得多的方法,即在一个 Matrix3D 对象中预先计算多种转换,然后对每个点执行一次矩阵转换。

注: 矩阵转换的应用顺序非常重要。矩阵运算的顺序是不能交换的。例如,先应用旋转再应用平移与先应用平移再应用旋转,二者的结果是不同的。

下面的示例演示执行多种 3D 转换的两种方式。

package { 
    import flash.display.Sprite;     
    import flash.display.Shape; 
    import flash.display.Graphics; 
    import flash.geom.*; 
 
public class Matrix3DTransformsExample extends Sprite 
    { 
        private var rect1:Shape; 
        private var rect2:Shape; 
         
public function Matrix3DTransformsExample():void 
        { 
            var pp:PerspectiveProjection = this.transform.perspectiveProjection; 
            pp.projectionCenter = new Point(275,200); 
            this.transform.perspectiveProjection = pp; 
             
            rect1 = new Shape(); 
            rect1.x = -70; 
            rect1.y = -40; 
            rect1.z = 0; 
            rect1.graphics.beginFill(0xFF8800); 
            rect1.graphics.drawRect(0,0,50,80); 
            rect1.graphics.endFill(); 
            addChild(rect1); 
 
            rect2 = new Shape(); 
            rect2.x = 20; 
            rect2.y = -40; 
            rect2.z = 0; 
            rect2.graphics.beginFill(0xFF0088); 
            rect2.graphics.drawRect(0,0,50,80); 
            rect2.graphics.endFill(); 
            addChild(rect2); 
             
            doTransforms(); 
        } 
 
        private function doTransforms():void 
        { 
            rect1.rotationX = 15; 
            rect1.scaleX = 1.2; 
            rect1.x += 100; 
            rect1.y += 50; 
            rect1.rotationZ = 10; 
 
            var matrix:Matrix3D = rect2.transform.matrix3D; 
            matrix.appendRotation(15, Vector3D.X_AXIS); 
            matrix.appendScale(1.2, 1, 1); 
            matrix.appendTranslation(100, 50, 0); 
            matrix.appendRotation(10, Vector3D.Z_AXIS); 
            rect2.transform.matrix3D = matrix; 
        } 
    } 
}

doTransforms() 方法中,第一个代码块使用 DisplayObject 属性更改矩形形状的旋转、缩放和位置。第二个代码块使用 Matrix3D 类的方法执行相同的转换。

使用 Matrix3D 方法的主要优点在于,所有计算都是在矩阵中提前执行的,然后这些计算只需对显示对象应用一次(前提是设置了显示对象的 transform.matrix3D 属性)。通过设置 DisplayObject 属性可使源代码更易于阅读。但是,每次设置旋转和缩放属性后,会导致进行大量计算并更改显示对象的多个属性。

如果您的代码要多次对显示对象应用相同的复杂转换,应将 Matrix3D 对象保存为变量,然后反复应用该变量。

使用 Matrix3D 对象重新排序显示

如前所述,显示列表中显示对象的层叠顺序确定了对象的显示顺序,这些对象的相对 z 轴值对显示顺序没有影响。如果您的动画将显示对象的属性转换为一种与显示列表中的顺序不同的顺序,则观察者看到的显示对象层叠顺序与 z 轴层叠顺序不一致。因此,在视觉上应当远离观察者的对象可能反而会靠近观察者。

为确保 3D 显示对象的层叠顺序对应于对象的相对深度,请使用如下方法:

  1. 使用 Transform 对象的 getRelativeMatrix3D() 方法获取子级 3D 显示对象的相对 z 轴值。

  2. 使用 removeChild() 方法从显示列表中删除对象。

  3. 根据显示对象的相对 z 轴值对显示对象进行排序。

  4. 使用 addChild() 方法以相反顺序将子对象添加到显示列表中。

这种重新排序方法可确保您的对象按照各自的相对 z 轴值进行显示。

下面的代码将 3D 框的六面设置为正确的显示顺序。这段代码对经过旋转的框的各面进行重新排序:

public var faces:Array; . . . 
 
public function ReorderChildren() 
{     
    for(var ind:uint = 0; ind < 6; ind++) 
    { 
        faces[ind].z = faces[ind].child.transform.getRelativeMatrix3D(root).position.z; 
        this.removeChild(faces[ind].child); 
    } 
    faces.sortOn("z", Array.NUMERIC | Array.DESCENDING); 
    for (ind = 0; ind < 6; ind++) 
    { 
        this.addChild(faces[ind].child); 
    } 
}

若要获取此范例的应用程序文件,请参阅 www.adobe.com/go/learn_programmingAS3samples_flash_cn。在 Samples/ReorderByZ 文件夹中可以找到这些应用程序文件。