/** * Create a new BSPTree instance from @mesh using @transform * to transform all vertices, normals, and tangents. */ public static BSPTree FromMesh(Mesh mesh, Matrix4x4 transform) { BSPTree tree = new BSPTree(); // get a list of all triangles in @mesh List <Triangle> meshTriangles = GetMeshTriangles(mesh); // loop through each triangle and transform its vertices by @transform for (int i = 0; i < meshTriangles.Count; i++) { Triangle tri = meshTriangles[i]; for (int vi = 0; vi < 3; vi++) { Vertex vtx = TransformVertex(tri.GetVertexByIndex(vi), transform); tri.SetVertexByIndex(vi, vtx); } tri.RebuildOrientationPlane(); meshTriangles[i] = tri; } tree.AddTriangles(meshTriangles); return(tree); }
/** * Produce a deep copy of this BSPTree instance. */ public BSPTree Clone() { BSPTree copy = new BSPTree(); copy.root = Clone(root); return(copy); }
/** * Create a Mesh instance from @tree. */ public static Mesh FromBSPtree(BSPTree tree) { if (tree == null) { return(null); } return(FromList(tree.GetAllTriangles())); }
/** * Recursive version of ClipByTree. This method recursively visits each node in this * BSPTree instance and clips the triangles of each based on the geometry of @tree. * By default it will remove the portions of triangles that are completely inside the * geometry contained by @tree. * * If @clipLessThan is false, the operation is reversed and triangle portions * outside the geometry of @tree instance are removed. */ private void ClipByTree(Node node, BSPTree tree, bool clipLessThan = true, IList <Triangle> discarded = null) { if (node == null) { return; } tree.ClipOutTriangles(node.GetTriangleList(), clipLessThan, discarded); ClipByTree(node.LessThan, tree, clipLessThan, discarded); ClipByTree(node.GreaterThan, tree, clipLessThan, discarded); }
/** * Returns geometry corresponding to volume that is occupied by @a, * but not by @b. */ public static BSPTree Subtract(BSPTree a, BSPTree b) { BSPTree aClone = a.Clone(); BSPTree bClone = b.Clone(); float startTime = Time.realtimeSinceStartup; bClone.Invert(); bClone.ClipByTree(a, false); aClone.ClipByTree(b); aClone.AddTriangles(bClone.GetAllTriangles()); return(aClone); }
/** * Returns geometry corresponding to volume @a that is divided into * two separate pieces by @b. Return results in the form of two BSPTree * instances: @side and @side2. */ public static void Slice(BSPTree a, BSPTree b, out BSPTree side1, out BSPTree side2) { side1 = a.Clone(); BSPTree bClone = b.Clone(); List<Triangle> side1Discarded = new List<Triangle>(); bClone.Invert (); bClone.ClipByTree (a, false); side1.ClipByTree (b, true, side1Discarded); side1.AddTriangles(bClone.GetAllTriangles()); bClone.Invert(); side2 = new BSPTree(); side2.AddTriangles(bClone.GetAllTriangles()); side2.AddTriangles(side1Discarded); }
/** * Returns geometry corresponding to volume @a that is divided into * two separate pieces by @b. Return results in the form of two BSPTree * instances: @side and @side2. */ public static void Slice(BSPTree a, BSPTree b, out BSPTree side1, out BSPTree side2) { side1 = a.Clone(); BSPTree bClone = b.Clone(); List <Triangle> side1Discarded = new List <Triangle>(); bClone.Invert(); bClone.ClipByTree(a, false); side1.ClipByTree(b, true, side1Discarded); side1.AddTriangles(bClone.GetAllTriangles()); bClone.Invert(); side2 = new BSPTree(); side2.AddTriangles(bClone.GetAllTriangles()); side2.AddTriangles(side1Discarded); }
/** * Returns geometry corresponding to volume @a that is divided into * two separate pieces by @b, but @b is treated as a plane (the first split plane * from the first node is used for splitting). * * Return results in the form of two List<Triangle> instances: @side and @side2. */ public static void FastSlice(BSPTree a, BSPTree b, out List <Triangle> side1, out List <Triangle> side2) { side1 = null; side2 = null; BSPTree bClone = b.Clone(); float startTime = Time.realtimeSinceStartup; bClone.ClipByTree(a, false); float clipTime = Time.realtimeSinceStartup - startTime; List <Triangle> aTriangles = a.GetAllTriangles(); List <Triangle> bTriangles = bClone.GetAllTriangles(); bClone.Invert(); List <Triangle> bInvertedTriangles = bClone.GetAllTriangles(); if (bTriangles.Count > 0) { Plane splitPlane = bTriangles[0].OrientationPlane; side1 = new List <Triangle>(); side2 = new List <Triangle>(); var coplanar = new List <Triangle>(); for (int i = 0; i < aTriangles.Count; i++) { Triangle tri = aTriangles[i]; Partitioner.SliceTriangle(tri, splitPlane, side1, side2, coplanar, coplanar); } side1.AddRange(bTriangles); side2.AddRange(bInvertedTriangles); } else { side1 = aTriangles; side2 = null; } }
/** * Returns geometry corresponding to volume @a that is divided into * two separate pieces by @b, but @b is treated as a plane (the first split plane * from the first node is used for splitting). * * Return results in the form of two List<Triangle> instances: @side and @side2. */ public static void FastSlice(BSPTree a, BSPTree b, out List<Triangle> side1, out List<Triangle> side2) { side1 = null; side2 = null; BSPTree bClone = b.Clone(); float startTime = Time.realtimeSinceStartup; bClone.ClipByTree (a, false); float clipTime = Time.realtimeSinceStartup - startTime; List<Triangle> aTriangles = a.GetAllTriangles(); List<Triangle> bTriangles = bClone.GetAllTriangles(); bClone.Invert(); List<Triangle> bInvertedTriangles = bClone.GetAllTriangles(); if(bTriangles.Count > 0) { Plane splitPlane = bTriangles[0].OrientationPlane; side1 = new List<Triangle>(); side2 = new List<Triangle>(); var coplanar = new List<Triangle>(); for(int i =0; i < aTriangles.Count; i++) { Triangle tri = aTriangles[i]; Partitioner.SliceTriangle(tri, splitPlane, side1, side2, coplanar, coplanar); } side1.AddRange(bTriangles); side2.AddRange(bInvertedTriangles); } else { side1 = aTriangles; side2 = null; } }
/** * Produce a deep copy of this BSPTree instance. */ public BSPTree Clone() { BSPTree copy = new BSPTree(); copy.root = Clone(root); return copy; }
/** * Remove the triangles in this BSPTree instance that are completely inside the * geometry contained by @tree. Triangles that are partially inside the geometry * are clipped against it. * * If @clipLessThan is false, the operation is reversed and triangle portions * outside the geometry of @tree instance are removed. */ public void ClipByTree(BSPTree tree, bool clipLessThan = true, IList<Triangle> discarded = null) { ClipByTree (root, tree, clipLessThan, discarded); }
/** * Recursive version of ClipByTree. This method recursively visits each node in this * BSPTree instance and clips the triangles of each based on the geometry of @tree. * By default it will remove the portions of triangles that are completely inside the * geometry contained by @tree. * * If @clipLessThan is false, the operation is reversed and triangle portions * outside the geometry of @tree instance are removed. */ private void ClipByTree(Node node, BSPTree tree, bool clipLessThan = true, IList<Triangle> discarded = null) { if(node == null)return; tree.ClipOutTriangles (node.GetTriangleList(), clipLessThan, discarded); ClipByTree (node.LessThan, tree, clipLessThan, discarded); ClipByTree (node.GreaterThan, tree, clipLessThan, discarded); }
/** * Returns geometry corresponding to volume that is occupied by @a, * but not by @b. */ public static BSPTree Subtract(BSPTree a, BSPTree b) { BSPTree aClone = a.Clone(); BSPTree bClone = b.Clone(); bClone.Invert (); bClone.ClipByTree (a, false); aClone.ClipByTree (b); aClone.AddTriangles(bClone.GetAllTriangles()); return aClone; }
/** * Remove the triangles in this BSPTree instance that are completely inside the * geometry contained by @tree. Triangles that are partially inside the geometry * are clipped against it. * * If @clipLessThan is false, the operation is reversed and triangle portions * outside the geometry of @tree instance are removed. */ public void ClipByTree(BSPTree tree, bool clipLessThan = true, IList <Triangle> discarded = null) { ClipByTree(root, tree, clipLessThan, discarded); }