note.x

[Astro] Vector3D / Matrix3D で座標変換

astro_test.swf(要:FlashPlayer10 beta)

Astro触ってみた。好評現実逃避中。
Targeting Flash Player 10 Beta with Flex SDK 3.0.x – Adobe Open Sourceを参照しつつFlashPlayer10向け環境をセットアップ。SDKはBuild 3.0.1.1739 を使った。

Sprite、MovieClipで使える3DEffect(.z とか、rotationX,Y,Z とか)って、flash.geom.Transform 使った変形をお手軽に使えるようにしたものっていう解釈でいいのかな? 簡単だし軽いんで、ちょっと3Dっぽくしたい時はこれで充分かと。
んで、もうちょっとマジメに3Dしたい場合はやっぱり頂点シェーダー的なものを実装しなくちゃならないわけで、その辺に挑戦してみたのが上記のデモ。
キモになる部分をまとめたソースが以下。

※09/01/10 コードを若干修正

package
{
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
 
    [SWF(backgroundColor="#000000")]
 
    public class astro_sample extends Sprite
    {
        private var view:Sprite;
        private var fov:PerspectiveProjection = new PerspectiveProjection();
        private var vertex:Vector.<Vector3D>;
        private var deg:Number = 0;
        private var dot:Vector.<Sprite> = new Vector.<Sprite>();
        private var pivot:Vector3D = new Vector3D(0,0,0);
        private var wid:Number = 200;
        private var hei:Number = 200;
        private var dep:Number = 200;
 
        public function astro_sample()
        {
            stage.frameRate = 60;
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.quality = StageQuality.BEST;
 
            init3D();
        }
 
        private function init3D():void
        {
            view = new Sprite();
            addChild(view);
            view.x = stage.stageWidth >> 1;
            view.y = stage.stageHeight >> 1;
            view.z = 0;
 
            //視野角の設定
            fov.fieldOfView = 55;
 
            //頂点の定義
            vertex = Vector.<Vector3D>
            ([
                new Vector3D(-wid/2, +hei/2, -dep/2),
                new Vector3D(+wid/2, +hei/2, -dep/2),
                new Vector3D(+wid/2, -hei/2, -dep/2),
                new Vector3D(-wid/2, -hei/2, -dep/2),
                new Vector3D(-wid/2, +hei/2, +dep/2),
                new Vector3D(+wid/2, +hei/2, +dep/2),
                new Vector3D(+wid/2, -hei/2, +dep/2),
                new Vector3D(-wid/2, -hei/2, +dep/2)
            ]);
 
            //表示オブジェクト定義
            for (var i:int = 0; i < 8; i++)
            {
                var s:Sprite = new Sprite();
                view.addChild(s);
                s.graphics.beginFill(0x0099CC);
                s.graphics.drawCircle(0, 0, 5);
                s.graphics.endFill();
                dot.push(s);
            }
 
            stage.addEventListener(Event.RESIZE, onStageResize);
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
 
        //Render Loop
        private function onEnterFrame(event:Event):void
        {
            //回転角度を増加
            deg++;
 
            var matrix:Matrix3D = new Matrix3D();
            //回転行列生成
            matrix.appendRotation(deg, Vector3D.Y_AXIS, pivot);
            matrix.appendRotation(deg, Vector3D.Z_AXIS, pivot);
 
            var vs:int = vertex.length;
            for(var i:int = 0; i < vs; i++ )
            {
                //座標変換
                var v:Vector3D = matrix.transformVector(vertex[i]);
                v.w = fov.focalLength / (fov.focalLength + v.z);
                v.project();
 
                //表示オブジェクト座標に割り当て
                dot[i].x = v.x;
                dot[i].y = v.y;
            }
        }
 
        private function onStageResize(event:Event):void
        {
            view.x = stage.stageWidth >> 1;
            view.y = stage.stageHeight >> 1;
        }
 
    }
}

下記の記事が大いに参考になりました。

地味で実装が辛いコアクラスが一通りビルトインされてるってのはスゲェ。
Vector3DとMatrix3DとPerspectiveProjectionクラスだけでそれっぽいものが出来た。やっててよかったPV3D。
PV3DやSandyをはじめとする既存3Dエンジンは、このへんのコアクラスを全部入れ替えて、Arrayの代わりにVectorは積極的に使いつつ、drawTrianglesで描画するように変更するだけでかなり高速化されるんじゃないのかなぁ。パースペクティブコレクトのおまけ付きだし。


TRACKBACK

  1. [...] 参考 http://blog.r3c7.net/?p=193 http://www.kuma-de.com/blog/1-application/1-flash/2009-04-19/395 [...]

Trackback URL : http://blog.r3c7.net/as3-software-rendering/193/trackback/

COMMENTS

  1. Demon.S - 2008.10.10 13:35:03

    dude, pls update ur script…
    vertex:Vector.; >>> vertex:Vector.;
    private var dot:Vector. = new Vector.(); >>> private var dot:Vector. = new Vector.();

    lower case types could not complie in flex.

    D:)S

  2. Demon.S - 2008.10.10 13:36:45

    faint , class types are filtered…
    i mean vector3d >>> Vector3D , and sprite >>> Sprite

  3. たけし - 2008.11.26 5:29:31

    Flex 3.2 SDKも安定版が公開され、Flash Player 10にも対応したので、キューブなど3D描画のサンプル記事をお願いします。

Leave a Reply