Alternativa3D Tips Reflection
Alternativa3D Tips Reflection
2台のカメラと2つのViewを使用した、Alternativa3Dでの鏡面反射です。
とりあえず、行列変換やクォータニオンは使わないで実装しています。
なので、下方向への反射のみです。
@narutohyper
/**
* Copyright narutohyper ( http://wonderfl.net/user/narutohyper )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/7E4t
*/
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();
}
}