public static SurfaceComponentGeometry CreatePlaneGeometry(
        float sizeX, float sizeZ, int segmentX, int segmentZ, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Smooth)
    {
        SurfaceComponentGeometry geometry = new SurfaceComponentGeometry();
        bool normalRequired  = (faceType != RenderGeometry.FaceType.Polygonal && faceType != RenderGeometry.FaceType.Triangular);
        bool tangentRequired = (faceType == RenderGeometry.FaceType.Directinal1 || faceType == RenderGeometry.FaceType.Directinal2);

        Vector3 origin = new Vector3(-sizeX / 2, 0, -sizeZ / 2);
        Vector3 d      = new Vector3(sizeX / segmentX, 0, sizeZ / segmentZ);

        for (int x = 0; x <= segmentX; x++)
        {
            for (int z = 0; z <= segmentZ; z++)
            {
                geometry.CreateVertex(origin + new Vector3(d.x * x, 0, d.z * z));
            }
        }
        Vertex vertice(int x, int z) => geometry.vertices[x * (segmentZ + 1) + z];

        for (int x = 0; x < segmentX; x++)
        {
            for (int z = 0; z < segmentZ; z++)
            {
                Face f = geometry.CreateFace(vertice(x, z), vertice(x, z + 1), vertice(x + 1, z + 1), vertice(x + 1, z));
                f.surfaceGroup = surfaceGroup;
                geometry.SetFaceType(f, faceType);
            }
        }

        if (normalRequired)
        {
            foreach (Halfedge e in geometry.halfedges)
            {
                geometry.SetNormal(e, Vector3.up);
            }
        }
        if (tangentRequired)
        {
            foreach (Halfedge e in geometry.halfedges)
            {
                geometry.SetTangent(e, -e.vector.normalized);
            }
        }
        geometry.DefineBoundaries(vertice(0, 0), vertice(0, segmentZ), vertice(segmentX, segmentZ), vertice(segmentX, 0));
        return(geometry);
    }
    public static SurfaceComponentGeometry CreateConeCapGeometry(
        float radius, float height, int segmentP, int segmentR, float cutAngle = 0, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Smooth,
        bool splitBoundary = false)
    {
        SurfaceComponentGeometry geometry = new SurfaceComponentGeometry();
        bool normalRequired  = (faceType != RenderGeometry.FaceType.Polygonal && faceType != RenderGeometry.FaceType.Triangular);
        bool tangentRequired = (faceType == RenderGeometry.FaceType.Directinal1 || faceType == RenderGeometry.FaceType.Directinal2);

        int   n          = cutAngle > 0 ? segmentP + 1 : segmentP;
        float deltaAngle = (2 * Mathf.PI - cutAngle) / segmentP;

        float Angle(float th) => cutAngle + deltaAngle * th;

        for (int rr = 0; rr < segmentR; rr++)
        {
            for (int th = 0; th < n; th++)
            {
                float r = radius * (segmentR - rr) / segmentR;
                float h = height * rr / segmentR;
                geometry.CreateVertex(new Vector3(r * Mathf.Cos(Angle(th)), h, -r * Mathf.Sin(Angle(th))));
            }
        }
        Vertex vertice(int rr, int th) => geometry.vertices[rr * n + th];

        Vertex center = geometry.CreateVertex(new Vector3(0, height, 0));

        for (int rr = 0; rr < segmentR - 1; rr++)
        {
            for (int th = 0; th < segmentP; th++)
            {
                int  th2 = (th + 1) % n;
                Face f   = geometry.CreateFace(vertice(rr, th), vertice(rr, th2), vertice(rr + 1, th2), vertice(rr + 1, th));
                if (tangentRequired)
                {
                    List <Halfedge> edges = f.edges;
                    geometry.SetTangent(edges[1], -edges[1].vector.normalized);
                    geometry.SetTangent(edges[3], -edges[3].vector.normalized);
                    geometry.SetTangent(edges[0], new Vector3(Mathf.Sin(Angle(th2)), 0, Mathf.Cos(Angle(th2))));
                    geometry.SetTangent(edges[2], new Vector3(-Mathf.Sin(Angle(th)), 0, -Mathf.Cos(Angle(th))));
                    if (rr == 0)
                    {
                        geometry.SetTangent(edges[0].opposite, new Vector3(-Mathf.Sin(Angle(th)), 0, -Mathf.Cos(Angle(th))));
                    }
                }
            }
        }
        for (int th = 0; th < segmentP; th++)
        {
            int  th2 = (th + 1) % n;
            Face f   = geometry.CreateFace(vertice(segmentR - 1, th), vertice(segmentR - 1, th2), center);
            if (tangentRequired)
            {
                List <Halfedge> edges = f.edges;
                geometry.SetTangent(edges[1], -edges[1].vector.normalized);
                geometry.SetTangent(edges[2], -edges[2].vector.normalized);
                geometry.SetTangent(edges[0], new Vector3(Mathf.Sin(Angle(th2)), 0, Mathf.Cos(Angle(th2))));
            }
        }
        foreach (Face f in geometry.faces)
        {
            f.surfaceGroup = surfaceGroup;
            geometry.SetFaceType(f, faceType);
        }

        if (normalRequired)
        {
            if (height == 0)
            {
                foreach (Halfedge e in geometry.halfedges)
                {
                    geometry.SetNormal(e, Vector3.up);
                }
            }
            else
            {
                for (int rr = 0; rr < segmentR; rr++)
                {
                    for (int th = 0; th < n; th++)
                    {
                        geometry.SetNormal(vertice(rr, th), new Vector3(Mathf.Cos(Angle(th)), radius / height, -Mathf.Sin(Angle(th))).normalized, surfaceGroup);
                    }
                }
                foreach (Halfedge e in center.edges)
                {
                    geometry.SetNormal(e, Vector3.Cross(e.vector, e.next.vector).normalized);
                }
            }
        }

        if (cutAngle == 0)
        {
            geometry.DefineBoundaries(vertice(0, 0));
        }
        else
        {
            geometry.DefineBoundaries(vertice(0, 0), vertice(0, n - 1), center);
        }
        if (splitBoundary)
        {
            geometry.SplitBoundaries();
        }
        return(geometry);
    }