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);
    }
    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);
    }
Beispiel #3
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);
    }
Beispiel #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);
    }
Beispiel #5
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);
    }
    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 void CreateFace(SurfaceComponentGeometry surfaceComponent, bool useAutoAdjust, params Vertex[] verts)
    {
        if (surfaceComponent.boundaries.Count != verts.Length)
        {
            throw new Exception("Edge count doesn't match!");
        }
        var  t       = FindBoundaryHalfedge(vertices[0], vertices[0]);
        Face newFace = CreateFace(verts);

        SetFaceComponent(newFace, surfaceComponent, useAutoAdjust);
    }
Beispiel #8
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);
    }
Beispiel #9
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);
    }
    public static SurfaceComponentGeometry CreateSphereSideGeometry(
        float radius, float angleTop, float angleBottom, int segmentP, int segmentH, float cutAngle = 0, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Smooth)
    {
        SurfaceComponentGeometry geometry = CreatePlaneGeometry(1, 1, segmentH, segmentP, 1, faceType);

        SpaceWarp warp = new SpaceWarp(
            $" th={angleTop}+(x+0.5)*{angleBottom - angleTop}",
            $" phi=(z+0.5)*(2*PI-{cutAngle})",
            $" X={radius}*sin(th)*cos(phi)",
            $" Y={radius}*cos(th)",
            $" Z={radius}*sin(th)*sin(phi)");

        geometry.ApplySpaceWarp(warp);
        return(geometry);
    }
    public void SetFaceComponent(Face face, SurfaceComponentGeometry surfaceComponent, bool useAutoAdjust)
    {
        surfaceComponents.Add(face, surfaceComponent);
        int i = 0;

        foreach (Halfedge e in face.edges)
        {
            AddVertexMapping(e.prev.vertex, surfaceComponent.boundaries[i][0].vertex);
            connections.Add(e, surfaceComponent.boundaries[i++]);
        }
        if (useAutoAdjust)
        {
            surfaceComponent.AutoAdjust(face.vertices.ToArray());
        }
    }
    public static SurfaceComponentGeometry CreateConeSideGeometry(
        float radiusBottom, float radiusTop, float height, int segmentP, int segmentH, float cutAngle = 0, bool flipped = false, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Smooth)
    {
        SurfaceComponentGeometry geometry = CreatePlaneGeometry(1, 1, segmentH, segmentP, 1, faceType);

        SpaceWarp warp = new SpaceWarp(
            $" phi=(z+0.5)*(2*PI-{cutAngle})",
            $" r={(radiusBottom + radiusTop) / 2}+x*{radiusBottom - radiusTop}",
            $" X=r*cos(phi)",
            $" Y={(flipped ? height : -height)}*x",
            $" Z=r*sin(phi)");

        geometry.ApplySpaceWarp(warp);
        return(geometry);
    }
