// forked from yd_niku's 3D演習その4 +Camera3Dの回転2 // 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 がおかしいのを直した。 // ぐるぐる回してみる。 // Matrix3Dにしてみた // せっかくなのでObject3Dに抽象化&ScaleとRotate実装 import flash.display.Sprite; import flash.display.DisplayObject; import flash.display.StageQuality; import flash.events.Event; import flash.utils.setInterval; import caurina.transitions.Tweener; [SWF (backgroundColor='#000A22',frameRate=60)] public class FlashTest extends Sprite { private var _scene:Scene3D; private var _camera:Camera3D; private var _easeCamera:EaseObject; private var screenX:Number; private var screenY:Number; public function FlashTest() { stage.quality = StageQuality.MEDIUM; setup(); putThemFar(); setInterval( changeScale, 2500 ); _easeCamera= new EaseObject( _camera ); addEventListener( Event.ENTER_FRAME, enterframeHandler ); } private function setup():void { Object3D.screenX = stage.stageWidth/2; Object3D.screenY = stage.stageHeight/2; _camera = new Camera3D(); _scene = new Scene3D( this, _camera ); var xNum:uint = 8, yNum:uint =8, zNum:uint = 8; var xInterval:uint = 15, yInterval:uint = 15, zInterval:uint =15; 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; obj.scaleX = obj.scaleY= obj.scaleZ = 0.5; Tweener.addTween( obj, { z: tz, time:2, delay:1, transition:"easeInOutQuart" } ); } } private function changeScale():void { var l:uint = _scene.renderList.length; var scale :Number = 2*Math.random()+0.4; var rotation:Number = 360*Math.random(); for( var i:uint=0; i<l; ++i ) { var obj:DisplayObject3D = _scene.renderList[i]; Tweener.addTween( obj, { rotateX:rotation, rotateY:rotation, rotateX:rotation, scaleX:scale , scaleY:scale , scaleZ:scale, time:2, transition:"easeInOutQuart" } ); } } private function enterframeHandler (e:Event):void{ _easeCamera.vRotateX = 1; _easeCamera.vRotateY = 1; _easeCamera.vRotateZ = 1; _easeCamera.calcuration(); } } } class EaseObject { public var vx :Number = 0; public var vy :Number = 0; public var vz :Number = 0; public var vRotateX:Number = 0; public var vRotateY:Number = 0; public var vRotateZ:Number = 0; private var friction:Number = 0.95; private var _target:Object; public function EaseObject ( target:Object ) { _target = target; } public function calcuration():void { vx *= friction; vy *= friction; vz *= friction; vRotateX *= friction; vRotateY *= friction; vRotateZ *= friction; _target.x += vx; _target.y += vy; _target.z += vz; _target.rotateX+= vRotateX; _target.rotateY+= vRotateY; _target.rotateZ+= vRotateZ; } } import flash.display.*; import flash.events.*; import flash.geom.*; 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 matrixCamera:Matrix3D = _camera.getMatrix3D(); var l:uint = _renderList.length; for( var i:uint=0; i<l; ++i ) { var obj:DisplayObject3D= _renderList[i]; var matrixObj :Matrix3D = obj.getMatrix3D(); var p:Vector3D = new Vector3D(obj.x,obj.y,obj.z); p = matrixObj.transformVector( p ); p = matrixCamera.transformVector( p ); if( _camera.isInFocus( p.z) ) { var persepective:Number= _camera.getPersepective(p.z); var tx:Number = p.x*persepective; var ty:Number = p.y*persepective; obj.render( tx, ty, persepective); obj.visible = true; _ZsortList.push( { z:p.z, 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 Object3D { public static var screenX:Number = 0; public static var screenY:Number = 0; public var x:Number = 0; public var y:Number = 0; public var z:Number = 0; public var scaleX:Number = 1.0; public var scaleY:Number = 1.0; public var scaleZ:Number = 1.0; public var rotateX:Number = 0.0; public var rotateY:Number = 0.0; public var rotateZ:Number = 0.0; public function getMatrix3D():Matrix3D { var matrix:Matrix3D = new Matrix3D(); matrix.appendTranslation(x, y, z); matrix.appendScale( scaleX, scaleY, scaleY ); matrix.appendRotation(rotateX, Vector3D.X_AXIS); matrix.appendRotation(rotateY, Vector3D.Y_AXIS); matrix.appendRotation(rotateZ, Vector3D.Z_AXIS); return matrix; } } class DisplayObject3D extends Object3D { public var view:DisplayObject; public function DisplayObject3D( view:DisplayObject=null ) { 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 Camera3D extends Object3D { public var focus:Number = 500; public function getPersepective( tz :Number ):Number { return focus/( focus+tz ); } public function isInFocus( tz:Number ):Boolean { var bool:Boolean = tz > -focus; return bool; } } import flash.filters.*; class Ball extends Sprite { public function Ball() { //graphics.lineStyle(0,0xffffff); graphics.beginFill(0xff9900, 1 ); graphics.drawCircle( 0, 0, 5 ); graphics.endFill(); // filters = [ new BlurFilter() ]; // cacheAsBitmap = true; } } 3D演習その5 +Matrix3DとScaleとRotate