FlatShading [Alternativa3D 7.6]
7.5では実装されていなかった、フラットシェーディングですが、7.6に実装される事を期待しつつ、とりあえず無理矢理実装してみました。
が、思った以上に重いです・・・
ちなみに、これは無理矢理MeshをFlatShadingしています。
Materialを継承してFlatShadingする場合は以下を参照ください。
http://marubayashi.net/alternativa3d7/labo/flatshadingmaterial/flatshadingmaterial.html
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/485b
*/
// forked from narutohyper's Alternativa3D 7.5 Template
package
{
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.loaders.MaterialLoader;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.primitives.Box;
import alternativ7.engine3d.primitives.GeoSphere;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import flash.system.LoaderContext;
/**
*
* Alternativa3D 7.6
*
* フラットシェーディングを無理矢理実装してみる
*
* ...
* @author narutohyper
*/
[SWF(backgroundColor="#000000", frameRate="24", width="800", height="600")]
public class Main extends Sprite
{
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);
//テスト表示
var bm:Bitmap=new Bitmap();
//Materialの作成
addChild(bm);
//AlternativaTemplate作成
var scene:AlternativaTemplate = new AlternativaTemplate(this);
addChild(scene.camera.diagram);
//回転させる為のContainer
var objectContainer:Object3DContainer = new Object3DContainer();
scene.container.addChild(objectContainer);
//色つき球
var material:FillMaterial = new FillMaterial(0x0000FF);
var sphere1:FlatShadingMesh = new FlatShadingMesh(new GeoSphere(200));
sphere1.setMaterialToAllFaces(material);
objectContainer.addChild(sphere1);
sphere1.x = -300;
sphere1.y = -200;
//虎柄球
var tigerMaterial:TextureMaterial = new TextureMaterial(null, false, true);
tigerMaterial.diffuseMapURL = 'http://assets.wonderfl.net/images/related_images/2/23/239d/239d90e633f3ab0f3e95d18c0fab3200d4a2820cm';
var textures:Vector.<TextureMaterial> = new Vector.<TextureMaterial>();
textures[0] = tigerMaterial;
var context:LoaderContext = new LoaderContext(true);
var materialLoader:MaterialLoader = new MaterialLoader()
materialLoader.load(textures,context);
var sphere2:FlatShadingMesh = new FlatShadingMesh(new GeoSphere(200));
sphere2.setMaterialToAllFaces(tigerMaterial);
objectContainer.addChild(sphere2);
sphere2.x = 300;
sphere2.y = -200;
//6面ぬり分けた箱
var leftM:FillMaterial = new FillMaterial(0x0000FF);
var rightM:FillMaterial = new FillMaterial(0xFF0000);
var frontM:FillMaterial = new FillMaterial(0x00FF00);
var backM:FillMaterial = new FillMaterial(0xFF00FF);
var bottomM:FillMaterial = new FillMaterial(0xFFFF00);
var topM:FillMaterial = new FillMaterial(0x666666);
var test:Box = new Box(400, 400, 400, 1, 1, 1, false, false, leftM, rightM, backM, frontM, bottomM, topM);
var box:FlatShadingBox = new FlatShadingBox(new Box(300,300,300,1,1,1,false,false,leftM,rightM,backM,frontM,bottomM, tigerMaterial));
//sphere2.setMaterialToAllFaces(tigerMaterial);
objectContainer.addChild(box);
box.x = 0;
box.y = 200;
var RADIAN:Number = Math.PI / 180;
var lightContainer:Object3DContainer = new Object3DContainer();
scene.container.addChild(lightContainer);
var light:Light = new Light(0xFFFFFF,0.8);
lightContainer.addChild(light);
lightContainer.rotationY = 30 * RADIAN;
light.x = 400;
//カメラの調整
//カメラはControllerに関連付けている為、x,y,zで直接位置を指定できないので
//SimpleController.setObjectPosXYZを使用
scene.cameraController.setObjectPosXYZ(0,-1400,0);
scene.cameraController.lookAtXYZ(0, 0, 0);
//ObjectControllerの作成
//MouseDragで、Objectを回転させる為のController
var objectController:SimpleObjectController = new SimpleObjectController(stage,objectContainer,100);
objectController.unbindAll();
//描画開始
var angle:Number=0;
scene.onPreRender = function():void {
objectController.update();
angle+=3;
light.x = Math.cos(angle * RADIAN) * 700;
light.y = Math.sin(angle * RADIAN) * 700;
//引数の2番目には、回転するObject3D
sphere1.calculateLight(light,[objectContainer]);
sphere2.calculateLight(light,[objectContainer]);
box.calculateLight(light,[objectContainer]);
//bm.bitmapData = sphere2.bmd;
}
scene.startRendering();
}
}
}
import alternativ7.engine3d.core.Face;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.materials.Material;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.objects.Mesh;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.GraphicsEndFill;
import flash.display.GraphicsPath;
import flash.display.GraphicsSolidFill;
import flash.display.GraphicsStroke;
import flash.display.IGraphicsData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
/**
*
* MeshオブジェクトをFlatShadingする、Meshに変更するクラス
* 全て同じMaterialをUVで用いる場合のみ有効
* BoxやOriginalCylinderでは使えません。
*
* また、Bone付き、スキンも使えません
*
* @param mesh
*/
class FlatShadingMesh extends Mesh
{
//テスト表示できるように、とりあえずpublic
private var _bmd:BitmapData;
private var _texture:BitmapData;
private var _materialType:String;
private var _textureMaterial:TextureMaterial;
private var _tempMaterial:TextureMaterial;
private var _rect:Rectangle;
private var _sp:Point;
private var _loaded:Boolean = false;
private var _count:int;
private var _paths:Vector.<GraphicsPath>;
private var _canvas:Sprite = new Sprite();
private var _fills:Shape = new Shape();
private var _lines:Shape = new Shape();
private var _endFill:GraphicsEndFill = new GraphicsEndFill();
private var _normals:Vector.<Number>;
public function FlatShadingMesh(mesh:Mesh) {
//引数のMeshのgeometryをコピー
clonePropertiesFrom(mesh);
_count = faces.length;
_canvas.addChild(_lines);
_canvas.addChild(_fills);
_normals = new Vector.<Number>;
var face:Face;
var textured:Boolean = false;
for (var i:int = 0; i < _count; i++)
{
face = faces[i];
//面の法線を得る
if (face.material && !textured) {
setTexture(face.material);
textured = true;
}
_normals[i*3] = face.normal.x;
_normals[i*3+1] = face.normal.y;
_normals[i*3+2] = face.normal.z;
}
}
override public function setMaterialToAllFaces(material:Material):void {
setTexture(material);
}
private function setPath():void
{
var count2:int;
//高速化の為、Mesh.facesからではなくGeometryのorderedFaces
//(DictionaryではなくVectorでcloneが帰ってくる)
_paths = new Vector.<GraphicsPath>();
var path:GraphicsPath;
var face:Face;
for (var i:int = 0; i < _count; i++)
{
face = faces[i];
var commands:Vector.<int> = new Vector.<int>();
var coords:Vector.<Number> = new Vector.<Number>();
commands[0] = 1;
coords[0] = face.vertices[0].u * _bmd.width;
coords[1] = face.vertices[0].v * _bmd.height;
//faceのUVを得る
//注意!Face.verticesは、Vector
count2 = face.vertices.length;
for (var j:int = 1; j < count2; j++ ) {
commands[j] = 2;
coords[j * 2] = face.vertices[j].u * _bmd.width;
coords[j * 2 + 1] = face.vertices[j].v * _bmd.height;
}
commands[j] = 2;
coords[j * 2] = coords[0];
coords[j * 2 + 1] = coords[1];
path = new GraphicsPath(commands, coords);
_paths.push(path);
}
}
private function setTexture(material:Material):void {
_tempMaterial = material as TextureMaterial;
if (_tempMaterial) {
_materialType = 'Texture';
if (_tempMaterial.texture) {
_texture = _tempMaterial.texture;
_bmd = new BitmapData(_texture.width, _texture.height, true, 0xFF666666);
_loaded = true;
} else {
_texture = new BitmapData(400, 400, false, 0);
_bmd = new BitmapData(400, 400, false, 0);
}
} else {
_materialType='Fill';
_texture = new BitmapData(400, 400, false, FillMaterial(material).color);
_bmd = new BitmapData(400, 400, false, FillMaterial(material).color);
}
_textureMaterial = new TextureMaterial(_bmd);
super.setMaterialToAllFaces(_textureMaterial);
_rect = _bmd.rect;
_sp = new Point(0, 0);
setPath();
}
/**
*各フェイスのnormalを取り、光源との内積で影の強さを判断する
*
*/
public function calculateLight(light:Light,rotaObject:Array = null):void {
//Textureをloadしている場合、load完了までは、仮のTexture
//読み込まれて、適用された段階で反映する
if (_materialType == 'Texture' && !_loaded && _tempMaterial.texture) {
_texture = _tempMaterial.texture;
_bmd = new BitmapData(_texture.width, _texture.height, true, 0xFF666666);
_textureMaterial = new TextureMaterial(_bmd);
super.setMaterialToAllFaces(_textureMaterial);
_loaded = true;
setPath();
}
var count2:int;
//光源の位置ベクトル
var lv:Vector3D = new Vector3D(light.x, light.y, light.z);
lv = light.localToGlobal(lv);
//自身の位置ベクトル
var target:Vector3D = new Vector3D(x, y, z);
target = localToGlobal(target);
//光源に対する方向(単位ベクトル)
var axis:Vector3D = lv.subtract(target);
var m:Number = axis.normalize();
//光源への距離(とりあえず距離は無視するけど)
//var length:Number = Vector3D.distance(target,lv)
_lines.graphics.clear();
_fills.graphics.clear();
var fillDrawing:Vector.<IGraphicsData> = new Vector.<IGraphicsData>();
var lineDrawing:Vector.<IGraphicsData> = new Vector.<IGraphicsData>();
//1フェースごとにMatrix変換は、負荷大なので、まとめて変換
var v3:Vector.<Vector3D>;
var mtr3D:Matrix3D = new Matrix3D();
var tempNormals:Vector.<Number> = new Vector.<Number>();
var i:int;
var j:int;
tempNormals = _normals.concat() as Vector.<Number>;
if (rotaObject)
{
count2 = rotaObject.length;
for (i = 0; i < count2; i++)
{
//回転だけ取り出す
v3 = rotaObject[i].matrix.decompose();
v3[0] = new Vector3D(0, 0, 0);
v3[2] = new Vector3D(1, 1, 1);
mtr3D.recompose(v3);
mtr3D.transformVectors(tempNormals, tempNormals);
}
} else {
v3 = matrix.decompose();
v3[0] = new Vector3D(0, 0, 0);
v3[2] = new Vector3D(1, 1, 1);
mtr3D.recompose(v3);
mtr3D.transformVectors(tempNormals, tempNormals);
}
for (i = 0; i < _count; i++)
{
//面の法線を得る
var normal:Vector3D = new Vector3D(tempNormals[i*3],tempNormals[i*3+1],tempNormals[i*3+2]);
//光源との内積で強さを決定
var strength:Number = normal.dotProduct(axis);
var r:int = light.colorR / 2 * strength * light.strength + light.colorR / 2;
var g:int = light.colorG / 2 * strength * light.strength + light.colorG / 2;
var b:int = light.colorB / 2 * strength * light.strength + light.colorB / 2;
var color:int = r << 16 | g << 8 | b;
//隙間防止の為、一回り大きな三角形を描画。
//簡略化の為、ラインで一回り大きな三角を描いた物を下に敷く
var fill:GraphicsSolidFill = new GraphicsSolidFill(0);
fill.color=color;
fillDrawing.push(fill,_paths[i],_endFill);
var stroke:GraphicsStroke = new GraphicsStroke(10);
stroke.fill = fill;
lineDrawing.push(stroke,_paths[i],_endFill);
}
_lines.graphics.drawGraphicsData(lineDrawing);
_fills.graphics.drawGraphicsData(fillDrawing);
_bmd.copyPixels(_texture, _rect, _sp);
_bmd.draw(_canvas, null, null,BlendMode.HARDLIGHT);
//_bmd.draw(_canvas);
}
public function get bmd():BitmapData { return _bmd; }
}
import alternativ7.engine3d.core.Face;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.materials.Material;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.objects.Mesh;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Shape;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Vector3D;
/**
* BoxオブジェクトをFlatShadingする、Meshに変更するクラス
*
* サーフェースの概念がなくなったので、ちょっと面倒・・・
*
* @author narutohyper
*/
class FlatShadingBox extends Mesh
{
private var _materialTypes:Vector.<String> = new Vector.<String>(6, true);;
private var _materials:Vector.<TextureMaterial> = new Vector.<TextureMaterial>(6, true);
private var _tempMaterials:Vector.<Material> = new Vector.<Material>(6, true);
private var _textures:Vector.<BitmapData> = new Vector.<BitmapData>(6, true);
private var _bmds:Vector.<BitmapData> = new Vector.<BitmapData>(6, true);
private var _normals:Vector.<Number> = new Vector.<Number>();
private var _bmd:BitmapData;
private var _loadeds:Vector.<Boolean> = new Vector.<Boolean>(6, true);
private var _fills:Shape = new Shape();
private var _sp:Point;
public function FlatShadingBox(mesh:Mesh)
{
var face:Face;
var item:*;
//引数のMeshのgeometryをコピー
clonePropertiesFrom(mesh);
//left左
_normals.push(1, 0, 0);
//right右
_normals.push( -1, 0, 0);
//back奥
_normals.push(0, 1, 0);
//front前
_normals.push(0, -1, 0);
//top上
_normals.push(0, 0, 1);
//bottom下
_normals.push(0, 0, -1);
//textureの取り込み
var i:uint;
var normal:Vector3D;
for (item in faces) {
face = faces[item];
for (i = 0; i < 6; i++)
{
normal = new Vector3D(_normals[i * 3], _normals[i * 3 + 1], _normals[i * 3 + 2]);
if (face.normal.x == normal.x && face.normal.y == normal.y && face.normal.z == normal.z) {
//この時点でTextureが設定されていたら、差し替え
if (!_textures[i] && face.material) {
setTexture(i, face.material);
}
}
}
}
var RADIAN:Number = Math.PI / 180;
_sp = new Point(0, 0);
}
private function setTexture(id:uint,material:Material):void {
var _tempMaterial:TextureMaterial = material as TextureMaterial;
trace(_tempMaterial);
if (_tempMaterial) {
_materialTypes[id] = 'Texture';
if (_tempMaterial.texture) {
_textures[id] = _tempMaterial.texture;
_bmds[id] = new BitmapData(_textures[id].width, _textures[id].height, true, 0xFF666666);
_loadeds[id] = true;
_materials[id] = new TextureMaterial(_bmds[id]);
setFaceTexture(id);
} else {
//Textureが読み込まれていなかったら、差し替えしない
_materials[id] = _tempMaterial;
}
} else {
_materialTypes[id]='Fill';
_textures[id] = new BitmapData(400, 400, false, FillMaterial(material).color);
_bmds[id] = new BitmapData(400, 400, false, FillMaterial(material).color);
_materials[id] = new TextureMaterial(_bmds[id]);
setFaceTexture(id);
}
}
private function setFaceTexture(id:uint):void {
//該当IDのフェースを差し替える
var face:Face;
var normal:Vector3D;
for (var item:* in faces) {
face = faces[item];
normal = new Vector3D(_normals[id * 3], _normals[id * 3 + 1], _normals[id * 3 + 2]);
if (face.normal.x == normal.x && face.normal.y == normal.y && face.normal.z == normal.z) {
face.material=_materials[id];
}
}
}
public function calculateLight(light:Light, rotaObject:Array = null):void {
var i:int;
var j:int;
//Textureをloadしている場合、load完了までは、Textureなし
//読み込まれて、適用された段階で反映する
var normal:Vector3D;
//光源の位置ベクトル
var lv:Vector3D = new Vector3D(light.x, light.y, light.z);
lv = light.localToGlobal(lv);
//自身の位置ベクトル
var target:Vector3D = new Vector3D(x, y, z);
target = localToGlobal(target);
//光源に対する方向(単位ベクトル)
var axis:Vector3D = lv.subtract(target);
var m:Number = axis.normalize();
//1フェースごとにMatrix変換は、負荷大なので、まとめて変換
var v3:Vector.<Vector3D>;
var mtr3D:Matrix3D = new Matrix3D();
var tempNormals:Vector.<Number> = new Vector.<Number>();
var count2:int;
tempNormals = _normals.concat() as Vector.<Number>;
if (rotaObject)
{
count2 = rotaObject.length;
for (i = 0; i < count2; i++)
{
//回転だけ取り出す
v3 = rotaObject[i].matrix.decompose();
v3[0] = new Vector3D(0, 0, 0);
v3[2] = new Vector3D(1, 1, 1);
mtr3D.recompose(v3);
mtr3D.transformVectors(tempNormals, tempNormals);
}
} else {
v3 = matrix.decompose();
v3[0] = new Vector3D(0, 0, 0);
v3[2] = new Vector3D(1, 1, 1);
mtr3D.recompose(v3);
mtr3D.transformVectors(tempNormals, tempNormals);
}
for (i = 0; i < 6; i++)
{
if (_materialTypes[i] == 'Texture') {
if (!_loadeds[i] && _materials[i].texture) {
_textures[i] = _materials[i].texture;
_bmds[i] = new BitmapData(_textures[i].width, _textures[i].height, true, 0xFF666666);
_loadeds[i] = true;
_materials[i] = new TextureMaterial(_bmds[i]);
setFaceTexture(i);
}
}
normal = new Vector3D(tempNormals[i * 3], tempNormals[i * 3 + 1], tempNormals[i * 3 + 2]);
//光源との内積で強さを決定
var strength:Number = normal.dotProduct(axis);
//lightの色成分を分解
var r:int = light.colorR / 2 * strength * light.strength + light.colorR / 2;
var g:int = light.colorG / 2 * strength * light.strength + light.colorG / 2;
var b:int = light.colorB / 2 * strength * light.strength + light.colorB / 2;
var color:int = r << 16 | g << 8 | b;
_fills.graphics.clear();
if (_bmds[i]) {
_fills.graphics.beginFill(color);
_fills.graphics.drawRect(0, 0, _bmds[i].width, _bmds[i].height);
_bmds[i].copyPixels(_textures[i], _textures[i].rect, _sp);
_bmds[i].draw(_fills, null, null,BlendMode.HARDLIGHT);
}
}
}
public function get bmd():BitmapData { return _bmd; }
}
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.primitives.GeoSphere;
/**
*
* Lightを表現するクラス
*
* @author narutohyper
*/
class Light extends GeoSphere
{
private var _color:int;
private var _colorR:int;
private var _colorG:int;
private var _colorB:int;
private var _strength:Number;
private var _material:FillMaterial;
public function Light(color:Number,strength:Number=1)
{
_color = color;
_strength = strength;
_colorR = ( _color & 0xff0000 ) >> 16;
_colorG = ( _color & 0xff00 ) >> 8;
_colorB = ( _color & 0xff );
_material = new FillMaterial(color);
super(20, 2, false, _material);
}
public function get colorR():int { return _colorR; }
public function get colorG():int { return _colorG; }
public function get colorB():int { return _colorB; }
public function get strength():Number { return _strength; }
public function set strength(value:Number):void
{
_strength = value;
}
public function get color():int { return _color; }
public function set color(value:int):void
{
_color = value;
}
}
/**
* 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.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
*/
private function onResize(e:Event = null):void
{
if (_scaleToStage)
{
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}
else
{
view.width = _viewWidth;
view.height = _viewHeight;
}
}
/**
* @private
*/
private function onRenderTick(e:Event = null):void
{
atPreRender();
_onPreRender();
cameraController.update();
camera.render();
atPostRender();
_onPostRender();
}
}