In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

[Alternativa3D] Collada Animation Sample

BlenderでつくったCollada Animationを再生するサンプル。

copyright (c) 2012 www.romatica.com
@author itoz ( http://www.romatica.com/ )

 [AlternativaTemplate]
 @see http://www.libspark.org/browser/as3/AlternativaTemplate
/**
 * Copyright romatica ( http://wonderfl.net/user/romatica )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/zrV5
 */

/**
 * copyright (c) 2012 www.romatica.com
 * @author itoz ( http://www.romatica.com/ )
 * 
 *  [AlternativaTemplate]
 *  @see http://www.libspark.org/browser/as3/AlternativaTemplate
 *  
 */
package
{
    import a24.tween.Ease24;
    import a24.tween.Tween24;

    import alternativa.engine3d.animation.AnimationClip;
    import alternativa.engine3d.animation.AnimationController;
    import alternativa.engine3d.core.Camera3D;
    import alternativa.engine3d.core.Object3D;
    import alternativa.engine3d.core.Resource;
    import alternativa.engine3d.core.View;
    import alternativa.engine3d.lights.AmbientLight;
    import alternativa.engine3d.lights.OmniLight;
    import alternativa.engine3d.loaders.ParserCollada;
    import alternativa.engine3d.materials.TextureMaterial;
    import alternativa.engine3d.materials.VertexLightTextureMaterial;
    import alternativa.engine3d.objects.Skin;
    import alternativa.engine3d.primitives.Box;
    import alternativa.engine3d.resources.BitmapTextureResource;

    import jp.progression.data.getResourceById;

    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.Stage3D;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;

    [SWF(backgroundColor="#ffffff", width="465", height="465", frameRate="60")]
    public class Wonderfl_Slime extends Sprite
    {
        private var stage3D : Stage3D;
        private var scene : Object3D;
        private var camera : Camera3D;
        private var container : Object3D;
        private var controllers : Array;
        private var cameraController : OrbitCameraController;
        private var jumpFlag : Boolean;
        
        private var _model : Skin;


       public function Wonderfl_Slime()
        {
            Wonderfl.disable_capture();
            if (stage) _initialize(null);
            else addEventListener(Event.ADDED_TO_STAGE, _initialize);
        }

        private function _initialize(event : Event) : void
        {
            removeEventListener(Event.ADDED_TO_STAGE, _initialize);
            //
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            // ----------------------------------
            // Assets Load Start
            // ----------------------------------
            var assetsLoader:AssetsLoader = AssetsLoader.getInstance();
            assetsLoader.addEventListener(Event.COMPLETE, onTexturesLoadComplete_Handler);
            assetsLoader.loadStart();
        }

        private function onTexturesLoadComplete_Handler(event : Event) : void
        {
            scene = new Object3D();
            camera = scene.addChild(new Camera3D(1, 1000)) as Camera3D;
            cameraController = new OrbitCameraController(camera, this, stage, stage);
            cameraController.mouseSensitivity = 0;
            cameraController.unbindAll();
            (cameraController as OrbitCameraController).bindBasicKey();
            cameraController.setObjectPosXYZ(0, -1000, 0);
            cameraController.lookAtXYZ(0, 0, 0);
            
            camera.view = addChild(new View(465, 465, true, 0x000000, 1, 4)) as View;
            camera.view.backgroundColor = 0x0;
            // addChild(camera.diagram);
            //
            stage3D = stage.stage3Ds[0];
            stage3D.addEventListener(Event.CONTEXT3D_CREATE, onCreateContext_Handler, false, 0, true);
            stage3D.requestContext3D();
        }


        private function onCreateContext_Handler(evt : Event) : void
        {
            stage3D.removeEventListener(Event.CONTEXT3D_CREATE, onCreateContext_Handler);
            createObject();
            createUI();
            addEventListener(Event.ENTER_FRAME, render, false, 0, true);
        }

        private function createUI() : void
        {
            var btn : MyButton = addChild(new MyButton("[JUMP]")) as MyButton;
            btn.addEventListener(MouseEvent.CLICK, onClickButton);
            var sw:Number =stage.stageWidth;
            var sh:Number = stage.stageHeight;
            var scx:int = (sw/2);
            btn.x = scx -(btn.width/2);
            btn.y= sh *0.85- btn.height ;
        }

        private function createObject() : void
        {
            // --------------------------------------------------------------------------
            //
            // container
            //
            // --------------------------------------------------------------------------
            container = scene.addChild(new Object3D())as Object3D;
            container.scaleX = container.scaleY = container.scaleZ = 2;
            container.z = -32;
            
            // --------------------------------------------------------------------------
            //
            // lights
            //
            // --------------------------------------------------------------------------
            scene.addChild(new AmbientLight(0xd8d8d8))  as AmbientLight;
            var oLight :OmniLight= scene.addChild(new OmniLight(0xffffff, 100, 10000)) as OmniLight;
            oLight.x = -210;
            oLight.y = 20;
            oLight.z = 500;
            
            // --------------------------------------------------------------------------
            //
            // ground
            //
            // --------------------------------------------------------------------------
            var grouudMaterial : TextureMaterial = new TextureMaterial(new BitmapTextureResource(getResourceById(AssetsLoader.GROUND_TEXTURE).data as BitmapData));
            var ground : Box = container.addChild(new Box(4, 4, 0.2, 2, 2, 2, false, grouudMaterial)) as Box;
            ground.scaleX = ground.scaleY = ground.scaleZ = 64;
            ground.z = -7;
            
            // --------------------------------------------------------------------------
            //
            // model
            //
            // --------------------------------------------------------------------------
            
            // texture
            var texture : VertexLightTextureMaterial = new VertexLightTextureMaterial(new BitmapTextureResource(getResourceById(AssetsLoader.IMAGE_URL_MAIN).data as BitmapData));
            
            // model
            var data : XML = XML(getResourceById(AssetsLoader.DAE_MODEL_URL).data);
            var parser : ParserCollada = new ParserCollada();
            parser.parse(data, "", true);
            for (var i : int = 0; i < parser.objects.length; i++)
            {
                var obj : Object3D = parser.objects[i];
                scene.addChild(obj);
                if (parser.objects[i] as Skin )
                {
                    var skin : Skin = parser.objects[i] as Skin;
                    skin.setMaterialToAllSurfaces(texture);
                    _model = skin;
                    container.addChild(_model);
                }
            }

            // animation
            controllers = [];
            for each (var animation:AnimationClip in parser.animations)
            {
                var controller : AnimationController = new AnimationController();
                controller.root = animation;
                controllers.push(controller);
            }
            
            // --------------------------------------------------------------------------
            //
            // resource upload
            //
            // --------------------------------------------------------------------------
            for each (var resource:Resource in scene.getResources(true))
            {
                resource.upload(stage3D.context3D);
            }
        }

        /**
         * jump
         */
        private function onClickButton(event : MouseEvent) : void
        {
            if(jumpFlag)return ;
            jumpFlag = true;
            
            Tween24.serial(
                Tween24.tween(_model,0.1,Ease24._3_CubicIn).scaleZ(0.5).scale(1.3)
                ,Tween24.parallel(
                    Tween24.tween(_model,0.6,Ease24._BackInOut).$$z(100)
                    ,Tween24.tween(_model,0.65,Ease24._BackInOut).scaleZ(1.5).scale(0.7)
                )
                ,Tween24.parallel(
                    Tween24.tween(_model,0.8,Ease24._BounceOut).z(0)
                    ,Tween24.tween(_model,0.8,Ease24._BounceOut).scaleZ(0.9).scale(1)
                )
                ,Tween24.tween(_model,0.8,Ease24._BounceOut).scaleZ(1)
            ).onComplete(function():void{jumpFlag = false;}).play();
        }

        private function render(evt : Event) : void
        {
            // ----------------------------------
            // animation update
            // ----------------------------------
            for each (var controller:AnimationController in controllers)
            {
                controller.update();
            }
            camera.render(stage3D);
            cameraController.update();
        }
    }
}


import alternativa.engine3d.controllers.SimpleObjectController;
import alternativa.engine3d.core.Object3D;

import jp.progression.commands.lists.LoaderList;
import jp.progression.commands.net.LoadBitmapData;
import jp.progression.commands.net.LoadURL;

import flash.display.GradientType;
import flash.display.InteractiveObject;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.geom.Vector3D;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import flash.ui.Mouse;
import flash.ui.MouseCursor;

// --------------------------------------------------------------------------
//
// button
//
// --------------------------------------------------------------------------
class MyButton extends Sprite
{
    public function MyButton(string : String, color : uint = 0xd8d8d8, w : int = 200, h : int = 35)
    {
        this.filters = [new GlowFilter(0x0, 0.5)];
        var gradType : String = GradientType.LINEAR;
        var gradMrx : Matrix = new Matrix();
        gradMrx.createGradientBox(w, h, Math.PI / 2, 0, 0);
        var gradColors : Array = [0xf5f5f5, color];
        var gradAlphas : Array = [1, 1];
        var gradRadios : Array = [0, 255];
        var gradSpread : String = SpreadMethod.PAD;
        this.graphics.beginGradientFill(gradType, gradColors, gradAlphas, gradRadios, gradMrx, gradSpread);
        this.graphics.drawRoundRect(0, 0, w, h, 15);
        this.graphics.endFill();
        this.addEventListener(MouseEvent.MOUSE_OVER, function(e:MouseEvent):void{(e.target as Sprite).alpha = 0.8;});
        this.addEventListener(MouseEvent.MOUSE_OUT, function(e:MouseEvent):void{(e.target as Sprite).alpha =1;});
        this.buttonMode = true;
        this.mouseChildren = false;
        var _label : TextField = this.addChild(new TextField()) as TextField;
        _label.defaultTextFormat = new TextFormat("_ゴシック", 12, 0x0);
        _label.autoSize = TextFieldAutoSize.LEFT;
        _label.text = string;
        _label.x = this.width / 2 - _label.width / 2;
        _label.y = this.height / 2 - _label.height / 2;
    }
}
// --------------------------------------------------------------------------
//
// assets loader
//
// --------------------------------------------------------------------------
class AssetsLoader extends EventDispatcher
{
    private var _startFlag : Boolean;
    private static const DOMAIN_PATH : String = "http://www.romatica.com/dev/wonderfl/slime/";
    public static const DAE_MODEL_URL : String = DOMAIN_PATH + "slimeBoneAnime.dae";
    public static const IMAGE_URL_MAIN : String = DOMAIN_PATH + "slime.png";
    public static const GROUND_TEXTURE : String = DOMAIN_PATH + "texture.png";
    
    public static var instance : AssetsLoader;
    

    public static function getInstance() : AssetsLoader
    {
        if ( instance == null ) instance = new  AssetsLoader(new SingletonEnforcer());
        return instance;
    }

    public function AssetsLoader(pvt : SingletonEnforcer)
    {
        if (pvt == null) throw new Error("TextureLoader is a singleton class, use getInstance() instead");
    }

    public function loadStart() : void
    {
        if (_startFlag) return;
        _startFlag = true;

        var loaderList : LoaderList = new LoaderList({
                onProgress:function():void{
//                    trace(this.percent);
                }                
                ,onComplete:function():void 
                {
                    dispatchEvent(new Event(Event.COMPLETE));
                }
                ,catchError:function(target:Object, e:Error):void
                {
                    trace( target, e );
                    // target.interrupt();
                }
                ,onError:function():void
                {
                    // _tf.text = "onError :" 
                }
            });
        loaderList.addCommand(new LoadBitmapData(new URLRequest(IMAGE_URL_MAIN),{context: new LoaderContext(true)}));
        loaderList.addCommand(new LoadBitmapData(new URLRequest(GROUND_TEXTURE),{context: new LoaderContext(true)}));
        loaderList.addCommand(new LoadURL(new URLRequest(DAE_MODEL_URL), {context:new LoaderContext(true)}));
        loaderList.execute();
    }
}
internal class SingletonEnforcer
{
}

/**
 * [AlternativaTemplate]
 * @see http://www.libspark.org/browser/as3/AlternativaTemplate
 */
class CameraType
{
    // ----------------------------------------------------------
    //
    // Static Property
    //
    // ----------------------------------------------------------
    /**
     * 3D オブジェクトの周りに配置するカメラモードを指定します。
     */
    public static const ORBIT : String = "orbit";
    /**
     * パノラマビューのカメラモードを指定します。
     */
    public static const PANORAMA : String = "panorama";
    /**
     * 原点(x:0, y:0, z:0)をターゲットとした Camera3D を定義します。
     */
    public static var TARGET : String = "target";
    /**
     * ターゲットの存在しない Camera3D を定義します。
     */
    public static var FREE : String = "free";
}

/**
 * [AlternativaTemplate]
 * @see http://www.libspark.org/browser/as3/AlternativaTemplate
 */
class OrbitCameraController extends SimpleObjectController
{

    //----------------------------------------------------------
    //
    //   Static Property 
    //
    //----------------------------------------------------------

    /** 中心と方向へ移動するアクションを示す定数です。 */
    public static const ACTION_FORWARD:String = "actionForward";

    /** 中心と反対方向へ移動するアクションを示す定数です。 */
    public static const ACTION_BACKWARD:String = "actionBackward";

    /** イージングの終了判断に用いるパラメーターです。0〜0.2で設定し、0に近いほどイージングが残されます。 */
    private static const ROUND_VALUE:Number = 0.1;

    //----------------------------------------------------------
    //
    //   Constructor 
    //
    //----------------------------------------------------------

    /**
     * 新しい GeoCameraController インスタンスを作成します。
     * @param targetObject    コントローラーで制御したいオブジェクトです。
     * @param mouseDownEventSource    マウスダウンイベントとひもづけるオブジェクトです。
     * @param mouseUpEventSource    マウスアップイベントとひもづけるオブジェクトです。推奨は stage です。
     * @param keyEventSource    キーダウン/キーマップイベントとひもづけるオブジェクトです。推奨は stage です。
     * @param useKeyControl    キーコントロールを使用するか指定します。
     * @param useMouseWheelControl    マウスホイールコントロールを使用するか指定します。
     */
    public function OrbitCameraController(
        targetObject:Object3D,
        mouseDownEventSource:InteractiveObject,
        mouseUpEventSource:InteractiveObject,
        keyEventSource:InteractiveObject,
        useKeyControl:Boolean = true,
        useMouseWheelControl:Boolean = true
        )
    {
        _target = targetObject;

        super(mouseDownEventSource, targetObject, 0, 3, mouseSensitivity);
        super.mouseSensitivity = 0;
        super.unbindAll();
        super.accelerate(true);

        this._mouseDownEventSource = mouseDownEventSource;
        this._mouseUpEventSource = mouseUpEventSource;
        this._keyEventSource = keyEventSource;

        _mouseDownEventSource.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);

        // マウスホイール操作
        if (useMouseWheelControl)
            _mouseDownEventSource.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);

        // キーボード操作
        if (useKeyControl)
        {
            _keyEventSource.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
            _keyEventSource.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
        }
    }

    //----------------------------------------------------------
    //
    //   Property 
    //
    //----------------------------------------------------------

    //--------------------------------------
    // easingSeparator 
    //--------------------------------------

    private var _easingSeparator:Number = 10;

    /**
     * イージング時の現在の位置から最後の位置までの分割係数
     * フレームレートと相談して使用
     * 1〜
     * 正の整数のみ。0 を指定しても 1 になります。
     * 1 でイージング無し。数値が高いほど、遅延しぬるぬるします
     */
    public function set easingSeparator(value:uint):void
    {
        if (value)
            _easingSeparator = value;
        else
            _easingSeparator = 1;
    }
    /** Camera から、中心までの最大距離です。デフォルト値は 2000 です。 */
    public var maxDistance:Number = 2000;
    /**
     * 最大緯度です。
     */
    public var maxLatitude:Number = 89.9;

    /** Camera から、中心までの最小距離です。デフォルト値は 200 です。 */
    public var minDistance:Number = 200;

    /**
     * 最小緯度です。
     */
    public var minLatitude:Number = -89.9;

    //--------------------------------------
    // mouseSensitivityX 
    //--------------------------------------

    private var _mouseSensitivityX:Number = -1;

    /**
     * マウスの X 方向の感度
     */
    public function set mouseSensitivityX(value:Number):void
    {
        _mouseSensitivityX = value;
    }

    //--------------------------------------
    // mouseSensitivityY 
    //--------------------------------------

    private var _mouseSensitivityY:Number = 1;

    /**
     * マウスの Y 方向の感度
     */
    public function set mouseSensitivityY(value:Number):void
    {
        _mouseSensitivityY = value;
    }

    public var multiplyValue:Number = 10;

    //--------------------------------------
    // needsRendering 
    //--------------------------------------

    private var _needsRendering:Boolean;

    /**
     * レンダリングが必要かどうかを取得します。
     * この値は update() メソッドが呼び出されたタイミングで更新されます。
     *
     * @see GeoCameraController.update
     */
    public function get needsRendering():Boolean
    {
        return _needsRendering;
    }

    //--------------------------------------
    // pitchSpeed 
    //--------------------------------------

    private var _pitchSpeed:Number = 5;

    /**
     * 上下スピード
     * 初期値は5(px)
     */
    public function set pitchSpeed(value:Number):void
    {
        _pitchSpeed = value;
    }

    public var useHandCursor:Boolean = true;

    //--------------------------------------
    // yawSpeed 
    //--------------------------------------

    private var _yawSpeed:Number = 5;

    /**
     * 回転スピード
     * 初期値は5(度)
     */
    public function set yawSpeed(value:Number):void
    {
        _yawSpeed = value * Math.PI / 180;
    }

    /**
     * Zoomスピード
     * 初期値は5(px)
     */
    public function set zoomSpeed(value:Number):void
    {
        _distanceSpeed = value;
    }

    private var _angleLatitude:Number = 0;
    private var _angleLongitude:Number = 0;
    private var _distanceSpeed:Number = 5;
    private var _keyEventSource:InteractiveObject;
    private var _lastLatitude:Number = 0;
    private var _lastLength:Number = 700;
    private var _lastLongitude:Number = _angleLongitude;
    private var _lastLookAtX:Number = _lookAtX;
    private var _lastLookAtY:Number = _lookAtY;
    private var _lastLookAtZ:Number = _lookAtZ;
    private var _length:Number = 700;
    private var _lookAtX:Number = 0;
    private var _lookAtY:Number = 0;
    private var _lookAtZ:Number = 0;
    private var _mouseDownEventSource:InteractiveObject;
    private var _mouseMove:Boolean;
    private var _mouseUpEventSource:InteractiveObject;
    private var _mouseX:Number;
    private var _mouseY:Number;
    private var _oldLatitude:Number;
    private var _oldLongitude:Number;
    private var _pitchDown:Boolean;
    private var _pitchUp:Boolean;
    private var _taregetDistanceValue:Number = 0;
    private var _taregetPitchValue:Number = 0;
    private var _taregetYawValue:Number = 0;
    private var _target:Object3D;
    private var _yawLeft:Boolean;
    private var _yawRight:Boolean;
    private var _zoomIn:Boolean;
    private var _zoomOut:Boolean;

    //----------------------------------------------------------
    //
    //   Function 
    //
    //----------------------------------------------------------

    /** 上方向に移動します。 */
    public function pitchUp():void
    {
        _taregetPitchValue = _pitchSpeed * multiplyValue;
    }

    /** 下方向に移動します。 */
    public function pitchDown():void
    {
        _taregetPitchValue = _pitchSpeed * -multiplyValue;
    }

    /** 左方向に移動します。 */
    public function yawLeft():void
    {
        _taregetYawValue = _yawSpeed * multiplyValue;
    }

    /** 右方向に移動します。 */
    public function yawRight():void
    {
        _taregetYawValue = _yawSpeed * -multiplyValue;
    }

    /** 中心へ向かって近づきます。 */
    public function moveForeward():void
    {
        _taregetDistanceValue -= _distanceSpeed * multiplyValue;
    }

    /** 中心から遠くに離れます。 */
    public function moveBackward():void
    {
        _taregetDistanceValue += _distanceSpeed * multiplyValue;
    }

    /**
     * @inheritDoc
     */
    override public function bindKey(keyCode:uint, action:String):void
    {
        switch (action)
        {
            case ACTION_FORWARD:
            {
                keyBindings[keyCode] = toggleForward;
                break;
            }
            case ACTION_BACKWARD:
            {
                keyBindings[keyCode] = toggleBackward;
                break;
            }
            case ACTION_YAW_LEFT:
            {
                keyBindings[keyCode] = toggleYawLeft;
                break;
            }
            case ACTION_YAW_RIGHT:
            {
                keyBindings[keyCode] = toggleYawRight;
                break;
            }
            case ACTION_PITCH_DOWN:
            {
                keyBindings[keyCode] = togglePitchDown;
                break;
            }
            case ACTION_PITCH_UP:
            {
                keyBindings[keyCode] = togglePitchUp;
                break;
            }
        }
        //super.bindKey(keyCode, action)
    }

    /**
     * 下方向に移動し続けるかを設定します。
     * @param value    true の場合は移動が有効になります。
     */
    public function togglePitchDown(value:Boolean):void
    {
        _pitchDown = value;
    }

    /**
     * 上方向に移動し続けるかを設定します。
     * @param value    true の場合は移動が有効になります。
     */
    public function togglePitchUp(value:Boolean):void
    {
        _pitchUp = value;
    }

    /**
     * 左方向に移動し続けるかを設定します。
     * @param value    true の場合は移動が有効になります。
     */
    public function toggleYawLeft(value:Boolean):void
    {
        _yawLeft = value;
    }

    /**
     * 右方向に移動し続けるかを設定します。
     * @param value    true の場合は移動が有効になります。
     */
    public function toggleYawRight(value:Boolean):void
    {
        _yawRight = value;
    }

    /**
     * 中心方向に移動し続けるかを設定します。
     * @param value    true の場合は移動が有効になります。
     */
    public function toggleForward(value:Boolean):void
    {
        _zoomIn = value;
    }

    /**
     * 中心と反対方向に移動し続けるかを設定します。
     * @param value    true の場合は移動が有効になります。
     */
    public function toggleBackward(value:Boolean):void
    {
        _zoomOut = value;
    }

    /**
     * @inheritDoc
     */
    override public function update():void
    {
//        const RADIAN:Number = Math.PI / 180;
        var oldAngleLatitude:Number = _angleLatitude;
        var oldAngleLongitude:Number = _angleLongitude;
        var oldLengh:Number = _lastLength;

        //CameraZoom制御
        if (_zoomIn)
            _lastLength -= _distanceSpeed;
        else if (_zoomOut)
            _lastLength += _distanceSpeed;

        // ズーム制御
        if (_taregetDistanceValue != 0)
        {
            _lastLength += _taregetDistanceValue;
            _taregetDistanceValue = 0;
        }

        if (_lastLength < minDistance)
            _lastLength = minDistance;
        else if (_lastLength > maxDistance)
            _lastLength = maxDistance;
        if (_lastLength - _length)
            _length += (_lastLength - _length) / _easingSeparator;

        if (Math.abs(_lastLength - _length) < ROUND_VALUE)
            _length = _lastLength;

        //Camera回転制御
        if (_mouseMove)
            _lastLongitude = _oldLongitude + (_mouseDownEventSource.mouseX - _mouseX) * _mouseSensitivityX;
        else if (_yawLeft)
            _lastLongitude += _yawSpeed;
        else if (_yawRight)
            _lastLongitude -= _yawSpeed;

        if (_taregetYawValue)
        {
            _lastLongitude += _taregetYawValue;
            _taregetYawValue = 0;
        }

        if (_lastLongitude - _angleLongitude)
            _angleLongitude += (_lastLongitude - _angleLongitude) / _easingSeparator;

        if (Math.abs(_lastLatitude - _angleLatitude) < ROUND_VALUE)
            _angleLatitude = _lastLatitude;

        //CameraZ位置制御
        if (_mouseMove)
            _lastLatitude = _oldLatitude + (_mouseDownEventSource.mouseY - _mouseY) * _mouseSensitivityY;
        else if (_pitchDown)
            _lastLatitude -= _pitchSpeed;
        else if (_pitchUp)
            _lastLatitude += _pitchSpeed;

        if (_taregetPitchValue)
        {
            _lastLatitude += _taregetPitchValue;
            _taregetPitchValue = 0;
        }

        // 最大緯度と最小緯度の間に抑える
        _lastLatitude = Math.max(minLatitude, Math.min(_lastLatitude, maxLatitude));

        if (_lastLatitude - _angleLatitude)
            _angleLatitude += (_lastLatitude - _angleLatitude) / _easingSeparator;
        if (Math.abs(_lastLongitude - _angleLongitude) < ROUND_VALUE)
            _angleLongitude = _lastLongitude;

        var vec3d:Vector3D = this.translateGeoCoords(_angleLatitude, _angleLongitude, _length);
        _target.x = vec3d.x;
        _target.y = vec3d.y;
        _target.z = vec3d.z;

        //lookAt制御
        if (_lastLookAtX - _lookAtX)
            _lookAtX += (_lastLookAtX - _lookAtX) / _easingSeparator;

        if (_lastLookAtY - _lookAtY)
            _lookAtY += (_lastLookAtY - _lookAtY) / _easingSeparator;

        if (_lastLookAtZ - _lookAtZ)
            _lookAtZ += (_lastLookAtZ - _lookAtZ) / _easingSeparator;

        //super.update()
        updateObjectTransform();
        lookAtXYZ(_lookAtX, _lookAtY, _lookAtZ);

        _needsRendering = oldAngleLatitude != _angleLatitude
            || oldAngleLongitude != _angleLongitude
            || oldLengh != _length;
    }

    /** @inheritDoc */
    override public function startMouseLook():void
    {
        // 封印
    }

    /** @inheritDoc */
    override public function stopMouseLook():void
    {
        // 封印
    }

    /**
     * Cameraの向く方向を指定します。
     * lookAtやlookAtXYZとの併用は不可。
     * @param x
     * @param y
     * @param z
     * @param immediate    trueで、イージングしないで変更
     */
    public function lookAtPosition(x:Number, y:Number, z:Number, immediate:Boolean = false):void
    {
        if (immediate)
        {
            _lookAtX = x;
            _lookAtY = y;
            _lookAtZ = z;
        }
        _lastLookAtX = x;
        _lastLookAtY = y;
        _lastLookAtZ = z;
    }

    /**
     * 経度を設定します。
     * @param value    0で、正面から中央方向(lookAtPosition)を見る
     * @param immediate    trueで、イージングしないで変更
     */
    public function setLongitude(value:Number, immediate:Boolean = false):void
    {
        if (immediate)
            _angleLongitude = value;
        _lastLongitude = value;
    }

    /**
     * 緯度を設定します。
     * @param value    0で、正面から中央方向(lookAtPosition)を見る
     * @param immediate    trueで、イージングしないで変更
     */
    public function setLatitude(value:Number, immediate:Boolean = false):void
    {
        // 最大緯度、最小緯度の範囲に丸める
        value = Math.max(minLatitude, Math.min(maxLatitude, value));

        if (immediate)
            _angleLatitude = value;
        _lastLatitude = value;
    }

    /**
     * Cameraから、targetObjectまでの距離を設定します。
     * @param value    Cameraから、targetObjectまでの距離
     * @param immediate trueで、イージングしないで変更
     */
    public function setDistance(value:Number, immediate:Boolean = false):void
    {
        if (immediate)
            _length = value;
        _lastLength = value;
    }

    /**
     * オブジェクトを使用不可にしてメモリを解放します。
     */
    public function dispose():void
    {
        // イベントの解放
        if (_mouseDownEventSource)
            _mouseDownEventSource.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);

        // マウスホイール操作
        if (_mouseDownEventSource)
            _mouseDownEventSource.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);

        // キーボード操作
        if (_keyEventSource)
        {
            _keyEventSource.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
            _keyEventSource.removeEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
        }

        // プロパティーの解放
        _easingSeparator = 0;
        maxDistance = 0;
        minDistance = 0;
        _mouseSensitivityX = 0;
        _mouseSensitivityY = 0;
        multiplyValue = 0;
        _needsRendering = false;
        _pitchSpeed = 0;
        useHandCursor = false;
        _yawSpeed = 0;
        _angleLatitude = 0;
        _angleLongitude = 0;
        _distanceSpeed = 0;
        _keyEventSource = null;
        _lastLatitude = 0;
        _lastLength = 0;
        _lastLongitude = 0;
        _lastLookAtX = 0;
        _lastLookAtY = 0;
        _lastLookAtZ = 0;
        _length = 0;
        _lookAtX = 0;
        _lookAtY = 0;
        _lookAtZ = 0;
        _mouseDownEventSource = null;
        _mouseMove = false;
        _mouseUpEventSource = null;
        _mouseX = 0;
        _mouseY = 0;
        _oldLatitude = 0;
        _oldLongitude = 0;
        _pitchDown = false;
        _pitchUp = false;
        _taregetDistanceValue = 0;
        _taregetPitchValue = 0;
        _taregetYawValue = 0;
        _target = null;
        _yawLeft = false;
        _yawRight = false;
        _zoomIn = false;
        _zoomOut = false;
    }

    /**
     * 自動的に適切なキーを割り当てます。
     */
    public function bindBasicKey():void
    {
        bindKey(Keyboard.LEFT, SimpleObjectController.ACTION_YAW_LEFT);
        bindKey(Keyboard.RIGHT, SimpleObjectController.ACTION_YAW_RIGHT);
        bindKey(Keyboard.DOWN, SimpleObjectController.ACTION_PITCH_DOWN);
        bindKey(Keyboard.UP, SimpleObjectController.ACTION_PITCH_UP);
        bindKey(Keyboard.PAGE_UP, OrbitCameraController.ACTION_BACKWARD);
        bindKey(Keyboard.PAGE_DOWN, OrbitCameraController.ACTION_FORWARD);
    }

    protected function mouseDownHandler(event:Event):void
    {
        _oldLongitude = _lastLongitude;
        _oldLatitude = _lastLatitude;
        _mouseX = _mouseDownEventSource.mouseX;
        _mouseY = _mouseDownEventSource.mouseY;
        _mouseMove = true;

        if (useHandCursor)
            Mouse.cursor = MouseCursor.HAND;

        _mouseUpEventSource.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
    }

    protected function mouseUpHandler(event:Event):void
    {
        if (useHandCursor)
            Mouse.cursor = MouseCursor.AUTO;

        _mouseMove = false;
        _mouseUpEventSource.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
    }

    private function keyDownHandler(event:KeyboardEvent):void
    {
        for (var key:String in keyBindings)
        {
            if (String(event.keyCode) == key)
                keyBindings[key](true);
        }
    }

    private function keyUpHandler(event:KeyboardEvent = null):void
    {
        for (var key:String in keyBindings)
            keyBindings[key](false);
    }

    private function mouseWheelHandler(event:MouseEvent):void
    {
        _lastLength -= event.delta * 20;
        if (_lastLength < minDistance)
            _lastLength = minDistance;
        else if (_lastLength > maxDistance)
            _lastLength = maxDistance;
    }

    /**
     * 経度と緯度から位置を算出します。
     * @param latitude    緯度
     * @param longitude    経度
     * @param radius    半径
     * @return 位置情報
     */
    private function translateGeoCoords(latitude:Number, longitude:Number, radius:Number):Vector3D
    {
        const latitudeDegreeOffset:Number = 90;
        const longitudeDegreeOffset:Number = -90;

        latitude = Math.PI * latitude / 180;
        longitude = Math.PI * longitude / 180;

        latitude -= (latitudeDegreeOffset * (Math.PI / 180));
        longitude -= (longitudeDegreeOffset * (Math.PI / 180));

        var x:Number = radius * Math.sin(latitude) * Math.cos(longitude);
        var y:Number = radius * Math.cos(latitude);
        var z:Number = radius * Math.sin(latitude) * Math.sin(longitude);

        return new Vector3D(x, z, y);
    }
}