Utility.Polygon SetOuterQuadsAndTris(List <LineSegment> lines)
    {
        Utility.Polygon mesh = new Utility.Polygon();

        for (int i = 0; i < lines.Count - 1; i++)
        {
            if (lines[i].v1 == lines[i + 1].v1)
            {
                mesh.AddTri(lines[i].v1, lines[i + 1].v2, lines[i].v2, ToUV(lines[i].v1), ToUV(lines[i + 1].v2), ToUV(lines[i].v2), flipMesh);
            }
            else if (lines[i].v2 == lines[i + 1].v2)
            {
                mesh.AddTri(lines[i].v1, lines[i + 1].v1, lines[i].v2, ToUV(lines[i].v1), ToUV(lines[i + 1].v1), ToUV(lines[i].v2), flipMesh);
            }
            else
            {
                mesh.AddQuad(lines[i].v1, lines[i + 1].v1, lines[i].v2, lines[i + 1].v2, ToUV(lines[i].v1), ToUV(lines[i + 1].v1), ToUV(lines[i].v2), ToUV(lines[i + 1].v2), flipMesh);
            }
        }
        if (lines[lines.Count - 1].v1 == lines[0].v1 && lines[lines.Count - 1].v2 != lines[0].v2)
        {
            mesh.AddTri(lines[lines.Count - 1].v1, lines[0].v2, lines[lines.Count - 1].v2, ToUV(lines[lines.Count - 1].v1), ToUV(lines[0].v2), ToUV(lines[lines.Count - 1].v2), flipMesh);
        }
        else if (lines[lines.Count - 1].v2 == lines[0].v2 && lines[lines.Count - 1].v1 != lines[0].v1)
        {
            mesh.AddTri(lines[lines.Count - 1].v1, lines[0].v1, lines[lines.Count - 1].v2, ToUV(lines[lines.Count - 1].v1), ToUV(lines[0].v1), ToUV(lines[lines.Count - 1].v2), flipMesh);
        }

        return(mesh);
    }
    Utility.Polygon AddInnerQuadsAndTris(List <Vector3> validQuads, List <Vector3> validTris)
    {
        Utility.Polygon poly = new Utility.Polygon();

        foreach (Vector3 quad in validQuads)
        {
            bool    xEven = Mathf.Round(quad.x * gridScale) % 2 == 0;
            bool    zEven = Mathf.Round(quad.z * gridScale) % 2 == 0;
            Vector3 quadR = Vector3.right * gridScale;
            Vector3 quadF = Vector3.forward * gridScale;



            if (!IsHole(quad, quad + quadF, quad + quadR, quad + quadR + quadF))
            {
                if (xEven == zEven)
                {
                    poly.AddQuad(quad, quad + quadF, quad + quadR, quad + quadR + quadF, ToUV(quad), ToUV(quad + quadF), ToUV(quad + quadR), ToUV(quad + quadR + quadF), flipMesh);
                }
                else
                {
                    poly.AddQuad(quad + quadF, quad + quadR + quadF, quad, quad + quadR, ToUV(quad + quadF), ToUV(quad + quadR + quadF), ToUV(quad), ToUV(quad + quadR), flipMesh);
                }
            }
        }
        for (int t = 0; t < validTris.Count; t += 3)
        {
            if (Vector3.Cross(validTris[t + 1] - validTris[t], validTris[t + 2] - validTris[t]).normalized == Vector3.up)
            {
                poly.AddTri(validTris[t], validTris[t + 1], validTris[t + 2], ToUV(validTris[t]), ToUV(validTris[t + 1]), ToUV(validTris[t + 2]), flipMesh);
            }
            else
            {
                poly.AddTri(validTris[t], validTris[t + 2], validTris[t + 1], ToUV(validTris[t]), ToUV(validTris[t + 2]), ToUV(validTris[t + 1]), flipMesh);
            }
        }

        return(poly);
    }
    protected void AddToMesh(Utility.Polygon mesh, List <Vector3> row1, List <Vector3> row2, int rowI, float widthMax, bool end = false)
    {
        float widthDelta  = 1f / widthMax * .5f;
        float heightDelta = 1f / row1.Count * .5f;
        float width1      = (rowI - 1) / widthMax;
        float width2      = (rowI) / widthMax;

        if (row1.Count == row2.Count)
        {
            for (int j = 0; j < row2.Count - 1 && j < row1.Count - 1; j++)
            {
                float height1 = (float)(j) / (row1.Count);
                float height2 = (float)(j + 1) / (row2.Count);
                if (!CheckQuadInHole(row1[j], row1[j + 1], row2[j], row2[j + 1], width1, width2, widthDelta, height2, height2, heightDelta))
                {
                    if ((rowI + j) % 2 == 0)
                    {
                        mesh.AddQuad(row1[j], row1[j + 1], row2[j], row2[j + 1], new Vector2(width1, height1), new Vector2(width1, height2), new Vector2(width2, height1), new Vector2(width2, height2), flipMesh);
                    }
                    else
                    {
                        mesh.AddQuad(row1[j + 1], row2[j + 1], row1[j], row2[j], new Vector2(width1, height2), new Vector2(width2, height2), new Vector2(width1, height1), new Vector2(width2, height1), flipMesh);
                    }
                }
            }
        }
        else
        {
            if (end)
            {
                if (Vector3.Distance(row1[0], row2[0]) > Vector3.Distance(row1[0], row2[row2.Count - 1]))
                {
                    row2.Reverse();
                }
            }
            else
            {
                if (Vector3.Distance(row1[0], row2[0]) > Vector3.Distance(row1[row1.Count - 1], row2[0]))
                {
                    row1.Reverse();
                }
            }

            int     i = 0, j = 0;
            Vector3 start1 = row1[0], start2 = row2[0];
            while (i < row1.Count - 1 && j < row2.Count - 1)
            {
                float height1 = (float)(i + 1) / (row1.Count);
                float height2 = (float)(j + 1) / (row2.Count);

                if (!CheckQuadInHole(row1[i], row1[i + 1], row2[j], row2[j + 1], width1, width2, widthDelta, height1, height2, heightDelta))
                {
                    if (Vector3.Distance(row1[i], row2[j + 1]) < Vector3.Distance(row2[j], row1[i + 1]))
                    {
                        ++j;
                        mesh.AddTri(start1, row2[j], start2, new Vector2(width1, height1), new Vector2(width2, height2), new Vector2(width2, height1), flipMesh);
                        start2 = row2[j];
                    }
                    else
                    {
                        ++i;
                        mesh.AddTri(start1, row1[i], start2, new Vector2(width1, height1), new Vector2(width1, height2), new Vector2(width2, height1), flipMesh);
                        start1 = row1[i];
                    }
                }
                else
                {
                    ++j;
                    ++i;
                }
            }
            if (i < row1.Count - 1)
            {
                while (i < row1.Count - 1)
                {
                    ++i;
                    float height1 = (float)(i + 1) / (row1.Count);
                    float height2 = (float)(j + 1) / (row2.Count);
                    if (!CheckQuadInHole(row1[i - 1], row1[i], row2[j], row2[j], width1, width2, widthDelta, height1, height2, heightDelta))
                    {
                        mesh.AddTri(start1, row1[i], start2, new Vector2(width1, height1), new Vector2(width1, height2), new Vector2(width2, height1), flipMesh);
                    }
                    start1 = row1[i];
                }
            }
            else if (j < row2.Count - 1)
            {
                while (j < row2.Count - 1)
                {
                    ++j;
                    float height1 = (float)(i + 1) / (row1.Count);
                    float height2 = (float)(j + 1) / (row2.Count);
                    if (!CheckQuadInHole(row1[i], row1[i], row2[j - 1], row2[j], width1, width2, widthDelta, height1, height2, heightDelta))
                    {
                        mesh.AddTri(start1, row2[j], start2, new Vector2(width1, height1), new Vector2(width2, height2), new Vector2(width2, height1), flipMesh);
                    }
                    start2 = row2[j];
                }
            }
        }
    }