// Static API

        // Rewrites data in mesh to ensure that it only contains valid particle quads.
        internal static void FilterMesh(Mesh mesh, WarningCallback callback)
        {
            ParticleMesh src = ParticleMesh.FromMesh(mesh);
            ParticleMesh dst = new ParticleMesh();

            // ClassifyQuad wants at least 6 indices (2 triangles) to examine
            int limit  = src.TriangleCount - 6;
            int iiVert = 0;

            while (iiVert < limit)
            {
                switch (src.ClassifyQuad(iiVert, callback))
                {
                case ParticleMesh.QuadType.FullParticle:
                    dst.AppendQuad(src, iiVert);
                    iiVert += 6;
                    break;

                case ParticleMesh.QuadType.Degenerate:
                    iiVert += 6;
                    break;

                case ParticleMesh.QuadType.LatterHalfParticle:
                    iiVert += 3;
                    break;

                case ParticleMesh.QuadType.Unknown:
                default:
                    iiVert += 1;
                    break;
                }
            }
            dst.CopyToMesh(mesh);
        }
        // iiVert is an index to an index to a vert (an index into m_triangles)
        // iiVert must be at least 6 verts from the end of the mesh.
        internal QuadType ClassifyQuad(int iiVert, WarningCallback callback)
        {
            if (iiVert + 6 > m_triangles.Count)
            {
                Debug.Assert(false, "Invalid ClassifyQuad {0}", m_sourceMesh);
                return(QuadType.Unknown);
            }

            int i = iiVert;
            int v = m_triangles[i];

            // AppendQuad assumes that the first index of the quad is the lowest index.
            // All of these "+n" offsets should be positive.
            if ((m_triangles[i] == v &&
                 m_triangles[i + 1] == v + 1 &&
                 m_triangles[i + 2] == v + 3 &&
                 m_triangles[i + 3] == v + 0 &&
                 m_triangles[i + 4] == v + 3 &&
                 m_triangles[i + 5] == v + 2) ||
                (m_triangles[i] == v &&
                 m_triangles[i + 1] == v + 1 &&
                 m_triangles[i + 2] == v + 2 &&
                 m_triangles[i + 3] == v + 0 &&
                 m_triangles[i + 4] == v + 2 &&
                 m_triangles[i + 5] == v + 3))
            {
                if (m_lastMod == null || (v % 4) != m_lastMod.Value)
                {
                    // if (m_lastMod != null) {
                    //   Debug.LogFormat(
                    //       "At {0}: changing mod to {1}\n{2} {3} {4} {5} {6} {7}",
                    //       iiVert, v % 4,
                    //       m_triangles[i  ], m_triangles[i+1], m_triangles[i+2],
                    //       m_triangles[i+3], m_triangles[i+4], m_triangles[i+5]);
                    // }
                    m_lastMod = (v % 4);
                }
                return(QuadType.FullParticle);
            }
            else if (m_triangles[i] == v &&
                     m_triangles[i + 1] == v &&
                     m_triangles[i + 2] == v &&
                     m_triangles[i + 3] == v &&
                     m_triangles[i + 4] == v &&
                     m_triangles[i + 5] == v)
            {
                // Seems to be produced by either TB or FBX export
                // Debug.LogFormat("At {0}: degenerate quad", iiVert);
                return(QuadType.Degenerate);
            }
            else if ((m_triangles[i] == v &&
                      m_triangles[i + 1] == v + 3 &&
                      m_triangles[i + 2] == v + 2) ||
                     (m_triangles[i] == v &&
                      m_triangles[i + 1] == v + 2 &&
                      m_triangles[i + 2] == v + 3))
            {
                // Will be produced by Unity splitting the particle mesh up
                // Debug.LogFormat("At {0}: half-particle", iiVert);
                return(QuadType.LatterHalfParticle);
            }
            else
            {
                if (m_bNoisy)
                {
                    m_bNoisy = false;
                    if (callback != null)
                    {
                        callback(string.Format(
                                     "Found unexpected index sequence @ {0}: {1} {2} {3} {4} {5} {6} {7} {8} {9}",
                                     iiVert,
                                     m_triangles[i], m_triangles[i + 1], m_triangles[i + 2],
                                     m_triangles[i + 3], m_triangles[i + 4], m_triangles[i + 5],
                                     m_triangles[i + 9], m_triangles[i + 10], m_triangles[i + 11]));
                    }
                }
                return(QuadType.Unknown);
            }
        }