|
|
|
@ -1,25 +1,29 @@
|
|
|
|
|
import { BufferGeometry, Face3, Geometry, Material, Matrix4, Mesh, Vector2, Vector3 } from "three";
|
|
|
|
|
|
|
|
|
|
const EPSILON = 1e-5,
|
|
|
|
|
COPLANAR = 0, //共面
|
|
|
|
|
FRONT = 1, //前
|
|
|
|
|
BACK = 2,
|
|
|
|
|
SPANNING = 3;
|
|
|
|
|
//ref: https://github.com/chandlerprall/ThreeCSG/blob/master/threeCSG.es6
|
|
|
|
|
|
|
|
|
|
export default class ThreeBSP
|
|
|
|
|
|
|
|
|
|
const EPSILON = 1e-5;
|
|
|
|
|
|
|
|
|
|
enum Side
|
|
|
|
|
{
|
|
|
|
|
Coplanar = 0,
|
|
|
|
|
Front = 1,
|
|
|
|
|
Back = 2,
|
|
|
|
|
Spanning = 3
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class CSG
|
|
|
|
|
{
|
|
|
|
|
tree: Node;
|
|
|
|
|
matrix: Matrix4;
|
|
|
|
|
Node: Node;
|
|
|
|
|
Vertex: Vertex[];
|
|
|
|
|
Polygon: Polygon[] = [];
|
|
|
|
|
constructor(obj: Geometry | Mesh | Node)
|
|
|
|
|
constructor(obj: Geometry | Mesh | Node, matrix?: Matrix4)
|
|
|
|
|
{
|
|
|
|
|
let geometry: Geometry;
|
|
|
|
|
if (obj instanceof Geometry)
|
|
|
|
|
{
|
|
|
|
|
geometry = obj;
|
|
|
|
|
this.matrix = new Matrix4();
|
|
|
|
|
this.matrix = matrix || new Matrix4();
|
|
|
|
|
}
|
|
|
|
|
else if (obj instanceof Mesh)
|
|
|
|
|
{
|
|
|
|
@ -34,15 +38,16 @@ export default class ThreeBSP
|
|
|
|
|
else if (obj instanceof Node)
|
|
|
|
|
{
|
|
|
|
|
this.tree = obj;
|
|
|
|
|
this.matrix = new Matrix4();
|
|
|
|
|
this.matrix = matrix || new Matrix4();
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw 'ThreeBSP: Given geometry is unsupported';
|
|
|
|
|
throw '未支持的类型';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let polgons: Polygon[] = [];
|
|
|
|
|
for (let i = 0; i < geometry.faces.length; i++)
|
|
|
|
|
{
|
|
|
|
|
let face = geometry.faces[i];
|
|
|
|
@ -51,33 +56,30 @@ export default class ThreeBSP
|
|
|
|
|
|
|
|
|
|
if (face instanceof Face3)
|
|
|
|
|
{
|
|
|
|
|
let vertex = geometry.vertices[face.a];
|
|
|
|
|
let uvs = faceVertexUvs ? new Vector2(faceVertexUvs[0].x, faceVertexUvs[0].y) : null;
|
|
|
|
|
let vertex1 = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0], uvs);
|
|
|
|
|
let uvs = faceVertexUvs ? faceVertexUvs[0].clone() : null;
|
|
|
|
|
let vertex1 = new Vertex(geometry.vertices[face.a], face.vertexNormals[0], uvs);
|
|
|
|
|
vertex1.applyMatrix4(this.matrix);
|
|
|
|
|
polygon.vertices.push(vertex1);
|
|
|
|
|
|
|
|
|
|
vertex = geometry.vertices[face.b];
|
|
|
|
|
uvs = faceVertexUvs ? new Vector2(faceVertexUvs[1].x, faceVertexUvs[1].y) : null;
|
|
|
|
|
let vertex2 = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[1], uvs);
|
|
|
|
|
uvs = faceVertexUvs ? faceVertexUvs[1].clone() : null;
|
|
|
|
|
let vertex2 = new Vertex(geometry.vertices[face.b], face.vertexNormals[1], uvs);
|
|
|
|
|
vertex2.applyMatrix4(this.matrix);
|
|
|
|
|
polygon.vertices.push(vertex2);
|
|
|
|
|
|
|
|
|
|
vertex = geometry.vertices[face.c];
|
|
|
|
|
uvs = faceVertexUvs ? new Vector2(faceVertexUvs[2].x, faceVertexUvs[2].y) : null;
|
|
|
|
|
let vertex3 = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[2], uvs);
|
|
|
|
|
uvs = faceVertexUvs ? faceVertexUvs[2].clone() : null;
|
|
|
|
|
let vertex3 = new Vertex(geometry.vertices[face.c], face.vertexNormals[2], uvs);
|
|
|
|
|
vertex3.applyMatrix4(this.matrix);
|
|
|
|
|
polygon.vertices.push(vertex3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
polygon.calculateProperties();
|
|
|
|
|
this.Polygon.push(polygon);
|
|
|
|
|
polgons.push(polygon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.tree = new Node(this.Polygon);
|
|
|
|
|
this.tree = new Node(polgons);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subtract(other_tree: ThreeBSP)
|
|
|
|
|
subtract(other_tree: CSG)
|
|
|
|
|
{
|
|
|
|
|
let a = this.tree.clone(),
|
|
|
|
|
b = other_tree.tree.clone();
|
|
|
|
@ -90,12 +92,10 @@ export default class ThreeBSP
|
|
|
|
|
b.invert();
|
|
|
|
|
a.build(b.allPolygons());
|
|
|
|
|
a.invert();
|
|
|
|
|
let bsp = new ThreeBSP(a);
|
|
|
|
|
bsp.matrix = this.matrix;
|
|
|
|
|
return bsp;
|
|
|
|
|
return new CSG(a, this.matrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
union(other_tree: ThreeBSP)
|
|
|
|
|
union(other_tree: CSG)
|
|
|
|
|
{
|
|
|
|
|
let a = this.tree.clone(),
|
|
|
|
|
b = other_tree.tree.clone();
|
|
|
|
@ -106,12 +106,10 @@ export default class ThreeBSP
|
|
|
|
|
b.clipTo(a);
|
|
|
|
|
b.invert();
|
|
|
|
|
a.build(b.allPolygons());
|
|
|
|
|
let bsp = new ThreeBSP(a);
|
|
|
|
|
bsp.matrix = this.matrix;
|
|
|
|
|
return bsp;
|
|
|
|
|
return new CSG(a, this.matrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intersect(other_tree: ThreeBSP)
|
|
|
|
|
intersect(other_tree: CSG)
|
|
|
|
|
{
|
|
|
|
|
let a = this.tree.clone(),
|
|
|
|
|
b = other_tree.tree.clone();
|
|
|
|
@ -123,15 +121,12 @@ export default class ThreeBSP
|
|
|
|
|
b.clipTo(a);
|
|
|
|
|
a.build(b.allPolygons());
|
|
|
|
|
a.invert();
|
|
|
|
|
let bsp = new ThreeBSP(a);
|
|
|
|
|
bsp.matrix = this.matrix;
|
|
|
|
|
return bsp;
|
|
|
|
|
return new CSG(a, this.matrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
toGeometry()
|
|
|
|
|
{
|
|
|
|
|
let
|
|
|
|
|
matrix = new Matrix4().getInverse(this.matrix),
|
|
|
|
|
let matrix = new Matrix4().getInverse(this.matrix),
|
|
|
|
|
geometry = new Geometry(),
|
|
|
|
|
polygons = this.tree.allPolygons(),
|
|
|
|
|
polygon_count = polygons.length,
|
|
|
|
@ -215,25 +210,13 @@ export default class ThreeBSP
|
|
|
|
|
|
|
|
|
|
export class Polygon
|
|
|
|
|
{
|
|
|
|
|
w: number;
|
|
|
|
|
normal: Vertex;
|
|
|
|
|
vertices: Vertex[]
|
|
|
|
|
constructor(vertices?: Vertex[], normal?: Vertex, w?: number)
|
|
|
|
|
constructor(
|
|
|
|
|
public vertices: Vertex[] = [],
|
|
|
|
|
public normal?: Vector3,
|
|
|
|
|
public w?: number)
|
|
|
|
|
{
|
|
|
|
|
if (!(vertices instanceof Array))
|
|
|
|
|
{
|
|
|
|
|
vertices = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.vertices = vertices;
|
|
|
|
|
if (vertices.length > 0)
|
|
|
|
|
{
|
|
|
|
|
if (vertices.length > 0 && !normal)
|
|
|
|
|
this.calculateProperties();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.normal = this.w = undefined;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
calculateProperties()
|
|
|
|
@ -242,62 +225,51 @@ export class Polygon
|
|
|
|
|
b = this.vertices[1],
|
|
|
|
|
c = this.vertices[2];
|
|
|
|
|
|
|
|
|
|
this.normal = b.clone().subtract(a).cross(
|
|
|
|
|
c.clone().subtract(a)
|
|
|
|
|
).normalize();
|
|
|
|
|
this.normal = b.clone().sub(a)
|
|
|
|
|
.cross(c.clone().sub(a))
|
|
|
|
|
.normalize();
|
|
|
|
|
|
|
|
|
|
this.w = this.normal.clone().dot(a);
|
|
|
|
|
this.w = this.normal.dot(a);
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clone()
|
|
|
|
|
{
|
|
|
|
|
let polygon = new Polygon();
|
|
|
|
|
for (let i = 0, vertice_count = this.vertices.length; i < vertice_count; i++)
|
|
|
|
|
{
|
|
|
|
|
polygon.vertices.push(this.vertices[i].clone());
|
|
|
|
|
}
|
|
|
|
|
polygon.calculateProperties();
|
|
|
|
|
|
|
|
|
|
return polygon;
|
|
|
|
|
return new Polygon(
|
|
|
|
|
this.vertices.map(v => v.clone()),
|
|
|
|
|
this.normal.clone(),
|
|
|
|
|
this.w
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flip()
|
|
|
|
|
{
|
|
|
|
|
let vertices = [];
|
|
|
|
|
|
|
|
|
|
this.normal.multiplyScalar(-1);
|
|
|
|
|
this.w *= -1;
|
|
|
|
|
|
|
|
|
|
for (let i = this.vertices.length - 1; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
vertices.push(this.vertices[i]);
|
|
|
|
|
}
|
|
|
|
|
this.vertices = vertices;
|
|
|
|
|
|
|
|
|
|
this.vertices.reverse();
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//划分?
|
|
|
|
|
classifyVertex(vertex: Vector3 | Vertex)
|
|
|
|
|
classifyVertex(vertex: Vector3 | Vertex): Side
|
|
|
|
|
{
|
|
|
|
|
let side_value = this.normal.dot(vertex) - this.w;
|
|
|
|
|
|
|
|
|
|
if (side_value < -EPSILON)
|
|
|
|
|
{
|
|
|
|
|
return BACK;
|
|
|
|
|
} else if (side_value > EPSILON)
|
|
|
|
|
return Side.Back;
|
|
|
|
|
}
|
|
|
|
|
else if (side_value > EPSILON)
|
|
|
|
|
{
|
|
|
|
|
return FRONT;
|
|
|
|
|
} else
|
|
|
|
|
return Side.Front;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return COPLANAR;
|
|
|
|
|
return Side.Coplanar;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//划分边?
|
|
|
|
|
classifySide(polygon: Polygon)
|
|
|
|
|
classifySide(polygon: Polygon): Side
|
|
|
|
|
{
|
|
|
|
|
let num_positive = 0,
|
|
|
|
|
num_negative = 0,
|
|
|
|
@ -307,36 +279,35 @@ export class Polygon
|
|
|
|
|
{
|
|
|
|
|
let vertex = polygon.vertices[i];
|
|
|
|
|
let classification = this.classifyVertex(vertex);
|
|
|
|
|
if (classification === FRONT)
|
|
|
|
|
if (classification === Side.Front)
|
|
|
|
|
num_positive++;
|
|
|
|
|
else if (classification === BACK)
|
|
|
|
|
else if (classification === Side.Back)
|
|
|
|
|
num_negative++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (num_positive > 0 && num_negative === 0)
|
|
|
|
|
return FRONT;
|
|
|
|
|
return Side.Front;
|
|
|
|
|
else if (num_positive === 0 && num_negative > 0)
|
|
|
|
|
return BACK;
|
|
|
|
|
return Side.Back;
|
|
|
|
|
else if (num_positive === 0 && num_negative === 0)
|
|
|
|
|
return COPLANAR;
|
|
|
|
|
return Side.Coplanar;
|
|
|
|
|
else
|
|
|
|
|
return SPANNING;
|
|
|
|
|
return Side.Spanning;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//分解 分离 区域?
|
|
|
|
|
splitPolygon(polygon: Polygon, coplanar_front: Polygon[], coplanar_back: Polygon[], front: Polygon[], back: Polygon[])
|
|
|
|
|
{
|
|
|
|
|
let classification = this.classifySide(polygon);
|
|
|
|
|
|
|
|
|
|
if (classification === COPLANAR)
|
|
|
|
|
if (classification === Side.Coplanar)
|
|
|
|
|
{
|
|
|
|
|
(this.normal.dot(polygon.normal) > 0 ? coplanar_front : coplanar_back).push(polygon);
|
|
|
|
|
}
|
|
|
|
|
else if (classification === FRONT)
|
|
|
|
|
else if (classification === Side.Front)
|
|
|
|
|
{
|
|
|
|
|
front.push(polygon);
|
|
|
|
|
}
|
|
|
|
|
else if (classification === BACK)
|
|
|
|
|
else if (classification === Side.Back)
|
|
|
|
|
{
|
|
|
|
|
back.push(polygon);
|
|
|
|
|
}
|
|
|
|
@ -353,12 +324,12 @@ export class Polygon
|
|
|
|
|
let ti = this.classifyVertex(vi);
|
|
|
|
|
let tj = this.classifyVertex(vj);
|
|
|
|
|
|
|
|
|
|
if (ti != BACK) f.push(vi);
|
|
|
|
|
if (ti != FRONT) b.push(vi);
|
|
|
|
|
if ((ti | tj) === SPANNING)
|
|
|
|
|
if (ti != Side.Back) f.push(vi);
|
|
|
|
|
if (ti != Side.Front) b.push(vi);
|
|
|
|
|
if ((ti | tj) === Side.Spanning)
|
|
|
|
|
{
|
|
|
|
|
let t = (this.w - this.normal.dot(vi)) / this.normal.dot(vj.clone().subtract(vi));
|
|
|
|
|
let v = vi.interpolate(vj, t);
|
|
|
|
|
let t = (this.w - this.normal.dot(vi)) / this.normal.dot(vj.clone().sub(vi));
|
|
|
|
|
let v = vi.clone().lerp(vj, t);
|
|
|
|
|
f.push(v);
|
|
|
|
|
b.push(v);
|
|
|
|
|
}
|
|
|
|
@ -370,139 +341,43 @@ export class Polygon
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type v3 = Vector3 | Vertex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Vertex
|
|
|
|
|
class Vertex extends Vector3
|
|
|
|
|
{
|
|
|
|
|
uv: Vector2;
|
|
|
|
|
normal: Vector3;
|
|
|
|
|
z: number;
|
|
|
|
|
y: number;
|
|
|
|
|
x: number;
|
|
|
|
|
constructor(x: number, y: number, z: number, normal: Vector3, uv: Vector2)
|
|
|
|
|
{
|
|
|
|
|
this.x = x;
|
|
|
|
|
this.y = y;
|
|
|
|
|
this.z = z;
|
|
|
|
|
this.normal = normal || new Vector3();
|
|
|
|
|
this.uv = uv || new Vector2();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clone()
|
|
|
|
|
constructor(
|
|
|
|
|
pos: Vector3,
|
|
|
|
|
public normal = new Vector3(),
|
|
|
|
|
public uv = new Vector2())
|
|
|
|
|
{
|
|
|
|
|
return new Vertex(this.x, this.y, this.z, this.normal.clone(), this.uv.clone());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add(vertex: v3)
|
|
|
|
|
{
|
|
|
|
|
this.x += vertex.x;
|
|
|
|
|
this.y += vertex.y;
|
|
|
|
|
this.z += vertex.z;
|
|
|
|
|
return this;
|
|
|
|
|
super(pos.x, pos.y, pos.z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subtract(vertex: v3)
|
|
|
|
|
clone(): Vertex
|
|
|
|
|
{
|
|
|
|
|
this.x -= vertex.x;
|
|
|
|
|
this.y -= vertex.y;
|
|
|
|
|
this.z -= vertex.z;
|
|
|
|
|
return this;
|
|
|
|
|
return new Vertex(this, this.normal.clone(), this.uv.clone());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
multiplyScalar(scalar)
|
|
|
|
|
lerp(v: Vertex, alpha: number)
|
|
|
|
|
{
|
|
|
|
|
this.x *= scalar;
|
|
|
|
|
this.y *= scalar;
|
|
|
|
|
this.z *= scalar;
|
|
|
|
|
super.lerp(v, alpha);
|
|
|
|
|
this.normal.lerp(v.normal, alpha);
|
|
|
|
|
this.uv.lerp(v.uv, alpha);
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//×乘
|
|
|
|
|
cross(vertex: v3)
|
|
|
|
|
{
|
|
|
|
|
let x = this.x,
|
|
|
|
|
y = this.y,
|
|
|
|
|
z = this.z;
|
|
|
|
|
|
|
|
|
|
this.x = y * vertex.z - z * vertex.y;
|
|
|
|
|
this.y = z * vertex.x - x * vertex.z;
|
|
|
|
|
this.z = x * vertex.y - y * vertex.x;
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
normalize()
|
|
|
|
|
{
|
|
|
|
|
let length = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
|
|
|
|
|
|
|
|
|
|
this.x /= length;
|
|
|
|
|
this.y /= length;
|
|
|
|
|
this.z /= length;
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//点乘
|
|
|
|
|
dot(vertex: v3)
|
|
|
|
|
{
|
|
|
|
|
return this.x * vertex.x + this.y * vertex.y + this.z * vertex.z;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//线性插值
|
|
|
|
|
lerp(a, t)
|
|
|
|
|
{
|
|
|
|
|
this.add(
|
|
|
|
|
a.clone().subtract(this).multiplyScalar(t)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this.normal.add(
|
|
|
|
|
a.normal.clone().sub(this.normal).multiplyScalar(t)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this.uv.add(
|
|
|
|
|
a.uv.clone().sub(this.uv).multiplyScalar(t)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//插值
|
|
|
|
|
interpolate(other, t)
|
|
|
|
|
{
|
|
|
|
|
return this.clone().lerp(other, t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyMatrix4(m)
|
|
|
|
|
{
|
|
|
|
|
// input: Matrix4 affine matrix
|
|
|
|
|
let x = this.x, y = this.y, z = this.z;
|
|
|
|
|
|
|
|
|
|
let e = m.elements;
|
|
|
|
|
|
|
|
|
|
this.x = e[0] * x + e[4] * y + e[8] * z + e[12];
|
|
|
|
|
this.y = e[1] * x + e[5] * y + e[9] * z + e[13];
|
|
|
|
|
this.z = e[2] * x + e[6] * y + e[10] * z + e[14];
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Node
|
|
|
|
|
{
|
|
|
|
|
divider: Polygon;
|
|
|
|
|
back: Node;
|
|
|
|
|
front: Node;
|
|
|
|
|
polygons: Polygon[];
|
|
|
|
|
constructor(polygons?: Polygon[])
|
|
|
|
|
constructor(public polygons: Polygon[] = [])
|
|
|
|
|
{
|
|
|
|
|
let front = [],
|
|
|
|
|
back = [];
|
|
|
|
|
let front: Polygon[] = [],
|
|
|
|
|
back: Polygon[] = [];
|
|
|
|
|
|
|
|
|
|
this.polygons = [];
|
|
|
|
|
this.front = this.back = undefined;
|
|
|
|
|
|
|
|
|
|
if (!(polygons instanceof Array) || polygons.length === 0) return;
|
|
|
|
|
if (polygons.length === 0) return;
|
|
|
|
|
|
|
|
|
|
this.divider = polygons[0].clone();
|
|
|
|
|
|
|
|
|
@ -528,7 +403,7 @@ class Node
|
|
|
|
|
{
|
|
|
|
|
for (let j = 0; j < polygons.length; j++)
|
|
|
|
|
{
|
|
|
|
|
if (i !== j && polygons[i].classifySide(polygons[j]) !== BACK)
|
|
|
|
|
if (i !== j && polygons[i].classifySide(polygons[j]) !== Side.Back)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -539,8 +414,8 @@ class Node
|
|
|
|
|
|
|
|
|
|
build(polygons: Polygon[])
|
|
|
|
|
{
|
|
|
|
|
let front = [],
|
|
|
|
|
back = [];
|
|
|
|
|
let front: Polygon[] = [],
|
|
|
|
|
back: Polygon[] = [];
|
|
|
|
|
|
|
|
|
|
if (!this.divider)
|
|
|
|
|
{
|
|
|
|
@ -578,23 +453,17 @@ class Node
|
|
|
|
|
let node = new Node();
|
|
|
|
|
|
|
|
|
|
node.divider = this.divider.clone();
|
|
|
|
|
node.polygons = this.polygons.map(function (polygon)
|
|
|
|
|
{
|
|
|
|
|
return polygon.clone();
|
|
|
|
|
});
|
|
|
|
|
node.polygons = this.polygons.map(p => p.clone());
|
|
|
|
|
node.front = this.front && this.front.clone();
|
|
|
|
|
node.back = this.back && this.back.clone();
|
|
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//反转
|
|
|
|
|
invert()
|
|
|
|
|
{
|
|
|
|
|
for (let i = 0, polygon_count = this.polygons.length; i < polygon_count; i++)
|
|
|
|
|
{
|
|
|
|
|
this.polygons[i].flip();
|
|
|
|
|
}
|
|
|
|
|
for (let p of this.polygons)
|
|
|
|
|
p.flip();
|
|
|
|
|
|
|
|
|
|
this.divider.flip();
|
|
|
|
|
if (this.front) this.front.invert();
|
|
|
|
@ -607,18 +476,15 @@ class Node
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
clipPolygons(polygons: Polygon[])
|
|
|
|
|
{
|
|
|
|
|
if (!this.divider) return polygons.slice();
|
|
|
|
|
|
|
|
|
|
let front = [];
|
|
|
|
|
let back = [];
|
|
|
|
|
let front: Polygon[] = [];
|
|
|
|
|
let back: Polygon[] = [];
|
|
|
|
|
|
|
|
|
|
for (let i = 0, polygon_count = polygons.length; i < polygon_count; i++)
|
|
|
|
|
{
|
|
|
|
|
this.divider.splitPolygon(polygons[i], front, back, front, back);
|
|
|
|
|
}
|
|
|
|
|
for (let polygon of polygons)
|
|
|
|
|
this.divider.splitPolygon(polygon, front, back, front, back);
|
|
|
|
|
|
|
|
|
|
if (this.front) front = this.front.clipPolygons(front);
|
|
|
|
|
if (this.back) back = this.back.clipPolygons(back);
|
|
|
|
|