Beautifl - Flash Gallery

Thumbnail : Alternativa3D Tips Reflection
Alternativa3D Tips Reflection
narutohyper 2010-03-07 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

package {
	import alternativ5.engine3d.controllers.WalkController;
	import alternativ5.engine3d.core.Camera3D;
	import alternativ5.engine3d.core.Object3D;
	import alternativ5.engine3d.core.Scene3D;
	import alternativ5.engine3d.display.View;

	import alternativ5.engine3d.materials.FillMaterial;
	import alternativ5.engine3d.primitives.Box;
	import alternativ5.engine3d.controllers.ObjectController
	import alternativ5.types.Point3D;
	import alternativ5.utils.KeyboardUtils
	import alternativ5.utils.FPS;


	import flash.display.*
	import flash.events.Event;

	/*
	*	Alternativa3D Tips Reflection
	* 
	* 2台のカメラと2つのViewを使用した、Alternativa3Dでの鏡面反射です。
	* とりあえず、行列変換やクォータニオンは使わないで実装しています。
	* なので、下方向への反射のみです。
	* 
	*	@narutohyper
	*/
	
	[SWF(width = 465, height = 465, frameRate = 60)]
	public class SimpleDemo extends Sprite {

		public var scene:Scene3D;
		public var view:View;
		public var camera:Camera3D;
		public var cameraController:WalkController;

		public var box:Array;
		public var plane:ReflectionPlane;


		public function SimpleDemo():void {
			FPS.init (stage);
			
			scene = new Scene3D();
			scene.splitAnalysis = false; // not analysis for performance
			scene.root = new Object3D();

			camera = new Camera3D();
			camera.y = -1000;
			camera.z = 0;
			scene.root.addChild(camera);

			//Controllerのインスタンスを作る
			cameraController=new WalkController(this.stage)
			cameraController.object=camera
			cameraController.coords=new Point3D(0,-1000,500)

			//キーボードのキー(Keyboard.KEY)を関連付ける(Bind)する	
			cameraController.mouseEnabled=false
			cameraController.bindKey(KeyboardUtils.W,					ObjectController.ACTION_FORWARD);
			cameraController.bindKey(KeyboardUtils.UP,				ObjectController.ACTION_FORWARD);
			cameraController.bindKey(KeyboardUtils.Z,					ObjectController.ACTION_BACK);
			cameraController.bindKey(KeyboardUtils.DOWN,			ObjectController.ACTION_BACK);
			cameraController.bindKey(KeyboardUtils.A,					ObjectController.ACTION_LEFT);
			cameraController.bindKey(KeyboardUtils.LEFT,			ObjectController.ACTION_LEFT);
			cameraController.bindKey(KeyboardUtils.D,					ObjectController.ACTION_RIGHT);
			cameraController.bindKey(KeyboardUtils.RIGHT,			ObjectController.ACTION_RIGHT);

			cameraController.bindKey(KeyboardUtils.SHIFT,	ObjectController.ACTION_ACCELERATE);
			cameraController.speed=400;
			cameraController.yawSpeed=800;
			cameraController.pitchSpeed=800;

			//メインビュー
			view = new View();
			view.camera = camera;
			view.width = 465;
			view.height = 465;


			//鏡面の作成
			plane=new ReflectionPlane(this,view,cameraController)
			scene.root.addChild(plane);
			plane.init()


			addChild(view);


			// プリミティブを作成します
			box=[]
			for (var i:uint=0;i<9;i++) {
				box[i] = new Box(100, 100, Math.floor(i/3)*50+100);
				

				box[i].setMaterialToSurface(new FillMaterial(0xFF<<(8*(i%3))),'top');
				box[i].setMaterialToSurface(new FillMaterial(0xCC<<(8*(i%3))),'front');
				box[i].setMaterialToSurface(new FillMaterial(0xCC<<(8*(i%3))),'back');
				box[i].setMaterialToSurface(new FillMaterial(0x99<<(8*(i%3))),'left');
				box[i].setMaterialToSurface(new FillMaterial(0x99<<(8*(i%3))),'right');
				box[i].setMaterialToSurface(new FillMaterial(0x33<<(8*(i%3))),'bottom');
				box[i].z=150
				box[i].x=Math.floor(i/3)*300-300
				box[i].y=(i%3)*300-300
				scene.root.addChild(box[i]);
			}

			var bmd:BitmapData=new BitmapData(100,100,true,0xFFFF0000)

			if (stage) {
				init();
			} else {
				addEventListener(Event.ADDED_TO_STAGE, init);
			}

		}

		private function init(e:Event = null):void {
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.quality = StageQuality.HIGH;

			stage.addEventListener(Event.RESIZE, onResize);
			onResize(null);
			
			startRendering();
			
		}
		
		private function startRendering():void {
			addEventListener(Event.ENTER_FRAME, onRenderTick);
		}



		private function onRenderTick(e:Event = null):void {
			for (var i:uint=0;i<9;i++) {
				box[i].rotationZ+=Math.PI/180
			}
			
			var dx:Number = box[4].coords.x-cameraController.coords.x
			var dy:Number = cameraController.coords.y-box[4].coords.y
			var dist:Number = Math.sqrt(dx * dx + dy * dy);
			
			if (dist<150) {
				cameraController.moveForward(false)
			}			

			cameraController.lookAt(box[4].coords);
			cameraController.processInput();


			plane.onRenderTick(box[4].coords)
			scene.calculate();
		}

		private function onResize(event:Event = null):void {
		}


	}
}



