スポンサーサイト

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

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

[ActionScript 3.0] 平面の傾き

2008-01-21 | 20:35

クリックしてフォーカスを移した後、上下左右キーで平面が傾き、傾きに沿ってキューブが動きます。
クリックで最初から。
(PaperVision3D 2.0 GreatWhite使用)

メモ:
macのfirefoxだとキーをいったん離さないとイベントが通知されない。
macのsafari/opera, windowsのfirefoxだと押しっぱなしでイベントが連続して通知される。

package {
        import flash.display.*;
        import flash.events.*;
        
        import org.papervision3d.core.*;
        import org.papervision3d.core.math.*;
        import org.papervision3d.core.geom.* ;
        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.*;
        import org.papervision3d.materials.special.LineMaterial ;
        
        [SWF(width="600", height="400", backgroundColor="#ffffff")]
        public class Gradient extends Sprite{
                private var renderer:BasicRenderEngine = new BasicRenderEngine();
                private var viewport:Viewport3D = new Viewport3D(600, 400, false, true);
                private var scene:Scene3D = new Scene3D();
                private var camera:Camera3D = new Camera3D();
                private var pointLight:PointLight3D;
                
                private var parentCube:Cube;
                private var childCube:Cube;
                // 勾配を表すベクトル
                private var grad:Number3D = new Number3D();
                
                public function Gradient():void
                {
                        stage.align = StageAlign.TOP_LEFT;
                        stage.scaleMode = StageScaleMode.NO_SCALE ;
                        
                        addChild(viewport);
                        
                        camera.y = 200;
                        camera.z = -550;
                        camera.x = 0;
                        camera.focus = 1100;
                        camera.zoom = 1;
                        
                        pointLight = new PointLight3D();
                        pointLight.y = 300;
                        pointLight.z = -100;
                        
                        parentCube = new Cube(new MaterialsList({
                                all:new WireframeMaterial(0xff)}),
                                                                                          //all:new PhongMaterial(pointLight, 0x88FFFF, 0x111111, 1)}),
                        600, 600, 10);
                        scene.addChild(parentCube);
                        
                        childCube = new Cube(new MaterialsList({
                                //all:new GouraudMaterial(pointLight,0xa00000, 0xff0000)}),
                                all:new PhongMaterial(pointLight, 0xFF88FF, 0x111111, 1)}),
                                                                                                                              80, 80, 80);
                        scene.addChild(childCube);
                        childCube.y = 50;
                        
                        camera.target = parentCube;
                        
                        stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e:*):void{
                                grad = new Number3D();
                                parentCube.rotationX = parentCube.rotationY = parentCube.rotationZ = 0;
                                childCube.transform = new Matrix3D();
                                childCube.x = childCube.z = 0;
                                childCube.y = 50;
                        });
                        
                        stage.addEventListener(KeyboardEvent.KEY_DOWN , function(e:KeyboardEvent):void{
                                rotate(e.keyCode);
                        });
                        
                        addEventListener(Event.ENTER_FRAME, onEnterFrame);
                        
                        renderer.renderScene(scene, camera, viewport);
                }
                
                private function rotate(keyCode:int):void{
                        var before:Matrix3D = Matrix3D.clone (parentCube.transform);
                        before.calculateInverse(before);
                        switch (keyCode){
                                case 37 :// ←
                                if(Math.abs (parentCube.rotationZ+1) < 70)
                                parentCube.rotationZ += 1;
                                break;
                                case 39 :// →
                                if( Math.abs(parentCube.rotationZ-1) < 70)
                                parentCube.rotationZ -= 1;
                                break;
                                case 38 :// ↑
                                if( Math.abs(parentCube.rotationX-1) < 70)
                                parentCube.rotationX -= 1;
                                break;
                                case 40 :// ↓
                                if( Math.abs(parentCube.rotationX+1) < 70)
                                parentCube.rotationX += 1;
                                break;
                        }
                        renderer.renderScene (scene, camera, viewport);
                        
                        var after:Matrix3D = Matrix3D.clone(parentCube.transform);
                        
                        // 面の傾きに連動してキューブの傾きも変える
                        update(before, after, childCube);
                        
                        updateGradient();
                }
                
                private function onEnterFrame(e:*):void{
                        // 面を基準にした相対位置を求めるために、面の姿勢ベクトルの逆行列を求める
                        var m:Matrix3D = Matrix3D.inverse (parentCube.transform);
                        // キューブの絶対座標に面の姿勢ベクトルの逆行列を掛けたものが相対位置
                        var rel:Number3D = new Number3D(childCube.x, childCube.y, childCube.z);
                        Matrix3D.multiplyVector(m,rel);
                        
                        // 相対位置を元に面を飛び出したか判断
                        if(Math.abs(rel.x - grad.x*5) > 340 || Math.abs(rel.z - grad.z*5) > 340){
                                grad.x = 0;
                                grad.y = 10;
                                grad.z = 0;
                        }
                        childCube.x -= grad.x*5;
                        childCube.y -= grad.y*5 ;
                        childCube.z -= grad.z*5;
                        renderer.renderScene(scene, camera, viewport);
                }
                
                private function updateGradient():void{
                        var m:Matrix3D = Matrix3D.clone (parentCube.transform);
                        
                        // x方向の勾配
                        grad.x = m.n21 / m.n11;
                        // z方向の勾配
                        grad.z = m.n23 / m.n33;
                        // gradX,gradZに対応するy軸の値を求める
                        grad.y = (-m.n12*grad.x - m.n32*grad.z) / m.n22;
                        
                        renderer.renderScene(scene, camera, viewport);
                }
                
                private function update(before:Matrix3D, after:Matrix3D, link:Cube):void{
                        // DisplayObject3Dの変換行列にbeforeを適用
                        var m:Matrix3D = Matrix3D.clone(link.transform );
                        m.calculateMultiply(before,m);
                        
                        // afterの変換行列を適用
                        m.calculateMultiply(after, m);
                        
                        link.transform = m;
                }
        }
}



傾きの求め方は こちらが丁寧に書かれている。
スポンサーサイト

Comment

Post a comment

Secret

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