Beispiel #13
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 RenderGeometry CreateConeGeometry(float radius, float height, int segmentP, int segmentH, bool smoothH, bool smoothV, float cutTop = 0, float cutAngle = 0)
    {
        if (cutTop == 0)
        {
            StructureGeometry       structure = new StructureGeometry();
            RenderGeometry.FaceType faceType  = GetFaceType(smoothH, smoothV);

            SurfaceComponentGeometry coneCap = SurfaceComponentGeometries.CreateConeCapGeometry(radius, height, segmentP, segmentH, cutAngle, 1, faceType);
            if (cutAngle == 0)
            {
                SurfaceComponentGeometry bottom = SurfaceComponentGeometries.CreateRegularPolygonGeometry(radius, segmentP, 2);
                bottom.ApplyRotation(Quaternion.AngleAxis(180, Vector3.right));

                Vertex corner = structure.CreateVertex();
                structure.CreateFace(coneCap, false, corner);
                structure.CreateFace(bottom, false, corner);
            }
            else
            {
                SurfaceComponentGeometry bottom = SurfaceComponentGeometries.CreateFanCapGeometry(radius, segmentP, 1, cutAngle, 2);
                SurfaceComponentGeometry wall1  = SurfaceComponentGeometries.CreateTriangleGeometry(1, 1, 0, segmentH, true, 3);
                SurfaceComponentGeometry wall2  = SurfaceComponentGeometries.CreateTriangleGeometry(1, 1, 0, segmentH, true, 4);

                Vertex cornerUp    = structure.CreateVertex(new Vector3(0, height, 0));
                Vertex cornerDownC = structure.CreateVertex(Vector3.zero);
                Vertex cornerDown1 = structure.CreateVertex(new Vector3(radius * Mathf.Cos(cutAngle), 0, -radius * Mathf.Sin(cutAngle)));
                Vertex cornerDown2 = structure.CreateVertex(new Vector3(radius, 0, 0));

                structure.CreateFace(coneCap, true, cornerDown1, cornerDown2, cornerUp);
                structure.CreateFace(bottom, true, cornerDown2, cornerDown1, cornerDownC);
                structure.CreateFace(wall1, true, cornerDown1, cornerUp, cornerDownC);
                structure.CreateFace(wall2, true, cornerDownC, cornerUp, cornerDown2);
            }
            return(structure.Build());
        }
        else
        {
            RenderGeometry geometry = CreateCylinderGeometry(radius, height, segmentP, segmentH, smoothH, smoothV, cutAngle);
            geometry.ApplyOffset(Vector3.up * (height / 2));

            float     shrinkCoeff = (1 - cutTop) / height;
            SpaceWarp warp        = new SpaceWarp($"x*(1-y*{shrinkCoeff})", "y", $"z*(1-y*{shrinkCoeff})");
            geometry.ApplySpaceWarp(warp);
            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);
    }
Beispiel #16
0
    public static SurfaceComponentGeometry CreatePantagonSquareGeometry(
        float sizeX, float sizeZ, int segmentX, int segmentZ, float pantagonRatio = 0.3f, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Polygonal)
    {
        SurfaceComponentGeometry planeGeometry = SurfaceComponentGeometries.CreatePlaneGeometry(sizeX, sizeZ, segmentX * 2, segmentZ * 2, surfaceGroup, faceType);
        var originalVertexList = new List <Vertex>(planeGeometry.vertices);

        Vertex corner(int x, int z) => originalVertexList[x * (segmentZ * 2 + 1) + z];

        float deltaX = sizeX / (segmentX * 2) * pantagonRatio;
        float deltaZ = sizeZ / (segmentZ * 2) * pantagonRatio;

        for (int x = 1; x < segmentX * 2; x++)
        {
            for (int z = 1; z < segmentZ * 2; z++)
            {
                if (x % 2 == 0 && z % 2 == 1)
                {
                    corner(x, z).p += deltaX * ((x + z) % 4 == 3 ? Vector3.left : Vector3.right);
                }
                else if (x % 2 == 1 && z % 2 == 0)
                {
                    corner(x, z).p += deltaZ * ((x + z) % 4 == 3 ? Vector3.forward : Vector3.back);
                }
            }
        }
        for (int x = 0; x < segmentX; x++)
        {
            for (int z = 0; z < segmentZ; z++)
            {
                if ((x + z) % 2 == 0)
                {
                    planeGeometry.MergeFaces(planeGeometry.FindHalfedge(corner(x * 2 + 1, z * 2 + 1), corner(x * 2 + 1, z * 2)));
                    planeGeometry.MergeFaces(planeGeometry.FindHalfedge(corner(x * 2 + 1, z * 2 + 1), corner(x * 2 + 1, z * 2 + 2)));
                }
                else
                {
                    planeGeometry.MergeFaces(planeGeometry.FindHalfedge(corner(x * 2 + 1, z * 2 + 1), corner(x * 2, z * 2 + 1)));
                    planeGeometry.MergeFaces(planeGeometry.FindHalfedge(corner(x * 2 + 1, z * 2 + 1), corner(x * 2 + 2, z * 2 + 1)));
                }
            }
        }
        return(planeGeometry);
    }
    public static RenderGeometry CreateSpringGeometry(float ringRadius, float barRadius, float heightPerCycle, int segmentPerCycle, int segmentBar, bool smoothH, bool smoothV, float angle = 0, float deltaAngle = 0)
    {
        StructureGeometry structure = new StructureGeometry();

        RenderGeometry.FaceType faceType = GetFaceType(smoothH, smoothV);
        float heightPerRad = heightPerCycle / (2 * Mathf.PI);
        float slope        = heightPerRad / ringRadius;
        float scaleH       = Mathf.Sqrt(1 + slope * slope);
        int   segmentRing  = Mathf.CeilToInt(segmentPerCycle * angle / (2 * Mathf.PI) - 1e-6f);

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

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

        face.ApplySpaceWarp(warp);

        SurfaceComponentGeometry cap1 = SurfaceComponentGeometries.CreateRegularPolygonGeometry(barRadius, segmentBar, 2);
        SurfaceComponentGeometry cap2 = SurfaceComponentGeometries.CreateRegularPolygonGeometry(barRadius, segmentBar, 2);

        cap1.ApplyLinearTransform(
            Matrix4x4.Translate(Vector3.right * ringRadius) *
            Matrix4x4.Scale(new Vector3(1, scaleH, 1)) *
            Matrix4x4.Rotate(Quaternion.LookRotation(Vector3.down, Vector3.back) * Quaternion.AngleAxis(-deltaAngle * Mathf.Rad2Deg, Vector3.up)));
        cap2.ApplyLinearTransform(
            Matrix4x4.Translate(new Vector3(ringRadius * Mathf.Cos(angle), heightPerRad * angle, ringRadius * Mathf.Sin(angle))) *
            Matrix4x4.Scale(new Vector3(1, scaleH, 1)) *
            Matrix4x4.Rotate(Quaternion.LookRotation(Vector3.up, Quaternion.AngleAxis(angle * Mathf.Rad2Deg, Vector3.down) * Vector3.forward) * Quaternion.AngleAxis(deltaAngle * Mathf.Rad2Deg, Vector3.up)));

        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());
    }
