miscellaneous

射影変換行列 + ビュー変換


前回、透視射影変換行列を示したが、あの説明はワールド座標のZ軸上にカメラがあり原点の方向をカメラが向いていることを前提としていた。 別な言い方をすると、カメラの向いている方向をZ軸と見立てた座標上の3次元の位置に対して透視射影変換行列を適用していた。

カメラの位置や向きが変わった場合、カメラの向いている方向をZ軸と見立てた座標(ビュー座標)に変換してから透視射影変換行列を適用すればよい。

対象物が固定でカメラの位置と向きが変わった場合、対象物の絶対的な位置は変わらないが軸が変わることにより座標が変わる。 (動かない建物を正面に見ている状態で視線を左に動かすと、その建物は相対的に視野の右に移動する)
package {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;

    import org.papervision3d.core.*;
    import org.papervision3d.core.geom.*;
    import org.papervision3d.core.math.*;
    [SWF(width="600", height="400", frameRate="10", backgroundColor="#ffffff")]
        public class Projection2 extends Sprite{
            private var LEN:int = 80;
            private var initialPoints:Array = 
                [new Number3D(LEN, +LEN, LEN),
                new Number3D(LEN, +LEN, -LEN),
                new Number3D(-LEN, +LEN, -LEN),
                new Number3D(-LEN, +LEN, LEN),
                new Number3D(LEN, -LEN, LEN),
                new Number3D(LEN, -LEN, -LEN),
                new Number3D(-LEN, -LEN, -LEN),
                new Number3D(-LEN, -LEN, LEN)
                    ];
            private var initialPoints2:Array = 
                [new Number3D(LEN + 200, +LEN, LEN),
                new Number3D(LEN + 200, +LEN, -LEN),
                new Number3D(-LEN + 200, +LEN, -LEN),
                new Number3D(-LEN + 200, +LEN, LEN),
                new Number3D(LEN + 200, -LEN, LEN),
                new Number3D(LEN + 200, -LEN, -LEN),
                new Number3D(-LEN + 200, -LEN, -LEN),
                new Number3D(-LEN + 200, -LEN, LEN)
                    ];

            private var ff:int = 0;

            private var m:Matrix3D = new Matrix3D();

            public function Projection2():void
            {
                var r:Number = 500;
                var l:Number = -500;
                var t:Number = 500;
                var b:Number = -500;
                var n:Number = 500;
                var f:Number = 1000;
                m.n11 = 2*n/(r-l);
                m.n13 = (r+l)/(r-l);
                m.n22 = 2*n/(t-b);
                m.n23 = (t+b)/(t-b);
                m.n33 = -(f+n)/(f-n);
                m.n34 = -2*n*f/(f-n);
                m.n43 = -1;

                addEventListener(Event.ENTER_FRAME, onEnterFrame);
               
            }

            private function onEnterFrame(e:*):void{

                ff++;

                graphics.clear();
                drawCube(initialPoints);
                drawCube(initialPoints2);

            }

            private function drawCube(points:Array):void{

                var points2D:Array = [];
                for each(var pp:Number3D in points){
                    var p:Number3D = pp.clone();

                    var point:Point = convertPoint(p);

                    points2D.push(p);
                }

                graphics.lineStyle(3,0,0.8);
                graphics.drawCircle(points2D[0].x, points2D[0].y, 5);
                graphics.moveTo(points2D[0].x, points2D[0].y);
                for (var i:int = 1 ; i < 4; i++){
                    graphics.lineTo(points2D[i].x, points2D[i].y);
                }
                graphics.lineTo(points2D[0].x, points2D[0].y);

                graphics.moveTo(points2D[4].x, points2D[4].y);
                for (i = 5 ; i < 8; i++){
                    graphics.lineTo(points2D[i].x, points2D[i].y);
                }
                graphics.lineTo(points2D[4].x, points2D[4].y);
                
                for (i = 0 ; i < 4; i++){
                    graphics.moveTo(points2D[i].x, points2D[i].y);
                    graphics.lineTo(points2D[i+4].x, points2D[i+4].y);
                }

                // draw x axis
                graphics.lineStyle(2,0xff0000,0.8);
                var p1:Point = convertPoint(new Number3D(-300, 0,0));
                var p2:Point = convertPoint(new Number3D(300, 0,0));
                graphics.moveTo(p1.x, p1.y);
                graphics.lineTo(p2.x, p2.y);

                graphics.lineStyle(2,0xff,0.8);
                p1= convertPoint(new Number3D(0, 300,0));
                p2= convertPoint(new Number3D(0, -300,0));
                graphics.moveTo(p1.x, p1.y);
                graphics.lineTo(p2.x, p2.y);


                graphics.lineStyle(2,0xff00,0.8);
                p1= convertPoint(new Number3D(0, 0, 300));
                p2= convertPoint(new Number3D(0, 0, -300));
                graphics.moveTo(p1.x, p1.y);
                graphics.lineTo(p2.x, p2.y);

            }

            private function convertPoint(p:Number3D):Point{
                // camera rotation matrix
                var rm:Matrix3D = Matrix3D.rotationMatrix(0, 1, 0,(ff)/180*Math.PI);
                rm = Matrix3D.multiply(Matrix3D.rotationMatrix(1,0,0, 0.1), rm);

                // apply camera rotation
                Matrix3D.multiplyVector(rm,p);

                // convert to 2D point
                Matrix3D.multiplyVector(m,p);

                p.x += 300; p.y = 200 - p.y;

                return new Point(p.x, p.y);
            }
        }
}




  1. 2008/02/28(木) 22:29:01|
  2. ActionScript 3.0
  3. | トラックバック:0
  4. | コメント:0
<<軽量3D | ホーム | 透視射影変換行列>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバックURLはこちら
http://yamasv.blog92.fc2.com/tb.php/141-02ee3119
この記事にトラックバックする(FC2ブログユーザー)
Google

プロフィール

Author:yamasv@gmail.com
コメント、トラックバック、リンクはお気軽に

最近の記事

ブログ検索

カテゴリー

-->

カレンダー

07 | 2008/08 | 09
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31 - - - - - -

過去ログ

最近のコメント

最近のトラックバック

RSSフィード

リンク

このブログをリンクに追加する

全ての記事を表示する

全ての記事を表示する



あわせて読みたい