/// <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);
        }