/** * Slice the gameobject mesh (if any) using the Plane, which will generate * a maximum of 2 other Meshes. * This function will recalculate new UV coordinates to ensure textures are applied * properly. * Returns null if no intersection has been found or the GameObject does not contain * a valid mesh to cut. */ public static SlicedHull Slice(Mesh sharedMesh, Plane pl, TextureRegion region, int crossIndex) { if (sharedMesh == null) { return(null); } Vector3[] verts = sharedMesh.vertices; Vector2[] uv = sharedMesh.uv; Vector3[] norm = sharedMesh.normals; Vector4[] tan = sharedMesh.tangents; int submeshCount = sharedMesh.subMeshCount; // each submesh will be sliced and placed in its own array structure SlicedSubmesh[] slices = new SlicedSubmesh[submeshCount]; // the cross section hull is common across all submeshes List <Vector3> crossHull = new List <Vector3>(); // we reuse this object for all intersection tests IntersectionResult result = new IntersectionResult(); // see if we would like to split the mesh using uv, normals and tangents bool genUV = verts.Length == uv.Length; bool genNorm = verts.Length == norm.Length; bool genTan = verts.Length == tan.Length; // iterate over all the submeshes individually. vertices and indices // are all shared within the submesh for (int submesh = 0; submesh < submeshCount; submesh++) { int[] indices = sharedMesh.GetTriangles(submesh); int indicesCount = indices.Length; SlicedSubmesh mesh = new SlicedSubmesh(); // loop through all the mesh vertices, generating upper and lower hulls // and all intersection points for (int index = 0; index < indicesCount; index += 3) { int i0 = indices[index + 0]; int i1 = indices[index + 1]; int i2 = indices[index + 2]; Triangle newTri = new Triangle(verts[i0], verts[i1], verts[i2]); // generate UV if available if (genUV) { newTri.SetUV(uv[i0], uv[i1], uv[i2]); } // generate normals if available if (genNorm) { newTri.SetNormal(norm[i0], norm[i1], norm[i2]); } // generate tangents if available if (genTan) { newTri.SetTangent(tan[i0], tan[i1], tan[i2]); } // slice this particular triangle with the provided // plane if (newTri.Split(pl, result)) { int upperHullCount = result.upperHullCount; int lowerHullCount = result.lowerHullCount; int interHullCount = result.intersectionPointCount; for (int i = 0; i < upperHullCount; i++) { mesh.upperHull.Add(result.upperHull[i]); } for (int i = 0; i < lowerHullCount; i++) { mesh.lowerHull.Add(result.lowerHull[i]); } for (int i = 0; i < interHullCount; i++) { crossHull.Add(result.intersectionPoints[i]); } } else { SideOfPlane sa = pl.SideOf(verts[i0]); SideOfPlane sb = pl.SideOf(verts[i1]); SideOfPlane sc = pl.SideOf(verts[i2]); SideOfPlane side = SideOfPlane.ON; if (sa != SideOfPlane.ON) { side = sa; } if (sb != SideOfPlane.ON) { Debug.Assert(side == SideOfPlane.ON || side == sb); side = sb; } if (sc != SideOfPlane.ON) { Debug.Assert(side == SideOfPlane.ON || side == sc); side = sc; } if (side == SideOfPlane.UP || side == SideOfPlane.ON) { mesh.upperHull.Add(newTri); } else { mesh.lowerHull.Add(newTri); } } } // register into the index slices[submesh] = mesh; } // check if slicing actually occured for (int i = 0; i < slices.Length; i++) { // check if at least one of the submeshes was sliced. If so, stop checking // because we need to go through the generation step if (slices[i] != null && slices[i].isValid) { return(CreateFrom(slices, CreateFrom(crossHull, pl.normal, region), crossIndex)); } } // no slicing occured, just return null to signify return(null); }
/** * Slice the gameobject mesh (if any) using the Plane, which will generate * a maximum of 2 other Meshes. * This function will recalculate new UV coordinates to ensure textures are applied * properly. * Returns null if no intersection has been found or the GameObject does not contain * a valid mesh to cut. */ public static SlicedHull Slice(Mesh sharedMesh, Plane pl, bool genCrossSection = true) { if (sharedMesh == null) { return(null); } Vector3[] verts = sharedMesh.vertices; Vector2[] uv = sharedMesh.uv; Vector3[] norm = sharedMesh.normals; Vector4[] tan = sharedMesh.tangents; int submeshCount = sharedMesh.subMeshCount; // each submesh will be sliced and placed in its own array structure SlicedSubmesh[] slices = new SlicedSubmesh[submeshCount]; // the cross section hull is common across all submeshes List <Vector3> crossHull = new List <Vector3>(); // we reuse this object for all intersection tests IntersectionResult result = new IntersectionResult(); // see if we would like to split the mesh using uv, normals and tangents bool genUV = verts.Length == uv.Length; bool genNorm = verts.Length == norm.Length; bool genTan = verts.Length == tan.Length; // iterate over all the submeshes individually. vertices and indices // are all shared within the submesh for (int submesh = 0; submesh < submeshCount; submesh++) { int[] indices = sharedMesh.GetTriangles(submesh); int indicesCount = indices.Length; SlicedSubmesh mesh = new SlicedSubmesh(); // loop through all the mesh vertices, generating upper and lower hulls // and all intersection points for (int index = 0; index < indicesCount; index += 3) { int i0 = indices[index + 0]; int i1 = indices[index + 1]; int i2 = indices[index + 2]; Triangle newTri = new Triangle(verts[i0], verts[i1], verts[i2]); // generate UV if available if (genUV) { newTri.SetUV(uv[i0], uv[i1], uv[i2]); } // generate normals if available if (genNorm) { newTri.SetNormal(norm[i0], norm[i1], norm[i2]); } // generate tangents if available if (genTan) { newTri.SetTangent(tan[i0], tan[i1], tan[i2]); } // slice this particular triangle with the provided // plane if (newTri.Split(pl, result)) { int upperHullCount = result.upperHullCount; int lowerHullCount = result.lowerHullCount; int interHullCount = result.intersectionPointCount; for (int i = 0; i < upperHullCount; i++) { mesh.upperHull.Add(result.upperHull[i]); } for (int i = 0; i < lowerHullCount; i++) { mesh.lowerHull.Add(result.lowerHull[i]); } for (int i = 0; i < interHullCount; i++) { crossHull.Add(result.intersectionPoints[i]); } } else { SideOfPlane side = pl.SideOf(verts[i0]); if (side == SideOfPlane.UP || side == SideOfPlane.ON) { mesh.upperHull.Add(newTri); } else { mesh.lowerHull.Add(newTri); } } } // register into the index slices[submesh] = mesh; } return(CreateFrom(slices, CreateFrom(crossHull, pl.normal))); }
/** * Slice the gameobject mesh (if any) using the Plane, which will generate * a maximum of 2 other Meshes. * This function will recalculate new UV coordinates to ensure textures are applied * properly. * Returns null if no intersection has been found or the GameObject does not contain * a valid mesh to cut. */ public static SlicedHull Slice(Mesh sharedMesh, Plane pl, bool genCrossSection = true) { if (sharedMesh == null) { return(null); } Vector3[] ve = sharedMesh.vertices; Vector2[] uv = sharedMesh.uv; int[] indices = sharedMesh.triangles; int indicesCount = indices.Length; // we reuse this object for all intersection tests IntersectionResult result = new IntersectionResult(); // all our buffers, as Triangles List <Triangle> upperHull = new List <Triangle>(); List <Triangle> lowerHull = new List <Triangle>(); List <Vector3> crossHull = new List <Vector3>(); // loop through all the mesh vertices, generating upper and lower hulls // and all intersection points for (int index = 0; index < indicesCount; index += 3) { int i0 = indices[index + 0]; int i1 = indices[index + 1]; int i2 = indices[index + 2]; Triangle newTri = new Triangle(ve[i0], ve[i1], ve[i2], uv[i0], uv[i1], uv[i2]); // slice this particular triangle with the provided // plane if (newTri.Split(pl, result)) { int upperHullCount = result.upperHullCount; int lowerHullCount = result.lowerHullCount; int interHullCount = result.intersectionPointCount; for (int i = 0; i < upperHullCount; i++) { upperHull.Add(result.upperHull[i]); } for (int i = 0; i < lowerHullCount; i++) { lowerHull.Add(result.lowerHull[i]); } for (int i = 0; i < interHullCount; i++) { crossHull.Add(result.intersectionPoints[i]); } } else { SideOfPlane side = pl.SideOf(ve[i0]); if (side == SideOfPlane.UP || side == SideOfPlane.ON) { upperHull.Add(newTri); } else { lowerHull.Add(newTri); } } } // start creating our hulls Mesh finalUpperHull = CreateFrom(upperHull); Mesh finalLowerHull = CreateFrom(lowerHull); // we need to generate the cross section if set // NOTE -> This uses a MonotoneChain algorithm which will only work // on cross sections which are Convex if (genCrossSection) { Mesh[] crossSections = CreateFrom(crossHull, pl.normal); if (crossSections != null) { return(new SlicedHull(finalUpperHull, finalLowerHull, crossSections[0], crossSections[1])); } } return(new SlicedHull(finalUpperHull, finalLowerHull)); }