EZCreateMesh
/**
* Copyright TmskSt ( http://wonderfl.net/user/TmskSt )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/nrH9
*/
package {
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.utils.getTimer;
import flash.geom.Point;
import alternativ5.engine3d.core.Mesh;
import alternativ5.engine3d.core.Vertex;
import alternativ5.engine3d.core.Face;
import alternativ5.engine3d.core.Surface;
import alternativ5.engine3d.materials.SurfaceMaterial;
import alternativ5.engine3d.materials.DevMaterial;
import alternativ5.engine3d.materials.FillMaterial;
import alternativ5.engine3d.materials.TextureMaterial;
import alternativ5.engine3d.materials.TextureMaterialPrecision;
import alternativ5.engine3d.materials.WireMaterial;
import alternativ5.types.Texture;
import alternativ5.types.Point3D;
import alternativ5.utils.MathUtils;
[SWF(width = 465, height = 465, frameRate = 60, backgroundColor="#0")]
public class Main extends Sprite {
public function Main():void {
var template:BasicTemplate = new BasicTemplate();
addChild(template);
/**
* 簡単に より早くメッシュを作成する為に
* forked from : clockmaker's [Alternativa3D] Basic Template
*/
var xml:XML =
<mesh>
<!--
surface
surface要素は 1つ以上必要です。数に上限はありません
マテリアルを指定できるのは、このサーフェス要素のみです
materialTypeにマテリアルの種類を その後、指定したマテリアルに対応する属性を記述します
-->
<surface materialType="FillMaterial" color="0xFF0000">
<!--
face
face要素は 1つ以上必要です。数に上限はありません
-->
<face>
<!-- この要素は TextureMaterial を指定した時のみ 必要です -->
<!-- UVマッピングを行います。テクスチャ(画像)の左下を P(0, 0)とし、テクスチャ(画像)の右上を P2(1, 1)として扱います
<UVs>
<aUV x="0" y="0" />
<bUV x="0" y="1" />
<cUV x="1" y="1" />
</UVs>
-->
<!-- Vertex は 3つ以上必要です -->
<!--
※ 頂点の座標を指定します。このときの座標はマップ内の絶対的な座標ではなく メッシュのみが配置された空間に対する座標です。
マップに追加する時には、メッシュプロパティを変更します。
フェイス作成時には、上から順に配列が作成されます
-->
<vertex x="100" y="100" z="0" />
<vertex x="-100" y="100" z="0" />
<vertex x="-100" y="-100" z="0" />
<vertex x="100" y="-100" z="0" />
</face>
</surface>
<surface materialType="WireMaterial" thickness="1" color="0xFF00FF">
<face>
<vertex x="100" y="100" z="150" />
<vertex x="-100" y="100" z="150" />
<vertex x="-100" y="-100" z="150" />
<vertex x="100" y="-100" z="150" />
</face>
</surface>
</mesh>;
var geo:XML =
<mesh>
<surface materialType="FillMaterial" color="0x222222" wirethickness="1" wirecolor="0xFFFFFF">
<face>
<vertex x="1000" y="1000" z="0" />
<vertex x="-1000" y="1000" z="0" />
<vertex x="-1000" y="-1000" z="0" />
<vertex x="1000" y="-1000" z="0" />
</face>
</surface>
</mesh>;
var ezMesh:Mesh = EZCreateMesh(xml);
ezMesh.z = -100;
ezMesh.scaleX = ezMesh.scaleY = ezMesh.scaleZ = 2;
template.scene.root.addChild(ezMesh);
var ezGeo:Mesh = EZCreateMesh(geo);
ezGeo.z = -150;
template.scene.root.addChild(ezGeo);
//enterFrame
template.onPreRender = function():void {
template.camera.x = 500 * Math.sin(getTimer() / 1000);
template.camera.y = 500 * Math.cos(getTimer() / 1000);
template.camera.z += ((400 * (mouseY / stage.stageHeight) + 300) - template.camera.z) * 0.1;
template.camera.y += ( - 1000 * mouseY / stage.stageHeight - template.camera.y) * 0.1;
template.cameraContoller.lookAt(new Point3D());
}
}
/**
* 簡単に より早くメッシュを作成する為に
*
* Alternativa3Dを利用したマップ(Mesh)作成時に ASでは 頂点やフェイス、サーフェス全てに id(名前)をつける必要があり、これらの作業は非常に面倒です
* XMLに情報を記述することによって 値 変更時にコンパイルが不要になり、誰でも簡単にマップ作成が可能です
* また、XMLを読み込んでいるだけなので サンドボックスの開発も可能です
*
* クラスとして書き出すこともできますが、その場合は Textureマテリアルに渡す BitamapData をパイプする方法を用意してください
*
* @author br
*/
/**
* メッシュ作成
* @param xml メッシュの情報が記載されたXML
* @return Mesh
*/
public function EZCreateMesh(xml:XML):Mesh {
var _mesh:Mesh = new Mesh();
var surfaces:Array = new Array();
for (var a:uint = 0; a < xml.surface.length(); a++)
{
var surfaceName:String = String("s" + a);
var faces:Array = new Array();
for (var b:uint = 0; b < xml.surface[a].face.length(); b++)
{
var faceName:String = String("f" + a + b);
var vertices:Array = new Array();
for (var c:uint = 0; c < xml.surface[a].face[b].vertex.length(); c++)
{
var vertexName:String = String("v" + 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);
/**
* setUVsToFace
*/
if ("UVs" in xml.surface[a].face[b]) {
_mesh.setUVsToFace(
new Point(
Number(xml.surface[a].face[b].UVs.aUV.@x),
Number(xml.surface[a].face[b].UVs.aUV.@y)
),
new Point(
Number(xml.surface[a].face[b].UVs.bUV.@x),
Number(xml.surface[a].face[b].UVs.bUV.@y)
),
new Point(
Number(xml.surface[a].face[b].UVs.cUV.@x),
Number(xml.surface[a].face[b].UVs.cUV.@y)
),
faceName
);
}
/**
* push Faces
*/
faces.push(faceName);
}
/**
* createSurface
*/
_mesh.createSurface(faces, surfaceName);
surfaces.push(surfaceName);
_mesh.setMaterialToSurface(createMaterial(xml.surface[a]), surfaceName);
}
return _mesh;
}
/**
* マテリアルを作成
* @param material マテリアル情報が記載されたXML
* @return SurfaceMaterial
* @exampleText XMLの例を示します
* <listing version="3.0">
* <surface materialType="FillMaterial" color="0x99ab4e" wirethickness="1" wirecolor="0x7b8d42" />
* <surface materialType="TextureMaterial" repeat="true" smooth="true" src="image" precision="BEST" />
* </listing>
*/
private function createMaterial(material:XML):SurfaceMaterial {
switch (true) {
/**
* DEV
*/
case material.@materialType == Matrials.DEV :
return new DevMaterial(
uint(material.@parametertype) ? material.@parametertype : 0,
uint(material.@color) ? material.@color : 0xFFFFFF,
Number(material.@maxparametervalue) ? material.@maxparametervalue : 20,
Boolean(material.@shownormals) ? material.@shownormals : false,
uint(material.@normalscolor) ? material.@normalscolor : 0x00FFFF,
int(material.@minmobility) ? material.@minmobility : 0,
int(material.@maxmobility) ? material.@maxmobility : 255,
Number(material.@alpha) ? material.@alpha : 1,
String(material.@blendmode) ? material.@blendmode : "normal",
Number(material.@wirethickness) ? material.@wirethickness : -1,
Number(material.@wirecolor) ? material.@wirecolor : 0
);
break;
/**
* FILL
*/
case material.@materialType == Matrials.FILL :
return new FillMaterial(
uint(material.@color)? material.@color: 0xffffff * Math.random(),
Number(material.@alpha)? material.@alpha : 1,
String(material.@blendmode)? material.@blendmode : "normal",
Number(material.@wirethickness)? material.@wirethickness : -1,
Number(material.@wirecolor)? material.@wirecolor : 0
);
break;
/**
* TEXTURE
*/
case material.@materialType == Matrials.TEXTURE :
return new TextureMaterial(
new Texture(
//テクスチャマテリアルを利用する場合は、
// Array$BitmapDataな配列を作成し、あらかじめ格納しておき
// Array$BiamapData[material.@src] とアクセスするのがよいと思います
new BitmapData(0,0)
),
uint(material.@alpha)? material.@alpha : 1,
Boolean(material.@repeat == "true")? true : true,
Boolean(material.@smooth == "true")? true : false,
String(material.@blendmode.toString())? material.@blendmode : BlendMode.NORMAL,
Number(material.@wirethickness)? material.@wirethickness : -1,
uint(material.@wirecolor)? material.@wirecolor : 0,
String(material.@precision.toString())? createTextureMaterialPrecision(material.@precision.toString()) : 10
);
break;
/**
* WIRE
*/
case material.@materialType == Matrials.WIRE :
return new WireMaterial(
Number(material.@thickness) ? material.@thickness : 0,
uint(material.@color) ? material.@color : 0xffffff * Math.random(),
Number(material.@alpha) ? material.@alpha : 1,
String(material.@blendmode) ? material.@blendmode : "normal"
);
break;
default :
return null;
break;
}
}
/**
* createTextureMaterialPrecision
* @param precision
* @return
*/
private function createTextureMaterialPrecision(precision:String):Number {
switch(true) {
case precision == "BEST" : return TextureMaterialPrecision.BEST; break;
case precision == "HIGH" : return TextureMaterialPrecision.HIGH; break;
case precision == "LOW" : return TextureMaterialPrecision.LOW; break;
case precision == "MEDIUM" : return TextureMaterialPrecision.MEDIUM; break;
case precision == "NONE" : return TextureMaterialPrecision.NONE; break;
case precision == "VERY_HIGH" : return TextureMaterialPrecision.VERY_HIGH; break;
case precision == "VERY_LOW" : return TextureMaterialPrecision.VERY_LOW; break;
default : return TextureMaterialPrecision.MEDIUM;
}
}
/**
* XMLを元にプロパティを変更したメッシュを返します
* @param mesh メッシュ
* @param properties プロパティが記載されたXML
* @return mesh プロパティが変更されたメッシュを返します
* @exampleText XMLの例を示します
* <listing version="3.0">
* <mesh z="-100" scaleX="5" scaleY="5" />
* </listing>
*/
public 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;
}
}
}
import alternativ5.engine3d.materials.DevMaterial;
import alternativ5.engine3d.materials.FillMaterial;
import alternativ5.engine3d.materials.TextureMaterial;
import alternativ5.engine3d.materials.WireMaterial;
import alternativ5.engine3d.materials.MovieClipMaterial;
import alternativ5.engine3d.materials.SpriteMaterial;
class Matrials extends SpriteMaterial {
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";
/**
* Original Material
*/
}
/**
* BasicTemplate for Alternativa3D
* Alternativa3Dを扱いやすくするためのテンプレートです
* @author Yasu
*/
import alternativ5.engine3d.controllers.CameraController;
import alternativ5.engine3d.core.Camera3D;
import alternativ5.engine3d.core.Object3D;
import alternativ5.engine3d.core.Scene3D;
import alternativ5.engine3d.display.View;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
class BasicTemplate extends Sprite{
/**
* シーンインスタンスです。
*/
public var scene:Scene3D;
/**
* ビューインスタンスです。
*/
public var view:View;
/**
* カメラインスタンスです。
*/
public var camera:Camera3D;
/**
* カメラコントローラーです。
*/
public var cameraContoller:CameraController;
private var _viewWidth:int;
private var _viewHeight:int;
private var _scaleToStage:Boolean;
/**
* 新しい BasicTemplate インスタンスを作成します。
* @param viewWidth
* @param viewHeight
* @param scaleToStage
*/
public function BasicTemplate(viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true) {
_viewWidth = viewWidth;
_viewHeight = viewHeight;
_scaleToStage = scaleToStage;
// Creating scene
scene = new Scene3D();
scene.splitAnalysis = false; // not analysis for performance
scene.root = new Object3D();
// Adding camera
camera = new Camera3D();
camera.z = -1000;
scene.root.addChild(camera);
// camera contoller
cameraContoller = new CameraController(this);
cameraContoller.camera = camera;
// set view
view = new View();
view.camera = camera;
addChild(view);
// stage
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理をオーバーライドして記述します。
*/
protected function atInit():void {}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理を記述します。
*/
private var _onInit:Function = function():void { };
public function get onInit():Function { return _onInit; }
public function set onInit(value:Function):void {
_onInit = value;
}
/**
* 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 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理を記述します。
*/
protected 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 {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.HIGH;
// resize
stage.addEventListener(Event.RESIZE, onResize);
onResize(null);
// render
startRendering();
atInit();
_onInit();
}
/**
* @private
*/
private function onRenderTick(e:Event = null):void {
atPostRender();
_onPostRender();
scene.calculate();
atPreRender();
_onPreRender();
}
/**
* @private
*/
private function onResize(event:Event = null):void {
if (_scaleToStage) {
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}else {
view.width = _viewWidth;
view.height = _viewHeight;
}
}
}