3D演習その3 +Camera3Dの回転
ActionScript3.0Animation読みながら、とりあえず3D投影してみる。
Z軸で動かしてみる
Camera を導入してみる
Camera を回転させてみた
Zsortをつけてみた
Camera.rotationY がおかしいのを直した。
// forked from yd_niku's 3D演習その3 +Camera3Dの回転
// forked from yd_niku's forked from: 3D演習その1
// forked from yd_niku's 3D演習その1
package {
// ActionScript3.0Animation読みながら、とりあえず3D投影してみる。
// Z軸で動かしてみる
// Camera を導入してみる
// Camera を回転させてみた
// Zsortをつけてみた
// Camera.rotationY がおかしいのを直した。
import flash.display.Sprite;
import flash.display.DisplayObject;
import flash.events.Event;
import caurina.transitions.Tweener;
public class FlashTest extends Sprite {
private var _scene:Scene3D;
private var _camera:Camera3D;
private var screenX:Number;
private var screenY:Number;
public function FlashTest() {
stage.frameRate = 60;
setup();
putThemFar();
}
private function setup():void {
DisplayObject3D.screenX = stage.stageWidth/2;
DisplayObject3D.screenY = stage.stageHeight/2;
_camera = new Camera3D();
_scene = new Scene3D( this, _camera );
var xNum:uint = 8, yNum:uint = 8, zNum:uint = 10;
var xInterval:uint = 50, yInterval:uint = 50, zInterval:uint = 50;
for( var i:int=0; i<xNum; ++i ) {
for( var j:int=0; j<yNum; ++j ) {
for( var k:int=0; k<zNum; ++k ) {
createBall(
(i-xNum*0.5)*xInterval,
(j-yNum*0.5)*yInterval,
(k-zNum*0.2)*zInterval
);
}
}
}
}
private function createBall( sx:Number, sy:Number, sz:Number ):void {
var obj3D:DisplayObject3D = new DisplayObject3D(new Ball());
obj3D.x = sx;
obj3D.y = sy;
obj3D.z = sz;
_scene.addChild( obj3D );
}
private function putThemFar():void {
var l:uint = _scene.renderList.length;
for( var i:uint=0; i<l; ++i ) {
var obj:DisplayObject3D = _scene.renderList[i];
var tz:Number= obj.z;
obj.z = 0;
Tweener.addTween( obj, { z: tz, time:2, transition:"easeInOutQuart" } );
}
Tweener.addTween( _camera,
{ rotationX:360, rotationY:360, rotationZ:180,
time:15, transition:"easeInOutQuart" } );
}
}
}
import flash.display.*;
import flash.events.*;
class DisplayObject3D {
public static var screenX:Number = 0;
public static var screenY:Number = 0;
public var view:DisplayObject;
public var x:Number = 0;
public var y:Number = 0;
public var z:Number = 0;
public function DisplayObject3D( view:DisplayObject ) {
this.view = view;
}
public function render( tx:Number, ty:Number, persepective:Number ):void {
view.x = tx + screenX;
view.y = ty + screenY;
view.scaleX = view.scaleY = persepective;
view.alpha = Math.min( 1, persepective);
}
public function set visible( value:Boolean ) :void {
view.visible = value;
}
public function get visible() :Boolean {
return view.visible;
}
}
class Scene3D {
private var _stage:DisplayObjectContainer;
private var _camera :Camera3D;
private var _renderList:Array = [];
private var _ZsortList:Array = [];
public function Scene3D( stage:DisplayObjectContainer, camera:Camera3D ){
_stage = stage;
_camera = camera;
_stage.addEventListener( Event.ENTER_FRAME, enterfameHandler );
}
private function enterfameHandler(e:Event):void {
render();
}
public function addChild( obj3D :DisplayObject3D ) :DisplayObject3D {
_renderList.push( obj3D );
_stage.addChild( obj3D.view );
return obj3D;
}
private const PI:Number = Math.PI;
public function render():void {
_ZsortList = [];
var camXCos:Number = Math.cos( PI*_camera.rotationX/180);
var camXSin:Number = Math.sin( PI*_camera.rotationX/180);
var camYCos:Number = Math.cos( PI*_camera.rotationY/180);
var camYSin:Number = Math.sin( PI*_camera.rotationY/180);
var camZCos:Number = Math.cos( PI*_camera.rotationZ/180);
var camZSin:Number = Math.sin( PI*_camera.rotationZ/180);
var l:uint = _renderList.length;
for( var i:uint=0; i<l; ++i ) {
var obj:DisplayObject3D= _renderList[i];
var tmpX:Number = obj.x - _camera.x;
var tmpY:Number = obj.y - _camera.y;
var tmpZ:Number = obj.z - _camera.z;
// TODO:Matrix3Dにまかせる
// Z Axis
var ZAxisX :Number = ( tmpX*camZCos - tmpY*camZSin );
var ZAxisY :Number = ( tmpX*camZSin + tmpY*camZCos );
var ZAxisZ :Number = tmpZ;
// X Axis
var XAxisY :Number = ( ZAxisY*camXCos - ZAxisZ*camXSin );
var XAxisZ :Number = ( ZAxisY*camXSin + ZAxisZ*camXCos );
var XAxisX :Number = ZAxisX;
// Y Axis
var YAxisZ :Number = ( XAxisZ*camYCos - XAxisX*camYSin );
var YAxisX :Number = ( XAxisZ*camYSin + XAxisX*camYCos );
var YAxisY :Number = XAxisY;
if( _camera.isInFocus( YAxisY ) ) {
var persepective:Number= _camera.getPersepective( YAxisZ );
var tx:Number = YAxisX*persepective;
var ty:Number = YAxisY*persepective;
obj.render( tx, ty, persepective);
obj.visible = true;
_ZsortList.push( { z:YAxisZ, view:obj.view } );
}
else {
obj.visible = false;
}
}
// Zsort
_ZsortList.sortOn( "z", Array.DESCENDING|Array.NUMERIC );
l = _ZsortList.length;
for( i=0; i<l; ++i ) {
var zobj:Object = _ZsortList[i] as Object;
_stage.setChildIndex( zobj.view, i );
}
}
public function get renderList():Array{ return _renderList; }
}
class Camera3D{
public var focus:Number = 500;
public var x:Number = 0;
public var y:Number = 0;
public var z:Number = 0;
public function getPersepective( tz :Number ):Number {
return focus/( focus+tz );
}
public function isInFocus( tz:Number ):Boolean {
var bool:Boolean = tz > -focus;
return bool;
}
public var rotationX:Number = 0;
public var rotationY:Number = 0;
public var rotationZ:Number = 0;
}
class Ball extends Sprite {
public function Ball() {
graphics.lineStyle(0,0xffffff);
graphics.beginFill(0xcc6600);
graphics.drawCircle( 0, 0, 10 );
graphics.endFill();
}
}