public static List <Face> ToQuads(this ProBuilderMesh mesh, IList <Face> faces, bool smoothing = true)
        {
            HashSet <Face> processed = new HashSet <Face>();

            List <WingedEdge> wings = WingedEdge.GetWingedEdges(mesh, faces, true);

            // build a lookup of the strength of edge connections between triangle faces
            Dictionary <EdgeLookup, float> connections = new Dictionary <EdgeLookup, float>();

            for (int i = 0; i < wings.Count; i++)
            {
                using (var it = new WingedEdgeEnumerator(wings[i]))
                {
                    while (it.MoveNext())
                    {
                        var border = it.Current;

                        if (border.opposite != null && !connections.ContainsKey(border.edge))
                        {
                            float score = mesh.GetQuadScore(border, border.opposite);
                            connections.Add(border.edge, score);
                        }
                    }
                }
            }

            List <SimpleTuple <Face, Face> > quads = new List <SimpleTuple <Face, Face> >();

            // move through each face and find it's best quad neighbor
            foreach (WingedEdge face in wings)
            {
                if (!processed.Add(face.face))
                {
                    continue;
                }

                float bestScore = 0f;
                Face  buddy     = null;

                using (var it = new WingedEdgeEnumerator(face))
                {
                    while (it.MoveNext())
                    {
                        var border = it.Current;

                        if (border.opposite != null && processed.Contains(border.opposite.face))
                        {
                            continue;
                        }

                        float borderScore;

                        // only add it if the opposite face's best score is also this face
                        if (connections.TryGetValue(border.edge, out borderScore) &&
                            borderScore > bestScore &&
                            face.face == GetBestQuadConnection(border.opposite, connections))
                        {
                            bestScore = borderScore;
                            buddy     = border.opposite.face;
                        }
                    }
                }

                if (buddy != null)
                {
                    processed.Add(buddy);
                    quads.Add(new SimpleTuple <Face, Face>(face.face, buddy));
                }
            }

            // don't collapse coincident vertices if smoothing is enabled, we need the original normals intact
            return(MergeElements.MergePairs(mesh, quads, smoothing));
        }