イナヅマTVログ

ActionScript 3, 立方体を3D回転

| 1件のコメント

Rotate CubeAdvanced ActionScript 3.0 Animation を参考に立方体を3D回転させてみた。

Bitmap を各面にはり、Mouse との距離で回転スピードを調整した。
200px X 200px の正立方体。

リフレッシュごとに各面のZ深度を調整しないと立方体が壊れてしまう。
Flash Player 10 から使える Marix3D を使うのは ActionScript リファレンスを見ただけでは思いつかないな。
Vector3D も登場して難易度はますます上がってしまう。

各面を配列に保持しリフレッシュ時にdeltaTransformVector値を比較しソートさせる。
書けば簡単だけど、イマイチ理論が理解できない。

perspectiveProjection を使うことで stage をリサイズした時の立方体のゆがみを抑制することができるんだね。
以前に比べて簡単なようなそうでもないような・・・


Demo : Rotate Cube - Flash Player 10 が必要です。

package {
import flash.display.StageAlign;
import flash.display.StageScaleMode;
 
import flash.events.Event;
import flash.display.Sprite;
import flash.display.DisplayObject;
import flash.display.Bitmap;
import flash.geom.Vector3D;
import flash.geom.Point;
 
[SWF(backgroundColor='#FFFFFF', frameRate='24')]
 
public class RotateCube extends Sprite {
 
	[Embed(source="dim1.png")]
	private var dim1:Class;
	[Embed(source="dim2.png")]
	private var dim2:Class;
	[Embed(source="dim3.png")]
	private var dim3:Class;
	[Embed(source="dim4.png")]
	private var dim4:Class;
	[Embed(source="dim5.png")]
	private var dim5:Class;
	[Embed(source="dim6.png")]
	private var dim6:Class;
 
	private var _surfaces:Array;
	private var _sprite:Sprite;
 
	public function RotateCube()
	{
		super();
		stage.addEventListener(Event.RESIZE, resizeHandler);
		stage.align = StageAlign.TOP_LEFT;
		stage.scaleMode = StageScaleMode.NO_SCALE;
 
		_sprite = new Sprite();
		_sprite.x = stage.stageWidth / 2;
		_sprite.y = stage.stageHeight / 2;
		_sprite.z = 0;
		addChild(_sprite);
 
		var d1:Sprite = makeSurface(dim1);
		d1.z = -100;
 
		var d2:Sprite = makeSurface(dim2);
		d2.rotationY = 180;// add
		d2.z = 100;
 
		var d3:Sprite = makeSurface(dim3);
		d3.x = 100;
		d3.rotationY = 90;
		d3.rotationX = 180;// add
		d3.z = 0;
 
		var d4:Sprite = makeSurface(dim4);;
		d4.x = -100;
		d4.rotationY = -90;
		d4.rotationX = 180;// add
		d4.z = 0;
 
		var d5:Sprite = makeSurface(dim5);;
		d5.y = 100;
		d5.rotationX = 90;
		d5.z = 0;
 
		var d6:Sprite = makeSurface(dim6);
		d6.y = -100;
		d6.rotationX = 270;// modify 90 to 270
		d6.z = 0;
 
		_surfaces = [d1, d2, d3, d4, d5, d6];
		sortSurfaces();
 
		stage.addEventListener( Event.ENTER_FRAME, enterFrameHandler );
	}
 
	private function makeSurface(cname:Class):Sprite
	{
		var d:Bitmap = new cname() as Bitmap;
		var s:Sprite = new Sprite();
		s.addChild(d)
		d.x = -100;
		d.y = -100;
 
		_sprite.addChild(s);
		return s;
	}
 
	private function resizeHandler(event:Event):void
	{
		root.transform.perspectiveProjection.projectionCenter = new Point(stage.stageWidth / 2, stage.stageHeight / 2);
		_sprite.x = stage.stageWidth / 2;
		_sprite.y = stage.stageHeight / 2;
	}
 
	private function enterFrameHandler(event:Event):void
	{
		var cons:Number = .009;
		var ry:Number = (mouseX - stage.stageWidth / 2) * cons;
		var rx:Number = (mouseY - stage.stageHeight / 2) * cons;
		_sprite.rotationX += rx;
		_sprite.rotationY += ry;
 
		sortSurfaces();
	}
 
	private function sortSurfaces():void
	{
		_surfaces.sort(depthSort);
		for (var i:int = 0; i < _surfaces.length; i++)
		{
			_sprite.addChildAt(_surfaces[i] as Sprite, i);
		}
	}
 
	private function depthSort(objA:DisplayObject, objB:DisplayObject):int
	{
		var posA:Vector3D = objA.transform.matrix3D.position;
		posA = _sprite.transform.matrix3D.deltaTransformVector(posA);
		var posB:Vector3D = objB.transform.matrix3D.position;
		posB = _sprite.transform.matrix3D.deltaTransformVector(posB);
		return posB.z - posA.z;
	}
}
 
}

TextMate + Flex SDK 3.3

あっ!これだと面の向きが合ってないなぁー。
やり直さなきゃ。

面にはり付けた画像の表裏が正しくなかったので修正した。

1件のコメント

  1. ピンバック: イナヅマtvログ » Actionscript 3, 筒状に並べた画像を回転させる

コメントを残す

必須欄は * がついています


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください