flash on 2010-1-10
元ネタ :
Alternativa3D Tips 平面プリミティブの頂点にアクセスして、変形する2
http://wonderfl.net/code/c98f38e927e47ec3dc415e553c7c5c13197a35bf
Planeプリミティブを自作して頂点情報を操作しています
twoSided は false です
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.*;
/**
* 元ネタ :
* Alternativa3D Tips 平面プリミティブの頂点にアクセスして、変形する2
* http://wonderfl.net/code/c98f38e927e47ec3dc415e553c7c5c13197a35bf
*
*
* Planeプリミティブを自作して頂点情報を操作しています
* twoSided は false です
*/
[SWF(backgroundColor="#000000", frameRate="60")]
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 = 600;
camera.z = 700;
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="0xAAAAAA">
<faces primitive={EZCreateMesh.PLANE} ox="0" oy="0" oz="0" w="1000" h="1000" ws="1" hs="36" twoSided="false" />;
</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 var angle:Number = 0;
private function onEnterFrame(e:Event):void {
cameraController.processInput();
angle++;
/**
* twoSidedをtrueにする場合は
* i < 282
* var vy:Number = Math.sin(MathUtils.toRadian((i+8 + angle) * 4)) * 50;
*
* と書き換えます
*/
for (var i:int = 0; i < 141; i++) {
var vy:Number = Math.sin(MathUtils.toRadian((i + 4 + angle) * 4)) * 50;
var vz:Number = Math.sin(MathUtils.toRadian((i + angle) * 4)) * 50;
var f:Number = Math.ceil(i / 4);
meshes["Geo"].getVertexById("v:0" + f + 0).z = vz;
meshes["Geo"].getVertexById("v:0" + f + 3).z = vz;
meshes["Geo"].getVertexById("v:0" + f + 2).z = vy;
meshes["Geo"].getVertexById("v:0" + f + 1).z = vy;
}
if (angle > 360) angle = 0;
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 {
import flash.utils.getTimer;
var now:Number = getTimer();
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 PLANE : return buildPlaneFaces(@ox, @oy, @oz, @w, @h, @ws, @hs, @twoSided);
default : return new XMLList();
}
}
function buildPlaneFaces(ox:Number, oy:Number, oz:Number, w:Number, h:Number, ws:Number, hs:Number, twoSided:String ="false"):XMLList {
var gridWidth:Number = w / ws;
var gridHeight:Number = h / hs;
import flash.utils.getTimer;
var now:Number = getTimer();
var aw:Number = ox - w / 2;
var ah:Number = oy - h / 2;
for ( var a:int = 0; a < ws; a++) {
for (var b:int = 0; b < hs; b++) {
var x1:Number = aw + gridWidth * a;
var x2:Number = aw + gridWidth * (a + 1);
var y1:Number = ah + gridHeight * b;
var y2:Number = ah + gridHeight * (b + 1);
_faces.appendChild( <face>
<vertex x={ x2 } y={ y1 } z="0" />
<vertex x={ x2 } y={ y2 } z="0" />
<vertex x={ x1 } y={ y2 } z="0" />
<vertex x={ x1 } y={ y1 } z="0" />
</face>);
if ( twoSided == "true" ) {
_faces.appendChild( <face>
<vertex x={ x1 } y={ y1 } z="0" />
<vertex x={ x1 } y={ y2 } z="0" />
<vertex x={ x2 } y={ y2 } z="0" />
<vertex x={ x2 } y={ y1 } z="0" />
</face>);
}
}
}
return _faces.face;
}
return new XMLList();
}
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 PLANE : return buildPlaneVertices(@ax, @ay, @az, @bx, @by, @bz, @cx, @cy, @cz, @dx, @dy, @dz, @rv);
default : return new XMLList();
}
}
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;
}
/**
* 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} />);
}
}
}