[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);
}
}