Alternativa3Dをやる その6-クリックでテクスチャを書き換える

Filed under 3D, Alternativa3D, AS3



Flashの3D表現ライブラリの1つである、Alternativa3Dに手を出してみました。

使ってるバージョンは7.5です。

今回は、Object3Dが持つ関数の1つの「intersectRay」を使ってみました。

Alternativa3D公式のサンプルを参考にしています。

で、作ったのはこれ

クリックすると、スタンプみたいなのが押されるはず。

以下ソースです。

package
{
	import alternativa.engine3d.containers.DistanceSortContainer;
	import alternativa.engine3d.core.Camera3D;
	import alternativa.engine3d.core.MouseEvent3D;
	import alternativa.engine3d.core.Object3D;
	import alternativa.engine3d.core.RayIntersectionData;
	import alternativa.engine3d.core.View;
	import alternativa.engine3d.materials.TextureMaterial;
	import alternativa.engine3d.primitives.Box;
	import alternativa.engine3d.primitives.Plane;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Point;

	[SWF(backgroundColor=0x000000)]
	public class Main extends Sprite
	{
		[Embed(source="image.png")]
		private var img:Class;

		private static const RADIAN:Number = Math.PI/180;
		private var rootContainer:DistanceSortContainer;
		private var camera:Camera3D;
		private var view:View;
		private var stamp:Shape;
		private var stamp_x:Number;
		private var stamp_y:Number;

		public function Main()
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.quality = StageQuality.HIGH;
			stage.frameRate = 30;

			// ベースとなるコンテナ。
			rootContainer = new DistanceSortContainer();
			rootContainer.sortByZ = true;

			// カメラの初期化 (PV3Dでいうフリーカメラみたいなの)。
			camera = rootContainer.addChild(new Camera3D) as Camera3D;
			camera.z = -800;
			camera.y = -400;
			camera.rotationX = -30*RADIAN;

			// ビューポート (View is DisplayObject)
			view = new View(stage.stageWidth, stage.stageHeight);
			view.logoAlign = StageAlign.TOP_LEFT;
			view.logoHorizontalMargin = 80;
			camera.view = addChild(view) as View;
			view.interactive = true;

			// デバッグ情報を表示する場合は記述
			camera.diagramAlign = StageAlign.TOP_LEFT;
			addChild(camera.diagram);

			// スタンプを作成
			stamp = new Shape;
			var bmpd:BitmapData = (new img as Bitmap).bitmapData;
			stamp_x = -bmpd.width*0.5;
			stamp_y = -bmpd.height*0.5;
			var g:Graphics = stamp.graphics;
			g.beginBitmapFill(bmpd);
			g.drawRect(0,0, bmpd.width, bmpd.height);
			g.endFill();

			// Boxを配置
			var box:Box = rootContainer.addChild(new Box(180, 180, 180)) as Box;
			var color:Array = [0xc7632e, 0xffdef7, 0x0000ff, 0xede07a, 0x00ffff, 0xd6def7];
			for(var i:int=0 ; i<6 ; i++) box.faces[i].material = new TextureMaterial(new BitmapData(400,400,false,color[i]));
			box.x = box.y = box.z = 0;
			box.rotationY = 45*RADIAN;

			// Planeを配置
			var plane:Plane = rootContainer.addChild(new Plane(800, 800)) as Plane;
			plane.setMaterialToAllFaces(new TextureMaterial(new BitmapData(700,700,false, 0x388c31)));
			plane.rotationX = 90*RADIAN;
			plane.rotationY = 45*RADIAN;
			plane.y = 90;

			// イベントの追加
			rootContainer.addEventListener(MouseEvent3D.MOUSE_DOWN, onMouseDown);

			addEventListener(Event.ENTER_FRAME, onFrame);
			stage.addEventListener(Event.RESIZE, onResize);
		}

		// マウスダウン時に実行される関数
		private function onMouseDown(e:MouseEvent3D):void
		{
			// クリックされたオブジェクトを取得
			var object:Object3D = e.target as Object3D;

			// レイとポリゴンの交差部分を検索。その結果を取得。
			var data:RayIntersectionData = object.intersectRay(e.localOrigin, e.localDirection);
			if (data != null)
			{
				// 交差部分の検索による、直近のマテリアルを取得
				var texture:BitmapData = (data.face.material as TextureMaterial).texture;
				// UV値の取得
				var uv:Point = data.face.getUV(data.point);

				// スタンプを押す位置を計算
				var mat:Matrix = new Matrix;
				mat.translate(stamp_x, stamp_y);
				mat.rotate(Math.PI*Math.random());
				mat.translate(uv.x*texture.width, uv.y*texture.height);
				texture.draw(stamp, mat);
			}
		}

		private function onResize(e:Event):void
		{
			view.width = stage.stageWidth;
			view.height = stage.stageHeight;
		}

		private function onFrame(e:Event):void
		{
			camera.render();
		}
	}
}

Post a Comment

Your email is never published nor shared.