複雑な 3D 変換の実行

Flash Player 10 以降、Adobe AIR 1.5 以降

Matrix3D クラスでは、座標空間内の 3D ポイントを変換したり、3D ポイントをある座標空間から別の座標空間にマップしたりすることができます。

Matrix3D クラスを使用するために、マトリックス数式を理解する必要はありません。一般的な変換操作のほとんどは、クラスのメソッドを使用して処理することができます。マトリックス内の各エレメントの値の明示的な設定や計算について心配する必要はありません。

表示オブジェクトの z プロパティを数値に設定した後で、表示オブジェクトの Transform オブジェクトの Matrix3D プロパティを使用してオブジェクトの変換マトリックスを取得することができます。

var leafMatrix:Matrix3D = this.transform.matrix3D;

Matrix3D オブジェクトのメソッドを使用して、表示オブジェクトに対して平行移動、回転、拡大/縮小および遠近法投影を実行することができます。

Vector3D クラスは、3D ポイントを管理するために x y および z プロパティと共に使用します。方向と大きさを持つ空間ベクターを物理的に表すこともできます。Vector3D クラスのメソッドでは、加算、ドット積、クロス積計算などの一般的な計算を空間ベクターで実行することができます。

注意: Vector3D クラスは、ActionScript の Vector クラスと関連していません。Vector3D クラスには、3D ポイントを定義および操作するためのプロパティとメソッドが含まれますが、Vector クラスでは型を持つオブジェクトの配列がサポートされます。

Matrix3D オブジェクトの作成

Matrix3D オブジェクトを作成または取得する主な方法は 3 つあります。

  • 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);
  • 表示オブジェクトの z プロパティの値を設定します。次に、そのオブジェクトの transform.matrix3D プロパティから変換マトリックスを取得します。

  • ルート表示オブジェクトの perspectiveProjection.toMatrix3D() メソッドを呼び出すことにより、ステージ上の 3D オブジェクトの表示を制御する Matrix3D オブジェクトを取得します。

複数の 3D 変換の適用

Matrix3D オブジェクトを使用して、一度に多数の 3D 変換を適用することができます。例えば、立方体を回転、拡大/縮小してから移動する場合は、立方体の各ポイントに 3 つの異なる変換を適用することができます。ただし、1 つの Matrix3D オブジェクトで複数の変換を事前計算してから、各ポイントに対して 1 つのマトリックス変換を実行する方がはるかに効率的です。

注意: マトリックス変換を適用する順序は重要です。マトリックス計算は累積されません。例えば、回転に続いて平行移動を適用すると、同じ平行移動に続いて同じ回転を適用した場合とは異なる結果が生成されます。

次の例に、複数の 3D 変換を実行する 2 つの方法を示します。

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 プロパティを使用して四角形シェイプの回転、拡大/縮小および位置を変更します。コードの 2 つ目のブロックでは、Matrix3D クラスのメソッドを使用して、同じ変換を行います。

Matrix3D メソッドを使用する主な利点は、すべての計算が最初にマトリックで実行されることです。その後、 transform.matrix3D プロパティが設定されたときに表示オブジェクトに 1 回のみ適用されます。DisplayObject プロパティを設定すると、ソースコードが若干読みやすくなります。ただし、回転プロパティや拡大/縮小プロパティが設定されるたびに、複数の計算が実行され、複数の表示オブジェクトプロパティが変更されます。

コードで同じ複雑な変換が表示オブジェクトに複数回適用される場合は、Matrix3D オブジェクトを変数として保存してから、繰り返し再適用します。

Matrix3D オブジェクトを使用した表示の並べ替え

前述のように、相対的な z 軸に関係なく、表示リスト内の表示オブジェクトのレイヤー順序によって表示のレイヤー順序が決定されます。アニメーションによって表示オブジェクトのプロパティが表示リスト順序とは異なる順序に変換される場合、ユーザーには、z 軸レイヤーに対応しない表示オブジェクトレイヤーが表示される場合があります。したがって、ユーザーから離れた場所に表示する必要のあるオブジェクトが、ユーザーに近い場所にあるオブジェクトの前に表示される場合があります。

3D 表示オブジェクトのレイヤーがオブジェクトの相対的な奥行きに対応していることを確認するには、次のようなアプローチを使用します。

  1. Transform オブジェクトの getRelativeMatrix3D() メソッドを使用して、子 3D 表示オブジェクトの相対的な z-axes を取得します。

  2. removeChild() メソッドを使用して、表示リストからオブジェクトを削除します。

  3. 相対的な z 軸値に基づいて表示オブジェクトを並べ替えます。

  4. addChild() メソッドを使用して、子を逆の順序で表示リストに再び追加します。

この並べ替えにより、オブジェクトが確実に相対的な z 軸に従って表示されます。

次のコードでは、3D ボックスの 6 つの面が正しく表示されます。回転が適用された後で、ボックスの面を並べ替えます。

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_jp を参照してください。 アプリケーションのファイルは、Samples/ReorderByZ フォルダーにあります。