/// <summary> /// cut mesh by plane /// </summary> /// <param name="mesh">mesh to cut</param> /// <param name="meshTransform">transformation of the mesh</param> /// <param name="plane">cutting plane</param> /// <param name="triangulateHoles">flag for triangulation of holes</param> /// <param name="crossSectionVertexColor">this color will be assigned to cross section, valid only for vertex color shaders</param> /// <param name="crossUV">uv mapping area for cross section</param> /// <param name="allowOpenMesh">allow cutting of open mesh</param> /// <returns>processing time</returns> public float Cut(ExploderMesh mesh, ExploderTransform meshTransform, Plane plane, bool triangulateHoles, bool allowOpenMesh, ref List <ExploderMesh> meshes, Color crossSectionVertexColor, Vector4 crossUV) { this.crossSectionVertexColour = crossSectionVertexColor; this.crossSectionUV = crossUV; return(Cut(mesh, meshTransform, plane, triangulateHoles, allowOpenMesh, ref meshes)); }
private Plane GetRandomPlane(ExploderMesh mesh) { Vector3 normal; ((Vector3) ref normal).\u002Ector((float)(this.random.NextDouble() * 2.0 - 1.0), (float)(this.random.NextDouble() * 2.0 - 1.0), (float)(this.random.NextDouble() * 2.0 - 1.0)); this.plane.Set(normal, mesh.centroid); return(this.plane); }
public ExploderMesh(Mesh unityMesh) { this.triangles = unityMesh.get_triangles(); this.vertices = unityMesh.get_vertices(); this.normals = unityMesh.get_normals(); this.uv = unityMesh.get_uv(); this.tangents = unityMesh.get_tangents(); this.colors32 = unityMesh.get_colors32(); ExploderMesh.CalculateCentroid(new List <Vector3>((IEnumerable <Vector3>) this.vertices), ref this.centroid, ref this.min, ref this.max); }
private Exploder.Plane GetRandomPlane(ExploderMesh mesh) { var randomPlaneNormal = new Vector3((float)random.NextDouble() * 2.0f - 1.0f, (float)random.NextDouble() * 2.0f - 1.0f, (float)random.NextDouble() * 2.0f - 1.0f); plane.Set(randomPlaneNormal, mesh.centroid); return(plane); }
private Plane GetRectangularRandom(ExploderMesh mesh, int attempt) { int index = this.random.Next(0, 3) + attempt; if (index > 2) { return(this.GetRandomPlane(mesh)); } this.plane.Set(CuttingPlane.rectAxis[index], mesh.centroid); return(this.plane); }
private Exploder.Plane GetRectangularRandom(ExploderMesh mesh, int attempt) { var axis = random.Next(0, 3); axis += attempt; if (axis > 2) { return(GetRandomPlane(mesh)); } plane.Set(rectAxis[axis], mesh.centroid); return(plane); }
private Plane GetRectangularRegularPlane(ExploderMesh mesh, int attempt) { float num1 = (float)(mesh.max.x - mesh.min.x); float num2 = (float)(mesh.max.y - mesh.min.y); float num3 = (float)(mesh.max.z - mesh.min.z); int index = ((double)num1 <= (double)num2 ? ((double)num2 <= (double)num3 ? 2 : 1) : ((double)num1 <= (double)num3 ? 2 : 0)) + attempt; if (index > 2) { return(this.GetRandomPlane(mesh)); } this.plane.Set(CuttingPlane.rectAxis[index], mesh.centroid); return(this.plane); }
public Exploder.Plane GetPlane(ExploderMesh mesh, int attempt) { switch (core.parameters.CuttingStyle) { case ExploderObject.CuttingStyleOption.Random: return(GetRandomPlane(mesh)); case ExploderObject.CuttingStyleOption.RectangularRandom: return(GetRectangularRandom(mesh, attempt)); case ExploderObject.CuttingStyleOption.RectangularRegular: return(GetRectangularRegularPlane(mesh, attempt)); } return(null); }
public Plane GetPlane(ExploderMesh mesh, int attempt) { switch (this.core.parameters.CuttingStyle) { case ExploderObject.CuttingStyleOption.Random: return(this.GetRandomPlane(mesh)); case ExploderObject.CuttingStyleOption.RectangularRandom: return(this.GetRectangularRandom(mesh, attempt)); case ExploderObject.CuttingStyleOption.RectangularRegular: return(this.GetRectangularRegularPlane(mesh, attempt)); default: return((Plane)null); } }
private Exploder.Plane GetRectangularRegularPlane(ExploderMesh mesh, int attempt) { var diffX = mesh.max.x - mesh.min.x; var diffY = mesh.max.y - mesh.min.y; var diffZ = mesh.max.z - mesh.min.z; var axis = 0; if (diffX > diffY) { if (diffX > diffZ) { axis = 0; } else { axis = 2; } } else { if (diffY > diffZ) { axis = 1; } else { axis = 2; } } axis += attempt; if (axis > 2) { return(GetRandomPlane(mesh)); } plane.Set(rectAxis[axis], mesh.centroid); return(plane); }
float Cut(ExploderMesh mesh, ExploderTransform meshTransform, Plane plane, bool triangulateHoles, bool allowOpenMesh, ref List <ExploderMesh> meshes) { var stopWatch = new Stopwatch(); stopWatch.Start(); #if PROFILING MeasureIt.Begin("CutAllocations"); #endif // cache mesh data var trianglesNum = mesh.triangles.Length; var verticesNum = mesh.vertices.Length; var meshTriangles = mesh.triangles; var meshTangents = mesh.tangents; var meshColors = mesh.colors32; var meshVertices = mesh.vertices; var meshNormals = mesh.normals; var meshUV = mesh.uv; var useMeshTangents = meshTangents != null && meshTangents.Length > 0; var useVertexColors = meshColors != null && meshColors.Length > 0; var useNormals = meshNormals != null && meshNormals.Length > 0; // preallocate buffers AllocateBuffers(trianglesNum, verticesNum, useMeshTangents, useVertexColors); ExploderMesh mesh0, mesh1; #if PROFILING MeasureIt.End("CutAllocations"); MeasureIt.Begin("CutCycleFirstPass"); #endif // first pass - find complete triangles on both sides of the plane for (int i = 0; i < trianglesNum; i += 3) { // get triangle points var v0 = meshVertices[meshTriangles[i]]; var v1 = meshVertices[meshTriangles[i + 1]]; var v2 = meshVertices[meshTriangles[i + 2]]; var side0 = plane.GetSideFix(ref v0); var side1 = plane.GetSideFix(ref v1); var side2 = plane.GetSideFix(ref v2); meshVertices[meshTriangles[i]] = v0; meshVertices[meshTriangles[i + 1]] = v1; meshVertices[meshTriangles[i + 2]] = v2; // Utils.Log(plane.Pnt + " " + v0 + " " + v1 + " " + " " + v2); // all points on one side if (side0 == side1 && side1 == side2) { var idx = side0 ? 0 : 1; if (meshTriangles[i] >= triCache.Length) { ExploderUtils.Log("TriCacheError " + meshTriangles[i] + " " + triCache.Length + " " + meshVertices.Length); } if (triCache[meshTriangles[i]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i]]); uvs[idx].Add(meshUV[meshTriangles[i]]); if (useNormals) { normals[idx].Add(meshNormals[meshTriangles[i]]); } if (useMeshTangents) { tangents[idx].Add(meshTangents[meshTriangles[i]]); } if (useVertexColors) { vertexColors[idx].Add(meshColors[meshTriangles[i]]); } centroid[idx] += meshVertices[meshTriangles[i]]; triCache[meshTriangles[i]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i]] - 1); } if (triCache[meshTriangles[i + 1]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 1]]); uvs[idx].Add(meshUV[meshTriangles[i + 1]]); if (useNormals) { normals[idx].Add(meshNormals[meshTriangles[i + 1]]); } if (useMeshTangents) { tangents[idx].Add(meshTangents[meshTriangles[i + 1]]); } if (useVertexColors) { vertexColors[idx].Add(meshColors[meshTriangles[i + 1]]); } centroid[idx] += meshVertices[meshTriangles[i + 1]]; triCache[meshTriangles[i + 1]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 1]] - 1); } if (triCache[meshTriangles[i + 2]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 2]]); uvs[idx].Add(meshUV[meshTriangles[i + 2]]); if (useNormals) { normals[idx].Add(meshNormals[meshTriangles[i + 2]]); } if (useMeshTangents) { tangents[idx].Add(meshTangents[meshTriangles[i + 2]]); } if (useVertexColors) { vertexColors[idx].Add(meshColors[meshTriangles[i + 2]]); } centroid[idx] += meshVertices[meshTriangles[i + 2]]; triCache[meshTriangles[i + 2]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 2]] - 1); } } else { // intersection triangles add to list and process it in second pass cutTris.Add(i); } } if (vertices[0].Count == 0) { centroid[0] = meshVertices[0]; } else { centroid[0] /= vertices[0].Count; } if (vertices[1].Count == 0) { centroid[1] = meshVertices[1]; } else { centroid[1] /= vertices[1].Count; } // UnityEngine.Debug.LogFormat("cut: {0} -- {1}, normal: {2}, tris: {3}", vertices[0].Count, vertices[1].Count, plane.Normal, cutTris.Count); #if PROFILING MeasureIt.End("CutCycleFirstPass"); MeasureIt.Begin("CutCycleSecondPass"); #endif if (cutTris.Count < 1) { stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } AllocateContours(cutTris.Count); // second pass - cut intersecting triangles in half foreach (var cutTri in cutTris) { var triangle = new Triangle { ids = new[] { meshTriangles[cutTri + 0], meshTriangles[cutTri + 1], meshTriangles[cutTri + 2] }, pos = new[] { meshVertices[meshTriangles[cutTri + 0]], meshVertices[meshTriangles[cutTri + 1]], meshVertices[meshTriangles[cutTri + 2]] }, normal = useNormals ? new[] { meshNormals[meshTriangles[cutTri + 0]], meshNormals[meshTriangles[cutTri + 1]], meshNormals[meshTriangles[cutTri + 2]] } : new[] { Vector3.zero, Vector3.zero, Vector3.zero }, uvs = new[] { meshUV[meshTriangles[cutTri + 0]], meshUV[meshTriangles[cutTri + 1]], meshUV[meshTriangles[cutTri + 2]] }, tangents = useMeshTangents ? new[] { meshTangents[meshTriangles[cutTri + 0]], meshTangents[meshTriangles[cutTri + 1]], meshTangents[meshTriangles[cutTri + 2]] } : new [] { Vector4.zero, Vector4.zero, Vector4.zero }, colors = useVertexColors ? new[] { meshColors[meshTriangles[cutTri + 0]], meshColors[meshTriangles[cutTri + 1]], meshColors[meshTriangles[cutTri + 2]] } : new Color32[] { Color.white, Color.white, Color.white }, }; // check points with a plane var side0 = plane.GetSide(triangle.pos[0]); var side1 = plane.GetSide(triangle.pos[1]); var side2 = plane.GetSide(triangle.pos[2]); float t0, t1; Vector3 s0 = Vector3.zero, s1 = Vector3.zero; var idxLeft = side0 ? 0 : 1; var idxRight = 1 - idxLeft; if (side0 == side1) { var a = plane.IntersectSegment(triangle.pos[2], triangle.pos[0], out t0, ref s0); var b = plane.IntersectSegment(triangle.pos[2], triangle.pos[1], out t1, ref s1); ExploderUtils.Assert(a && b, "!!!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.tangents[0], triangle.colors[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v1Left = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.tangents[1], triangle.colors[1], triangle.ids[1], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); // Triangle (s0, v0, s1) triangles[idxLeft].Add(s0Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // Triangle (s1, v0, v1) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(v1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.tangents[2], triangle.colors[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); // Triangle (v2, s0, s1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } else if (side0 == side2) { var a = plane.IntersectSegment(triangle.pos[1], triangle.pos[0], out t0, ref s1); var b = plane.IntersectSegment(triangle.pos[1], triangle.pos[2], out t1, ref s0); ExploderUtils.Assert(a && b, "!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.tangents[0], triangle.colors[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v2Left = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.tangents[2], triangle.colors[2], triangle.ids[2], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); // Triangle (v2, s1, s0) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(s0Left); // Triangle (v2, v0, s1) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.tangents[1], triangle.colors[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); // Triangle (s0, s1, v1) triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } else { var a = plane.IntersectSegment(triangle.pos[0], triangle.pos[1], out t0, ref s0); var b = plane.IntersectSegment(triangle.pos[0], triangle.pos[2], out t1, ref s1); ExploderUtils.Assert(a && b, "!!!!!!!!!!!!!"); // right side ... 2 triangles var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.tangents[1], triangle.colors[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.tangents[2], triangle.colors[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); // Triangle (v2, s1, v1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); // Triangle (s1, s0, v1) triangles[idxRight].Add(s1Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(v1Right); // left side ... 1 triangle var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.tangents[0], triangle.colors[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); // Triangle (s1, v0, s0) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s0Left); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } } #if PROFILING MeasureIt.End("CutCycleSecondPass"); #endif if (triangulateHoles) { #if PROFILING MeasureIt.Begin("FindContours"); #endif contour.FindContours(); if (contour.contour.Count == 0 || contour.contour[0].Count < 3) { // triangulateHoles = false; if (allowOpenMesh) { triangulateHoles = false; } else { stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } } #if PROFILING MeasureIt.End("FindContours"); #endif } List <int>[] trianglesCut = null; var centroid0 = Vector3.zero; var centroid1 = Vector3.zero; var min0 = Vector3.zero; var max0 = Vector3.zero; var min1 = Vector3.zero; var max1 = Vector3.zero; ExploderMesh.CalculateCentroid(vertices[0], ref centroid0, ref min0, ref max0); ExploderMesh.CalculateCentroid(vertices[1], ref centroid1, ref min1, ref max1); if (triangulateHoles) { #if PROFILING MeasureIt.Begin("Triangulate"); #endif trianglesCut = new List <int>[2] { new List <int>(contour.MidPointsCount), new List <int>(contour.MidPointsCount) }; Triangulate(contour.contour, plane, vertices, normals, uvs, tangents, vertexColors, trianglesCut, true, useMeshTangents, useVertexColors, useNormals); #if PROFILING MeasureIt.End("Triangulate"); #endif } if (vertices[0].Count > 3 && vertices[1].Count > 3) { #if PROFILING MeasureIt.Begin("CutEndCopyBack"); #endif mesh0 = new ExploderMesh(); mesh1 = new ExploderMesh(); var verticesArray0 = vertices[0].ToArray(); var verticesArray1 = vertices[1].ToArray(); mesh0.vertices = verticesArray0; mesh0.uv = uvs[0].ToArray(); mesh1.vertices = verticesArray1; mesh1.uv = uvs[1].ToArray(); if (useNormals) { mesh0.normals = normals[0].ToArray(); mesh1.normals = normals[1].ToArray(); } if (useMeshTangents) { mesh0.tangents = tangents[0].ToArray(); mesh1.tangents = tangents[1].ToArray(); } if (useVertexColors) { mesh0.colors32 = vertexColors[0].ToArray(); mesh1.colors32 = vertexColors[1].ToArray(); } if (trianglesCut != null && trianglesCut[0].Count > 3) { triangles[0].AddRange(trianglesCut[0]); triangles[1].AddRange(trianglesCut[1]); } mesh0.triangles = triangles[0].ToArray(); mesh1.triangles = triangles[1].ToArray(); mesh0.centroid = centroid0; mesh0.min = min0; mesh0.max = max0; mesh1.centroid = centroid1; mesh1.min = min1; mesh1.max = max1; #if PROFILING MeasureIt.End("CutEndCopyBack"); #endif meshes = new List <ExploderMesh> { mesh0, mesh1 }; stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } stopWatch.Stop(); // UnityEngine.Debug.Log("Empty cut! " + vertices[0].Count + " " + vertices[1].Count); return(stopWatch.ElapsedMilliseconds); }
private float Cut( ExploderMesh mesh, ExploderTransform meshTransform, Plane plane, bool triangulateHoles, bool allowOpenMesh, ref List <ExploderMesh> meshes) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int length1 = mesh.triangles.Length; int length2 = mesh.vertices.Length; int[] triangles1 = mesh.triangles; Vector4[] tangents = mesh.tangents; Color32[] colors32 = mesh.colors32; Vector3[] vertices = mesh.vertices; Vector3[] normals = mesh.normals; Vector2[] uv = mesh.uv; bool flag1 = tangents != null && tangents.Length > 0; bool flag2 = colors32 != null && colors32.Length > 0; bool useNormals = normals != null && normals.Length > 0; this.AllocateBuffers(length1, length2, flag1, flag2); for (int index1 = 0; index1 < length1; index1 += 3) { Vector3 n1 = vertices[triangles1[index1]]; Vector3 n2 = vertices[triangles1[index1 + 1]]; Vector3 n3 = vertices[triangles1[index1 + 2]]; bool sideFix1 = plane.GetSideFix(ref n1); bool sideFix2 = plane.GetSideFix(ref n2); bool sideFix3 = plane.GetSideFix(ref n3); vertices[triangles1[index1]] = n1; vertices[triangles1[index1 + 1]] = n2; vertices[triangles1[index1 + 2]] = n3; if (sideFix1 == sideFix2 && sideFix2 == sideFix3) { int index2 = !sideFix1 ? 1 : 0; if (triangles1[index1] < this.triCache.Length) { ; } if (this.triCache[triangles1[index1]] == 0) { this.triangles[index2].Add(this.triCounter[index2]); this.vertices[index2].Add(vertices[triangles1[index1]]); this.uvs[index2].Add(uv[triangles1[index1]]); if (useNormals) { this.normals[index2].Add(normals[triangles1[index1]]); } if (flag1) { this.tangents[index2].Add(tangents[triangles1[index1]]); } if (flag2) { this.vertexColors[index2].Add(colors32[triangles1[index1]]); } ref Vector3 local = ref this.centroid[index2]; local = Vector3.op_Addition(local, vertices[triangles1[index1]]); this.triCache[triangles1[index1]] = this.triCounter[index2] + 1; ++this.triCounter[index2]; } else { this.triangles[index2].Add(this.triCache[triangles1[index1]] - 1); } if (this.triCache[triangles1[index1 + 1]] == 0) { this.triangles[index2].Add(this.triCounter[index2]); this.vertices[index2].Add(vertices[triangles1[index1 + 1]]); this.uvs[index2].Add(uv[triangles1[index1 + 1]]); if (useNormals) { this.normals[index2].Add(normals[triangles1[index1 + 1]]); } if (flag1) { this.tangents[index2].Add(tangents[triangles1[index1 + 1]]); } if (flag2) { this.vertexColors[index2].Add(colors32[triangles1[index1 + 1]]); } ref Vector3 local = ref this.centroid[index2]; local = Vector3.op_Addition(local, vertices[triangles1[index1 + 1]]); this.triCache[triangles1[index1 + 1]] = this.triCounter[index2] + 1; ++this.triCounter[index2]; }
/// <summary> /// find and isolate independent (not connecting) parts in a mesh /// </summary> public static List <ExploderMesh> IsolateMeshIslands(ExploderMesh mesh) { var triangles = mesh.triangles; var vertexCount = mesh.vertices.Length; // cache mesh data var trianglesNum = mesh.triangles.Length; var tangents = mesh.tangents; var colors = mesh.colors32; var vertices = mesh.vertices; var normals = mesh.normals; var uvs = mesh.uv; var useMeshTangents = tangents != null && tangents.Length > 0; var useVertexColors = colors != null && colors.Length > 0; var useNormals = normals != null && normals.Length > 0; if (trianglesNum <= 3) { return(null); } ExploderUtils.Assert(trianglesNum > 3, "IsolateMeshIslands error: " + trianglesNum); var lsHash = new LSHash(0.1f, vertexCount); var vertHash = new int[trianglesNum]; for (int i = 0; i < trianglesNum; i++) { vertHash[i] = lsHash.Hash(vertices[triangles[i]]); } var islands = new List <HashSet <int> > { new HashSet <int> { vertHash[0], vertHash[1], vertHash[2] } }; var islandsIdx = new List <List <int> > { new List <int>(trianglesNum) { 0, 1, 2 } }; var triVisited = new bool[trianglesNum]; triVisited[0] = true; triVisited[1] = true; triVisited[2] = true; var currIsland = islands[0]; var currIslandIdx = islandsIdx[0]; var counter = 3; var lastInvalidIdx = -1; var loopCounter = 0; while (true) { var foundIsland = false; for (int j = 3; j < trianglesNum; j += 3) { if (triVisited[j]) { continue; } if (currIsland.Contains(vertHash[j]) || currIsland.Contains(vertHash[j + 1]) || currIsland.Contains(vertHash[j + 2])) { currIsland.Add(vertHash[j]); currIsland.Add(vertHash[j + 1]); currIsland.Add(vertHash[j + 2]); currIslandIdx.Add(j); currIslandIdx.Add(j + 1); currIslandIdx.Add(j + 2); triVisited[j] = true; triVisited[j + 1] = true; triVisited[j + 2] = true; counter += 3; foundIsland = true; } else { lastInvalidIdx = j; } } if (counter == trianglesNum) { break; } if (!foundIsland) { // create new island currIsland = new HashSet <int> { vertHash[lastInvalidIdx], vertHash[lastInvalidIdx + 1], vertHash[lastInvalidIdx + 2] }; currIslandIdx = new List <int>(trianglesNum / 2) { lastInvalidIdx, lastInvalidIdx + 1, lastInvalidIdx + 2 }; islands.Add(currIsland); islandsIdx.Add(currIslandIdx); } loopCounter++; if (loopCounter > 100) { ExploderUtils.Log("10000 loop exceeded, islands: " + islands.Count); break; } } var islandNum = islands.Count; ExploderUtils.Assert(islandNum >= 1, "No island found!"); // no more than one islands if (islandNum == 1) { return(null); } var result = new List <ExploderMesh>(islands.Count); foreach (var island in islandsIdx) { var cutterMesh = new ExploderMesh(); var triCount = island.Count; var m = cutterMesh; var tt = new List <int>(triCount); var vs = new List <Vector3>(triCount); var ns = new List <Vector3>(triCount); var us = new List <Vector2>(triCount); var cs = new List <Color32>(triCount); var ts = new List <Vector4>(triCount); var triCache = new Dictionary <int, int>(trianglesNum); var centroid = Vector3.zero; var centroidCounter = 0; var triCounter = 0; foreach (var i in island) { var tri = triangles[i]; var id = 0; if (triCache.TryGetValue(tri, out id)) { tt.Add(id); continue; } tt.Add(triCounter); triCache.Add(tri, triCounter); triCounter++; centroid += vertices[tri]; centroidCounter++; vs.Add(vertices[tri]); us.Add(uvs[tri]); if (useNormals) { ns.Add(normals[tri]); } if (useVertexColors) { cs.Add(colors[tri]); } if (useMeshTangents) { ts.Add(tangents[tri]); } } m.vertices = vs.ToArray(); m.uv = us.ToArray(); if (useNormals) { m.normals = ns.ToArray(); } if (useVertexColors) { m.colors32 = cs.ToArray(); } if (useMeshTangents) { m.tangents = ts.ToArray(); } m.triangles = tt.ToArray(); cutterMesh.centroid = centroid / centroidCounter; result.Add(cutterMesh); } return(result); }