[Flash Player 10 #1] 3D のプリミティブを回してみる。

ついにベータ版が登場した Flash Player 10 。GPU サポートやテキスト周りの強化なんかがありますが、その辺りは他の人に任せるとして…。3D が正式にサポートされたことが何とも嬉しいです。いくつか試してみたので、デモをアップしてみます。

※ 要 Flash Player 10

平面の回転デモはこちら
立方体の回転デモはこちら

解説を交えたコードは下記の通り。

package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.geom.PerspectiveProjection;
    import flash.geom.Vector3D;
    import flash.text.TextField;
    import net.unbland.debug.FPS;
    import primitives.Cube;
    import primitives.Plane;

    [SWF(width=320, height=320, backgroundColor=0xDDDDDD, frameRate=30)]
    public class Demo01 extends Sprite
    {
        // 描画用のスプライト
        private var canvas:Sprite = new Sprite();

        // 透視投影のためのクラス
        private var projection:PerspectiveProjection = new PerspectiveProjection();
        // 3D シーン(ステージには配置しない)
        private var scene:Sprite = new Sprite();

        // 3D プリミティブ(別クラスで定義)
        // 平面用
        private var primitive:Plane = new Plane();
        // 立方体用
        //private var primitive:Cube = new Cube();

        public function Demo01():void
        {
            // ステージの設定、3D には関係無い
            setupStage();

            // 3D では中心点が左上でなく、中央になるので画面中央に配置
            canvas.x = canvas.y = 160;
            addChild(canvas);

            // プロジェクションの視野角を決める
            // これにより焦点距離が変わる
            projection.fieldOfView = 60;

            // scene.transform.matrix3D は最初は空になっている(バグ?)ので、
            // 行列を代入しておく
            scene.transform.matrix3D = new Matrix3D();
            // 実際に描画を行う関数を毎フレーム実行
            scene.addEventListener(Event.ENTER_FRAME, renderScene);
        }

        private function renderScene(e:Event):void
        {
            // 変換用行列を作成
            var world:Matrix3D = scene.transform.matrix3D.clone();
            // 描画用の頂点情報が格納されたベクター
            var vertices:Vector.<Number> = new Vector.<Number>();

            // プロジェクションの行列を変換用行列に乗算
            world.append(projection.toMatrix3D());

            // プリミティブの各頂点を走査
            for each (var vertex:Vector3D in primitive.vertices)
            {
                // 変換用行列で頂点をシーンの座標系に変換
                var v:Vector3D = world.transformVector(vertex);

                // プロジェクションの焦点距離を元に計算
                v.w = projection.focalLength / (projection.focalLength + v.z);
                // スクリーン上に投影
                v.project();

                // 描画用頂点に追加
                vertices.push(v.x, v.y);
            }

            // ポリゴンを描画
            canvas.graphics.clear();
            canvas.graphics.beginFill(0xDDDDDD);
            // 平面用
            canvas.graphics.drawTriangles(vertices, primitive.indices);
            // 立方体用
            //canvas.graphics.drawTriangles(
                //vertices, primitive.indices, null, TriangleCulling.NEGATIVE
            //);

            // シーンを回転
            scene.rotationY += 2;
            scene.rotationZ += 1;
        }

        private function setupStage():void
        {
            FPS.show(stage);

            stage.showDefaultContextMenu = false;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            graphics.lineStyle(1, 0xAAAAAA);
            graphics.beginFill(0xFFFFFF);
            graphics.drawRect(10, 10, 300, 300);
        }
    }
}

FlashDevelop の開発途中版が早くも Flash Player 10 に対応しており、Vector とかのコードヒントとかもで出るのでオススメです。twitter での beinteractive 先生のコメントで知ったのですが、Flash Player 10 Debug 版もこっそりあるみたいなので合わせて使えばウハウハです。今回のサンプルに使ったプロジェクト(プリミティブ含む)を上げておきますので、参考にどうぞ。

プロジェクトファイルはこちら

One Comment

  1. [FLASH10]drawRectanglesでパノラマ画像をテクスチャリング

    円環状の多面体(長方形が複数繋がったようなやつ。各長方形は三角形二つで構成)に沿ってパノラマ画像を貼付け。胆はテクスチャ貼付け用のUVT座標の設定と、円環…

Leave a Reply