public static SurfaceComponentGeometry CreateStarConvexPolygonGeometry(List <Vector3> vertices, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        SurfaceComponentGeometry geometry = new SurfaceComponentGeometry();
        bool normalRequired = (faceType != RenderGeometry.FaceType.Polygonal && faceType != RenderGeometry.FaceType.Triangular);

        foreach (Vector3 vertex in vertices)
        {
            geometry.CreateVertex(vertex);
        }
        for (int i = 1; i < vertices.Count - 1; i++)
        {
            Face f = geometry.CreateFace(geometry.vertices[0], geometry.vertices[i], geometry.vertices[i + 1]);
            f.surfaceGroup = surfaceGroup;
            geometry.SetFaceType(f, faceType);
        }
        if (normalRequired)
        {
            Vector3 normal = Vector3.Cross(geometry.vertices[1].p - geometry.vertices[0].p, geometry.vertices[vertices.Count - 1].p - geometry.vertices[0].p).normalized;
            foreach (Halfedge e in geometry.halfedges)
            {
                geometry.SetNormal(e, normal);
            }
        }
        geometry.DefineBoundaries(geometry.vertices[0]);
        geometry.SplitBoundaries();
        return(geometry);
    }
    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 SurfaceComponentGeometry CreateRegularPolygonGeometry(
        float radius, int segmentP, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal, bool splitBoundary = false)
    {
        SurfaceComponentGeometry geometry = new SurfaceComponentGeometry();
        bool normalRequired = (faceType != RenderGeometry.FaceType.Polygonal && faceType != RenderGeometry.FaceType.Triangular);

        float dth = 2 * Mathf.PI / segmentP;

        for (int i = 0; i < segmentP; i++)
        {
            geometry.CreateVertex(new Vector3(radius * Mathf.Cos(dth * i), 0, -radius * Mathf.Sin(dth * i)));
        }

        Face f = geometry.CreateFace(geometry.vertices.ToArray());

        f.surfaceGroup = surfaceGroup;
        geometry.SetFaceType(f, faceType);

        if (normalRequired)
        {
            foreach (Halfedge e in geometry.halfedges)
            {
                geometry.SetNormal(e, Vector3.up);
            }
        }
        geometry.DefineBoundaries(geometry.vertices[0]);
        if (splitBoundary)
        {
            geometry.SplitBoundaries();
        }
        return(geometry);
    }
Example #4
0
    public static SurfaceComponentGeometry CreateDiamondCenterOctaSplitSquareGeometry(
        float sizeX, float sizeZ, int segmentX, int segmentZ, float diamondRatio = 0.6f, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        SurfaceComponentGeometry planeGeometry = SurfaceComponentGeometries.CreatePlaneGeometry(sizeX, sizeZ, segmentX, segmentZ);
        List <Vertex>            corners       = planeGeometry.corners;

        var structure    = new StructureGeometry(planeGeometry);
        var edgesToMerge = new List <Halfedge>();

        structure.faces.ForEach(f => {
            var component = CreateSingleDiamondCenterOctaSplitSquareGeometry(1, 1, diamondRatio, surfaceGroup, faceType);
            edgesToMerge.AddRange(component.boundaries.SelectMany(b => b).Select(e => e.opposite));
            structure.SetFaceComponent(f, component, true);
        });
        var geometry = new SurfaceComponentGeometry(structure.Build());

        foreach (Halfedge edge in edgesToMerge)
        {
            if (edge.index >= 0 && !edge.opposite.isBoundary)
            {
                geometry.MergeFaces(edge);
            }
        }
        geometry.DefineBoundaries(corners.Select(structure.GetBuiltVertex).ToArray());

        return(geometry);
    }
