Exemplo n.º 1
0
        public static bool GenerateConicalFrustumSubMesh(CSGBrushSubMesh subMesh, CSGCircleDefinition bottom, CSGCircleDefinition top, float rotation, int segments, CSGSurfaceAsset[] surfaceAssets, SurfaceDescription[] surfaceDescriptions)
        {
            if (segments < 3 || (top.height - bottom.height) == 0 || (bottom.diameterX == 0 && top.diameterX == 0) || (bottom.diameterZ == 0 && top.diameterZ == 0))
            {
                subMesh.Clear();
                return(false);
            }

            if (surfaceAssets.Length < 3 ||
                surfaceDescriptions.Length < segments + 2)
            {
                subMesh.Clear();
                return(false);
            }
            // TODO: handle situation where diameterX & diameterZ are 0 (only create one vertex)

            if (top.diameterX == 0)
            {
                var vertices = new Vector3[segments + 1];
                GetConeFrustumVertices(bottom, top.height, rotation, segments, ref vertices, inverse: false);

                // TODO: the polygon/half-edge part would be the same for any extruded shape and should be re-used
                CreateConeSubMesh(subMesh, segments, null, vertices, surfaceAssets, surfaceDescriptions);
            }
            else
            if (bottom.diameterX == 0)
            {
                var vertices = new Vector3[segments + 1];
                GetConeFrustumVertices(top, bottom.height, rotation, segments, ref vertices, inverse: true);

                // TODO: the polygon/half-edge part would be the same for any extruded shape and should be re-used
                CreateConeSubMesh(subMesh, segments, null, vertices, surfaceAssets, surfaceDescriptions);
            }
            else
            {
                if (top.height > bottom.height)
                {
                    var temp = top; top = bottom; bottom = temp;
                }

                var vertices = new Vector3[segments * 2];
                GetConicalFrustumVertices(bottom, top, rotation, segments, ref vertices);

                // TODO: the polygon/half-edge part would be the same for any extruded shape and should be re-used
                CreateExtrudedSubMesh(subMesh, segments, null, 0, 1, vertices, surfaceAssets, surfaceDescriptions);
            }

            return(true);
        }
        public static bool GenerateSphereSubMesh(CSGBrushSubMesh subMesh, Vector3 diameterXYZ, float offsetY, bool generateFromCenter, Matrix4x4 transform, int horzSegments, int vertSegments, CSGSurfaceAsset[] surfaceAssets, SurfaceDescription[] surfaceDescriptions)
        {
            if (diameterXYZ.x == 0 ||
                diameterXYZ.y == 0 ||
                diameterXYZ.z == 0)
            {
                subMesh.Clear();
                return(false);
            }

            var brushMesh = BrushMeshFactory.CreateSphere(diameterXYZ, offsetY, generateFromCenter, horzSegments, vertSegments);

            subMesh.HalfEdges = brushMesh.halfEdges;
            subMesh.Vertices  = brushMesh.vertices;
            subMesh.Polygons  = new CSGBrushSubMesh.Polygon[brushMesh.polygons.Length];

            for (int i = 0; i < brushMesh.polygons.Length; i++)
            {
                subMesh.Polygons[i] = new CSGBrushSubMesh.Polygon
                {
                    surfaceID    = i,
                    edgeCount    = brushMesh.polygons[i].edgeCount,
                    firstEdge    = brushMesh.polygons[i].firstEdge,
                    surfaceAsset = i < surfaceAssets.Length ? surfaceAssets[i] : surfaceAssets[0],
                    description  = i < surfaceDescriptions.Length ? surfaceDescriptions[i] : surfaceDescriptions[0],
                };
            }

            return(true);
        }
