public static SurfaceComponentGeometry CreateExtrudedPolygonCapGeometry(
        float radius, float height, int segmentP, int segmentH, float topRatio = 1, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Smooth,
        bool splitBoundary = false)
    {
        if (topRatio == 0)
        {
            return(CreateConeCapGeometry(radius, height, segmentP, segmentH, 0, surfaceGroup, faceType, splitBoundary));
        }
        if (topRatio == 1 && height == 0)
        {
            return(CreateRegularPolygonGeometry(radius, segmentP, surfaceGroup, RenderGeometry.FaceType.Polygonal, true));
        }

        StructureGeometry structure = new StructureGeometry();

        SurfaceComponentGeometry upperCap = CreateRegularPolygonGeometry(radius * topRatio, segmentP, surfaceGroup + 1);
        SurfaceComponentGeometry side     = CreateConeSideGeometry(radius, radius * topRatio, height, segmentP, segmentH, 0, false, surfaceGroup, faceType);

        side.ApplyOffset(Vector3.up * (height / 2));

        Vertex cornerUp   = structure.CreateVertex(new Vector3(radius * topRatio, height, 0));
        Vertex cornerDown = structure.CreateVertex(new Vector3(radius, 0, 0));

        structure.CreateFace(side, false, cornerUp, cornerUp, cornerDown, cornerDown);
        structure.CreateFace(upperCap, true, cornerUp);

        SurfaceComponentGeometry geometry = new SurfaceComponentGeometry(structure.Build());

        geometry.DefineBoundaries(structure.GetBuiltVertex(cornerDown));
        if (splitBoundary)
        {
            geometry.SplitBoundaries();
        }
        return(geometry);
    }
    public static RenderGeometry CreateTorusGeometry(float ringRadius, float barRadius, int segmentRing, int segmentBar, bool smoothH, bool smoothV, float cutAngle = 0, float deltaAngle = 0)
    {
        StructureGeometry structure = new StructureGeometry();

        RenderGeometry.FaceType faceType = GetFaceType(smoothH, smoothV);

        SurfaceComponentGeometry face = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, segmentBar, segmentRing, 1, faceType);

        var warp = new SpaceWarp(
            $" a1=(z+0.5)*(2*PI-{cutAngle})",
            $" a2={deltaAngle}-x*(2*PI)",
            $" r={ringRadius}+{barRadius}*cos(a2)",
            $" X=r*cos(a1)",
            $" Y={barRadius}*sin(a2)",
            $" Z=r*sin(a1)"
            );

        face.ApplySpaceWarp(warp);

        if (cutAngle == 0)
        {
            Vertex corner = structure.CreateVertex();
            structure.CreateFace(face, false, corner, corner, corner, corner);
        }
        else
        {
            SurfaceComponentGeometry cap1 = SurfaceComponentGeometries.CreateRegularPolygonGeometry(barRadius, segmentBar, 2);
            SurfaceComponentGeometry cap2 = SurfaceComponentGeometries.CreateRegularPolygonGeometry(barRadius, segmentBar, 2);
            cap1.ApplyRotation(Quaternion.LookRotation(Vector3.down, Vector3.back) * Quaternion.AngleAxis(-deltaAngle, Vector3.up));
            cap1.ApplyOffset(Vector3.right * ringRadius);
            cap2.ApplyRotation(Quaternion.LookRotation(Vector3.up, Quaternion.AngleAxis(cutAngle * Mathf.Rad2Deg, Vector3.up) * Vector3.forward) * Quaternion.AngleAxis(deltaAngle * Mathf.Rad2Deg, Vector3.up));
            cap2.ApplyOffset(new Vector3(ringRadius * Mathf.Cos(cutAngle), 0, -ringRadius * Mathf.Sin(cutAngle)));

            Vertex corner1 = structure.CreateVertex();
            Vertex corner2 = structure.CreateVertex();
            structure.CreateFace(face, false, corner1, corner2, corner2, corner1);
            structure.CreateFace(cap1, false, corner1);
            structure.CreateFace(cap2, false, corner2);
        }
        return(structure.Build());
    }