Example #5
0
    public static SurfaceComponentGeometry CreateSingleDiamondCenterOctaSplitSquareGeometry(
        float sizeX, float sizeZ, float diamondRatio = 0.6f, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        var geometry = new SurfaceComponentGeometry();

        var outerRing = new Vertex[] {
            geometry.CreateVertex(new Vector3(0, 0, -sizeZ / 2)),
            geometry.CreateVertex(new Vector3(-sizeX / 2, 0, -sizeZ / 2)),
            geometry.CreateVertex(new Vector3(-sizeX / 2, 0, 0)),
            geometry.CreateVertex(new Vector3(-sizeX / 2, 0, sizeZ / 2)),
            geometry.CreateVertex(new Vector3(0, 0, sizeZ / 2)),
            geometry.CreateVertex(new Vector3(sizeX / 2, 0, sizeZ / 2)),
            geometry.CreateVertex(new Vector3(sizeX / 2, 0, 0)),
            geometry.CreateVertex(new Vector3(sizeX / 2, 0, -sizeZ / 2))
        };
        var innerRing = outerRing.Select((vertex, index) => geometry.CreateVertex(vertex.p * (index % 2 == 0 ? diamondRatio : diamondRatio / 2))).ToArray();

        for (int i = 0; i < 8; i++)
        {
            geometry.CreateFace(outerRing[i], outerRing[(i + 1) % 8], innerRing[(i + 1) % 8], innerRing[i]);
        }
        geometry.CreateFace(innerRing);

        geometry.DefineBoundaries(outerRing[1], outerRing[3], outerRing[5], outerRing[7]);
        return(geometry);
    }
Example #6
0
    public static SurfaceComponentGeometry CreateSingleDiamondCenterCrossSplitSquareGeometry(
        float sizeX, float sizeZ, float diamondRatio = 0.6f, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        var geometry = new SurfaceComponentGeometry();

        Vertex bottomLeft   = geometry.CreateVertex(new Vector3(-sizeX / 2, 0, -sizeZ / 2));
        Vertex bottom       = geometry.CreateVertex(new Vector3(0, 0, -sizeZ / 2));
        Vertex bottomRight  = geometry.CreateVertex(new Vector3(sizeX / 2, 0, -sizeZ / 2));
        Vertex left         = geometry.CreateVertex(new Vector3(-sizeX / 2, 0, 0));
        Vertex right        = geometry.CreateVertex(new Vector3(sizeX / 2, 0, 0));
        Vertex topLeft      = geometry.CreateVertex(new Vector3(-sizeX / 2, 0, sizeZ / 2));
        Vertex top          = geometry.CreateVertex(new Vector3(0, 0, sizeZ / 2));
        Vertex topRight     = geometry.CreateVertex(new Vector3(sizeX / 2, 0, sizeZ / 2));
        Vertex centerLeft   = geometry.CreateVertex(new Vector3(-diamondRatio * sizeX / 2, 0, 0));
        Vertex centerRight  = geometry.CreateVertex(new Vector3(diamondRatio * sizeX / 2, 0, 0));
        Vertex centerBottom = geometry.CreateVertex(new Vector3(0, 0, -diamondRatio * sizeZ / 2));
        Vertex centerTop    = geometry.CreateVertex(new Vector3(0, 0, diamondRatio * sizeZ / 2));

        geometry.CreateFace(bottomLeft, left, centerLeft, centerBottom, bottom);
        geometry.CreateFace(topLeft, top, centerTop, centerLeft, left);
        geometry.CreateFace(topRight, right, centerRight, centerTop, top);
        geometry.CreateFace(bottomRight, bottom, centerBottom, centerRight, right);
        geometry.CreateFace(centerBottom, centerLeft, centerTop, centerRight);

        geometry.DefineBoundaries(bottomLeft, topLeft, topRight, bottomRight);
        return(geometry);
    }
Example #7
0
    public static SurfaceComponentGeometry CreateSplitTriangleGeometry(
        float sizeBase, float sizeHeight, float offsetTop, int segment, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        SurfaceComponentGeometry triangleGeometry = SurfaceComponentGeometries.CreateTriangleGeometry(sizeBase, sizeHeight, offsetTop, segment, false);
        List <Vertex>            corners          = triangleGeometry.corners;

        var structure = new StructureGeometry(triangleGeometry);

        structure.faces.ForEach(f => structure.SetFaceComponent(f, CreateSingleSplitTriangleGeometry(1, 1, 0, surfaceGroup, faceType), true));
        var geometry = new SurfaceComponentGeometry(structure.Build());

        geometry.DefineBoundaries(corners.Select(structure.GetBuiltVertex).ToArray());

        return(geometry);
    }