import alternativ5.engine3d.controllers.WalkController;
import alternativ5.engine3d.core.Camera3D;
import alternativ5.engine3d.core.Object3D;
import alternativ5.engine3d.display.View;
import alternativ5.engine3d.materials.FillMaterial;
import alternativ5.engine3d.primitives.Plane;
import alternativ5.types.Point3D;

import flash.display.*
import flash.events.Event;


class ReflectionPlane extends Object3D{
	private var view:View;
	private var cameraController:WalkController;
	private var plane:Plane;
	private var localCamera:Camera3D;
	private var localView:View;
	private var localController:WalkController;
	private var msk:Sprite;


	public function ReflectionPlane(mc:DisplayObjectContainer,_view:View,_cameraController:WalkController,_width:Number=1000,_height:Number=1000,_color:uint=0x000000,_alpha:Number=0.1) {
		view=_view
		cameraController=_cameraController

		//鏡面
		plane=new Plane(_width,_height,1,1);
		plane.cloneMaterialToAllSurfaces(new FillMaterial(_color,_alpha));
		this.addChild(plane);

		//鏡面用のカメラ
		localCamera = new Camera3D();
		localCamera.y = -1000;
		localCamera.z = 0;

		//鏡面用のView
		localView = new View();
		localView.camera = localCamera;
		localView.x = 0;
		localView.width = 465;
		localView.height = 465;
		localView.y = 465
		localView.scaleY = -1
		mc.addChild(localView);

		msk=new Sprite();
		mc.addChild(msk);
		localView.mask=msk

		localController=new WalkController(mc.stage)
		localController.coords=new Point3D(0,0,0)
		localController.object=localCamera

	}

	public function init():void {
		scene.root.addChild(localCamera);
	}


	public function onRenderTick(lookAt:Point3D):void {
		//鏡面処理
		
		//鏡面用のカメラを面を基準にリフレクション
		var p1:Point3D=plane.globalToLocal(cameraController.coords)
		var p2:Point3D=new Point3D(p1.x,p1.y,-p1.z)
		localController.coords=plane.localToGlobal(p2)
		localController.lookAt(new Point3D(lookAt.x,lookAt.y,-lookAt.z));

		msk.graphics.clear();
		msk.graphics.beginFill(0x0000FF);
		var p:Point3D
		for (var i:uint=0;i<4;i++ ) {
			p=view.projectPoint(plane.localToGlobal(plane.vertices['0_0'].coords))
			msk.graphics.moveTo(p.x, p.y);
			p=view.projectPoint(plane.localToGlobal(plane.vertices['0_1'].coords))
			msk.graphics.lineTo(p.x, p.y);
			p=view.projectPoint(plane.localToGlobal(plane.vertices['1_1'].coords))
			msk.graphics.lineTo(p.x, p.y);
			p=view.projectPoint(plane.localToGlobal(plane.vertices['1_0'].coords))
			msk.graphics.lineTo(p.x, p.y);
		}
		msk.graphics.endFill();
	}


}