Exemplo n.º 3
0
        // TODO: clean up
        public static bool GenerateSegmentedSubMesh(CSGBrushSubMesh subMesh, int horzSegments, int vertSegments, Vector3[] segmentVertices, bool topCap, bool bottomCap, int topVertex, int bottomVertex, CSGSurfaceAsset[] surfaceAssets, SurfaceDescription[] surfaceDescriptions)
        {
            // FIXME: hack, to fix math below ..
            vertSegments++;

            //if (bottomCap || topCap)
            //	vertSegments++;

            int triangleCount, quadCount, capCount, extraVertices;

            capCount      = 0;
            triangleCount = 0;
            extraVertices = 0;
            if (topCap)
            {
                capCount += 1;
            }
            else
            {
                extraVertices += 1;
                triangleCount += horzSegments;
            }

            if (bottomCap)
            {
                capCount += 1;
            }
            else
            {
                extraVertices += 1;
                triangleCount += horzSegments;
            }

            quadCount = horzSegments * (vertSegments - 2);

            var vertexCount       = (horzSegments * (vertSegments - 1)) + extraVertices;
            var assetPolygonCount = triangleCount + quadCount + capCount;
            var halfEdgeCount     = (triangleCount * 3) + (quadCount * 4) + (capCount * horzSegments);

            if (segmentVertices.Length != vertexCount)
            {
                Debug.LogError("segmentVertices.Length (" + segmentVertices.Length + ") != expectedVertexCount (" + vertexCount + ")");
                subMesh.Clear();
                return(false);
            }

            var vertices  = segmentVertices;
            var polygons  = new CSGBrushSubMesh.Polygon[assetPolygonCount];
            var halfEdges = new BrushMesh.HalfEdge[halfEdgeCount];

            var twins = new int[horzSegments];

            var edgeIndex       = 0;
            var polygonIndex    = 0;
            var startVertex     = extraVertices;
            var startSegment    = topCap ? 1 : 0;
            var lastVertSegment = vertSegments - 1;
            var endSegment      = bottomCap ? lastVertSegment : vertSegments;

            if (topCap)
            {
                var polygonEdgeCount = horzSegments;
                for (int h = 0, p = horzSegments - 1; h < horzSegments; p = h, h++)
                {
                    var currEdgeIndex = edgeIndex + (horzSegments - 1) - h;
                    halfEdges[currEdgeIndex] = new BrushMesh.HalfEdge {
                        twinIndex = -1, vertexIndex = startVertex + (horzSegments - 1) - p
                    };
                    twins[h] = currEdgeIndex;
                }
                polygons[polygonIndex] = new CSGBrushSubMesh.Polygon {
                    surfaceID = polygonIndex, firstEdge = edgeIndex, edgeCount = polygonEdgeCount, description = surfaceDescriptions[0], surfaceAsset = surfaceAssets[0]
                };
                edgeIndex += polygonEdgeCount;
                polygonIndex++;
            }

            for (int v = startSegment; v < endSegment; v++)
            {
                var startEdge = edgeIndex;
                for (int h = 0, p = horzSegments - 1; h < horzSegments; p = h, h++)
                {
                    var n = (h + 1) % horzSegments;
                    int polygonEdgeCount;
                    if (v == 0) // top
                    {
                        //          0
                        //          *
                        //         ^ \
                        //     p1 /0 1\ n0
                        //       /  2  v
                        //		*<------*
                        //     2    t    1
                        polygonEdgeCount = 3;
                        var p1 = (p * 3) + 1;
                        var n0 = (n * 3) + 0;
                        halfEdges[edgeIndex + 0] = new BrushMesh.HalfEdge {
                            twinIndex = p1, vertexIndex = topVertex
                        };
                        halfEdges[edgeIndex + 1] = new BrushMesh.HalfEdge {
                            twinIndex = n0, vertexIndex = startVertex + (horzSegments - 1) - h
                        };
                        halfEdges[edgeIndex + 2] = new BrushMesh.HalfEdge {
                            twinIndex = -1, vertexIndex = startVertex + (horzSegments - 1) - p
                        };
                        twins[h] = edgeIndex + 2;
                    }
                    else
                    if (v == lastVertSegment) // bottom
                    {
                        //     0    t    1
                        //		*------>*
                        //       ^  1  /
                        //     p2 \0 2/ n0
                        //         \ v
                        //          *
                        //          2
                        polygonEdgeCount = 3;
                        var p2 = startEdge + (p * 3) + 2;
                        var n0 = startEdge + (n * 3) + 0;
                        var t  = twins[h];
                        halfEdges[twins[h]].twinIndex = edgeIndex + 1;
                        halfEdges[edgeIndex + 0]      = new BrushMesh.HalfEdge {
                            twinIndex = p2, vertexIndex = startVertex + (horzSegments - 1) - p
                        };
                        halfEdges[edgeIndex + 1] = new BrushMesh.HalfEdge {
                            twinIndex = t, vertexIndex = startVertex + (horzSegments - 1) - h
                        };
                        halfEdges[edgeIndex + 2] = new BrushMesh.HalfEdge {
                            twinIndex = n0, vertexIndex = bottomVertex
                        };
                    }
                    else
                    {
                        //     0    t3   1
                        //		*------>*
                        //      ^   1   |
                        //   p1 |0     2| n0
                        //      |   3   v
                        //		*<------*
                        //     3    t1   2
                        polygonEdgeCount = 4;
                        var p1 = startEdge + (p * 4) + 2;
                        var n0 = startEdge + (n * 4) + 0;
                        var t  = twins[h];
                        halfEdges[twins[h]].twinIndex = edgeIndex + 1;
                        halfEdges[edgeIndex + 0]      = new BrushMesh.HalfEdge {
                            twinIndex = p1, vertexIndex = startVertex + (horzSegments - 1) - p
                        };
                        halfEdges[edgeIndex + 1] = new BrushMesh.HalfEdge {
                            twinIndex = t, vertexIndex = startVertex + (horzSegments - 1) - h
                        };
                        halfEdges[edgeIndex + 2] = new BrushMesh.HalfEdge {
                            twinIndex = n0, vertexIndex = startVertex + (horzSegments - 1) - h + horzSegments
                        };
                        halfEdges[edgeIndex + 3] = new BrushMesh.HalfEdge {
                            twinIndex = -1, vertexIndex = startVertex + (horzSegments - 1) - p + horzSegments
                        };
                        twins[h] = edgeIndex + 3;
                    }
                    polygons[polygonIndex] = new CSGBrushSubMesh.Polygon {
                        surfaceID = polygonIndex, firstEdge = edgeIndex, edgeCount = polygonEdgeCount, description = surfaceDescriptions[0], surfaceAsset = surfaceAssets[0]
                    };
                    edgeIndex += polygonEdgeCount;
                    polygonIndex++;
                }
                if (v > 0)
                {
                    startVertex += horzSegments;
                }
            }
            if (bottomCap)
            {
                var polygonEdgeCount = horzSegments;
                for (int h = 0; h < horzSegments; h++)
                {
                    var currEdgeIndex = edgeIndex + h;
                    halfEdges[twins[h]].twinIndex = currEdgeIndex;
                    halfEdges[currEdgeIndex]      = new BrushMesh.HalfEdge {
                        twinIndex = twins[h], vertexIndex = startVertex + (horzSegments - 1) - h
                    };
                }
                polygons[polygonIndex] = new CSGBrushSubMesh.Polygon {
                    surfaceID = polygonIndex, firstEdge = edgeIndex, edgeCount = polygonEdgeCount, description = surfaceDescriptions[0], surfaceAsset = surfaceAssets[0]
                };
            }

            subMesh.Polygons  = polygons;
            subMesh.HalfEdges = halfEdges;
            subMesh.Vertices  = vertices;
            return(true);
        }
