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(); } } Alternativa3D Tips Reflection