SpringCamera [Alternativa3D 7.6 TIPS]
clockmakerさんが作成されたSpringCameraのデモ
http://wonderfl.net/code/377fb950a67300bf295d28010a9cd590ba7c0ad5
を5.6に移植した物
http://wonderfl.net/c/cBLj
を、さらに7.6に移植しました。
2011/01/12 7.5から7.6仕様に変更
/**
* Copyright narutohyper ( http://wonderfl.net/user/narutohyper )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/coV8
*/
// forked from narutohyper's Alternativa3D 7.5 Template
package {
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.primitives.Sphere;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Vector3D;
[SWF(width = 465, height = 465, frameRate = 60, backgroundColor=0x00000000)]
public class Test extends Sprite {
public function Test():void {
// テンプレートを作成します
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event=null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
//AlternativaTemplate作成
var scene:AlternativaTemplate = new AlternativaTemplate(this);
// レールを作成する
for(var i:int=0; i<100; i++) {
var s:Sphere=new Sphere(100,4,2,false);
s.setMaterialToAllFaces(new FillMaterial(0xFFFFFF,0,0,0xFF0000));
scene.container.addChild(s);
var angle:Number = (i / 100) * 360 * Math.PI / 180;
s.x = Math.cos(angle * 1) * 3000;
s.y = Math.sin(angle * 2) * 3000;
s.z = 0.3 * Math.sin(angle * 1) * 3000;
}
// 星
for(i = 0; i<200; i++) {
s = new Sphere(100,4,2,false);
s.setMaterialToAllFaces(new FillMaterial(0x666666,0,0,0x666666));
scene.container.addChild(s);
s.x = 20000 * (Math.random() - 0.5);
s.y = 20000 * (Math.random() - 0.5);
s.z = 20000 * (Math.random() - 0.5);
}
// マーカー
var ball:Sphere=new Sphere(100,4,2,false);
ball.setMaterialToAllFaces(new FillMaterial(0x0,1,0,0xFFFFFF));
scene.container.addChild(ball);
// SpringCameraController
var cameraContoller:SpringCameraController=new SpringCameraController(this,scene.camera,100);
cameraContoller.target=ball;
scene.camera.fov=100*Math.PI/180;
cameraContoller.mass = 30;
cameraContoller.damping = 30;
cameraContoller.stiffness = 1;
cameraContoller.positionOffset = new Vector3D(0, 200, 0);
cameraContoller.lookOffset = new Vector3D(0, 0, 0);
var rot:Number = 0;
//描画開始
scene.startRendering();
scene.onPreRender = function():void {
rot += 0.15;
var angle:Number = (rot / 100) * 360 * Math.PI / 180;
ball.x = Math.cos(angle * 1) * 3000;
ball.y = Math.sin(angle * 2) * 3000;
ball.z = 0.3 * Math.sin(angle * 1) * 3000 + 300;
//SpringCameraの追従
cameraContoller.update();
scene.camera.render();
}
}
}
}
import alternativ7.engine3d.controllers.SimpleObjectController;
import flash.display.InteractiveObject;
import alternativ7.engine3d.core.Object3D;
import flash.geom.Vector3D;
/**
*
* SpringCameraControl
*
* @author narutohyper
*/
class SpringCameraController extends SimpleObjectController
{
private var _camTarget:Object3D;
private var _zrot:Number = 0;
public var mass:Number = 40;
public var damping:Number = 4;
public var stiffness:Number = 1;
public var positionOffset:Vector3D = new Vector3D(0, -50, 5);
public var lookOffset:Vector3D = new Vector3D(0, 10, 2);
public function SpringCameraController(eventSource:InteractiveObject, object:Object3D, speed:Number, speedMultiplier:Number = 3, mouseSensitivity:Number = 1) {
super(eventSource, object, speed, speedMultiplier, mouseSensitivity);
}
public function set target(t:Object3D):void {
_camTarget=t;
}
public function get target():Object3D {
return _camTarget;
}
public function set zrot(n:Number):void {
_zrot = n;
if(_zrot < 0.001) n = 0;
}
public function get zrot():Number {
return _zrot;
}
private var _velocity:Vector3D = new Vector3D();
private var _dv:Vector3D = new Vector3D();
private var _stretch:Vector3D = new Vector3D();
private var _force:Vector3D = new Vector3D();
private var _acceleration:Vector3D = new Vector3D();
private var _desiredPosition:Vector3D = new Vector3D();
private var _lookAtPosition:Vector3D = new Vector3D();
private var _xPosition:Vector3D = new Vector3D();
override public function update():void {
if(_camTarget != null) {
_desiredPosition = new Vector3D(_camTarget.x,_camTarget.y,_camTarget.z);
_desiredPosition=_desiredPosition.add(positionOffset.clone());
_stretch.x = (object.x - _desiredPosition.x) * -stiffness;
_stretch.y = (object.y - _desiredPosition.y) * -stiffness;
_stretch.z = (object.z - _desiredPosition.z) * -stiffness;
_dv.x = _velocity.x * damping;
_dv.y = _velocity.y * damping;
_dv.z = _velocity.z * damping;
_force.x = _stretch.x - _dv.x;
_force.y = _stretch.y - _dv.y;
_force.z = _stretch.z - _dv.z;
_acceleration.x = _force.x * (1 / mass);
_acceleration.y = _force.y * (1 / mass);
_acceleration.z = _force.z * (1 / mass);
_velocity=_velocity.add(_acceleration);
_xPosition=new Vector3D(object.x,object.y,object.z);
_xPosition=_xPosition.add(_velocity);
setObjectPos(_xPosition);
_lookAtPosition= new Vector3D(_camTarget.x,_camTarget.y,_camTarget.z);
_lookAtPosition=_lookAtPosition.add(lookOffset.clone());
lookAt(_lookAtPosition);
if(Math.abs(_zrot) > 0) object.rotationY = _zrot;
updateObjectTransform()
}
}
}
/**
* BasicTemplate for Alternativa3D 7.5
* Alternativa3D 7.5を扱いやすくするためのテンプレートです
* @author narutohyper & clockmaker
*
*/
import alternativ7.engine3d.containers.BSPContainer;
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.containers.DistanceSortContainer;
import alternativ7.engine3d.containers.KDContainer;
import alternativ7.engine3d.containers.LODContainer;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.core.View;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
class AlternativaTemplate extends Sprite
{
/**
* 子オブジェクトを最適な方法でソートするコンテナ
* (ConflictContainer)
*/
public static const CONFLICT:String = 'conflict';
/**
* 子オブジェクトをBSP(バイナリ空間分割法)によってソートするコンテナ
* (BSPContainer)
*/
public static const BSP:String = 'bsp';
/**
* 子オブジェクトをカメラからのZ値でソートするコンテナ
* (DistanceSortContainer)
*/
public static const ZSORT:String = 'zsort';
/**
* KDツリー(http://ja.wikipedia.org/wiki/Kd%E6%9C%A8)によってソートするコンテナ
* (KDContainer)
*/
public static const KD:String = 'kd';
/**
* detalizationと子オブジェクトの距離でソートするコンテナ(詳細は調査中)
* (LODContainer)
*/
public static const LOD:String = 'lod';
/**
* 3dオブジェクト格納するコンテナインスタンス。
*/
public var container:Object3DContainer;
/**
* ビューインスタンスです。
*/
public var view:View;
/**
* カメラインスタンスです。
*/
public var camera:Camera3D;
/**
* カメラコントローラーです。
*/
public var cameraController:SimpleObjectController;
private var _mc:DisplayObjectContainer;
private var _viewWidth:int;
private var _viewHeight:int;
private var _scaleToStage:Boolean;
private var _containerType:String;
/**
* 新しい Alternativa3DTemplate インスタンスを作成します。
* @param mc
* @param containerType
* @param viewWidth
* @param viewHeight
* @param scaleToStage
*/
public function AlternativaTemplate(mc:DisplayObjectContainer,containerType:String=CONFLICT,viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true)
{
_mc = mc;
_mc.addChild(this);
_containerType = containerType;
_viewWidth = viewWidth;
_viewHeight = viewHeight;
_scaleToStage = scaleToStage;
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理をオーバーライドして記述します。
*/
protected function atInit():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
protected function atPreRender():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
private var _onPreRender:Function = function():void{};
public function get onPreRender():Function { return _onPreRender; }
public function set onPreRender(value:Function):void
{
_onPreRender = value;
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理をオーバーライドして記述します。
*/
protected function atPostRender():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理を記述します。
*/
private var _onPostRender:Function = function():void{};
public function get onPostRender():Function { return _onPostRender; }
public function set onPostRender(value:Function):void
{
_onPostRender = value;
}
/**
* レンダリングを開始します。
*/
public function startRendering():void
{
addEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* レンダリングを停止します。
*/
public function stopRendering():void
{
removeEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* シングルレンダリング(レンダリングを一回だけ)を実行します。
*/
public function singleRender():void
{
onRenderTick();
}
/**
* @private
*/
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.HIGH;
//Root objectの作成
if (_containerType == CONFLICT) {
container = new ConflictContainer();
} else if (_containerType == BSP) {
container = new BSPContainer();
} else if (_containerType == ZSORT) {
container = new DistanceSortContainer();
} else if (_containerType == KD) {
container = new KDContainer();
} else if (_containerType == LOD) {
container = new LODContainer();
}
//Viewの作成
view = new View(stage.stageWidth, stage.stageHeight);
_mc.addChild(view);
//cameraの作成
camera = new Camera3D();
camera.view = view;
camera.x = 0;
camera.y = -500;
camera.z = 0;
container.addChild(camera);
// Camera controller
cameraController = new SimpleObjectController(stage, camera, 10);
cameraController.mouseSensitivity = 0;
cameraController.unbindAll();
cameraController.lookAtXYZ(0, 0, 0);
onResize();
stage.addEventListener(Event.RESIZE, onResize);
atInit();
}
/**
* @private
*/
private function onResize(e:Event = null):void
{
if (_scaleToStage)
{
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}
else
{
view.width = _viewWidth;
view.height = _viewHeight;
}
}
/**
* @private
*/
private function onRenderTick(e:Event = null):void
{
atPreRender();
_onPreRender();
cameraController.update();
camera.render();
atPostRender();
_onPostRender();
}
}