スポンサーサイト

-------- | --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

スプライトの3D化

2008-03-02 | 12:26

マウス移動で視点変更できます。

前回はgraphicsに描画する時の座標およびスプライトの座標にビュー変換と射影変換を適用して3Dに見えるようにしてたので、頂点を指定して自分でgraphicsに描画する場合しか使えなかった。
今回はスプライト自身の変形はtransform.matrixで行っているので、前回のやり方では対応できなかった円やビットマップにも適用できる。

package{
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.utils.*;

    import org.papervision3d.core.math.*;

    [SWF(width="400", height="400",backgroundColor="0xffffff")]

        public class Light3D2 extends Sprite{
            // 射影変換行列
            private var m:Matrix3D = new Matrix3D();
            // ビュー変換行列
            private var rm:Matrix3D = new Matrix3D();
            // カメラ位置
            private var cameraPos:Number3D;

            private var objects:Array = [];

            public function Light3D2(){

                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;

                var triangle:Triangle = new Triangle();
                addChild(triangle);
                triangle.x = triangle.y = 200;
                triangle.zz = 0;
                objects.push(triangle);

                var circle:Circle = new Circle();
                addChild(circle);
                circle.x = circle.y = 200;
                circle.zz = 25;
                objects.push(circle);

                var star:Star = new Star();
                addChild(star);
                star.x = star.y = 200;
                star.zz = 50;
                objects.push(star);

                var picture:Picture = new Picture();
                addChild(picture);
                picture.x = picture.y = 200;
                picture.zz = 75;
                objects.push(picture);

                var rectangle:Rectangle = new Rectangle();
                addChild(rectangle);
                rectangle.x = rectangle.y = 200;
                rectangle.zz = 100;
                objects.push(rectangle);

                stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);

                onMouseMove(new MouseEvent(MouseEvent.MOUSE_MOVE));
            }

            private function onMouseMove(e:*):void{

                var theta:Number = (200 - mouseY)*Math.PI/400;
                var phi:Number = (mouseX-200)*Math.PI/400;

                cameraPos = new Number3D(Math.sin(phi)*300, Math.sin(theta)*300, -Math.cos(phi)*300);
                // カメラ視点ベクトル
                var cev:Number3D = new Number3D(-cameraPos.x, -cameraPos.y, -cameraPos.z);
                cev.normalize();
                var cxv:Number3D = new Number3D(1,0,0);
                Matrix3D.multiplyVector(Matrix3D.rotationMatrix(0,1,0, phi), cxv);
                cxv.normalize();
                var cuv:Number3D = new Number3D(0,1,0);
                Matrix3D.multiplyVector(Matrix3D.rotationMatrix(cxv.x, cxv.y, cxv.z, theta), cuv);
                cuv.normalize();

                rm = new Matrix3D();
                rm.n11 = cxv.x;
                rm.n21 = cxv.y;
                rm.n31 = cxv.z;
                rm.n12 = cuv.x;
                rm.n22 = cuv.y;
                rm.n32 = cuv.z;
                rm.n13 = cev.x;
                rm.n23 = cev.y;
                rm.n33 = cev.z;

                var xxv:Matrix3D = Matrix3D.rotationMatrix(1,0,0, theta);
                var yyv:Matrix3D = Matrix3D.rotationMatrix(0,1,0, -phi);

                // ビュー変換 x 射影変換
                var mm:Matrix3D = Matrix3D.multiply(m, rm);

                for each(var o:Base3D in objects){
                    o.transform.matrix = new Matrix(mm.n11, mm.n12, mm.n21, mm.n22);
                    var p:Number3D = new Number3D(o.xx, o.yy, o.zz);
                    Matrix3D.multiplyVector(mm,p);
                    o.x = p.x + 200;
                    o.y = 200 - p.y;
                    o.z = p.z;
                }

                // Zオーダーを考慮して並べ替える
                objects.sort(zSort);
                var i:int = 0;
                for each(var b:Base3D in objects){
                    setChildIndex(b,i++);
                }

                /*
                graphics.clear();
                // 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);

                graphics.lineStyle(2,0xee0000,0.8);
                p1= convertPoint(new Number3D(0, 0, 0));
                p2= convertPoint(new Number3D(cxv.x*300, cxv.y*300, cxv.z*300));
                graphics.moveTo(p1.x, p1.y);
                graphics.lineTo(p2.x, p2.y);

                graphics.lineStyle(2,0xee,0.8);
                p1= convertPoint(new Number3D(0, 0, 0));
                p2= convertPoint(new Number3D(cuv.x*300, cuv.y*300, cuv.z*300));
                graphics.moveTo(p1.x, p1.y);
                graphics.lineTo(p2.x, p2.y);

                graphics.lineStyle(2,0xee00,0.8);
                p1= convertPoint(new Number3D(0, 0, 0));
                p2= convertPoint(new Number3D(cev.x*300, cev.y*300, cev.z*300));
                graphics.moveTo(p1.x, p1.y);
                graphics.lineTo(p2.x, p2.y);

                trace(cameraPos.z);
                graphics.lineStyle(2,0x0,0.8);
                p1= convertPoint(cameraPos);
                graphics.drawCircle(p1.x, p1.y, 20);
                graphics.lineStyle(2,0xff,0.8);
                p1= convertPoint(new Number3D(100,0,-300));
                graphics.drawCircle(p1.x, p1.y, 20);
                */
            }

            private function zSort(lhs:Base3D, rhs:Base3D):int{
                var ll:Number = Math.sqrt((lhs.xx - cameraPos.x)*(lhs.xx - cameraPos.x) + 
                        (lhs.yy - cameraPos.y)*(lhs.yy - cameraPos.y) + 
                        (lhs.zz - cameraPos.z)*(lhs.zz - cameraPos.z));
                var rl:Number = Math.sqrt((rhs.xx - cameraPos.x)*(rhs.xx - cameraPos.x) + 
                        (rhs.yy - cameraPos.y)*(rhs.yy - cameraPos.y) + 
                        (rhs.zz - cameraPos.z)*(rhs.zz - cameraPos.z));
                return (ll - rl < 0) ? 1 : -1;
            }

            private function convertPoint(p:Number3D):Point{
                var temp:Number3D = p.clone();
                var mm:Matrix3D = Matrix3D.multiply(m, rm);

                // convert to 2D point
                Matrix3D.multiplyVector(mm,temp);

                temp.x += 200; temp.y = 200 - temp.y;

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

internal class Base3D extends Sprite{
    public var xx:int =0;
    public var yy:int =0;
    public var zz:int =0;

    public var z:Number;
}

import flash.display.Sprite;
import flash.geom.*;

import org.papervision3d.core.math.*;

internal class Triangle extends Base3D {

    public function Triangle() {
        graphics.clear();
        graphics.lineStyle(1, 0, 1);
        graphics.beginFill(0xff0000);
        graphics.moveTo(-30, -30);
        graphics.lineTo(30, 30);
        graphics.lineTo(-30, 30);
        graphics.endFill();
    }
}

internal class Rectangle extends Base3D {

    public function Rectangle() {
        graphics.clear();
        graphics.lineStyle(1, 0, 1);
        graphics.beginFill(0xff00);

        graphics.moveTo(0,0);
        graphics.lineTo(0, 150);
        graphics.lineTo(150, 150)
        graphics.lineTo(150, 0);
        graphics.endFill();
    }
}

internal class Star extends Base3D{
    public function Star(){
        graphics.clear();
        graphics.lineStyle(1, 0xff, 0.8);
        graphics.beginFill(0xff);
        var seq:Array=[2,4,1,3,0];
        graphics.moveTo(100,200);
        for(var j:int = 0 ; j < 5 ; j++){
            var rad:Number = seq[j] * Math.PI * 2 / 5;
            graphics.lineTo(-Math.sin(rad)*100+100, Math.cos(rad)*100+100);
        }
        graphics.endFill();
    }
}

internal class Circle extends Base3D{
    public function Circle(){
        graphics.clear();
        graphics.lineStyle(1, 0xff0000, 0.8);
        graphics.beginFill(0xff0000);
        graphics.drawCircle(30, 30, 30);
        graphics.endFill();
    }
}

internal class Picture extends Base3D{
    [Embed(source="lena.jpg")]
        private var myImage:Class;
    public function Picture(){
        addChild(new myImage());
    }
}

スポンサーサイト
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。