Example #8
0
    public static SurfaceComponentGeometry CreateDiamondCenterCrossSplitSquareGeometry(
        float sizeX, float sizeZ, int segmentX, int segmentZ, float diamondRatio = 0.6f, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        SurfaceComponentGeometry planeGeometry = SurfaceComponentGeometries.CreatePlaneGeometry(sizeX, sizeZ, segmentX, segmentZ);
        List <Vertex>            corners       = planeGeometry.corners;

        var structure = new StructureGeometry(planeGeometry);

        structure.faces.ForEach(f => structure.SetFaceComponent(f, CreateSingleDiamondCenterCrossSplitSquareGeometry(1, 1, diamondRatio, surfaceGroup, faceType), true));
        var geometry = new SurfaceComponentGeometry(structure.Build());

        geometry.DefineBoundaries(corners.Select(structure.GetBuiltVertex).ToArray());

        return(geometry);
    }
Example #9
0
    public static SurfaceComponentGeometry CreateTrianglesCombinedRegularPolygonGeometry(float radius, int segmentP, Func <SurfaceComponentGeometry> triangleSurfaceComponentProvider)
    {
        SurfaceComponentGeometry polygonGeometry = SurfaceComponentGeometries.CreateFanCapGeometry(radius, segmentP, 1);

        polygonGeometry.SplitBoundaries();
        List <Vertex> corners = polygonGeometry.corners;

        var structure = new StructureGeometry(polygonGeometry);

        structure.faces.ForEach(f => structure.SetFaceComponent(f, triangleSurfaceComponentProvider(), true));
        var geometry = new SurfaceComponentGeometry(structure.Build());

        geometry.DefineBoundaries(corners.Select(structure.GetBuiltVertex).ToArray());

        return(geometry);
    }
    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);
    }
Example #11
0
    public static SurfaceComponentGeometry CreateSingleSplitTriangleGeometry(
        float sizeBase, float sizeHeight, float offsetTop, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        var geometry = new SurfaceComponentGeometry();

        Vertex baseLeft   = geometry.CreateVertex(new Vector3(-sizeBase / 2, 0, 0));
        Vertex baseCenter = geometry.CreateVertex(Vector3.zero);
        Vertex baseRight  = geometry.CreateVertex(new Vector3(sizeBase / 2, 0, 0));
        Vertex top        = geometry.CreateVertex(new Vector3(offsetTop * sizeBase, 0, sizeHeight));
        Vertex sideLeft   = geometry.CreateVertex(Vector3.Lerp(baseLeft.p, top.p, 0.5f));
        Vertex sideRight  = geometry.CreateVertex(Vector3.Lerp(baseRight.p, top.p, 0.5f));
        Vertex center     = geometry.CreateVertex(top.p / 3);

        geometry.CreateFace(baseLeft, sideLeft, center, baseCenter);
        geometry.CreateFace(baseRight, baseCenter, center, sideRight);
        geometry.CreateFace(top, sideRight, center, sideLeft);

        geometry.DefineBoundaries(baseLeft, top, baseRight);
        return(geometry);
    }
Example #12
0
    public static SurfaceComponentGeometry CreateXSplitSquareGeometry(
        float sizeX, float sizeZ, int segmentX, int segmentZ, float spikeHeight = 0, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        var           planeGeometry = SurfaceComponentGeometries.CreatePlaneGeometry(sizeX, sizeZ, segmentX, segmentZ);
        List <Vertex> corners       = planeGeometry.corners;

        var structure  = new StructureGeometry(planeGeometry);
        var coneHeight = spikeHeight / (sizeZ / segmentZ) * Mathf.Sqrt(2);

        structure.faces.ForEach(f => {
            var component = SurfaceComponentGeometries.CreateConeCapGeometry(1, coneHeight, 4, 1, 0, surfaceGroup, faceType);
            component.SplitBoundaries();
            structure.SetFaceComponent(f, component, true);
        });
        var geometry = new SurfaceComponentGeometry(structure.Build());

        geometry.DefineBoundaries(corners.Select(structure.GetBuiltVertex).ToArray());

        return(geometry);
    }
