/// <summary> /// Merge coincident vertices where possible, optimizing the vertex count of a UnityEngine.Mesh. /// </summary> /// <param name="mesh">The mesh to optimize.</param> /// <param name="vertices"> /// If provided these values are used in place of extracting attributes from the Mesh. /// <br /> /// This is a performance optimization for when this array already exists. If not provided this array will be /// automatically generated for you. /// </param> public static void CollapseSharedVertices(Mesh mesh, Vertex[] vertices = null) { if (mesh == null) { throw new System.ArgumentNullException("mesh"); } bool hasCollapsedVertices = vertices != null; if (vertices == null) { vertices = mesh.GetVertices(); } int smc = mesh.subMeshCount; List <Dictionary <Vertex, int> > subVertices = new List <Dictionary <Vertex, int> >(); int[][] tris = new int[smc][]; int subIndex = 0; for (int i = 0; i < smc; ++i) { tris[i] = mesh.GetTriangles(i); Dictionary <Vertex, int> newVertices = new Dictionary <Vertex, int>(); for (int n = 0; n < tris[i].Length; n++) { Vertex v = vertices[tris[i][n]]; int index; if (newVertices.TryGetValue(v, out index)) { tris[i][n] = index; } else { tris[i][n] = subIndex; newVertices.Add(v, subIndex); subIndex++; } } subVertices.Add(newVertices); } Vertex[] collapsed = subVertices.SelectMany(x => x.Keys).ToArray(); //Check if new vertices have been collapsed hasCollapsedVertices |= (collapsed.Length != vertices.Length); if (hasCollapsedVertices) { Vertex.SetMesh(mesh, collapsed); mesh.subMeshCount = smc; for (int i = 0; i < smc; i++) { mesh.SetTriangles(tris[i], i); } } }
/// <summary> /// Create an array of @"UnityEngine.ProBuilder.Vertex" values that are ordered as individual triangles. This modifies the source mesh to match the new individual triangles format. /// </summary> /// <param name="mesh">The mesh to extract vertices from, and apply per-triangle topology to.</param> /// <returns>A @"UnityEngine.ProBuilder.Vertex" array of the per-triangle vertices.</returns> internal static Vertex[] GeneratePerTriangleMesh(Mesh mesh) { if (mesh == null) { throw new ArgumentNullException("mesh"); } Vertex[] vertices = mesh.GetVertices(); int smc = mesh.subMeshCount; Vertex[] tv = new Vertex[mesh.triangles.Length]; int[][] triangles = new int[smc][]; int triIndex = 0; for (int s = 0; s < smc; s++) { triangles[s] = mesh.GetTriangles(s); int tl = triangles[s].Length; for (int i = 0; i < tl; i++) { tv[triIndex++] = new Vertex(vertices[triangles[s][i]]); triangles[s][i] = triIndex - 1; } } Vertex.SetMesh(mesh, tv); mesh.subMeshCount = smc; for (int s = 0; s < smc; s++) { mesh.SetTriangles(triangles[s], s); } return(tv); }