OriginalPrimitive MultiCylinder [Alternativa3D 7.6 TIPS]
汎用性のあるマルチシリンダークラス
MultiCylinderと銘売ってますが、Cylinderクラスです。
色々出来るようにしたら、引数多くなりすぎた・・・
結構勢いで作ってるので、もしバグがあったらコメントお願いします。
UV設定もできてるはず。
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/u1d8
*/
// forked from narutohyper's Alternativa3D 7.5 Template
package
{
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.loaders.MaterialLoader;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.core.Sorting;
import flash.display.Sprite;
import flash.events.Event;
import flash.system.LoaderContext;
//import com.bit101.components.RadioButton
//import com.bit101.components.Label
/**
* Alternativa3D 7.6
*
* オリジナルのプリミティブを作成
*
* ...
* @author narutohyper
*/
[SWF(backgroundColor="#000000", frameRate="100", 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);
//AlternativaTemplate作成
var scene:AlternativaTemplate = new AlternativaTemplate(this);
//まとめてcontrolするために、core.Object3DContainerを作成し、各Objectを入れ子にする
var animeObject:Object3DContainer = new Object3DContainer;
scene.container.addChild(animeObject);
//外部読み込み画像によるmaterial
var material:FillMaterial = new FillMaterial(0xCCCCFF,1,0,1);
//外部読み込み画像によるmaterial
var dolphinMaterial:TextureMaterial = new TextureMaterial(null, false, true);
dolphinMaterial.diffuseMapURL = 'http://assets.wonderfl.net/images/related_images/e/e9/e987/e9876c502c9e9693205335e106de6baa8865c1a6m';
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>(2);
textures[0] = dolphinMaterial;
textures[1] = tigerMaterial;
var context:LoaderContext = new LoaderContext(true);
var materialLoader:MaterialLoader = new MaterialLoader();
materialLoader.load(textures,context);
var cylinder1:Cylinder = new Cylinder(100,0,300,2,8,-90,false,false,false,false,Cylinder.CIRCLE);
//cylinder1.setMaterialToAllFaces(dolphinMaterial);
cylinder1.sideMaterial = dolphinMaterial;
cylinder1.sorting = Sorting.DYNAMIC_BSP;
animeObject.addChild(cylinder1);
cylinder1.x=-500;
cylinder1.y=-500;
var cylinder2:Cylinder = new Cylinder(500,0,100,2,8,-90,false,false,false);
cylinder2.star = true;
cylinder2.setMaterialToAllFaces(dolphinMaterial);
cylinder2.sorting = Sorting.DYNAMIC_BSP;
animeObject.addChild(cylinder2);
cylinder2.x=500;
cylinder2.y=-500;
var cylinder3:Cylinder = new Cylinder(500,100,0,6,8,-90,false,false,false);
cylinder3.setMaterialToAllFaces(dolphinMaterial);
cylinder3.sorting = Sorting.DYNAMIC_BSP;
animeObject.addChild(cylinder3);
cylinder3.x=-500;
cylinder3.y=500;
var cylinder4:Cylinder = new Cylinder(500,100,50,2,12,-90,false,false,false);
cylinder4.setMaterialToAllFaces(dolphinMaterial);
cylinder4.sorting = Sorting.DYNAMIC_BSP;
animeObject.addChild(cylinder4);
cylinder4.x=500;
cylinder4.y=500;
var cylinder5:Cylinder = new Cylinder(500,100,100,2,12,-90,false,false,false);
cylinder5.setMaterialToAllFaces(dolphinMaterial);
cylinder5.sorting = Sorting.DYNAMIC_BSP;
animeObject.addChild(cylinder5);
var cylinder6:Cylinder = new Cylinder(500,100,50,8,12,-90,false,false,false);
cylinder6.setMaterialToAllFaces(dolphinMaterial);
cylinder6.sorting = Sorting.DYNAMIC_BSP;
animeObject.addChild(cylinder6);
cylinder6.x=-500;
var cylinder7:Cylinder = new Cylinder(500,50,100,1,12,-90,false,false,false);
cylinder7.setMaterialToAllFaces(dolphinMaterial);
cylinder7.sorting = Sorting.DYNAMIC_BSP;
animeObject.addChild(cylinder7);
cylinder7.x=500;
var cylinder8:Cylinder = new Cylinder(100,100,100,2,12,-90,false,false,false);
cylinder8.setMaterialToAllFaces(dolphinMaterial);
cylinder8.sorting = Sorting.DYNAMIC_BSP;
animeObject.addChild(cylinder8);
cylinder8.y=-500;
var cylinder9:Cylinder = new Cylinder(1000,100,100,10,12,-90,false,false,false);
cylinder9.setMaterialToAllFaces(dolphinMaterial);
cylinder9.sorting = Sorting.DYNAMIC_BSP;
animeObject.addChild(cylinder9);
cylinder9.y=500;
//カメラの調整
//カメラはControllerに関連付けている為、x,y,zで直接位置を指定できないので
//SimpleController.setObjectPosXYZを使用
scene.cameraController.setObjectPosXYZ(0, -1500, 500);
scene.cameraController.lookAtXYZ(0, 0, 0);
//ObjectControllerの作成
//MouseDragで、Objectを回転させる為のController
var objectController:SimpleObjectController = new SimpleObjectController(stage,animeObject,100);
objectController.unbindAll();
scene.onPreRender = function():void {
objectController.update();
}
//描画開始
scene.startRendering();
}
}
}
import alternativ7.engine3d.core.Vertex;
import alternativ7.engine3d.core.Face;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.materials.Material;
import alternativ7.engine3d.objects.Mesh;
/**
* 汎用性のあるシリンダー&コーンプリミティブクラス
*
*
* @author narutohyper
*/
class Cylinder extends Mesh
{
/**
*/
public static const CIRCLE:String = 'circle';
/**
* sideのfaceへ筒状にUV設定するタイプ
*/
public static const LINER:String = 'liner';
/**
* 新しい Alternativa3DTemplate インスタンスを作成します。
*
* @param height;
* @param topRadius;
* @param bottomRadius;
* @param heightSegments;
* @param radialSegments;
* @param startVertexAngle;
* @param star;
* @param twoSided;
* @param reverse;
* @param triangulate;
* @param sideTextureType;
* @param topMaterial;
* @param bottomMaterial;
* @param sideMaterial;
* @param topVisible;
* @param bottomVisible;
*/
public function Cylinder(height:Number = 100,
topRadius:Number = 0,bottomRadius:Number = 100,
heightSegments:uint = 1, radialSegments:uint = 12,
startVertexAngle:Number=-90,star:Boolean = false,
twoSided:Boolean = false, reverse:Boolean = false,
triangulate:Boolean = false, sideTextureType:String = LINER,
topVisible:Boolean = true,bottomVisible:Boolean = true,
topMaterial:Material=null,bottomMaterial:Material=null,sideMaterial:Material=null) {
this.height = height;
this.topRadius = topRadius;
this.bottomRadius = bottomRadius;
this.heightSegments = heightSegments;
this.radialSegments = radialSegments;
this.startVertexAngle = startVertexAngle;
this.star = star;
this.twoSided = twoSided;
this.reverse = reverse;
this.triangulate = triangulate;
this.sideTextureType = sideTextureType;
this.topMaterial = topMaterial;
this.bottomMaterial = bottomMaterial;
this.sideMaterial = sideMaterial;
this.topVisible = topVisible;
this.bottomVisible = bottomVisible;
if (this.sideMaterial == null) {
this.sideMaterial = new FillMaterial(0x666666,1);
}
makeMesh(true);
}
private function makeMesh(value:Boolean=false):void {
if (_geometryFlag || value) {
_geometryFlag = true;
makeSide();
if (topRadius && topVisible) {
makePlane(height / 2, topRadius, topMaterial, true, 'top');
}
if (bottomRadius && bottomVisible) {
makePlane(-height/2,bottomRadius,bottomMaterial,false,'bottom');
}
calculateNormals();
}
}
private function makePlane(tz:Number,radius:Number,material:Material,top:Boolean,pre:String):void {
var vertex:Vector.<Vertex> = new Vector.<Vertex>(radialSegments);
var RADIAN:Number = Math.PI / 180;
var sr:Number = startVertexAngle;
var pitch:Number = 360/radialSegments;
var angle:Number;
var i:uint;
var length:Number = radius;
var tw:Number = Math.cos(0 * RADIAN) * length * 2;
var th:Number = Math.sin(90 * RADIAN) * length * 2;
var tx:Number;
var ty:Number;
var tu:Number;
var tv:Number;
var v:Vertex;
for (i = 0; i < radialSegments; i++) {
angle = (sr + (pitch * i)) * RADIAN;
if (star) {
if (i && i % 2) {
tx = Math.cos(angle) * length;
ty = Math.sin(angle) * length;
} else {
tx = Math.cos(angle) * length/2;
ty = Math.sin(angle) * length/2;
}
} else {
tx = Math.cos(angle) * length;
ty = Math.sin(angle) * length;
}
tu = (tx + tw / 2) / tw;
tv = (ty + th / 2) / th;
vertex[i] = addVertex(tx, ty, tz, tu, tv, pre+'Vertex'+i);
}
//bottom
//底辺は反転
var turn:Boolean=reverse;
if (!top) turn = !turn
if (!turn) {
trace(vertex);
addFace(vertex,material, pre+'Front');
if (twoSided) {
vertex.reverse();
v = vertex.shift()
vertex.push(v);
addFace(vertex,material, pre+'Back');
}
} else {
if (twoSided) {
trace(vertex);
addFace(vertex,material, pre+'Front');
}
vertex.reverse();
v = vertex.shift()
vertex.push(v);
addFace(vertex,material, pre+'Back');
}
}
private function makeSide():void {
var h:Number = height/heightSegments;
var offsetRadius:Number;
var iz:int;
var ir:int;
var nh:Number;
var oh:Number;
var nx:Number;
var ny:Number;
var nz:Number;
var nr:Number; //半径
var tu:Number //U
var tv:Number //V
var uvx:Number;
var uvy:Number;
var tuStep:Number = 1/radialSegments;
var tvStep:Number = 1/heightSegments;
var sinR:Number = Math.sin((360 / radialSegments) * Math.PI / 180);
var cosR:Number = Math.cos((360 / radialSegments) * Math.PI / 180);
var step:Number = 360 / radialSegments;
var vertex:Vector.<Vertex> = new Vector.<Vertex>;
var id:uint = 0;
var v0:Vertex;
//Vertex(頂点)の登録
var start:uint;
var end:uint;
if (topRadius > bottomRadius) {
offsetRadius = topRadius - bottomRadius;
if (bottomRadius == 0) {
end = 1;
} else {
end = 0;
}
for (iz = 0; iz <= heightSegments-end; iz++)
{
for (ir = 0; ir <= radialSegments;ir++ )
{
nh = (h * iz);
oh = (nh) ? (height - nh) / height:1;
nr = (bottomRadius + (offsetRadius * oh));
if (star) {
if (ir && ir % 2) {
} else {
nr=nr/2;
}
}
nz = (height / 2) - nh;
nx = Math.cos((step * ir + startVertexAngle) * Math.PI / 180)*nr;
ny = Math.sin((step * ir + startVertexAngle) * Math.PI / 180) * nr;
//UV計算
//とりあえず、巻きつけ
if (sideTextureType == Cylinder.CIRCLE) {
//高さ
//半径0.5
//長さは、(0.5/heightSegments)*iz
uvx = Math.cos((step * ir + startVertexAngle) * Math.PI / 180) * (0.5-(0.5 / heightSegments) * iz)+0.5;
uvy = Math.sin((step * ir + startVertexAngle) * Math.PI / 180) * (0.5-5(0.5 / heightSegments) * iz)+0.5;
v0 = addVertex(nx, ny, nz, uvx, uvy, 'sideVertex' + id);
} else {
v0 = addVertex(nx, ny, nz, tuStep * ir, tvStep * iz, 'sideVertex' + id);
}
id++;
}
}
if (bottomRadius == 0) {
start = 1;
nz = (height / -2);
if (sideTextureType == Cylinder.CIRCLE) {
v0 = addVertex(0, 0, nz, 0, 0, 'sideVertex' + id);
} else {
v0 = addVertex(0, 0, nz, tuStep * ir, tvStep * iz, 'sideVertex' + id);
}
id++;
}
} else {
offsetRadius = bottomRadius - topRadius;
if (topRadius == 0) {
nz = (height / 2);
if (sideTextureType == Cylinder.CIRCLE) {
v0 = addVertex(0, 0, nz, 0.5, 0.5, 'sideVertex' + id);
} else {
v0 = addVertex(0, 0, nz, tuStep * ir, tvStep * iz, 'sideVertex' + id);
}
id++;
start = 1;
} else {
start = 0;
}
for (iz = start; iz <= heightSegments; iz++)
{
for (ir = 0; ir <= radialSegments;ir++ )
{
nh = (h * iz);
oh = (nh) ? nh / height:0;
nr = (topRadius + (offsetRadius * oh));
if (star) {
if (ir && ir % 2) {
} else {
nr = nr * starRadius;
}
}
nz = (height / 2) - nh;
nx = Math.cos((step * ir + startVertexAngle) * Math.PI / 180) * nr;
ny = Math.sin((step * ir + startVertexAngle) * Math.PI / 180) * nr;
if (sideTextureType == Cylinder.CIRCLE) {
//高さ
//半径0.5
//長さは、(0.5/heightSegments)*iz
uvx = Math.cos((step * ir + startVertexAngle) * Math.PI / 180) * (0.5 / heightSegments) * iz+0.5;
uvy = Math.sin((step * ir + startVertexAngle) * Math.PI / 180) * (0.5 / heightSegments) * iz+0.5;
v0 = addVertex(nx, ny, nz, uvx, uvy, 'sideVertex' + id);
} else {
v0 = addVertex(nx, ny, nz, tuStep * ir, tvStep * iz, 'sideVertex' + id);
}
id++;
}
}
}
//コーンの場合(topSegment or bottomSegment =0)と、シリンダーでは、SideのUVの割り当てを変える
//コーンでは、Textureの中心から円状に
//シリンダーの場合は、巻きつけ
//Face(面・四角)の登録
id = 0;
var n1:uint;
var n2:uint;
var n3:int;
var v1:Vertex;
var v2:Vertex;
var v3:Vertex;
var v4:Vertex;
for (iz = 0; iz < heightSegments; iz++)
{
for (ir = 0; ir < radialSegments;ir++ )
{
n1 = ir;
n2 = ir + 1;
//n3
if (topRadius == 0) {
//Cone上向き
n3 = (iz * (radialSegments + 1) - radialSegments);
} else {
n3 = (iz * (radialSegments+1));
}
if (topRadius == 0 && iz == 0) {
n3 = 1;
v1 = getVertexById('sideVertex' + 0);
v2 = getVertexById('sideVertex' + (n3 + n2));
v3 = getVertexById('sideVertex' + (n3 + n1));
if (!reverse) {
addTriFace(v1, v3, v2, sideMaterial, 'sideFront' + id);
if (twoSided) {
addTriFace(v1, v2, v3, sideMaterial, 'sideBack' + id);
}
} else {
addTriFace(v1, v2, v3, sideMaterial, 'sideBack' + id);
if (twoSided) {
addTriFace(v1, v3, v2, sideMaterial, 'sideFront' + id);
}
}
} else if (bottomRadius == 0 && iz == heightSegments - 1) {
v1 = getVertexById('sideVertex' + (n3 + n1));
v2 = getVertexById('sideVertex' + (n3 + n2));
v3 = getVertexById('sideVertex' + (n3 + radialSegments + 1));
if (!reverse) {
addTriFace(v1, v3, v2, sideMaterial, 'sideFront' + id);
if (twoSided) {
addTriFace(v1, v2, v3, sideMaterial, 'sideBack' + id);
}
} else {
addTriFace(v1, v3, v2, sideMaterial, 'sideBack' + id);
if (twoSided) {
addTriFace(v1, v2, v3, sideMaterial, 'sideFront' + id);
}
}
} else {
v1 = getVertexById('sideVertex' + (n3 + n1));
v2 = getVertexById('sideVertex' + (n3 + n2));
v3 = getVertexById('sideVertex' + (n3 + n2 + radialSegments+1));
v4 = getVertexById('sideVertex' + (n3 + n1 + radialSegments + 1));
if (!reverse) {
addQuadFace(v1, v4, v3, v2, sideMaterial, 'sideFront' + id);
if (twoSided) {
addQuadFace(v1, v2, v3, v4, sideMaterial, 'sideBack' + id);
}
} else {
addQuadFace(v1, v2, v3, v4, sideMaterial, 'sideBack' + id);
if (twoSided) {
addQuadFace(v1, v4, v3, v2, sideMaterial, 'sideFront' + id);
}
}
}
id++;
}
}
}
/**
* シリンダー or コーンの高さ
* 0以下を指定するとArgumentError
*/
public function get height():Number { return _height; }
public function set height(value:Number):void
{
_height = value;
if (height <= 0)
{
throw new ArgumentError("height are given below 0");
}
makeMesh();
}
/**
* シリンダー or コーンの上面の半径
* topRadiusとbottomRadius両方に0以下を指定するとArgumentError
*/
public function get topRadius():Number { return _topRadius; }
public function set topRadius(value:Number):void
{
_topRadius = value;
if (bottomRadius <= 0 && topRadius <= 0)
{
throw new ArgumentError("bottomRadius and topRadius are given below 0");
}
makeMesh();
}
/**
* シリンダー or コーンの底面の半径
* topRadiusとbottomRadius両方に0以下を指定するとArgumentError
*/
public function get bottomRadius():Number { return _bottomRadius; }
public function set bottomRadius(value:Number):void
{
_bottomRadius = value;
if (bottomRadius <= 0 && topRadius <= 0)
{
throw new ArgumentError("bottomRadius and topRadius are given below 0");
}
makeMesh();
}
/**
* シリンダー or コーンの高さの分割数
* 1未満を指定するとArgumentError
*/
public function get heightSegments():uint { return _heightSegments; }
public function set heightSegments(value:uint):void
{
_heightSegments = value;
if (heightSegments < 1)
{
throw new ArgumentError("heightSegments are given below 1");
}
makeMesh();
}
/**
* シリンダー or コーンの円周の分割数
* 3未満を指定するとArgumentError
*
*/
public function get radialSegments():uint { return _radialSegments; }
public function set radialSegments(value:uint):void
{
_radialSegments = value;
if (radialSegments < 3)
{
throw new ArgumentError("radialSegments are given below 3");
}
makeMesh();
}
/**
* シリンダー or コーンの円周のVertexの始まりの角度。
* UVマップに影響する。
* 5角形や、星型といった形状作成の時、上部中央に頂点を持ってくる場合、-90を指定する
*
*/
public function get startVertexAngle():Number { return _startVertexAngle; }
public function set startVertexAngle(value:Number):void
{
_startVertexAngle = value;
makeMesh();
}
/**
* 星型にする
*/
public function get star():Boolean { return _star; }
public function set star(value:Boolean):void
{
_star = value;
if (_star && radialSegments % 2)
{
throw new ArgumentError("if the star is true, the radialSegments is Even");
}
makeMesh();
}
/**
* 両面にする
*
*/
public function get twoSided():Boolean { return _twoSided; }
public function set twoSided(value:Boolean):void
{
_twoSided = value;
makeMesh();
}
/**
* 反転する
* frontFaceとbackFaceを入れ替える
*
* twoSidedがfalseの場合
* sideFront(topFront、bottomFront)が有効になる
*
* twoSidedがtrueの場合
* sideBack(topBack、bottomBack)が有効になる
*
*/
public function get reverse():Boolean { return _reverse; }
public function set reverse(value:Boolean):void
{
_reverse = value;
makeMesh();
}
/**
* Faceの最小単位を三角形にする。(未実装)
*/
public function get triangulate():Boolean { return _triangulate; }
public function set triangulate(value:Boolean):void
{
_triangulate = value;
makeMesh();
}
/**
* sideのUV割付タイプを指定
*
* Cylinder.CIRCLE : sideのfaceへ円状にUV設定するタイプ
* Cylinder.LINER : sideのfaceへ筒状にUV設定するタイプ
*
*/
public function get sideTextureType():String { return _sideTextureType; }
public function set sideTextureType(value:String):void
{
_sideTextureType = value;
makeMesh();
}
/**
* top(上面)のMaterialの設定
*/
public function get topMaterial():Material { return _topMaterial; }
public function set topMaterial(value:Material):void
{
_topMaterial = value;
}
/**
* bottom(底面)のMaterialの設定
*/
public function get bottomMaterial():Material { return _bottomMaterial }
public function set bottomMaterial(value:Material):void
{
_bottomMaterial = value;
}
/**
* side(横面)のMaterialの設定
*/
public function get sideMaterial():Material { return _sideMaterial; }
public function set sideMaterial(value:Material):void
{
_sideMaterial = value;
if (faces.length) {
for each (var face:Face in faces) {
face.material = _sideMaterial;
}
}
}
/**
* top(上面)の表示・非表示
*/
public function get topVisible():Boolean { return _topVisible; }
public function set topVisible(value:Boolean):void
{
_topVisible = value;
makeMesh();
}
/**
* bottom(底面)の表示・非表示
*/
public function get bottomVisible():Boolean { return _bottomVisible; }
public function set bottomVisible(value:Boolean):void
{
_bottomVisible = value;
makeMesh();
}
/**
* 星型の内側頂点の割合
* 0~1
*/
public function get starRadius():Number { return _starRadius; }
public function set starRadius(value:Number):void
{
_starRadius = value;
}
/**
* private property
*/
private var _height:Number;
private var _topRadius:Number=3;
private var _bottomRadius:Number=3;
private var _heightSegments:uint;
private var _radialSegments:uint;
private var _startVertexAngle:Number;
private var _star:Boolean;
private var _twoSided:Boolean;
private var _reverse:Boolean;
private var _triangulate:Boolean;
private var _sideTextureType:String;
private var _topMaterial:Material;
private var _bottomMaterial:Material;
private var _sideMaterial:Material;
private var _topVisible:Boolean=true;
private var _bottomVisible:Boolean=true;
private var _geometryFlag:Boolean = false;
private var _starRadius:Number=0.5;
}
/**
* BasicTemplate for Alternativa3D 7.6
* Alternativa3D 7.6を扱いやすくするためのテンプレートです
* @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
*/
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();
}
}