スポンサーサイト

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

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

3次元での回転の合成

2008-01-25 | 23:22

上のプログラムでは、赤いキューブは(100,200,0) 青いキューブは(300,200,0)に最初に移動させた後、


// X軸周りに回転する回転行列
var m:Matrix3D = Matrix3D.rotationMatrix(1,0,0,0.1);

// X軸周りの回転行列 x 姿勢行列を赤いキューブには適用
redCube.transform = Matrix3D.multiply(m, redCube.transform);
// 姿勢行列 x X軸周りの回転行列を青いキューブには適用
blueCube.transform = Matrix3D.multiply(blueCube.transform,m);

という処理をフレームごとに行っている。

行列A 掛ける 行列B
という演算は、Bの変換を適用してからAの変換を適用することになるので、赤いキューブは(原点にあるキューブに対して)自分の直前の姿勢行列を適用してからX軸周りに回転する処理になる。先に動かした後にX軸周りに回転させているので、X軸を中心に大きく回る。
対して青いキューブは、X軸周りに回転させてから自分の直前の姿勢行列を適用しているので、位置は変わらないまま回転している。

package {
        import flash.display.*;
        import flash.events.*;
        
        import org.papervision3d.core.*;
        import org.papervision3d.core.geom.*;
        import org.papervision3d.core.math.*;
        import org.papervision3d.scenes.* ;
        import org.papervision3d.objects.*;
        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.*;
        import org.papervision3d.materials.special.LineMaterial ;
        
        [SWF(width="600", height="400", frameRate="10", backgroundColor="#ffffff")]
        public class RotationAxis extends Sprite{
                private var renderer:BasicRenderEngine = new BasicRenderEngine();
                private var viewport:Viewport3D = new Viewport3D(600, 800, false, true);
                private var scene:Scene3D = new Scene3D();
                private var camera:FreeCamera3D = new FreeCamera3D();
                
                private var linkList:Array = [];
                
                private var lines:Array = null;
                
                private var redCube:Cube;
                private var blueCube:Cube;
                
                private var cubes:Array = [];
                
                public function RotationAxis():void
                {
                        stage.align = StageAlign.TOP_LEFT;
                        stage.scaleMode = StageScaleMode.NO_SCALE;
                        
                        //viewport.y = 50;
                        addChild(viewport);
                        
                        camera.y = 0;
                        camera.z = -1100;
                        camera.x = -200;
                        camera.focus = 1100;
                        camera.zoom = 1;
                        camera.tilt(15);
                        camera.yaw(15);
                        
                        var xl:Lines3D = new Lines3D(new LineMaterial());
                        scene.addChild(xl);
                        xl.addNewLine(1, 0,0,0,500,0,0);
                        
                        var redwire:WireframeMaterial = new WireframeMaterial( 0xff0000 );
                        var bluewire:WireframeMaterial = new WireframeMaterial( 0xff );
                        redCube = new Cube(new MaterialsList({all:redwire}), 100, 100, 100);
                        blueCube = new Cube(new MaterialsList({all:bluewire}), 100, 100, 100);
                        redCube.x = 100;
                        redCube.y = 200;
                        blueCube.x = 300;
                        blueCube.y = 200;
                        scene.addChild(redCube);
                        scene.addChild(blueCube);
                        cubes.push(redCube);
                        cubes.push(blueCube);
                        
                    // メモリリークが発生するようなのでローカル座標軸を表示するのは止める
                    //    showVector();
                        
                        renderer.renderScene(scene, camera, viewport);
                        
                        addEventListener(Event.ENTER_FRAME, rotate);
                        //stage.addEventListener(KeyboardEvent.KEY_DOWN, rotate);
                }
                
                private function rotate(e:*):void{
                        // X軸周りに回転する回転行列
                        var m:Matrix3D = Matrix3D.rotationMatrix(1,0,0,0.1);
                        
                        // X軸周りの回転行列 x 姿勢行列を赤いキューブには適用
                        redCube.transform = Matrix3D.multiply(m, redCube.transform);
                        // 姿勢行列 x X軸周りの回転行列を青いキューブには適用
                        blueCube.transform = Matrix3D.multiply(blueCube.transform,m);
                        
                        renderer.renderScene(scene, camera, viewport);
                        // メモリリークが発生するようなのでローカル座標軸を表示するのは止める
                        //showVector();
                }
                
                private function showVector():void{
                        if(lines != null){
                                for each(var l:Lines3D in lines){
                                        scene.removeChild(l);
                                }
                        }
                        lines = [];
                        
                        for each(var cube:Cube in cubes){
                                var m:Matrix3D = cube.transform;
                                var xl:Lines3D = new Lines3D(new LineMaterial());
                                scene.addChild(xl);
                                xl.addNewLine(2, cube.x,cube.y,cube.z,
                                                             cube.x + m.n11*100, cube.y + m.n21*100 , cube.z + m.n31*100);
                                lines.push(xl);
                                
                                var yl:Lines3D =  new Lines3D(new LineMaterial(0xff));
                                scene.addChild(yl);
                                yl.addNewLine(2, cube.x,cube.y,cube.z,
                                                             cube.x + m.n12*100, cube.y + m.n22*100 , cube.z + m.n32*100);
                                lines.push(yl);
                                
                                var zl:Lines3D = new Lines3D(new LineMaterial(0xff00));
                                scene.addChild (zl);
                                zl.addNewLine(2, cube.x,cube.y,cube.z,
                                                              cube.x + m.n13*100, cube.y + m.n23*100 , cube.z + m.n33*100);
                                lines.push(zl);
                        }
                        renderer.renderScene(scene, camera, viewport);
                }
        }
}

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