スポンサーサイト

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

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

位置関係を保ったままの変換を表す変換行列(3D)

2007-12-21 | 20:39

前回の 「Aの変換前の変換行列の逆行列とAの変換後の変換行列の合成をBに適用することによって、AとBの位置関係を維持する」方法の3D版。
下のウィンドウをクリックしてフォーカスを移動した後、赤いキューブと青いキューブは Rキーでロー/ Pキーでピッチ / Yキーでヨー の回転を行います。
緑のキューブには 「赤の変換前の変換行列の逆行列と赤の変換後の変換行列の合成」を適用しています。
赤と青は回転方向は同じですが、位置関係(互いに見える方向)は変わってしまいます。
赤と緑は常に位置関係は同じですので、ひとつのつながった部品のように見えます。

package {
        import flash.display.*;
        import flash.events.*;
       
        import org.papervision3d.core.*;
        import org.papervision3d.core.math.*;
        import org.papervision3d.scenes.*;
        import org.papervision3d.objects.primitives.*;
        import org.papervision3d.cameras.*;
        import org.papervision3d.materials.*;
        import org.papervision3d.materials.shadematerials.*;
        import org.papervision3d.materials.utils.*;
        import org.papervision3d.view.*;
        import org.papervision3d.render.*;
        import org.papervision3d.lights.*;
       
        [SWF(width="400", height="400", backgroundColor="#ffffff")]
        public class GW extends Sprite{
                private var renderer:BasicRenderEngine = new BasicRenderEngine();
                private var viewport:Viewport3D = new Viewport3D(400, 400, false, true);
                private var scene:Scene3D = new Scene3D();
                private var camera:Camera3D = new Camera3D();
                private var redCube:Cube;
                private var greenCube:Cube;
                private var blueCube:Cube;
               
                public function GW():void
                {
                        stage.align = StageAlign.TOP_LEFT;
                        stage.scaleMode = StageScaleMode.NO_SCALE;
                       
                        addChild(viewport);
                       
                        camera.y = 0;
                        camera.z = -550;
                        camera.x = 0;
                        camera.focus = 1100;
                        camera.zoom = 1;
                       
                        var m:WireframeMaterial = new WireframeMaterial( 0xff0000 );
                        redCube = new Cube(new MaterialsList({all:m}), 100, 100, 100);
                        redCube.x = 100;
                        redCube.y = 100;
                        scene.addChild(redCube);
                       
                        var m2:WireframeMaterial = new WireframeMaterial( 0xff00 );
                        greenCube = new Cube(new MaterialsList({all:m2}), 100, 100, 100);
                        greenCube.x = 200;
                        greenCube.y = 200;
                        scene.addChild(greenCube);
                       
                        var m3:WireframeMaterial = new WireframeMaterial( 0xff );
                        blueCube = new Cube(new MaterialsList({all:m3}), 100, 100, 100);
                        blueCube.x = 0;
                        blueCube.y = 0;
                        scene.addChild(blueCube);
                       
                        camera.target = redCube;
                       
                        stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent):void{
                                rotate(e.keyCode);
                        });
                        renderer.renderScene(scene, camera, viewport);
                }
               
                private function rotate(keyCode:int):void{
                       
                        // 回転前のredCubeの変換行列
                        var ma:Matrix3D = Matrix3D.clone(redCube.transform);
                        // 原点座標に戻すために逆行列をとる
                        ma.calculateInverse(ma);
                       
                        switch (keyCode){
                                case 80 :// p
                                redCube.pitch(1);
                                blueCube.pitch(1);
                                break;
                                case 82 :// r
                                redCube.roll(1);
                                blueCube.roll(1);
                                break;
                                case 89 :// y
                                redCube.yaw(1);
                                blueCube.yaw(1);
                                break;
                        }
                       
                        // greenCubeの変換行列
                        var m2:Matrix3D = Matrix3D.clone(greenCube.transform);
                        m2.calculateMultiply(ma,m2);
                       
                        // 回転後のredCubeの変換行列を適用
                        m2.calculateMultiply(redCube.transform,m2);
                       
                        greenCube.transform = m2;
                        renderer.renderScene(scene, camera, viewport);
                }
        }
}

注意:
行列Xによる写像と行列Yによる写像を合成する場合(Xを先に適用する場合)、行列の演算はXYではなくYXである。

スポンサーサイト

Comment

Post a comment

Secret

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