Beispiel #18
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);
    }
    public static SurfaceComponentGeometry CreateSphereCapGeometry(
        float radius, int segmentP, int segmentH, float angle = Mathf.PI, float cutAngle = 0, int surfaceGroup = 0, RenderGeometry.FaceType faceType = RenderGeometry.FaceType.Smooth,
        bool splitBoundary = false)
    {
        SurfaceComponentGeometry geometry = CreateFanCapGeometry(1, segmentP, segmentH, cutAngle, surfaceGroup, faceType, splitBoundary);

        Vector3 spherify(Vector3 pos, out Matrix4x4 localTransform)
        {
            float th  = pos.magnitude * angle / 2;
            float phi = Mathf.Atan2(pos.z, pos.x);

            Vector3 newPos = radius * new Vector3(Mathf.Sin(th) * Mathf.Cos(phi), Mathf.Cos(th), Mathf.Sin(th) * Mathf.Sin(phi));

            localTransform = Matrix4x4.Rotate(Quaternion.FromToRotation(Vector3.up, newPos));
            return(newPos);
        }

        geometry.ApplyPositionTransform(spherify);
        return(geometry);
    }
Beispiel #20
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);
    }
    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());
    }
    public static RenderGeometry CreateCapsuleGeometry(float radius, float height, int segmentP, int segmentH1, int segmentH2, bool smoothH, bool smoothV)
    {
        StructureGeometry structure = new StructureGeometry();

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

        SurfaceComponentGeometry side = SurfaceComponentGeometries.CreateCylinderSideGeometry(radius, height, segmentP, segmentH1, faceType: faceType);

        SurfaceComponentGeometry upperCap = SurfaceComponentGeometries.CreateSphereCapGeometry(radius, segmentP, segmentH2, faceType: faceType);
        SurfaceComponentGeometry lowerCap = SurfaceComponentGeometries.CreateSphereCapGeometry(radius, segmentP, segmentH2, faceType: faceType);

        lowerCap.ApplyRotation(Quaternion.AngleAxis(180, Vector3.right));

        Vertex cornerUp   = structure.CreateVertex(new Vector3(radius, height / 2, 0));
        Vertex cornerDown = structure.CreateVertex(new Vector3(radius, -height / 2, 0));

        structure.CreateFace(side, false, cornerUp, cornerUp, cornerDown, cornerDown);
        structure.CreateFace(upperCap, true, cornerUp);
        structure.CreateFace(lowerCap, true, cornerDown);
        return(structure.Build());
    }
    private static void CreateStraightPlatformPart(
        StructureGeometry structure,
        Vertex cornerTopLeft1, Vertex cornerTopLeft2, Vertex cornerTopRight1, Vertex cornerTopRight2,
        Vertex cornerBottomLeft1, Vertex cornerBottomLeft2, Vertex cornerBottomRight1, Vertex cornerBottomRight2,
        bool addLeftSide, bool addRightSide, int segmentLength, RenderGeometry.FaceType sideFaceType)
    {
        SurfaceComponentGeometry topFace    = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, segmentLength, 0, sideFaceType);
        SurfaceComponentGeometry bottomFace = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, segmentLength, 1, sideFaceType);

        if (cornerTopLeft1 == cornerBottomLeft1)
        {
            // Copy vertices since it is a flat face.
            Vertex cornerLeft1  = structure.CreateVertex(cornerBottomLeft1.p);
            Vertex cornerLeft2  = structure.CreateVertex(cornerBottomLeft2.p);
            Vertex cornerRight1 = structure.CreateVertex(cornerBottomRight1.p);
            Vertex cornerRight2 = structure.CreateVertex(cornerBottomRight2.p);
            structure.CreateFace(topFace, true, cornerLeft1, cornerLeft2, cornerRight2, cornerRight1);
            structure.CreateFace(bottomFace, true, cornerRight1, cornerRight2, cornerLeft2, cornerLeft1);
        }
        else
        {
            SurfaceComponentGeometry backFace  = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, 1, 4, RenderGeometry.FaceType.Polygonal);
            SurfaceComponentGeometry frontFace = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, 1, 5, RenderGeometry.FaceType.Polygonal);
            structure.CreateFace(topFace, true, cornerTopLeft1, cornerTopLeft2, cornerTopRight2, cornerTopRight1);
            structure.CreateFace(bottomFace, true, cornerBottomRight1, cornerBottomRight2, cornerBottomLeft2, cornerBottomLeft1);
            structure.CreateFace(backFace, true, cornerBottomLeft1, cornerTopLeft1, cornerTopRight1, cornerBottomRight1);
            structure.CreateFace(frontFace, true, cornerBottomRight2, cornerTopRight2, cornerTopLeft2, cornerBottomLeft2);

            if (addLeftSide)
            {
                SurfaceComponentGeometry leftFace = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, segmentLength, 2, sideFaceType);
                structure.CreateFace(leftFace, true, cornerBottomLeft1, cornerBottomLeft2, cornerTopLeft2, cornerTopLeft1);
            }
            if (addRightSide)
            {
                SurfaceComponentGeometry rightFace = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, segmentLength, 3, sideFaceType);
                structure.CreateFace(rightFace, true, cornerTopRight1, cornerTopRight2, cornerBottomRight2, cornerBottomRight1);
            }
        }
    }
