public CSG_Node(List <CSG_Polygon> list, CSG_Plane plane, CSG_Node front, CSG_Node back) { this.polygons = list; this.plane = plane; this.front = front; this.back = back; }
/** * Return a new mesh by intersecting @lhs with @rhs. This operation * is non-commutative, so set @lhs and @rhs accordingly. */ public static Mesh Intersect(CSG_Model csg_model_a, CSG_Model csg_model_b) { CSG_Node a = new CSG_Node(csg_model_a.ToPolygons()); CSG_Node b = new CSG_Node(csg_model_b.ToPolygons()); List <CSG_Polygon> polygons = CSG_Node.Intersect(a, b).AllPolygons(); CSG_Model result = new CSG_Model(polygons); return(result.ToMesh()); }
/** * Returns a new mesh by subtracting @rhs from @lhs. */ public static Mesh Subtract(GameObject lhs, GameObject rhs) { CSG_Model csg_model_a = new CSG_Model(lhs); CSG_Model csg_model_b = new CSG_Model(rhs); CSG_Node a = new CSG_Node(csg_model_a.ToPolygons()); CSG_Node b = new CSG_Node(csg_model_b.ToPolygons()); List <CSG_Polygon> polygons = CSG_Node.Subtract(a, b).AllPolygons(); CSG_Model result = new CSG_Model(polygons); return(result.ToMesh()); }
// Remove all polygons in this BSP tree that are inside the other BSP tree // `bsp`. public void ClipTo(CSG_Node other) { this.polygons = other.ClipPolygons(this.polygons); if (this.front != null) { this.front.ClipTo(other); } if (this.back != null) { this.back.ClipTo(other); } }
// Build a BSP tree out of `polygons`. When called on an existing tree, the // new polygons are filtered down to the bottom of the tree and become new // nodes there. Each set of polygons is partitioned using the first polygon // (no heuristic is used to pick a good split). public void Build(List <CSG_Polygon> list) { if (list.Count < 1) { return; } if (this.plane == null || !this.plane.Valid()) { this.plane = new CSG_Plane(); this.plane.normal = list[0].plane.normal; this.plane.w = list[0].plane.w; } if (this.polygons == null) { this.polygons = new List <CSG_Polygon>(); } List <CSG_Polygon> list_front = new List <CSG_Polygon>(); List <CSG_Polygon> list_back = new List <CSG_Polygon>(); for (int i = 0; i < list.Count; i++) { this.plane.SplitPolygon(list[i], this.polygons, this.polygons, list_front, list_back); } if (list_front.Count > 0) { if (this.front == null) { this.front = new CSG_Node(); } this.front.Build(list_front); } if (list_back.Count > 0) { if (this.back == null) { this.back = new CSG_Node(); } this.back.Build(list_back); } }
// Return a new CSG solid representing space both this solid and in the // solid `csg`. Neither this solid nor the solid `csg` are modified. public static CSG_Node Intersect(CSG_Node a1, CSG_Node b1) { CSG_Node a = a1.Clone(); CSG_Node b = b1.Clone(); a.Invert(); b.ClipTo(a); b.Invert(); a.ClipTo(b); b.ClipTo(a); a.Build(b.AllPolygons()); a.Invert(); CSG_Node ret = new CSG_Node(a.AllPolygons()); return(ret); }
// Convert solid space to empty space and empty space to solid space. public void Invert() { for (int i = 0; i < this.polygons.Count; i++) { this.polygons[i].Flip(); } this.plane.Flip(); if (this.front != null) { this.front.Invert(); } if (this.back != null) { this.back.Invert(); } CSG_Node tmp = this.front; this.front = this.back; this.back = tmp; }
public CSG_Node Clone() { CSG_Node clone = new CSG_Node(this.polygons, this.plane, this.front, this.back); return(clone); }
public CSG_Node() { this.front = null; this.back = null; }