Exemplo n.º 4
0
        public static bool GenerateHemisphereSubMesh(CSGBrushSubMesh subMesh, Vector3 diameterXYZ, Matrix4x4 transform, int horzSegments, int vertSegments, CSGSurfaceAsset[] surfaceAssets, SurfaceDescription[] surfaceDescriptions)
        {
            if (diameterXYZ.x == 0 ||
                diameterXYZ.y == 0 ||
                diameterXYZ.z == 0)
            {
                subMesh.Clear();
                return(false);
            }

            var bottomCap     = true;
            var topCap        = false;
            var extraVertices = ((!bottomCap) ? 1 : 0) + ((!topCap) ? 1 : 0);

            var rings       = (vertSegments) + (topCap ? 1 : 0);
            var vertexCount = (horzSegments * rings) + extraVertices;

            var topVertex    = 0;
            var bottomVertex = (!topCap) ? 1 : 0;
            var radius       = new Vector3(diameterXYZ.x * 0.5f,
                                           diameterXYZ.y,
                                           diameterXYZ.z * 0.5f);

            var   heightY = radius.y;
            float topY, bottomY;

            if (heightY < 0)
            {
                topY    = 0;
                bottomY = heightY;
            }
            else
            {
                topY    = heightY;
                bottomY = 0;
            }

            var vertices = new Vector3[vertexCount];

            if (!topCap)
            {
                vertices[topVertex] = transform.MultiplyPoint(Vector3.up * topY);                   // top
            }
            if (!bottomCap)
            {
                vertices[bottomVertex] = transform.MultiplyPoint(Vector3.up * bottomY);             // bottom
            }
            var degreePerSegment = (360.0f / horzSegments) * Mathf.Deg2Rad;
            var angleOffset      = ((horzSegments & 1) == 1) ? 0.0f : 0.5f * degreePerSegment;
            var vertexIndex      = extraVertices;

            if (heightY < 0)
            {
                for (int h = horzSegments - 1; h >= 0; h--, vertexIndex++)
                {
                    var hRad = (h * degreePerSegment) + angleOffset;
                    vertices[vertexIndex] = transform.MultiplyPoint(new Vector3(Mathf.Cos(hRad) * radius.x,
                                                                                0.0f,
                                                                                Mathf.Sin(hRad) * radius.z));
                }
            }
            else
            {
                for (int h = 0; h < horzSegments; h++, vertexIndex++)
                {
                    var hRad = (h * degreePerSegment) + angleOffset;
                    vertices[vertexIndex] = transform.MultiplyPoint(new Vector3(Mathf.Cos(hRad) * radius.x,
                                                                                0.0f,
                                                                                Mathf.Sin(hRad) * radius.z));
                }
            }
            for (int v = 1; v < rings; v++)
            {
                var segmentFactor = ((v - (rings / 2.0f)) / rings) + 0.5f;                      // [0.0f ... 1.0f]
                var segmentDegree = (segmentFactor * 90);                                       // [0 .. 90]
                var segmentHeight = Mathf.Sin(segmentDegree * Mathf.Deg2Rad) * heightY;
                var segmentRadius = Mathf.Cos(segmentDegree * Mathf.Deg2Rad);                   // [0 .. 0.707 .. 1 .. 0.707 .. 0]
                for (int h = 0; h < horzSegments; h++, vertexIndex++)
                {
                    vertices[vertexIndex].x = vertices[h + extraVertices].x * segmentRadius;
                    vertices[vertexIndex].y = segmentHeight;
                    vertices[vertexIndex].z = vertices[h + extraVertices].z * segmentRadius;
                }
            }

            return(GenerateSegmentedSubMesh(subMesh, horzSegments, vertSegments, vertices, bottomCap, topCap, bottomVertex, topVertex, surfaceAssets, surfaceDescriptions));
        }