Camera3D.fov と Mesh.Clippingのテスト [Alternativa3D 7.6 TIPS]
Mesh.Clippingのテスト。
Fovを調整して、Boxが枠(View)からはみ出す大きさにして、各Clippingを選択してみてください。
なお、このサンプルでは、わかりませんが、BOUND.CULLINGは、Object3DのBOUNDBOX全てが、Viewからはみ出すと、カリングされます。
2011/01/12 7.5から7.6仕様に変更
/**
* Copyright narutohyper ( http://wonderfl.net/user/narutohyper )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/pFpc
*/
// forked from narutohyper's Alternativa3D 7.5 Template
package
{
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.primitives.Box;
import alternativ7.engine3d.primitives.Plane;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.View;
import alternativ7.engine3d.containers.LODContainer;
import alternativ7.engine3d.core.Clipping;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import com.bit101.components.Slider;
import com.bit101.components.RadioButton;
import com.bit101.components.Label;
/**
*
* Alternativa3D 7.5
*
* Camera3D.fov と Mesh.Clipping
*
* ...
* @author narutohyper
*/
[SWF(backgroundColor="#333333", frameRate="100", width="800", height="600")]
public class Main extends Sprite
{
private var camera:Camera3D;
private var view:View;
private var box:Box;
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event=null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
//AlternativaTemplate作成
var scene:AlternativaTemplate = new AlternativaTemplate(this);
camera = scene.camera;
view = scene.view;
//Materialの作成
var material:FillMaterial = new FillMaterial(0xCCCCCC, 0.5, 0,0x0);
//box
box = new Box(300,300,300,4,4,4);
box.setMaterialToAllFaces(material);
scene.container.addChild(box);
//カメラの調整
//カメラはControllerに関連付けている為、x,y,zで直接位置を指定できないので
//SimpleController.setObjectPosXYZを使用
scene.cameraController.setObjectPosXYZ(0,-500,500);
scene.cameraController.lookAtXYZ(0, 0, 0);
//ObjectControllerの作成
//MouseDragで、Objectを回転させる為のController
//var objectController:SimpleObjectController = new SimpleObjectController(stage,plane,100)
//objectController.unbindAll()
//描画開始
scene.startRendering();
var RADIAN:Number = Math.PI / 180;
scene.onPreRender = function():void {
//objectController.update();
box.rotationY+=1*RADIAN;
}
//一時的に、TemplateのonResizeにアクセスできるようにしてます
scene.onPreResize = function():void {
view.width = ((stage.stageWidth-200)*0.7);
view.height = (stage.stageHeight*0.7);
view.x = (stage.stageWidth-view.width)/2+100;
view.y = (stage.stageHeight-view.height)/2;
this.graphics.clear();
this.graphics.beginFill(0x0);
this.graphics.drawRect(view.x, view.y, view.width, view.height);
this.graphics.endFill();
}
scene.onPreResize();
settingPanel();
}
private function settingPanel():void {
var base:Sprite = new Sprite();
addChild(base);
base.graphics.beginFill(0xCCCCCC);
base.graphics.drawRect(0, 0, 200, 1000);
var label:Label = new Label(base, 20,200);
label.text = "FOV";
var slider:Slider = new Slider(Slider.HORIZONTAL, base, 54, 204, onSlider);
slider.value = 50;
var ragio1:RadioButton = new RadioButton(base, 20, 230, 'BOUND_CULLING', false, onBound);
var ragio2:RadioButton = new RadioButton(base, 20, 250, 'FACE_CLIPPING', true, onClip);
var ragio3:RadioButton = new RadioButton(base, 20, 270, 'FACE_CULLING', false, onFace);
function onBound(e:Event):void {
box.clipping=Clipping.BOUND_CULLING;
}
function onClip(e:Event):void {
box.clipping=Clipping.FACE_CLIPPING;
}
function onFace(e:Event):void {
box.clipping=Clipping.FACE_CULLING;
}
//fov
var fovSp:Shape = new Shape();
base.addChild(fovSp);
//Camera
var cameraSp:Sprite = new Sprite();
cameraSp.graphics.beginFill(0x666666);
cameraSp.graphics.moveTo(-8, 0);
cameraSp.graphics.lineTo(8, 0);
cameraSp.graphics.lineTo(0, 8);
cameraSp.graphics.lineTo( -8, 0);
cameraSp.graphics.endFill();
cameraSp.graphics.beginFill(0x666666);
cameraSp.graphics.drawRect( -5, 7, 10, 20);
cameraSp.graphics.endFill();
cameraSp.graphics.lineStyle(0, 0xCCCCCC);
cameraSp.graphics.drawCircle(0,0,40);
cameraSp.x = 100;
cameraSp.y = 160;
base.addChild(cameraSp);
var labelHSlider:Label = new Label(cameraSp, -8, -40);
var box:Shape = new Shape();
box.graphics.beginFill(0x666666);
box.graphics.drawRect( -20, -20, 40, 40);
base.addChild(box);
box.x = 100;
box.y = 80;
var RADIAN:Number = Math.PI / 180;
var fov:Number=Math.ceil(53 * 180 / 100);
labelHSlider.text = fov.toString();
//screen
fovSp.graphics.clear();
fovSp.x = 100;
onSlider(null);
function onSlider(e:Event):void {
if (slider.value) {
fov = Math.ceil(slider.value * 180 / 100);
} else {
fov = 1;
}
labelHSlider.text = fov.toString();
var length:Number = 1/Math.tan((fov / 2) * RADIAN) * 100;
fovSp.graphics.clear();
fovSp.graphics.beginFill(0xFFFFFF);
var sy:Number = 0;
if (length<160) {
fovSp.graphics.drawRect( -100, 0, 200, 160 - length);
sy=160-length;
}
fovSp.graphics.moveTo(-100, sy);
fovSp.graphics.lineTo(100,sy);
fovSp.graphics.lineTo(0,length+sy);
fovSp.graphics.lineTo(-100, sy);
fovSp.graphics.endFill();
fovSp.y = -fovSp.height + 160;
camera.fov=fov*RADIAN;
}
}
}
}
/**
* BasicTemplate for Alternativa3D 7.5
* Alternativa3D 7.5を扱いやすくするためのテンプレートです
* @author narutohyper & clockmaker
*
*/
import alternativ7.engine3d.containers.BSPContainer;
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.containers.DistanceSortContainer;
import alternativ7.engine3d.containers.KDContainer;
import alternativ7.engine3d.containers.LODContainer;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.core.View;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
class AlternativaTemplate extends Sprite
{
/**
* 子オブジェクトを最適な方法でソートするコンテナ
* (ConflictContainer)
*/
public static const CONFLICT:String = 'conflict';
/**
* 子オブジェクトをBSP(バイナリ空間分割法)によってソートするコンテナ
* (BSPContainer)
*/
public static const BSP:String = 'bsp';
/**
* 子オブジェクトをカメラからのZ値でソートするコンテナ
* (DistanceSortContainer)
*/
public static const ZSORT:String = 'zsort';
/**
* KDツリー(http://ja.wikipedia.org/wiki/Kd%E6%9C%A8)によってソートするコンテナ
* (KDContainer)
*/
public static const KD:String = 'kd';
/**
* detalizationと子オブジェクトの距離でソートするコンテナ(詳細は調査中)
* (LODContainer)
*/
public static const LOD:String = 'lod';
/**
* 3dオブジェクト格納するコンテナインスタンス。
*/
public var container:Object3DContainer;
/**
* ビューインスタンスです。
*/
public var view:View;
/**
* カメラインスタンスです。
*/
public var camera:Camera3D;
/**
* カメラコントローラーです。
*/
public var cameraController:SimpleObjectController;
private var _mc:DisplayObjectContainer;
private var _viewWidth:int;
private var _viewHeight:int;
private var _scaleToStage:Boolean;
private var _containerType:String;
/**
* 新しい Alternativa3DTemplate インスタンスを作成します。
* @param mc
* @param containerType
* @param viewWidth
* @param viewHeight
* @param scaleToStage
*/
public function AlternativaTemplate(mc:DisplayObjectContainer,containerType:String=CONFLICT,viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true)
{
_mc = mc;
_mc.addChild(this);
_containerType = containerType;
_viewWidth = viewWidth;
_viewHeight = viewHeight;
_scaleToStage = scaleToStage;
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理をオーバーライドして記述します。
*/
protected function atInit():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
protected function atPreRender():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
private var _onPreRender:Function = function():void{};
public function get onPreRender():Function { return _onPreRender; }
public function set onPreRender(value:Function):void
{
_onPreRender = value;
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理をオーバーライドして記述します。
*/
protected function atPostRender():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理を記述します。
*/
private var _onPostRender:Function = function():void{};
public function get onPostRender():Function { return _onPostRender; }
public function set onPostRender(value:Function):void
{
_onPostRender = value;
}
/**
* レンダリングを開始します。
*/
public function startRendering():void
{
addEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* レンダリングを停止します。
*/
public function stopRendering():void
{
removeEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* シングルレンダリング(レンダリングを一回だけ)を実行します。
*/
public function singleRender():void
{
onRenderTick();
}
/**
* @private
*/
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.HIGH;
//Root objectの作成
if (_containerType == CONFLICT) {
container = new ConflictContainer();
} else if (_containerType == BSP) {
container = new BSPContainer();
} else if (_containerType == ZSORT) {
container = new DistanceSortContainer();
} else if (_containerType == KD) {
container = new KDContainer();
} else if (_containerType == LOD) {
container = new LODContainer();
}
//Viewの作成
view = new View(stage.stageWidth, stage.stageHeight);
_mc.addChild(view);
//cameraの作成
camera = new Camera3D();
camera.view = view;
camera.x = 0;
camera.y = -500;
camera.z = 0;
container.addChild(camera);
// Camera controller
cameraController = new SimpleObjectController(stage, camera, 10);
cameraController.mouseSensitivity = 0;
cameraController.unbindAll();
cameraController.lookAtXYZ(0, 0, 0);
onResize();
stage.addEventListener(Event.RESIZE, onResize);
atInit();
}
private var _onPreResize:Function = function():void{
view.x=200;
if (_scaleToStage)
{
view.width = stage.stageWidth-200;
view.height = stage.stageHeight;
}
else
{
view.width = _viewWidth;
view.height = _viewHeight;
}
}
public function get onPreResize():Function { return _onPreResize; }
public function set onPreResize(value:Function):void
{
_onPreResize = value;
}
/**
* @private
*/
private function onResize(e:Event = null):void
{
_onPreResize();
}
/**
* @private
*/
private function onRenderTick(e:Event = null):void
{
atPreRender();
_onPreRender();
cameraController.update();
camera.render();
atPostRender();
_onPostRender();
}
}