fc2ブログ

PV3D オブジェクトの姿勢の補間間隔をTweenerで

2008-03-10 | 20:56

左側のトランジッション名をクリックするとそれにあわせて姿勢を変えます。


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

    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.utils.*;
    import org.papervision3d.view.*;
    import org.papervision3d.render.*;
    import org.papervision3d.materials.special.LineMaterial ;

    import caurina.transitions.Tweener;

    [SWF(width="600", height="400", frameRate="10", backgroundColor="#ffffff")]
        public class SlerpTweener 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 cube:SlerpObject;

            private var transitions:Array = ["linear",
                "easeInSine", "easeOutSine", "easeInOutSine",
                "easeInQuad", "easeOutQuad", "easeInOutQuad",
                "easeInCubic", "easeOutCubic", "easeInOutCubic",
                "easeInQuart", "easeOutQuart", "easeInOutQuart",
                "easeInQuint", "easeOutQuint", "easeInOutQuint",
                "easeInExpo", "easeOutExpo", "easeInOutExpo",
                "easeInCirc", "easeOutCirc", "easeInOutCirc",
                "easeInElstic", "easeOutElstic", "easeInOutElstic",
                "easeInBack", "easeOutBack", "easeInOutBack",
                "easeInBounce", "easeOutBounce", "easeInOutBounce" ];

            public function SlerpTweener():void
            {
                stage.align = StageAlign.TOP_LEFT;
                stage.scaleMode = StageScaleMode.NO_SCALE;

                addChild(viewport);

                camera.y = -300;
                camera.z = -1100;
                camera.x = 0;
                camera.focus = 1100;
                camera.zoom = 1;

                var c:Cube = new Cube(new MaterialsList(
                                {all:new WireframeMaterial(0xff00)}), 
                            100, 200, 300);
                cube = new SlerpObject(c);
                scene.addChild(c);
                renderer.renderScene(scene, camera, viewport);

                SlerpUtil.init();

                for(var i:int = 0 ; i < transitions.length ; i++){

                    var tf:TextField = new TextField();
                    tf.text = transitions[i];
                    tf.addEventListener(MouseEvent.MOUSE_DOWN, function(e:*):void{
                            slerp(e.target);
                            });
                    addChild(tf);
                    tf.y = i*12;
                }
            }

            private function slerp(tf:TextField):void{
                Tweener.addTween(cube, {time:2, _t:1, transition:tf.text, 
                        onUpdate:function():void{
                        renderer.renderScene(scene, camera, viewport);
                        }, onComplete:function():void{
                        cube.onComplete();
                        }
                        });
                Tweener.addTween(tf, {time:2, x:400, transition:tf.text, 
                        onComplete:function():void{
                        tf.x = 0;
                        }
                        });
            }
        }
}

internal class SlerpObject{
    public var t:Number=0;
    public var o3d:DisplayObject3D;
    // 元の姿勢のクォータニオン
    public var qSrc:Quaternion;
    // 移動後の姿勢のクォータニオン
    public var qDst:Quaternion;

    public function SlerpObject(o:DisplayObject3D){
        o3d = o;

        qSrc = Quaternion.createFromAxisAngle(0,0,1, -Math.PI/2);
        qDst = Quaternion.createFromAxisAngle(0,1,0, Math.PI/2);
    }

    public function onComplete():void{
        t = 0;
        var temp:Quaternion = qSrc;
        qSrc = qDst;
        qDst = temp;
    }
}

import org.papervision3d.core.math.*;
import org.papervision3d.objects.*;
import caurina.transitions.Tweener;

internal class SlerpUtil{
    public static function init(): void {
        Tweener.registerSpecialProperty("_t", _get_t, _set_t, ["t"]);
    }

    protected static function _get_t(p_obj:Object, p_parameters:Array, p_extra:Object = null):Number
    {
        return p_obj.t;
    }

    protected static function _set_t(p_obj:Object, p_value:Number, p_parameters:Array, p_extra:Object = null):void
    {
        trace(p_value);
        p_obj.t = p_value;
        var q:Quaternion = Quaternion.slerp(p_obj.qSrc, p_obj.qDst, p_value);
        p_obj.o3d.transform = q.toMatrix();
    }
}

スポンサーサイト