Files
Pyogenics c58621fb99 Add A3D5
2024-09-28 17:29:26 +01:00

861 lines
31 KiB
ActionScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package alternativa.utils {
import alternativa.engine3d.*;
import alternativa.engine3d.core.Face;
import alternativa.engine3d.core.Mesh;
import alternativa.engine3d.core.Surface;
import alternativa.engine3d.core.Vertex;
import alternativa.engine3d.materials.FillMaterial;
import alternativa.engine3d.materials.SurfaceMaterial;
import alternativa.engine3d.materials.TextureMaterial;
import alternativa.engine3d.materials.TextureMaterialPrecision;
import alternativa.engine3d.materials.WireMaterial;
import alternativa.types.*;
import flash.display.BlendMode;
import flash.geom.Point;
use namespace alternativa3d;
use namespace alternativatypes;
/**
* Утилиты для работы с Mesh-объектами.
*/
public class MeshUtils {
static private var verticesSort:Array = ["x", "y", "z"];
static private var verticesSortOptions:Array = [Array.NUMERIC, Array.NUMERIC, Array.NUMERIC];
/**
* Объединение нескольких Mesh-объектов. Объекты, переданные как аргументы метода, не изменяются.
*
* @param meshes объединяемые объекты класса <code>alternativa.engine3d.core.Mesh</code>
*
* @return новый Mesh-объект, содержащий результат объединения переданных Mesh-объектов
*/
static public function uniteMeshes(... meshes):Mesh {
var res:Mesh = new Mesh();
var length:uint = meshes.length;
var key:*;
var vertex:Vertex;
var face:Face;
var j:uint;
for (var i:uint = 0; i < length; i++) {
var mesh:Mesh = meshes[i];
var vertices:Map = mesh._vertices.clone();
for (key in vertices) {
vertex = vertices[key];
vertices[key] = res.createVertex(vertex.x, vertex.y, vertex.z);
}
var faces:Map = mesh._faces.clone();
for (key in faces) {
face = faces[key];
var faceVertices:Array = new Array().concat(face._vertices);
for (j = 0; j < face._verticesCount; j++) {
vertex = faceVertices[j];
faceVertices[j] = vertices[vertex.id];
}
faces[key] = res.createFace(faceVertices);
res.setUVsToFace(face._aUV, face._bUV, face._cUV, faces[key]);
}
for (key in mesh._surfaces) {
var surface:Surface = mesh._surfaces[key];
var surfaceFaces:Array = surface._faces.toArray();
var numFaces:uint = surfaceFaces.length;
for (j = 0; j < numFaces; j++) {
face = surfaceFaces[j];
surfaceFaces[j] = faces[face.id];
}
var newSurface:Surface = res.createSurface(surfaceFaces);
newSurface.material = SurfaceMaterial(surface.material.clone());
}
}
return res;
}
/**
* Слияние вершин Mesh-объекта с одинаковыми координатами. Равенство координат проверяется с учётом погрешности.
*
* @param mesh объект, вершины которого объединяются
* @param threshold погрешность измерения расстояний
*/
static public function autoWeldVertices(mesh:Mesh, threshold:Number = 0):void {
// Получаем список вершин меша и сортируем по координатам
var vertices:Array = mesh._vertices.toArray(true);
vertices.sortOn(verticesSort, verticesSortOptions);
// Поиск вершин с одинаковыми координатами
var weld:Map = new Map(true);
var vertex:Vertex;
var currentVertex:Vertex = vertices[0];
var length:uint = vertices.length;
var i:uint;
for (i = 1; i < length; i++) {
vertex = vertices[i];
if ((currentVertex.x - vertex.x <= threshold) && (currentVertex.x - vertex.x >= -threshold) && (currentVertex.y - vertex.y <= threshold) && (currentVertex.y - vertex.y >= -threshold) && (currentVertex.z - vertex.z <= threshold) && (currentVertex.z - vertex.z >= -threshold)) {
weld[vertex] = currentVertex;
} else {
currentVertex = vertex;
}
}
// Собираем грани объединяемых вершин
var faces:Set = new Set(true);
var keyVertex:*;
var keyFace:*;
for (keyVertex in weld) {
vertex = keyVertex;
for (keyFace in vertex._faces) {
faces[keyFace] = true;
}
}
// Заменяем грани
for (keyFace in faces) {
var face:Face = keyFace;
var id:Object = mesh.getFaceId(face);
var surface:Surface = face._surface;
var aUV:Point = face._aUV;
var bUV:Point = face._bUV;
var cUV:Point = face._cUV;
vertices = new Array().concat(face._vertices);
length = vertices.length;
for (i = 0; i < length; i++) {
vertex = weld[vertices[i]];
if (vertex != null) {
vertices[i] = vertex;
}
}
mesh.removeFace(face);
face = mesh.createFace(vertices, id);
if (surface != null) {
surface.addFace(face);
}
face.aUV = aUV;
face.bUV = bUV;
face.cUV = cUV;
}
// Удаляем вершины
for (keyVertex in weld) {
mesh.removeVertex(keyVertex);
}
}
/**
* Объединение соседних граней, образующих плоский выпуклый многоугольник.
*
* @param mesh объект, грани которого объединяются
* @param angleThreshold погрешность измерения углов
* @param uvThreshold погрешность измерения UV-координат
*/
static public function autoWeldFaces(mesh:Mesh, angleThreshold:Number = 0, uvThreshold:Number = 0):void {
angleThreshold = Math.cos(angleThreshold);
var face:Face;
var sibling:Face;
var key:*;
var i:uint;
// Формируем списки граней
var faces1:Set = new Set(true);
var faces2:Set = new Set(true);
// Формируем список нормалей
var normals:Map = new Map(true);
for each (face in mesh._faces.clone()) {
var faceNormal:Point3D = face.normal;
if (faceNormal.x != 0 || faceNormal.y != 0 || faceNormal.z != 0) {
faces1[face] = true;
normals[face] = faceNormal;
} else {
mesh.removeFace(face);
}
}
// Объединение
do {
// Флаг объединения
var weld:Boolean = false;
// Объединяем грани
while ((face = faces1.take()) != null) {
//var num:uint = face.num;
//var vertices:Array = face.vertices;
var currentWeld:Boolean = false;
// Проверка общих граней по точкам
// Проверка общих граней по рёбрам
// Перебираем точки грани
for (i = 0; (i < face._verticesCount) && !currentWeld; i++) {
var faceIndex1:uint = i;
var faceIndex2:uint;
var siblingIndex1:int;
var siblingIndex2:uint;
// Перебираем грани текущей точки
var vertex:Vertex = face._vertices[faceIndex1];
var vertexFaces:Set = vertex.faces;
for (key in vertexFaces) {
sibling = key;
// Если грань в списке на объединение и в одной поверхности
if (faces1[sibling] && face._surface == sibling._surface) {
faceIndex2 = (faceIndex1 < face._verticesCount - 1) ? (faceIndex1 + 1) : 0;
siblingIndex1 = sibling._vertices.indexOf(face._vertices[faceIndex2]);
// Если общее ребро
if (siblingIndex1 >= 0) {
// Если грани сонаправлены
var normal:Point3D = normals[face];
if (Point3D.dot(normal, normals[sibling]) >= angleThreshold) {
// Если в точках объединения нет перегибов
siblingIndex2 = (siblingIndex1 < sibling._verticesCount - 1) ? (siblingIndex1 + 1) : 0;
// Расширяем грани объединения
var i1:uint;
var i2:uint;
while (true) {
i1 = (faceIndex1 > 0) ? (faceIndex1 - 1) : (face._verticesCount - 1);
i2 = (siblingIndex2 < sibling._verticesCount - 1) ? (siblingIndex2 + 1) : 0;
if (face._vertices[i1] == sibling._vertices[i2]) {
faceIndex1 = i1;
siblingIndex2 = i2;
} else {
break;
}
}
while (true) {
i1 = (faceIndex2 < face._verticesCount - 1) ? (faceIndex2 + 1) : 0;
i2 = (siblingIndex1 > 0) ? (siblingIndex1 - 1) : (sibling._verticesCount - 1);
if (face._vertices[i1] == sibling._vertices[i2]) {
faceIndex2 = i1;
siblingIndex1 = i2;
} else {
break;
}
}
vertex = face._vertices[faceIndex1];
var a:Point3D = vertex.coords;
vertex = face._vertices[faceIndex2];
var b:Point3D = vertex.coords;
// Считаем первый перегиб
vertex = sibling._vertices[(siblingIndex2 < sibling._verticesCount - 1) ? (siblingIndex2 + 1) : 0];
var c:Point3D = vertex.coords;
vertex = face._vertices[(faceIndex1 > 0) ? (faceIndex1 - 1) : (face._verticesCount - 1)];
var d:Point3D = vertex.coords;
var cx:Number = c.x - a.x;
var cy:Number = c.y - a.y;
var cz:Number = c.z - a.z;
var dx:Number = d.x - a.x;
var dy:Number = d.y - a.y;
var dz:Number = d.z - a.z;
var crossX:Number = cy*dz - cz*dy;
var crossY:Number = cz*dx - cx*dz;
var crossZ:Number = cx*dy - cy*dx;
if (crossX == 0 && crossY == 0 && crossZ == 0) {
if (cx*dx + cy*dy + cz*dz > 0) {
break;
}
}
var dot:Number = crossX*normal.x + crossY*normal.y + crossZ*normal.z;
// Если в первой точке перегиба нет
if (dot >= 0) {
// Считаем второй перегиб
vertex = face._vertices[(faceIndex2 < face._verticesCount - 1) ? (faceIndex2 + 1) : 0];
c = vertex.coords;
vertex = sibling._vertices[(siblingIndex1 > 0) ? (siblingIndex1 - 1) : (sibling._verticesCount - 1)];
d = vertex.coords;
cx = c.x - b.x;
cy = c.y - b.y;
cz = c.z - b.z;
dx = d.x - b.x;
dy = d.y - b.y;
dz = d.z - b.z;
crossX = cy*dz - cz*dy;
crossY = cz*dx - cx*dz;
crossZ = cx*dy - cy*dx;
if (crossX == 0 && crossY == 0 && crossZ == 0) {
if (cx*dx + cy*dy + cz*dz > 0) {
break;
}
}
dot = crossX*normal.x + crossY*normal.y + crossZ*normal.z;
// Если во второй точке перегиба нет
if (dot >= 0) {
// Флаг наличия UV у обеих граней
var hasUV:Boolean = (face._aUV != null && face._bUV != null && face._cUV != null && sibling._aUV != null && sibling._bUV != null && sibling._cUV != null);
if (hasUV || (face._aUV == null && face._bUV == null && face._cUV == null && sibling._aUV == null && sibling._bUV == null && sibling._cUV == null)) {
// Если грани имеют UV, проверяем совместимость
if (hasUV) {
vertex = sibling._vertices[0];
var uv:Point = face.getUVFast(vertex.coords, normal);
if ((uv.x - sibling._aUV.x > uvThreshold) || (uv.x - sibling._aUV.x < -uvThreshold) || (uv.y - sibling._aUV.y > uvThreshold) || (uv.y - sibling._aUV.y < -uvThreshold)) {
break;
}
vertex = sibling._vertices[1];
uv = face.getUVFast(vertex.coords, normal);
if ((uv.x - sibling._bUV.x > uvThreshold) || (uv.x - sibling._bUV.x < -uvThreshold) || (uv.y - sibling._bUV.y > uvThreshold) || (uv.y - sibling._bUV.y < -uvThreshold)) {
break;
}
vertex = sibling._vertices[2];
uv = face.getUVFast(vertex.coords, normal);
if ((uv.x - sibling._cUV.x > uvThreshold) || (uv.x - sibling._cUV.x < -uvThreshold) || (uv.y - sibling._cUV.y > uvThreshold) || (uv.y - sibling._cUV.y < -uvThreshold)) {
break;
}
}
// Формируем новую грань
var newVertices:Array = new Array();
var n:uint = faceIndex2;
do {
newVertices.push(face._vertices[n]);
n = (n < face._verticesCount - 1) ? (n + 1) : 0;
} while (n != faceIndex1);
n = siblingIndex2;
do {
newVertices.push(sibling._vertices[n]);
n = (n < sibling._verticesCount - 1) ? (n + 1) : 0;
} while (n != siblingIndex1);
// Выбираем начальную точку
n = getBestBeginVertexIndex(newVertices);
for (var m:uint = 0; m < n; m++) {
newVertices.push(newVertices.shift());
}
// Заменяем грани новой
var surface:Surface = face._surface;
var newFace:Face = mesh.createFace(newVertices);
if (hasUV) {
newFace.aUV = face.getUVFast(newVertices[0].coords, normal);
newFace.bUV = face.getUVFast(newVertices[1].coords, normal);
newFace.cUV = face.getUVFast(newVertices[2].coords, normal);
}
if (surface != null) {
surface.addFace(newFace);
}
mesh.removeFace(face);
mesh.removeFace(sibling);
// Обновляем список нормалей
delete normals[sibling];
delete normals[face];
normals[newFace] = newFace.normal;
// Обновляем списки расчётов
delete faces1[sibling];
faces2[newFace] = true;
// Помечаем объединение
weld = true;
currentWeld = true;
break;
}
}
}
}
}
}
}
}
// Если не удалось объединить, переносим грань
faces2[face] = true;
}
// Меняем списки
var fs:Set = faces1;
faces1 = faces2;
faces2 = fs;
} while (weld);
removeIsolatedVertices(mesh);
removeUselessVertices(mesh);
}
/**
* Удаление вершин объекта, не принадлежащим ни одной грани.
*
* @param mesh объект, вершины которого удаляются
*/
static public function removeIsolatedVertices(mesh:Mesh):void {
for each (var vertex:Vertex in mesh._vertices.clone()) {
if (vertex._faces.isEmpty()) {
mesh.removeVertex(vertex);
}
}
}
/**
* Удаление вершин объекта, которые во всех своих гранях лежат на отрезке между предыдущей и следующей вершиной.
*
* @param mesh объект, вершины которого удаляются
*/
static public function removeUselessVertices(mesh:Mesh):void {
var v:Vertex;
var key:*;
var face:Face;
var index:uint;
var length:uint;
for each (var vertex:Vertex in mesh._vertices.clone()) {
var unless:Boolean = true;
var indexes:Map = new Map(true);
for (key in vertex._faces) {
face = key;
length = face._vertices.length;
index = face._vertices.indexOf(vertex);
v = face._vertices[index];
var a:Point3D = v.coords;
v = face._vertices[(index < length - 1) ? (index + 1) : 0];
var b:Point3D = v.coords;
v = face._vertices[(index > 0) ? (index - 1) : (length - 1)];
var c:Point3D = v.coords;
var abx:Number = b.x - a.x;
var aby:Number = b.y - a.y;
var abz:Number = b.z - a.z;
var acx:Number = c.x - a.x;
var acy:Number = c.y - a.y;
var acz:Number = c.z - a.z;
if (aby*acz - abz*acy == 0 && abz*acx - abx*acz == 0 && abx*acy - aby*acx == 0) {
indexes[face] = index;
} else {
unless = false;
break;
}
}
if (unless && !indexes.isEmpty()) {
// Удаляем
for (key in indexes) {
var i:uint;
face = key;
index = indexes[face];
length = face._vertices.length;
var newVertices:Array = new Array();
for (i = 0; i < length; i++) {
if (i != index) {
newVertices.push(face._vertices[i]);
}
}
var n:uint = getBestBeginVertexIndex(newVertices);
for (i = 0; i < n; i++) {
newVertices.push(newVertices.shift());
}
var surface:Surface = face._surface;
var newFace:Face = mesh.createFace(newVertices);
if (face._aUV != null && face._bUV != null && face._cUV != null) {
var normal:Point3D = face.normal;
newFace.aUV = face.getUVFast(newVertices[0].coords, normal);
newFace.bUV = face.getUVFast(newVertices[1].coords, normal);
newFace.cUV = face.getUVFast(newVertices[2].coords, normal);
}
if (surface != null) {
surface.addFace(newFace);
}
mesh.removeFace(face);
}
mesh.removeVertex(vertex);
}
}
}
/**
* Удаление вырожденных граней.
*
* @param mesh объект, грани которого удаляются
*/
static public function removeSingularFaces(mesh:Mesh):void {
for each (var face:Face in mesh._faces.clone()) {
var normal:Point3D = face.normal;
if (normal.x == 0 && normal.y == 0 && normal.z == 0) {
mesh.removeFace(face);
}
}
}
/**
* @private
* Находит наиболее подходящую первую точку.
* @param vertices
* @return
*/
static public function getBestBeginVertexIndex(vertices:Array):uint {
var bestIndex:uint = 0;
var num:uint = vertices.length;
if (num > 3) {
var maxCrossLength:Number = 0;
var v:Vertex = vertices[num - 1];
var c1:Point3D = v.coords;
v = vertices[0];
var c2:Point3D = v.coords;
var prevX:Number = c2.x - c1.x;
var prevY:Number = c2.y - c1.y;
var prevZ:Number = c2.z - c1.z;
for (var i:uint = 0; i < num; i++) {
c1 = c2;
v = vertices[(i < num - 1) ? (i + 1) : 0];
c2 = v.coords;
var nextX:Number = c2.x - c1.x;
var nextY:Number = c2.y - c1.y;
var nextZ:Number = c2.z - c1.z;
var crossX:Number = prevY*nextZ - prevZ*nextY;
var crossY:Number = prevZ*nextX - prevX*nextZ;
var crossZ:Number = prevX*nextY - prevY*nextX;
var crossLength:Number = crossX*crossX + crossY*crossY + crossZ*crossZ;
if (crossLength > maxCrossLength) {
maxCrossLength = crossLength;
bestIndex = i;
}
prevX = nextX;
prevY = nextY;
prevZ = nextZ;
}
// Берём предыдущий
bestIndex = (bestIndex > 0) ? (bestIndex - 1) : (num - 1);
}
return bestIndex;
}
/**
* Генерация AS-класса.
*
* @param mesh объект, на базе которого генерируется класс
* @param packageName имя пакета для генерируемого класса
* @return AS-класс в текстовом виде
*/
static public function generateClass(mesh:Mesh, packageName:String = ""):String {
var className:String = mesh._name.charAt(0).toUpperCase() + mesh._name.substr(1);
var header:String = "package" + ((packageName != "") ? (" " + packageName + " ") : " ") + "{\r\r";
var importSet:Object = new Object();
importSet["alternativa.engine3d.core.Mesh"] = true;
var materialSet:Map = new Map(true);
var materialName:String;
var materialNum:uint = 1;
var footer:String = "\t\t}\r\t}\r}";
var classHeader:String = "\tpublic class "+ className + " extends Mesh {\r\r";
var constructor:String = "\t\tpublic function " + className + "() {\r";
constructor += "\t\t\tsuper(\"" + mesh._name +"\");\r\r";
var newLine:Boolean = false;
if (mesh.mobility != 0) {
constructor += "\t\t\tmobility = " + mesh.mobility +";\r";
newLine = true;
}
if (mesh.x != 0 && mesh.y != 0 && mesh.z != 0) {
importSet["alternativa.types.Point3D"] = true;
constructor += "\t\t\tcoords = new Point3D(" + mesh.x + ", " + mesh.y + ", " + mesh.z +");\r";
newLine = true;
} else {
if (mesh.x != 0) {
constructor += "\t\t\tx = " + mesh.x + ";\r";
newLine = true;
}
if (mesh.y != 0) {
constructor += "\t\t\ty = " + mesh.y + ";\r";
newLine = true;
}
if (mesh.z != 0) {
constructor += "\t\t\tz = " + mesh.z + ";\r";
newLine = true;
}
}
if (mesh.rotationX != 0) {
constructor += "\t\t\trotationX = " + mesh.rotationX + ";\r";
newLine = true;
}
if (mesh.rotationY != 0) {
constructor += "\t\t\trotationY = " + mesh.rotationY + ";\r";
newLine = true;
}
if (mesh.rotationZ != 0) {
constructor += "\t\t\trotationZ = " + mesh.rotationZ + ";\r";
newLine = true;
}
if (mesh.scaleX != 1) {
constructor += "\t\t\tscaleX = " + mesh.scaleX + ";\r";
newLine = true;
}
if (mesh.scaleY != 1) {
constructor += "\t\t\tscaleY = " + mesh.scaleY + ";\r";
newLine = true;
}
if (mesh.scaleZ != 1) {
constructor += "\t\t\tscaleZ = " + mesh.scaleZ + ";\r";
newLine = true;
}
constructor += newLine ? "\r" : "";
function idToString(value:*):String {
return isNaN(value) ? ("\"" + value + "\"") : value;
}
function blendModeToString(value:String):String {
switch (value) {
case BlendMode.ADD: return "BlendMode.ADD";
case BlendMode.ALPHA: return "BlendMode.ALPHA";
case BlendMode.DARKEN: return "BlendMode.DARKEN";
case BlendMode.DIFFERENCE: return "BlendMode.DIFFERENCE";
case BlendMode.ERASE: return "BlendMode.ERASE";
case BlendMode.HARDLIGHT: return "BlendMode.HARDLIGHT";
case BlendMode.INVERT: return "BlendMode.INVERT";
case BlendMode.LAYER: return "BlendMode.LAYER";
case BlendMode.LIGHTEN: return "BlendMode.LIGHTEN";
case BlendMode.MULTIPLY: return "BlendMode.MULTIPLY";
case BlendMode.NORMAL: return "BlendMode.NORMAL";
case BlendMode.OVERLAY: return "BlendMode.OVERLAY";
case BlendMode.SCREEN: return "BlendMode.SCREEN";
case BlendMode.SUBTRACT: return "BlendMode.SUBTRACT";
default: return "BlendMode.NORMAL";
}
}
function colorToString(value:uint):String {
var hex:String = value.toString(16).toUpperCase();
var res:String = "0x";
var len:uint = 6 - hex.length;
for (var j:uint = 0; j < len; j++) {
res += "0";
}
res += hex;
return res;
}
var i:uint;
var length:uint;
var key:*;
var id:String;
var face:Face;
var surface:Surface;
newLine = false;
for (id in mesh._vertices) {
var vertex:Vertex = mesh._vertices[id];
var coords:Point3D = vertex.coords;
constructor += "\t\t\tcreateVertex(" + coords.x + ", " + coords.y + ", " + coords.z + ", " + idToString(id) + ");\r";
newLine = true;
}
constructor += newLine ? "\r" : "";
newLine = false;
for (id in mesh._faces) {
face = mesh._faces[id];
length = face._verticesCount;
constructor += "\t\t\tcreateFace(["
for (i = 0; i < length - 1; i++) {
constructor += idToString(mesh.getVertexId(face._vertices[i])) + ", ";
}
constructor += idToString(mesh.getVertexId(face._vertices[i])) + "], " + idToString(id) + ");\r";
if (face._aUV != null || face._bUV != null || face._cUV != null) {
importSet["flash.geom.Point"] = true;
constructor += "\t\t\tsetUVsToFace(new Point(" + face._aUV.x + ", " + face._aUV.y + "), new Point(" + face._bUV.x + ", " + face._bUV.y + "), new Point(" + face._cUV.x + ", " + face._cUV.y + "), " + idToString(id) + ");\r";
}
newLine = true;
}
constructor += newLine ? "\r" : "";
for (id in mesh._surfaces) {
surface = mesh._surfaces[id];
var facesStr:String = "";
for (key in surface._faces) {
facesStr += idToString(mesh.getFaceId(key)) + ", ";
}
constructor += "\t\t\tcreateSurface([" + facesStr.substr(0, facesStr.length - 2) + "], " + idToString(id) + ");\r";
if (surface.material != null) {
var material:String;
var defaultAlpha:Boolean = surface.material.alpha == 1;
var defaultBlendMode:Boolean = surface.material.blendMode == BlendMode.NORMAL;
if (surface.material is WireMaterial) {
importSet["alternativa.engine3d.materials.WireMaterial"] = true;
var defaultThickness:Boolean = WireMaterial(surface.material).thickness == 0;
var defaultColor:Boolean = WireMaterial(surface.material).color == 0;
material = "new WireMaterial(";
if (!defaultThickness || !defaultColor || !defaultAlpha || !defaultBlendMode) {
material += WireMaterial(surface.material).thickness;
if (!defaultColor || !defaultAlpha || !defaultBlendMode) {
material += ", " + colorToString(WireMaterial(surface.material).color);
if (!defaultAlpha || !defaultBlendMode) {
material += ", " + surface.material.alpha ;
if (!defaultBlendMode) {
importSet["flash.display.BlendMode"] = true;
material += ", " + blendModeToString(surface.material.blendMode);
}
}
}
}
}
var defaultWireThickness:Boolean;
var defaultWireColor:Boolean;
if (surface.material is FillMaterial) {
importSet["alternativa.engine3d.materials.FillMaterial"] = true;
defaultWireThickness = FillMaterial(surface.material).wireThickness < 0;
defaultWireColor = FillMaterial(surface.material).wireColor == 0;
material = "new FillMaterial(" + colorToString(FillMaterial(surface.material).color);
if (!defaultAlpha || !defaultBlendMode || !defaultWireThickness || !defaultWireColor) {
material += ", " + surface.material.alpha;
if (!defaultBlendMode || !defaultWireThickness || !defaultWireColor) {
importSet["flash.display.BlendMode"] = true;
material += ", " + blendModeToString(surface.material.blendMode);
if (!defaultWireThickness || !defaultWireColor) {
material += ", " + FillMaterial(surface.material).wireThickness;
if (!defaultWireColor) {
material += ", " + colorToString(FillMaterial(surface.material).wireColor);
}
}
}
}
}
if (surface.material is TextureMaterial) {
importSet["alternativa.engine3d.materials.TextureMaterial"] = true;
var defaultRepeat:Boolean = TextureMaterial(surface.material).repeat;
var defaultSmooth:Boolean = !TextureMaterial(surface.material).smooth;
defaultWireThickness = TextureMaterial(surface.material).wireThickness < 0;
defaultWireColor = TextureMaterial(surface.material).wireColor == 0;
var defaultPrecision:Boolean = TextureMaterial(surface.material).precision == TextureMaterialPrecision.MEDIUM;
if (TextureMaterial(surface.material).texture == null) {
materialName = "null";
} else {
importSet["alternativa.types.Texture"] = true;
if (materialSet[TextureMaterial(surface.material).texture] == undefined) {
materialName = (TextureMaterial(surface.material).texture._name != null) ? TextureMaterial(surface.material).texture._name : "texture" + materialNum++;
materialSet[TextureMaterial(surface.material).texture] = materialName;
} else {
materialName = materialSet[TextureMaterial(surface.material).texture];
}
materialName = materialName.split(".")[0];
}
material = "new TextureMaterial(" + materialName;
if (!defaultAlpha || !defaultRepeat || !defaultSmooth || !defaultBlendMode || !defaultWireThickness || !defaultWireColor || !defaultPrecision) {
material += ", " + TextureMaterial(surface.material).alpha;
if (!defaultRepeat || !defaultSmooth || !defaultBlendMode || !defaultWireThickness || !defaultWireColor || !defaultPrecision) {
material += ", " + TextureMaterial(surface.material).repeat;
if (!defaultSmooth || !defaultBlendMode || !defaultWireThickness || !defaultWireColor || !defaultPrecision) {
material += ", " + TextureMaterial(surface.material).smooth;
if (!defaultBlendMode || !defaultWireThickness || !defaultWireColor || !defaultPrecision) {
importSet["flash.display.BlendMode"] = true;
material += ", " + blendModeToString(surface.material.blendMode);
if (!defaultWireThickness || !defaultWireColor || !defaultPrecision) {
material += ", " + TextureMaterial(surface.material).wireThickness;
if (!defaultWireColor || !defaultPrecision) {
material += ", " + colorToString(TextureMaterial(surface.material).wireColor);
if (!defaultPrecision) {
material += ", " + TextureMaterial(surface.material).precision;
}
}
}
}
}
}
}
}
constructor += "\t\t\tsetMaterialToSurface(" + material + "), " + idToString(id) + ");\r";
}
}
var imports:String = "";
newLine = false;
var importArray:Array = new Array();
for (key in importSet) {
importArray.push(key);
}
importArray.sort();
length = importArray.length;
for (i = 0; i < length; i++) {
var pack:String = importArray[i];
var current:String = pack.substr(0, pack.indexOf("."));
imports += (current != prev && prev != null) ? "\r" : "";
imports += "\timport " + pack + ";\r";
var prev:String = current;
newLine = true;
}
imports += newLine ? "\r" : "";
var embeds:String = "";
newLine = false;
for each (materialName in materialSet) {
var materialClassName:String = materialName.split(".")[0];
var materialBmpName:String = materialClassName.charAt(0).toUpperCase() + materialClassName.substr(1);
embeds += "\t\t[Embed(source=\"" + materialName + "\")] private static const bmp" + materialBmpName + ":Class;\r";
embeds += "\t\tprivate static const " + materialClassName + ":Texture = new Texture(new bmp" + materialBmpName + "().bitmapData, \"" + materialName + "\");\r";
newLine = true;
}
embeds += newLine ? "\r" : "";
return header + imports + classHeader + embeds + constructor + footer;
}
// /**
// * @private
// * Убирает лишние точки на ребрах и добавляет точки в месте распилов на соседних гранях
// *
// * @param object объект
// * @param recursive если установлена в <code>true</code>, метод будет вызываться рекурсивно на потомках потомков потомков объекта тоже.
// *
// * @return количество добавленных точек с вычетом убранных
// */
// p function fixGaps(object:Object3D, recursive:Boolean = false):int {
// var result:int = 0;
// if (object is Mesh) {
// var mesh:Mesh = Mesh(object);
// var faces:Map = mesh._faces;
// for each (var face:Face in faces) {
// //face.
// }
// }
// if (recursive) {
// var children:Set = object._children;
// for (var child:* in children) {
// result += fixGaps(child, true);
// }
// }
// return result;
// }
}
}