faces (Arrow) - EZCreateMesh
Faces要素から複数のフェイスを一度に呼ぶことができます
click属性などが使えないため
その場合のコードジェネレータ作成する予定です
デモのために矢印を作成しました
引数は次の画像を参照してください
http://twitpic.com/x7z6b
package {
import alternativ5.engine3d.controllers.*;
import alternativ5.engine3d.core.*;
import alternativ5.engine3d.display.*;
import alternativ5.engine3d.events.MouseEvent3D;
import alternativ5.types.*;
import alternativ5.utils.*;
import flash.display.*;
import flash.events.*;
/**
* Faces要素から複数のフェイスを一度に呼ぶことができます
*
* click属性などが使えないため
* その場合のコードジェネレータ作成する予定です
*
* デモのために矢印を作成しました
* 引数は次の画像を参照してください
* http://twitpic.com/x7z6b
*/
[SWF(backgroundColor="#000000", frameRate="120")]
public class Main extends Sprite {
private var scene:Scene3D;
private var view:View;
private var camera:Camera3D;
private var cameraController:CameraController;
public var textures:Array;
private var meshes:/*Mesh*/Array;
private var map:Map;
public function Main() {
this.addEventListener(Event.ADDED, init);
}
public function init(e:Event):void {
this.removeEventListener(Event.ADDED, init);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
scene = new Scene3D();
scene.root = new Object3D();
camera = new Camera3D();
camera.x = camera.y = 500;
camera.z = 800;
scene.root.addChild(camera);
view = new View();
view.interactive = true;
view.camera = camera;
addChild(view);
cameraController = new CameraController(stage);
cameraController.camera = camera;
cameraController.checkCollisions = false;
cameraController.speed = 500;
cameraController.controlsEnabled = true;
cameraController.setDefaultBindings();
cameraController.lookAt(new Point3D());
FPS.init(stage);
stage.addEventListener(Event.RESIZE, onResize);
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
onResize(null);
//create
create();
}
/**
*
*/
private function create():void {
var xml:XML =
<meshes>
<mesh name="Geo">
<surface materialType={EZCreateMesh.FILL} color="0xFF0000" wirethickness="2" wirecolor="0xFFFFFF">
<faces primitive={EZCreateMesh.ARROW} aw="500" ah="500" bw="500" bh="500" tz="0" ch="50" />
</surface>
</mesh>
</meshes>;
// createMeshes
meshes = EZCreateMesh.createMeshes(xml, textures, this);
// addMehses
addMehses(meshes);
}
/**
* addMeshes
* @param meshes
*/
private function addMehses(meshes:Array):void {
for (var o:* in meshes) {
scene.root.addChild(meshes[o]);
}
}
/**
*
* @param targetMap
* @param targetSet
*/
private function addSetObjects(targetMap:Map, targetSet:String):void {
addObjects(targetMap[EZCreateMesh.KEY_MAP + EZCreateMesh.ID_CONCAT + targetSet]);
}
/**
* addObjects
* @param objects
*/
private function addObjects(objects:Set):void {
for (var o:* in objects) {
scene.root.addChild(o);
}
}
/**
* onResize
* @param e
*/
private function onResize(e:Event):void {
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}
/**
*
* @param e
*/
private function onEnterFrame(e:Event):void {
cameraController.processInput();
scene.calculate();
}
}
}
/**
* EZCreateMesh
*
* 簡単に より早くメッシュを作成する為に
*
* Alternativa3Dを利用したマップ(Mesh)作成時に ASでは 頂点やフェイス、
* サーフェス全てに id(名前)をつける必要があり、これらの作業は非常に面倒です
*
* XMLに情報を記述することによって
* 値 変更時にコンパイルが不要になり、誰でも簡単にマップ作成が可能です
*
* @author br
*/
import alternativ5.engine3d.core.*;
import alternativ5.engine3d.materials.*;
import alternativ5.types.*;
import alternativ5.utils.*;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.tweens.ITween;
import flash.geom.*;
import flash.display.*;
import alternativ5.engine3d.core.*;
import alternativ5.engine3d.materials.*;
import alternativ5.types.*;
import alternativ5.utils.*;
import flash.geom.*;
import flash.display.*;
import alternativ5.engine3d.events.*;
class EZCreateMesh {
/**
* static const
*/
// MATERIAL
public static const DEV:String = "DevMaterial";
public static const FILL:String = "FillMaterial";
public static const TEXTURE:String = "TextureMaterial";
public static const WIRE:String = "WireMaterial";
public static const MOVIECLIP:String = "MovieClipMaterial";
// SPEITE 3D
public static const SPRITE_TEXTURE:String = "SpriteTextureMaterial";
public static const SPRITE:String = "SpriteMaterial";
public static const ID_CONCAT:String = ":";
public static const ID_SURFACE:String = "s";
public static const ID_FACE:String = "f";
public static const ID_VERTEX:String = "v";
public static const KEY_MAP:String = "m";
private static const _PI:Number = Math.PI;
/**
* 渡されたXMLに記載されているMeshを全て作成し配列で返します
* @param db
*/
public static function createMeshes(db:XML, textures:Array = null, main:Main = null):/*Mesh*/Array {
var _meshes:/*Mesh*/Array = [];
for (var a:int = 0; a < db.mesh.length(); a++) {
_meshes[db.mesh[a].@name] = new Mesh();
var textureLists:XMLList = db.mesh[a].surface.(@materialType == TEXTURE).@name;
_meshes[db.mesh[a].@name] = createMesh(db.mesh[a], textures, main) as Mesh;
}
return _meshes;
}
/**
* マップを作成
* @param map
* @param mapName
*/
public static function createMap(db:XML, _meshes:/*Mesh*/Array):Map {
var map:Map = new Map();
for (var a:int = 0; a < db.set.length(); a++) {
var _set:Set;
var elements:Array = [];
for (var b:int = 0; b < db.set[a].mesh.length(); b++) {
var mesh:Mesh = meshPropertiesSetup(
_meshes[db.set[a].mesh[b].@name].clone(),
db.set[a].mesh[b]
);
elements.push(mesh);
}
_set = Set.createFromArray(elements);
map.add(KEY_MAP + ID_CONCAT + db.set[a].@name, _set);
}
return map;
}
/**
* XMLを元にプロパティを変更したメッシュを返します
* @param mesh メッシュ
* @param properties プロパティが記載されたXML
* @return mesh プロパティが変更されたメッシュを返します
* @exampleText XMLの例を示します
* <listing version="3.0">
* <mesh z="-100" scaleX="5" scaleY="5" />
* </listing>
*/
public static function meshPropertiesSetup(mesh:Mesh, properties:XML):Mesh {
if (properties.hasOwnProperty("@x")) mesh.x = Number(properties.@x);
if (properties.hasOwnProperty("@y")) mesh.y = Number(properties.@y);
if (properties.hasOwnProperty("@z")) mesh.z = Number(properties.@z);
if (properties.hasOwnProperty("@scaleX")) mesh.scaleX = Number(properties.@scaleX);
if (properties.hasOwnProperty("@scaleY")) mesh.scaleY = Number(properties.@scaleY);
if (properties.hasOwnProperty("@scaleZ")) mesh.scaleZ = Number(properties.@scaleZ);
if (properties.hasOwnProperty("@rotationX")) mesh.rotationX = MathUtils.toRadian(Number(properties.@rotationX));
if (properties.hasOwnProperty("@rotationY")) mesh.rotationY = MathUtils.toRadian(Number(properties.@rotationY));
if (properties.hasOwnProperty("@rotationZ")) mesh.rotationZ = MathUtils.toRadian(Number(properties.@rotationZ));
return mesh;
}
/**
* メッシュ作成
* @param xml メッシュの情報が記載されたXML
* @return Mesh
*/
public static function createMesh(xml:XML, textures:/*BitmapData*/Array = null, main:Main = null):Mesh {
var _mesh:Mesh = new Mesh();
var surfaces:Array = [];
for (var a:int = 0; a < xml.surface.length(); a++)
{
if ("faces" in xml.surface[a]) {
for ( var f:int = 0; f < xml.surface[a].faces.length(); f++) {
xml.surface[a].faces.prependChild(createFacesPrimitive(xml.surface[a].faces[f]));
}
}
// eg - s:s (s:0)
var surfaceName:String = xml.surface[a].hasOwnProperty("@id") ? xml.surface[a].@id : String(ID_SURFACE + ID_CONCAT + a);
var materialType:String = xml.surface[a].@materialType;
var faces:Array = [];
for (var b:int = 0; b < xml.surface[a]..face.length(); b++)
{
if ("vertices" in xml.surface[a]..face[b]) {
for (var v:int = 0; v < xml.surface[a]..face[b].vertices.length(); v++) {
xml.surface[a]..face[b].vertices[v].prependChild(createVerticesPrimitive(xml.surface[a]..face[b].vertices[v]));
}
}
// eg - f:sf (f:00)
var faceName:String = xml.surface[a]..face[b].hasOwnProperty("@id") ? xml.surface[a]..face[b].@id : String(ID_FACE + ID_CONCAT + a + b);
var vertices:Array = [];
for (var c:int = 0; c < xml.surface[a]..face[b]..vertex.length(); c++)
{
// eg - v:sfv (v:000)
var vertexName:String = xml.surface[a]..face[b]..vertex[c].hasOwnProperty("@id") ? xml.surface[a]..face[b]..vertex[c].@id : String(ID_VERTEX + ID_CONCAT + a + b + c);
/**
* createVertex
*/
_mesh.createVertex(
xml.surface[a]..face[b]..vertex[c].@x,
xml.surface[a]..face[b]..vertex[c].@y,
xml.surface[a]..face[b]..vertex[c].@z,
vertexName
);
vertices.push(vertexName);
}
/**
* createFace
*/
_mesh.createFace(vertices, faceName);
with ( _mesh.getFaceById( faceName ) ) {
if ( xml.surface[a]..face[b].hasOwnProperty("@click") )
addEventListener(MouseEvent3D.CLICK , main[xml.surface[a]..face[b].@click]);
if ( xml.surface[a]..face[b].hasOwnProperty("@mouseDown") )
addEventListener(MouseEvent3D.MOUSE_DOWN, main[xml.surface[a]..face[b].@mouseDown]);
if ( xml.surface[a]..face[b].hasOwnProperty("@mouseMove") )
addEventListener(MouseEvent3D.MOUSE_MOVE , main[xml.surface[a]..face[b].@mouseMove]);
if ( xml.surface[a]..face[b].hasOwnProperty("@mouseOut") )
addEventListener(MouseEvent3D.MOUSE_OUT, main[xml.surface[a]..face[b].@mouseOut]);
if ( xml.surface[a]..face[b].hasOwnProperty("@mouseOver") )
addEventListener(MouseEvent3D.MOUSE_OVER, main[xml.surface[a]..face[b].@mouseOver]);
if ( xml.surface[a]..face[b].hasOwnProperty("@mouseUp") )
addEventListener(MouseEvent3D.MOUSE_UP , main[xml.surface[a]..face[b].@mouseUp]);
if ( xml.surface[a]..face[b].hasOwnProperty("@mouseWheel") )
addEventListener(MouseEvent3D.MOUSE_WHEEL, main[xml.surface[a]..face[b].@mouseWheel]);
}
/**
* setUVsToFace
*/
if ("UVs" in xml.surface[a]..face[b]) {
with ( xml.surface[a]..face[b].UVs ) {
_mesh.setUVsToFace(
new Point(aUV.@x, aUV.@y),
new Point(bUV.@x, bUV.@y),
new Point(cUV.@x, cUV.@y),
faceName
);
}
}
/**
* push Faces
*/
faces.push(faceName);
}
/**
* createSurface
*/
_mesh.createSurface(faces, surfaceName);
with ( _mesh.getSurfaceById(surfaceName) ) {
if ( xml.surface[a].hasOwnProperty("@click") )
addEventListener(MouseEvent3D.CLICK , main[xml.surface[a].@click]);
if ( xml.surface[a].hasOwnProperty("@mouseDown") )
addEventListener(MouseEvent3D.MOUSE_DOWN, main[xml.surface[a].@mouseDown]);
if ( xml.surface[a].hasOwnProperty("@mouseMove") )
addEventListener(MouseEvent3D.MOUSE_MOVE , main[xml.surface[a].@mouseMove]);
if ( xml.surface[a].hasOwnProperty("@mouseOut") )
addEventListener(MouseEvent3D.MOUSE_OUT, main[xml.surface[a].@mouseOut]);
if ( xml.surface[a].hasOwnProperty("@mouseOver") )
addEventListener(MouseEvent3D.MOUSE_OVER, main[xml.surface[a].@mouseOver]);
if ( xml.surface[a].hasOwnProperty("@mouseUp") )
addEventListener(MouseEvent3D.MOUSE_UP , main[xml.surface[a].@mouseUp]);
if ( xml.surface[a].hasOwnProperty("@mouseWheel") )
addEventListener(MouseEvent3D.MOUSE_WHEEL, main[xml.surface[a].@mouseWheel]);
}
/**
* push
*/
surfaces.push(surfaceName);
/**
* setMaterialToSurface
*/
_mesh.setMaterialToSurface(
createMaterial(
xml.surface[a],
( materialType == TEXTURE || materialType == MOVIECLIP ) ? textures[xml.surface[a].@name] : null),
surfaceName
);
}
return _mesh;
}
/**
* マテリアルを作成
* @param material マテリアル情報が記載されたXML
* @return SurfaceMaterial
* @exampleText XMLの例を示します
* <listing version="3.0">
* <surface materialType={EZCreateMesh.FILL} color="0x99ab4e" wirethickness="1" wirecolor="0x7b8d42" />
* <surface materialType="TextureMaterial" repeat="true" smooth="true" src="image" precision="BEST" />
* </listing>
*/
public static function createMaterial(material:XML, texture:* = null):SurfaceMaterial {
with ( material ) {
switch ( @materialType.toString() ) {
case DEV :
return new DevMaterial(
hasOwnProperty("@parametertype") ? @parametertype : 0,
hasOwnProperty("@color") ? @color: 0xffffff * Math.random(),
hasOwnProperty("@maxparametervalue") ? @maxparametervalue : 20,
hasOwnProperty("@shownormals") ? @shownormals : false,
hasOwnProperty("@normalscolor") ? @normalscolor : 0x00FFFF,
hasOwnProperty("@minmobility") ? @minmobility : 0,
hasOwnProperty("@maxmobility") ? @maxmobility : 255,
hasOwnProperty("@alpha") ? @alpha : 1,
hasOwnProperty("@blendmode") ? @blendmode : BlendMode.NORMAL,
hasOwnProperty("@wirethickness") ? @wirethickness : -1,
hasOwnProperty("@wirecolor") ? @wirecolor : 0
);
break;
case FILL :
return new FillMaterial(
hasOwnProperty("@color") ? @color: 0xffffff * Math.random(),
hasOwnProperty("@alpha") ? @alpha : 1,
hasOwnProperty("@blendmode") ? @blendmode : BlendMode.NORMAL,
hasOwnProperty("@wirethickness") ? @wirethickness : -1,
hasOwnProperty("@wirecolor") ? @wirecolor : 0
);
break;
case TEXTURE :
return new TextureMaterial(
new Texture(texture),
hasOwnProperty("@alpha") ? @alpha : 1,
hasOwnProperty("@repeat") ? (@repeat == "true" ? true : false) : true,
hasOwnProperty("@smooth") ? (@smooth == "true" ? true : false) : false,
hasOwnProperty("@blendmode") ? @blendmode : BlendMode.NORMAL,
hasOwnProperty("@wirethickness") ? @wirethickness : -1,
hasOwnProperty("@wirecolor") ? @wirecolor : 0,
hasOwnProperty("@precision") ? @precision : 10
);
break;
case WIRE :
return new WireMaterial(
hasOwnProperty("@thickness") ? @thickness : 0,
hasOwnProperty("@color") ? @color : 0xffffff * Math.random(),
hasOwnProperty("@alpha") ? @alpha : 1,
hasOwnProperty("@blendmode") ? @blendmode : BlendMode.NORMAL
);
break;
case MOVIECLIP :
return new MovieClipMaterial(
MovieClip( texture ),
@textureWidth,
@textureHeight,
new Rectangle(
hasOwnProperty("@clipX") ? @clipX : 0,
hasOwnProperty("@clipY") ? @clipY : 0,
hasOwnProperty("@clipWidth") ? @clipWidth : 0,
hasOwnProperty("@clipHeight") ? @clipHeight : 0
),
new Matrix(
hasOwnProperty("@a") ? @a : 1,
hasOwnProperty("@b") ? @b : 0,
hasOwnProperty("@c") ? @c : 0,
hasOwnProperty("@d") ? @d : 1,
hasOwnProperty("@tx") ? @tx : 0,
hasOwnProperty("@ty") ? @ty : 0
),
hasOwnProperty("@smooth") ? (@smooth == "true" ? true : false) : false,
hasOwnProperty("@precision") ? @precision : 10,
hasOwnProperty("@fillColor") ? @fillColor : 0xffffff * Math.random(),
hasOwnProperty("@refreshRate") ? @refreshRate : 1
);
break;
default :
return null;
break;
}
}
}
/**
* PRIMITIVE
*/
/**
*
* @param primitive
* @return
*/
public static function createFacesPrimitive(primitive:XML):XMLList {
var _faces:XML = <faces></faces>;
with (primitive) {
switch ( @primitive.toString() ) {
case CIRCLE : return buildCircleFaces(@tx, @ty, @tz, @r, @rp, @rv, @twoSided);
case ARROW : return buildArrowFaces(@aw,@ah, @bw, @bh, @ch, @tz);
default : return new XMLList();
}
}
function buildArrowFaces(aw:Number, ah:Number, bw:Number, bh:Number, ch:Number, tz:Number):XMLList {
_faces.appendChild(<face><vertices primitive={ ARROW } rv="false" aw={aw} ah={ah} bw={bw} bh={bh} tz={tz + ch / 2} ch={ch} /></face>);
_faces.appendChild(<face><vertices primitive = { PLANE } rv="false" ax={bw} ay="0" az={tz - ch / 2} bx={bw} by="0" bz={ch / 2} cx="0" cy={bh} cz={ch / 2} dx="0" dy={bh} dz={tz - ch / 2} /></face>);
_faces.appendChild(<face><vertices primitive = { PLANE } rv="false" ax="0" ay={-bh} az={tz - ch / 2} bx="0" by={-bh} bz={ch / 2} cx={bw} cy="0" cz={ch / 2} dx={bw} dy="0" dz={tz - ch / 2} /></face>);
_faces.appendChild(<face><vertices primitive = { PLANE } rv="false" ax="0" ay={bh} az={tz - ch / 2} bx="0" by={bh} bz={ch / 2} cx="0" cy={bh - ah / 2} cz={ch / 2} dx="0" dy={bh - ah / 2} dz={tz - ch / 2} /></face>);
_faces.appendChild(<face><vertices primitive = { PLANE } rv="false" ax="0" ay={-(bh - ah / 2)} az={tz - ch / 2} bx="0" by={-(bh - ah / 2)} bz={ch / 2} cx="0" cy={-bh} cz={ch / 2} dx="0" dy={-bh} dz={tz - ch / 2} /></face>);
_faces.appendChild(<face><vertices primitive = { PLANE } rv="false" ax="0" ay={bh - ah / 2} az={tz - ch / 2} bx="0" by={bh - ah / 2} bz={ch / 2} cx={-aw} cy={bh - ah / 2} cz={ch / 2} dx={-aw} dy={bh - ah / 2} dz={tz - ch / 2} /></face>);
_faces.appendChild(<face><vertices primitive = { PLANE } rv="false" ax={-aw} ay={-(bh - ah / 2)} az={tz - ch / 2} bx={-aw} by={-(bh - ah / 2)} bz={ch / 2} cx="0" cy={-(bh - ah / 2)} cz={ch / 2} dx="0" dy={-(bh - ah / 2)} dz={tz - ch / 2} /></face>);
_faces.appendChild(<face><vertices primitive = { PLANE } rv="false" ax={-aw} ay={bh - ah / 2} az={tz - ch / 2} bx={-aw} by={bh - ah / 2} bz={ch / 2} cx={-aw} cy={-(bh - ah / 2)} cz={ch / 2} dx={-aw} dy={-(bh - ah / 2)} dz={tz - ch / 2} /></face >);
_faces.appendChild(<face><vertices primitive={ ARROW } rv="true" aw={aw} ah={ah} bw={bw} bh={bh} tz={tz - (ch / 2)} ch={ch} /></face>);
return _faces.face;
}
function buildCircleFaces(tx: Number, ty: Number, tz:Number, r:Number, rp:Number, rv:String, twoSided:String = "false"): XMLList {
_faces.appendChild(<face><vertices primitive={CIRCLE} tx={tx} ty={ty} tz={tz} r={r} rp={rp} rv={rv} /></face>);
if (twoSided) _faces.appendChild(<face><vertices primitive={CIRCLE} tx={tx} ty={ty} tz={tz} r={r} rp={rp} rv="true" /></face>);
return _faces.face;
}
return new XMLList();
}
public static const CIRCLE:String = "Circle";
public static const ARROW:String = "Arrow";
public static const PLANE:String = "Plane";
/**
* 頂点の情報を返します UV情報は含まれません。
* @param primitive
* @return
*/
public static function createVerticesPrimitive(primitive:XML):XMLList {
var _vertices:XML = <vertices></vertices>;
with (primitive) {
switch ( @primitive.toString() ) {
case CIRCLE : return buildCircleVertices(@tx, @ty, @tz, @r, @rp, @rv);
case ARROW : return buildArrowVertices(@aw, @ah, @bw, @bh, @tz, @rv);
case PLANE : return buildPlaneVertices(@ax, @ay, @az, @bx, @by, @bz, @cx, @cy, @cz, @dx, @dy, @dz, @rv);
case TRIANGLE : return buildTriangleVertices(@ax, @ay, @az, @bx, @by, @bz, @cx, @cy , @cz ,@rv)
default : return new XMLList();
}
}
function buildTriangleVertices(ax:Number, ay:Number, az:Number, bx:Number, by:Number, bz:Number, cx:Number, cy:Number, cz:Number, rv:String = "false"):XMLList {
if (rv == "true") {
v(ax, ay, az);
v(bx, by, bz);
v(cx, cy, cz);
}
else {
v(cx, cy, cz);
v(bx, by, bz);
v(ax, ay, az);
}
return _vertices.vertex
}
function buildPlaneVertices(ax:Number, ay:Number, az:Number, bx:Number, by:Number, bz:Number, cx:Number, cy:Number, cz:Number, dx:Number, dy:Number, dz:Number, rv:String = "false"):XMLList {
if ( rv == "true" ) {
v(ax, ay, az);
v(bx, by, bz);
v(cx, cy, cz);
v(dx, dy, dz);
}
else {
v(dx, dy, dz);
v(cx, cy, cz);
v(bx, by, bz);
v(ax, ay, az);
}
return _vertices.vertex;
}
function buildArrowVertices(aw:Number, ah:Number, bw:Number, bh:Number, tz:Number, rv:String = "false"):XMLList {
if ( rv == "true" ) {
v(0, bh, tz);
v(bw, 0, tz);
v(0, -bh, tz);
v( 0, -(bh - (ah / 2)), tz);
v( -aw, -(bh - (ah / 2)), tz);
v( -aw, bh - (ah / 2), tz);
v( 0, bh - (ah / 2), tz);
}
else {
v( 0, bh - (ah / 2), tz);
v( -aw, bh - (ah / 2), tz);
v( -aw, -(bh - (ah / 2)), tz);
v( 0, -(bh - (ah / 2)), tz);
v(0, -bh, tz);
v(bw, 0, tz);
v(0, bh, tz);
}
return _vertices.vertex;
}
function buildCircleVertices(tx: Number, ty: Number, tz:Number, r:Number, rp:Number, rv:String = "false"): XMLList {
var rad:int = 0;
if ( rv == "true" ) {
for (rad = 0; rad < 360; rad += rp) {
v(Math.cos(rad * _PI / 180) * r, Math.sin(rad * _PI / 180) * r, tz);
}
}
else {
for (rad = 360; rad > 0; rad -= rp) {
v(Math.cos(rad * _PI / 180) * r, Math.sin(rad * _PI / 180) * r, tz);
}
}
return _vertices.vertex;
}
/**
* create v
* @param _x
* @param _y
* @param _z
*/
function v(_x:Number, _y:Number, _z:Number):void {
_vertices.appendChild(<vertex x={_x} y={_y} z={_z} />);
}
}
}