Beispiel #24
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 void CreateFace(SurfaceComponentGeometry surfaceComponent, bool useAutoAdjust, bool inverse, params Vertex[] verts)
 {
     CreateFace(surfaceComponent, useAutoAdjust, inverse ? verts.Reverse().ToArray() : verts);
 }
    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);
    }
    public static RenderGeometry CreateCylinderGeometry(float radius, float height, int segmentP, int segmentH, bool smoothH, bool smoothV, float cutAngle = 0, float hollowRatio = 0)
    {
        StructureGeometry structure = new StructureGeometry();

        RenderGeometry.FaceType faceType = GetFaceType(smoothH, smoothV);
        float hollowRadius = hollowRatio * radius;

        SurfaceComponentGeometry side      = SurfaceComponentGeometries.CreateCylinderSideGeometry(radius, height, segmentP, segmentH, cutAngle, false, 1, faceType);
        SurfaceComponentGeometry sideInner = null;

        if (hollowRatio > 0)
        {
            sideInner = SurfaceComponentGeometries.CreateCylinderSideGeometry(hollowRadius, height, segmentP, segmentH, cutAngle, true, 1, faceType);
        }
        SurfaceComponentGeometry upperCap, lowerCap;

        if (hollowRatio > 0)
        {
            upperCap = SurfaceComponentGeometries.CreateRingCapGeometry(radius, hollowRadius, segmentP, 1, cutAngle, 2);
            lowerCap = SurfaceComponentGeometries.CreateRingCapGeometry(radius, hollowRadius, segmentP, 1, cutAngle, 2);
        }
        else if (cutAngle == 0)
        {
            upperCap = SurfaceComponentGeometries.CreateRegularPolygonGeometry(radius, segmentP, 2);
            lowerCap = SurfaceComponentGeometries.CreateRegularPolygonGeometry(radius, segmentP, 2);
        }
        else
        {
            upperCap = SurfaceComponentGeometries.CreateFanCapGeometry(radius, segmentP, 1, cutAngle, 2);
            lowerCap = SurfaceComponentGeometries.CreateFanCapGeometry(radius, segmentP, 1, cutAngle, 2);
        }
        lowerCap.ApplyRotation(Quaternion.AngleAxis(cutAngle * Mathf.Rad2Deg, Vector3.up) * Quaternion.AngleAxis(180, Vector3.right));

        if (cutAngle == 0)
        {
            Vertex cornerUp   = structure.CreateVertex(new Vector3(radius, height / 2, 0));
            Vertex cornerDown = structure.CreateVertex(new Vector3(radius, -height / 2, 0));
            if (hollowRatio == 0)
            {
                structure.CreateFace(side, false, cornerUp, cornerUp, cornerDown, cornerDown);
                structure.CreateFace(upperCap, true, cornerUp);
                structure.CreateFace(lowerCap, true, cornerDown);
            }
            else
            {
                Vertex cornerUpInner   = structure.CreateVertex(new Vector3(hollowRadius, height / 2, 0));
                Vertex cornerDownInner = structure.CreateVertex(new Vector3(hollowRadius, -height / 2, 0));
                structure.CreateFace(side, false, cornerUp, cornerUp, cornerDown, cornerDown);
                structure.CreateFace(sideInner, false, cornerDownInner, cornerDownInner, cornerUpInner, cornerUpInner);
                structure.CreateFace(upperCap, true, cornerUpInner, cornerUpInner, cornerUp, cornerUp);
                structure.CreateFace(lowerCap, true, cornerDownInner, cornerDownInner, cornerDown, cornerDown);
            }
        }
        else
        {
            SurfaceComponentGeometry wall1 = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, segmentH, 3);
            SurfaceComponentGeometry wall2 = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, segmentH, 4);

            Vertex cornerUp1   = structure.CreateVertex(new Vector3(radius * Mathf.Cos(cutAngle), height / 2, -radius * Mathf.Sin(cutAngle)));
            Vertex cornerUp2   = structure.CreateVertex(new Vector3(radius, height / 2, 0));
            Vertex cornerDown1 = structure.CreateVertex(new Vector3(radius * Mathf.Cos(cutAngle), -height / 2, -radius * Mathf.Sin(cutAngle)));
            Vertex cornerDown2 = structure.CreateVertex(new Vector3(radius, -height / 2, 0));
            if (hollowRatio == 0)
            {
                Vertex cornerUpC   = structure.CreateVertex(new Vector3(0, height / 2, 0));
                Vertex cornerDownC = structure.CreateVertex(new Vector3(0, -height / 2, 0));
                structure.CreateFace(side, false, cornerUp2, cornerUp1, cornerDown1, cornerDown2);
                structure.CreateFace(upperCap, true, cornerUp1, cornerUp2, cornerUpC);
                structure.CreateFace(lowerCap, true, cornerDown2, cornerDown1, cornerDownC);
                structure.CreateFace(wall1, true, cornerUpC, cornerDownC, cornerDown1, cornerUp1);
                structure.CreateFace(wall2, true, cornerDownC, cornerUpC, cornerUp2, cornerDown2);
            }
            else
            {
                Vertex cornerUp1Inner   = structure.CreateVertex(new Vector3(hollowRadius * Mathf.Cos(cutAngle), height / 2, -hollowRadius * Mathf.Sin(cutAngle)));
                Vertex cornerUp2Inner   = structure.CreateVertex(new Vector3(hollowRadius, height / 2, 0));
                Vertex cornerDown1Inner = structure.CreateVertex(new Vector3(hollowRadius * Mathf.Cos(cutAngle), -height / 2, -hollowRadius * Mathf.Sin(cutAngle)));
                Vertex cornerDown2Inner = structure.CreateVertex(new Vector3(hollowRadius, -height / 2, 0));
                structure.CreateFace(side, false, cornerUp2, cornerUp1, cornerDown1, cornerDown2);
                structure.CreateFace(sideInner, false, cornerDown2Inner, cornerDown1Inner, cornerUp1Inner, cornerUp2Inner);
                structure.CreateFace(upperCap, true, cornerUp2Inner, cornerUp1Inner, cornerUp1, cornerUp2);
                structure.CreateFace(lowerCap, true, cornerDown1Inner, cornerDown2Inner, cornerDown2, cornerDown1);
                structure.CreateFace(wall1, true, cornerUp1Inner, cornerDown1Inner, cornerDown1, cornerUp1);
                structure.CreateFace(wall2, true, cornerDown2Inner, cornerUp2Inner, cornerUp2, cornerDown2);
            }
        }
        return(structure.Build());
    }
    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);
    }
    private static void CreateStraightRampPart(
        StructureGeometry structure, bool isLeftRamp,
        Vertex cornerTopLeft1, Vertex cornerTopLeft2, Vertex cornerTopRight1, Vertex cornerTopRight2,
        Vertex cornerBottomLeft1, Vertex cornerBottomLeft2, Vertex cornerBottomRight1, Vertex cornerBottomRight2,
        bool addLeftSide, bool addRightSide, int segmentWidth, int segmentLength, float curvature, RenderGeometry.FaceType rampFaceType, RenderGeometry.FaceType sideFaceType)
    {
        bool hasBase = (cornerTopLeft1 != cornerBottomLeft1) && (cornerTopRight1 != cornerBottomRight1);

        SurfaceComponentGeometry rampFace = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, segmentWidth, segmentLength, 0, rampFaceType);
        SurfaceComponentGeometry rampBottom = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, segmentLength, 1, sideFaceType);
        SurfaceComponentGeometry rampLeftSide = null, rampRightSide = null;

        if (addLeftSide && (cornerTopLeft1 != cornerBottomLeft1))
        {
            rampLeftSide = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, segmentLength, 2, sideFaceType);
        }
        if (addRightSide && (cornerTopRight1 != cornerBottomRight1))
        {
            rampRightSide = SurfaceComponentGeometries.CreatePlaneGeometry(1, 1, 1, segmentLength, 3, sideFaceType);
        }

        if (curvature != 0)
        {
            float angle = -curvature * Mathf.PI / 2;
            rampFace.ApplySpaceWarp(new SpaceWarp($"sin(x*{angle})/{angle}", $"(1-cos(x*{angle}))/{angle}", "z"));
        }
        // Fit to a 45 degree ramp, then scale.
        rampFace.ApplyLinearTransform(
            Matrix4x4.Translate(cornerTopLeft1.p) *
            Matrix4x4.Scale(VectorUtil.Abs(cornerTopRight2.p - cornerTopLeft1.p)) *
            MatrixUtil.PointToPointTransform(
                rampFace.corners[0].p, rampFace.corners[3].p, rampFace.corners[1].p,
                Vector3.zero, new Vector3(1, isLeftRamp ? 1 : -1, 0), Vector3.forward));

        structure.CreateFace(rampFace, false, cornerTopLeft1, cornerTopLeft2, cornerTopRight2, cornerTopRight1);
        structure.CreateFace(rampBottom, true, cornerBottomRight1, cornerBottomRight2, cornerBottomLeft2, cornerBottomLeft1);
        if (rampLeftSide != null)
        {
            structure.CreateFace(rampLeftSide, true, cornerBottomLeft1, cornerBottomLeft2, cornerTopLeft2, cornerTopLeft1);
        }
        if (rampRightSide != null)
        {
            structure.CreateFace(rampRightSide, true, cornerTopRight1, cornerTopRight2, cornerBottomRight2, cornerBottomRight1);
        }

        var backVertices = new List <Vector3>();

        backVertices.Add(isLeftRamp ? cornerBottomRight1.p : cornerBottomLeft1.p);
        if (isLeftRamp && hasBase)
        {
            backVertices.Add(cornerBottomLeft1.p);
        }
        backVertices.Add(rampFace.boundaries[3].Last().prev.vertex.p);
        backVertices.AddRange(rampFace.boundaries[3].Select(e => e.vertex.p).Reverse());
        if (!isLeftRamp && hasBase)
        {
            backVertices.Add(cornerBottomRight1.p);
        }
        var movedBackVertices = backVertices.Select(p => p + (cornerTopLeft2.p - cornerTopLeft1.p));
        var frontVertices = movedBackVertices.Take(1).Concat(movedBackVertices.Reverse().Take(backVertices.Count - 1)).ToList();

        SurfaceComponentGeometry backFace  = SurfaceComponentGeometries.CreateStarConvexPolygonGeometry(backVertices, 4, RenderGeometry.FaceType.Smooth);
        SurfaceComponentGeometry frontFace = SurfaceComponentGeometries.CreateStarConvexPolygonGeometry(frontVertices, 5, RenderGeometry.FaceType.Smooth);

        if (hasBase)
        {
            if (isLeftRamp)
            {
                backFace.CombineBoundaries(1, 1, segmentWidth, 1);
                frontFace.CombineBoundaries(1, segmentWidth, 1, 1);
                structure.CreateFace(backFace, false, cornerBottomRight1, cornerBottomLeft1, cornerTopLeft1, cornerTopRight1);
                structure.CreateFace(frontFace, false, cornerBottomRight2, cornerTopRight2, cornerTopLeft2, cornerBottomLeft2);
            }
            else
            {
                backFace.CombineBoundaries(1, segmentWidth, 1, 1);
                frontFace.CombineBoundaries(1, 1, segmentWidth, 1);
                structure.CreateFace(backFace, false, cornerBottomLeft1, cornerTopLeft1, cornerTopRight1, cornerBottomRight1);
                structure.CreateFace(frontFace, false, cornerBottomLeft2, cornerBottomRight2, cornerTopRight2, cornerTopLeft2);
            }
        }
        else
        {
            backFace.CombineBoundaries(1, segmentWidth, 1);
            frontFace.CombineBoundaries(1, segmentWidth, 1);
            structure.CreateFace(backFace, false, isLeftRamp ? cornerBottomRight1 : cornerBottomLeft1, cornerTopLeft1, cornerTopRight1);
            structure.CreateFace(frontFace, false, isLeftRamp ? cornerBottomRight2 : cornerBottomLeft2, cornerTopRight2, cornerTopLeft2);
        }
    }