Example #13
0
    public static SurfaceComponentGeometry CreateWallTiledTriangleGeometry(float sizeBase, float sizeHeight, float offsetTop, int segment, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        SurfaceComponentGeometry triangleGeometry = SurfaceComponentGeometries.CreateTriangleGeometry(sizeBase, sizeHeight, offsetTop, segment, true);
        List <Vertex>            corners          = triangleGeometry.corners;

        var      newVertices = new Dictionary <Vector2, Vertex>();
        Halfedge currentEdge = triangleGeometry.FindHalfedge(corners[2], corners[0]);
        Vector3  delta       = -currentEdge.vector / segment / 2;

        for (int i = 0; i < segment; i++)
        {
            Halfedge nextEdge  = currentEdge.next.next.opposite;
            Vector3  leftPoint = currentEdge.vertex.p;
            for (int j = 1; j < (segment - i) * 2; j++)
            {
                if (i == 0 && j % 2 == 1)
                {
                    continue;
                }
                Vertex newVertex = triangleGeometry.SplitEdge(currentEdge);
                newVertex.p            = leftPoint + j * delta;
                newVertices[Key(i, j)] = newVertex;
            }
            currentEdge = nextEdge;
        }

        for (int i = 0; i < segment - 1; i++)
        {
            for (int j = 1; j < segment - i; j++)
            {
                triangleGeometry.SplitFace(newVertices[Key(i, j * 2)], newVertices[Key(i + 1, j * 2 - 1)]);
            }
        }

        triangleGeometry.DefineBoundaries(corners.ToArray());
        return(triangleGeometry);
    }
    public static SurfaceComponentGeometry CreateTriangleGeometry(
        float sizeBase, float sizeHeight, float offsetTop, int segment, bool divideHeightOnly = false, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Smooth)
    {
        SurfaceComponentGeometry geometry = new SurfaceComponentGeometry();
        bool normalRequired = (faceType != RenderGeometry.FaceType.Polygonal && faceType != RenderGeometry.FaceType.Triangular);

        Vector3 corner = new Vector3(-sizeBase / 2, 0, 0);
        Vector3 dx     = new Vector3(sizeBase / segment, 0, 0);
        Vector3 dz     = new Vector3((offsetTop + 0.5f) * sizeBase / segment, 0, sizeHeight / segment);

        if (divideHeightOnly)
        {
            for (int z = 0; z < segment; z++)
            {
                geometry.CreateVertex(corner + dz * z);
                geometry.CreateVertex(corner + dz * z + dx * (segment - z));
            }
            geometry.CreateVertex(corner + dz * segment);

            for (int z = 0; z < segment - 1; z++)
            {
                geometry.CreateFace(geometry.vertices[2 * z], geometry.vertices[2 * z + 2], geometry.vertices[2 * z + 3], geometry.vertices[2 * z + 1]);
            }
            geometry.CreateFace(geometry.vertices[2 * segment - 2], geometry.vertices[2 * segment], geometry.vertices[2 * segment - 1]);
            geometry.DefineBoundaries(geometry.vertices[0], geometry.vertices[2 * segment], geometry.vertices[1]);
        }
        else
        {
            // Full triangular subdivision
            for (int x = 0; x <= segment; x++)
            {
                for (int z = 0; z <= segment - x; z++)
                {
                    geometry.CreateVertex(corner + dx * x + dz * z);
                }
            }
            Vertex vertice(int x, int z) => geometry.vertices[x * (2 * (segment + 1) - (x - 1)) / 2 + z];

            for (int x = 0; x < segment; x++)
            {
                for (int z = 0; z < segment - x; z++)
                {
                    geometry.CreateFace(vertice(x, z), vertice(x, z + 1), vertice(x + 1, z));
                    if (x + z < segment - 1)
                    {
                        geometry.CreateFace(vertice(x + 1, z), vertice(x, z + 1), vertice(x + 1, z + 1));
                    }
                }
            }
            geometry.DefineBoundaries(vertice(0, 0), vertice(0, segment), vertice(segment, 0));
        }

        foreach (Face f in geometry.faces)
        {
            f.surfaceGroup = surfaceGroup;
            geometry.SetFaceType(f, faceType);
        }
        if (normalRequired)
        {
            foreach (Halfedge e in geometry.halfedges)
            {
                geometry.SetNormal(e, Vector3.up);
            }
        }
        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);
    }