Exemple #1
0
        public static bool GenerateHemisphereVertices(ref ChiselHemisphereDefinition definition, ref Vector3[] vertices)
        {
            definition.Validate();
            var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one);

            return(GenerateHemisphereVertices(definition.diameterXYZ, transform, definition.horizontalSegments, definition.verticalSegments, ref vertices));
        }
Exemple #2
0
        public static bool GenerateSphere(ref BrushMesh brushMesh, ref ChiselSphereDefinition definition)
        {
            definition.Validate();
            var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one);

            return(BrushMeshFactory.GenerateSphere(ref brushMesh, definition.diameterXYZ, definition.offsetY, definition.generateFromCenter, transform, definition.horizontalSegments, definition.verticalSegments, definition.surfaceDefinition));
        }
Exemple #3
0
        public static bool GenerateHemisphere(ref BrushMesh brushMesh, ref ChiselHemisphereDefinition definition)
        {
            definition.Validate();
            var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one);

            return(GenerateHemisphereSubMesh(ref brushMesh, definition.diameterXYZ, transform, definition.horizontalSegments, definition.verticalSegments, definition.surfaceDefinition));
        }
        public static bool GenerateSphereSubMesh(CSGBrushSubMesh subMesh, CSGSphereDefinition definition)
        {
            definition.Validate();
            var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one);

            return(GenerateSphereSubMesh(subMesh, definition.diameterXYZ, definition.offsetY, definition.generateFromCenter, transform, definition.horizontalSegments, definition.verticalSegments, definition.surfaceAssets, definition.surfaceDescriptions));
        }
Exemple #5
0
        // TODO: could probably figure out "inverse" from direction of topY compared to bottomY
        public static Vector3[] GetConeFrustumVertices(CSGCircleDefinition definition, float topHeight, float rotation, int segments, ref Vector3[] vertices, bool inverse = false)
        {
            var rotate      = Quaternion.AngleAxis(rotation, Vector3.up);
            var bottomAxisX = rotate * Vector3.right * definition.diameterX * 0.5f;
            var bottomAxisZ = rotate * Vector3.forward * definition.diameterZ * 0.5f;
            var topY        = Vector3.up * topHeight;
            var bottomY     = Vector3.up * definition.height;

            if (vertices == null ||
                vertices.Length != segments + 1)
            {
                vertices = new Vector3[segments + 1];
            }

            float angleOffset = ((segments & 1) == 1) ? 0.0f : ((360.0f / segments) * 0.5f);

            vertices[0] = topY;
            for (int v = 0; v < segments; v++)
            {
                var r = (((v * 360.0f) / (float)segments) + angleOffset) * Mathf.Deg2Rad;
                var s = Mathf.Sin(r);
                var c = Mathf.Cos(r);

                var bottomVertex = (bottomAxisX * c) + (bottomAxisZ * s);
                bottomVertex += bottomY;
                var vi = inverse ? (segments - v) : (v + 1);
                vertices[vi] = bottomVertex;
            }

            return(vertices);
        }
        public static bool GenerateSphereVertices(CSGSphereDefinition definition, ref Vector3[] vertices)
        {
            definition.Validate();
            var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one);

            BrushMeshFactory.CreateSphereVertices(definition.diameterXYZ, definition.offsetY, definition.generateFromCenter, definition.horizontalSegments, definition.verticalSegments, ref vertices);
            return(true);
        }
Exemple #7
0
        public static Vector3[] GetConicalFrustumVertices(CSGCircleDefinition bottom, CSGCircleDefinition top, float rotation, int segments, ref Vector3[] vertices)
        {
            if (top.height > bottom.height)
            {
                var temp = top; top = bottom; bottom = temp;
            }

            var rotate      = Quaternion.AngleAxis(rotation, Vector3.up);
            var topAxisX    = rotate * Vector3.right * top.diameterX * 0.5f;
            var topAxisZ    = rotate * Vector3.forward * top.diameterZ * 0.5f;
            var bottomAxisX = rotate * Vector3.right * bottom.diameterX * 0.5f;
            var bottomAxisZ = rotate * Vector3.forward * bottom.diameterZ * 0.5f;
            var topY        = Vector3.up * top.height;
            var bottomY     = Vector3.up * bottom.height;

            // TODO: handle situation where diameterX & diameterZ are 0 (only create one vertex)

            if (vertices == null ||
                vertices.Length != segments * 2)
            {
                vertices = new Vector3[segments * 2];
            }

            float angleOffset = ((segments & 1) == 1) ? 0.0f : ((360.0f / segments) * 0.5f);

            for (int v = 0; v < segments; v++)
            {
                var r = (((v * 360.0f) / (float)segments) + angleOffset) * Mathf.Deg2Rad;
                var s = Mathf.Sin(r);
                var c = Mathf.Cos(r);

                var topVertex    = (topAxisX * c) + (topAxisZ * s);
                var bottomVertex = (bottomAxisX * c) + (bottomAxisZ * s);
                topVertex             += topY;
                bottomVertex          += bottomY;
                vertices[v]            = topVertex;
                vertices[v + segments] = bottomVertex;
            }

            return(vertices);
        }
Exemple #8
0
        public static bool GenerateRevolvedShape(ref ChiselBrushContainer brushContainer, ref ChiselRevolvedShapeDefinition definition)
        {
            definition.Validate();


            var shapeVertices       = new List <Vector2>();
            var shapeSegmentIndices = new List <int>();

            BrushMeshFactory.GetPathVertices(definition.shape, definition.curveSegments, shapeVertices, shapeSegmentIndices);

            Vector2[][] polygonVerticesArray;
            int[][]     polygonIndicesArray;

            if (!Decomposition.ConvexPartition(shapeVertices, shapeSegmentIndices,
                                               out polygonVerticesArray,
                                               out polygonIndicesArray))
            {
                return(false);
            }

            // TODO: splitting it before we do the composition would be better
            var polygonVerticesList = polygonVerticesArray.ToList();

            for (int i = polygonVerticesList.Count - 1; i >= 0; i--)
            {
                SplitPolygon(polygonVerticesList, i);
            }

            var brushMeshesList      = new List <BrushMesh>();
            var horzSegments         = definition.revolveSegments;           //horizontalSegments;
            var horzDegreePerSegment = definition.totalAngle / horzSegments;


            // TODO: make this work when intersecting rotation axis
            //			1. split polygons along rotation axis
            //			2. if edge lies on rotation axis, make sure we don't create infinitely thin quad
            //					collapse this quad, or prevent this from happening
            // TODO: share this code with torus generator
            for (int p = 0; p < polygonVerticesList.Count; p++)
            {
                var polygonVertices = polygonVerticesList[p];
//				var segmentIndices		= polygonIndicesArray[p];
                var shapeSegments = polygonVertices.Length;

                var vertSegments     = polygonVertices.Length;
                var descriptionIndex = new int[2 + vertSegments];

                descriptionIndex[0] = 0;
                descriptionIndex[1] = 1;

                for (int v = 0; v < vertSegments; v++)
                {
                    descriptionIndex[v + 2] = 2;
                }

                var horzOffset = definition.startAngle;
                for (int h = 1, pr = 0; h < horzSegments + 1; pr = h, h++)
                {
                    var hDegree0        = (pr * horzDegreePerSegment) + horzOffset;
                    var hDegree1        = (h * horzDegreePerSegment) + horzOffset;
                    var rotation0       = Quaternion.AngleAxis(hDegree0, Vector3.forward);
                    var rotation1       = Quaternion.AngleAxis(hDegree1, Vector3.forward);
                    var subMeshVertices = new Vector3[vertSegments * 2];
                    for (int v = 0; v < vertSegments; v++)
                    {
                        subMeshVertices[v + vertSegments] = rotation0 * new Vector3(polygonVertices[v].x, 0, polygonVertices[v].y);
                        subMeshVertices[v] = rotation1 * new Vector3(polygonVertices[v].x, 0, polygonVertices[v].y);
                    }

                    var brushMesh = new BrushMesh();
                    if (!BrushMeshFactory.CreateExtrudedSubMesh(ref brushMesh, vertSegments, descriptionIndex, 0, 1, subMeshVertices, in definition.surfaceDefinition))
                    {
                        continue;
                    }

                    if (!brushMesh.Validate())
                    {
                        return(false);
                    }
                    brushMeshesList.Add(brushMesh);
                }
            }

            brushContainer.CopyFrom(brushMeshesList);
            return(true);
        }
Exemple #9
0
            public void Update(IChiselHandles handles, ChiselCylinderDefinition definition)
            {
                var tempBottomDiameterX = definition.BottomDiameterX;
                var tempBottomDiameterZ = definition.isEllipsoid ? definition.BottomDiameterZ : definition.BottomDiameterX;

                float tempTopDiameterX, tempTopDiameterZ;

                if (definition.type == CylinderShapeType.Cone)
                {
                    tempTopDiameterX = 0;
                    tempTopDiameterZ = 0;
                }
                else
                if (definition.type == CylinderShapeType.Cylinder)
                {
                    tempTopDiameterX = tempBottomDiameterX;
                    tempTopDiameterZ = tempBottomDiameterZ;
                }
                else
                {
                    tempTopDiameterX = definition.TopDiameterX;
                    tempTopDiameterZ = definition.isEllipsoid ? definition.TopDiameterZ : definition.TopDiameterX;
                }

                topY    = (definition.height + definition.bottomOffset);
                bottomY = definition.bottomOffset;
                var rotate = Quaternion.AngleAxis(definition.rotation, Vector3.up);

                topXVector    = rotate * Vector3.right * tempTopDiameterX * 0.5f;
                topZVector    = rotate * Vector3.forward * tempTopDiameterZ * 0.5f;
                bottomXVector = rotate * Vector3.right * tempBottomDiameterX * 0.5f;
                bottomZVector = rotate * Vector3.forward * tempBottomDiameterZ * 0.5f;
                normal        = Vector3.up;
                if (topY < bottomY)
                {
                    normal = -Vector3.up;
                }
                else
                {
                    normal = Vector3.up;
                }
                topPoint    = normal * topY;
                bottomPoint = normal * bottomY;


                // Render vertical horizon of cylinder
                // TODO: make this work with math instead of "finding" it
                Vector3     bottomPointA, topPointA;
                Vector3     bottomPointB, topPointB;
                var         camera          = UnityEngine.Camera.current;
                var         cameraTransform = camera.transform;
                var         cameraPosition  = handles.inverseMatrix.MultiplyPoint(cameraTransform.position);
                const float degreeStep      = 5;
                var         pointA          = fullTopCircleHandle.GetPointAtDegree(360 - degreeStep);
                var         pointB          = fullBottomCircleHandle.GetPointAtDegree(360 - degreeStep);
                var         camOrtho        = camera.orthographic;
                var         camForward      = handles.inverseMatrix.MultiplyVector(cameraTransform.forward).normalized;
                var         camDir          = camOrtho ? camForward : (pointA - cameraPosition).normalized;


                var delta   = (pointA - pointB).normalized;
                var normal3 = -Vector3.Cross(delta, Vector3.Cross((pointB - bottomPoint).normalized, delta)).normalized;
                var prevDot = Vector3.Dot(normal3, camDir) < 0;

                bool renderHorizon = false;

                //*
                bottomPointA = Vector3.zero;
                topPointA    = Vector3.zero;
                bottomPointB = Vector3.zero;
                topPointB    = Vector3.zero;
                var lineCount = 0;

                for (float degree = 0; degree < 360; degree += degreeStep)
                {
                    pointA = fullTopCircleHandle.GetPointAtDegree(degree);
                    pointB = fullBottomCircleHandle.GetPointAtDegree(degree);

                    delta   = (pointA - pointB).normalized;
                    normal3 = -Vector3.Cross(delta, Vector3.Cross((pointB - bottomPoint).normalized, delta)).normalized;

                    camDir = camOrtho ? camForward : (pointB - cameraPosition).normalized;
                    var currDot = Vector3.Dot(normal3, camDir) < 0;

                    if (prevDot != currDot)
                    {
                        lineCount++;
                        if (lineCount == 1)
                        {
                            topPointA    = pointA;
                            bottomPointA = pointB;
                        }
                        else
                        //if (lineCount == 2)
                        {
                            topPointB     = pointA;
                            bottomPointB  = pointB;
                            renderHorizon = true;
                            break;
                        }
                    }
                    prevDot = currDot;
                }

    #if false
                {
                    var pointC = (Vector3.right * (definition.topDiameterX * 0.5f)) + (Vector3.up * (definition.height + definition.bottomOffset));
                    var pointD = (Vector3.right * (definition.bottomDiameterX * 0.5f)) + (Vector3.up * definition.bottomOffset);
                    //var deltar      = (pointC - pointD).normalized;
                    //var normala     = -Vector3.Cross(Vector3.forward, deltar).normalized;


                    var DT  = (cameraPosition - topPoint);
                    var DB  = (cameraPosition - bottomPoint);
                    var DmT = DT.magnitude;
                    var DmB = DB.magnitude;
                    //var Dv = D / Dm;

                    var RmT = definition.topDiameterX * 0.5f;
                    var RmB = definition.bottomDiameterX * 0.5f;

                    var cosAT = RmT / DmT;
                    var cosAB = RmB / DmB;
                    var AT    = Mathf.Acos(cosAT) * Mathf.Rad2Deg;
                    var AB    = Mathf.Acos(cosAB) * Mathf.Rad2Deg;
                    var RvT   = (Quaternion.AngleAxis(AT, Vector3.up) * DT).normalized;
                    var RvB   = (Quaternion.AngleAxis(AB, Vector3.up) * DB).normalized;
                    //var R = Rv * Rm;

                    var angleT = Vector3.SignedAngle(Vector3.right, RvT, Vector3.up);
                    var angleB = Vector3.SignedAngle(Vector3.right, RvB, Vector3.up);

                    var arotationT = Quaternion.AngleAxis(angleT, Vector3.up);
                    var arotationB = Quaternion.AngleAxis(angleB, Vector3.up);
                    var ptA        = arotationT * pointC;
                    var ptB        = arotationB * pointD;
                    var prevCol    = handles.color;
                    handles.color = UnityEngine.Color.red;
                    handles.DrawLine(bottomPoint, bottomPoint + Vector3.right);
                    //handles.DrawLine(bottomPoint, bottomPoint + Vector3.forward);
                    //handles.DrawLine(bottomPoint, bottomPoint + normala);
                    //handles.DrawLine(bottomPoint, bottomPoint + deltar);
                    //handles.DrawLine(bottomPoint, bottomPoint + R);
                    handles.DrawLine(bottomPoint, bottomPoint + RvT);
                    handles.DrawLine(bottomPoint, bottomPoint + RvB);
                    //handles.DrawLine(bottomPoint, bottomPoint + desired);
                    handles.DrawLine(ptA, ptB);
                    handles.color = prevCol;
                }
    #endif


                /*/
                 * if (camera.orthographic)
                 * {
                 *  {
                 *      var radius = definition.bottomDiameterX * 0.5f;
                 *      var center = bottomPoint;
                 *      bottomPointA = center + (cameraTransform.right * radius);
                 *      bottomPointB = center - (cameraTransform.right * radius);
                 *  }
                 *  {
                 *      var radius = definition.topDiameterX * 0.5f;
                 *      var center = topPoint;
                 *      topPointA = center + (cameraTransform.right * radius);
                 *      topPointB = center - (cameraTransform.right * radius);
                 *  }
                 * } else
                 * {
                 *  var handleMatrix = handles.matrix;
                 *  renderHorizon = GeometryMath.FindCircleHorizon(handleMatrix, definition.bottomDiameterX, bottomPoint, -normal, out bottomPointB, out bottomPointA);
                 *  renderHorizon = GeometryMath.FindCircleHorizon(handleMatrix, definition.topDiameterX,    topPoint,     normal, out topPointA,    out topPointB) && renderHorizon;
                 *
                 *  if (renderHorizon && definition.bottomDiameterX != definition.topDiameterX)
                 *  {
                 *      renderHorizon = !(GeometryMath.PointInCameraCircle(handleMatrix, bottomPointA, definition.topDiameterX,    topPoint,     normal) ||
                 *                        GeometryMath.PointInCameraCircle(handleMatrix, topPointA,    definition.bottomDiameterX, bottomPoint, -normal) ||
                 *                        GeometryMath.PointInCameraCircle(handleMatrix, bottomPointB, definition.topDiameterX,    topPoint,     normal) ||
                 *                        GeometryMath.PointInCameraCircle(handleMatrix, topPointB,    definition.bottomDiameterX, bottomPoint, -normal));
                 *  }
                 * }
                 * //*/

                if (!renderHorizon)
                {
                    bottomPointA = Vector3.zero;
                    topPointA    = Vector3.zero;
                    bottomPointB = Vector3.zero;
                    topPointB    = Vector3.zero;
                }

                verticalHandle1.From = bottomPointA;
                verticalHandle1.To   = topPointA;
                verticalHandle2.From = bottomPointB;
                verticalHandle2.To   = topPointB;

                fullTopCircleHandle.Center    = topPoint;
                fullBottomCircleHandle.Center = bottomPoint;

                fullTopCircleHandle.DiameterX    = tempTopDiameterX;
                fullTopCircleHandle.DiameterZ    = tempTopDiameterZ;
                fullBottomCircleHandle.DiameterX = tempBottomDiameterX;
                fullBottomCircleHandle.DiameterZ = tempBottomDiameterZ;

                topHandle.Origin    = topPoint;
                bottomHandle.Origin = bottomPoint;


                fullTopCircleHandle.Normal    = normal;
                fullBottomCircleHandle.Normal = -normal;

                topHandle.Normal    = normal;
                bottomHandle.Normal = -normal;


                if (definition.isEllipsoid)
                {
                    if (bottomRadiusHandles == null || bottomRadiusHandles.Length != 4)
                    {
                        bottomRadiusHandles = new IChiselEllipsoidHandle[]
                        {
                            handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: +45f, angles: 90),        // left
                            handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: +45f + 180f, angles: 90), // right
                            handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: -45f, angles: 90),        // forward
                            handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: -45f + 180f, angles: 90), // back
                        };
                    }

                    if (topRadiusHandles == null || topRadiusHandles.Length != 4)
                    {
                        topRadiusHandles = new IChiselEllipsoidHandle[]
                        {
                            handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: +45f, angles: 90),          // left
                            handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: +45f + 180f, angles: 90),   // right
                            handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: -45f, angles: 90),          // forward
                            handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: -45f + 180f, angles: 90),   // back
                        };
                    }

                    for (int i = 0; i < bottomRadiusHandles.Length; i++)
                    {
                        bottomRadiusHandles[i].Center    = bottomPoint;
                        bottomRadiusHandles[i].Normal    = -normal;
                        bottomRadiusHandles[i].DiameterX = tempBottomDiameterX;
                        bottomRadiusHandles[i].DiameterZ = tempBottomDiameterZ;
                        bottomRadiusHandles[i].Rotation  = definition.rotation;
                    }

                    for (int i = 0; i < topRadiusHandles.Length; i++)
                    {
                        topRadiusHandles[i].Center    = topPoint;
                        topRadiusHandles[i].Normal    = normal;
                        topRadiusHandles[i].DiameterX = tempTopDiameterX;
                        topRadiusHandles[i].DiameterZ = tempTopDiameterZ;
                        topRadiusHandles[i].Rotation  = definition.rotation;
                    }

                    if (bottomHandles == null || bottomHandles.Length != 4)
                    {
                        bottomHandles = new IChiselHandle[] { bottomHandle, bottomRadiusHandles[0], bottomRadiusHandles[1], bottomRadiusHandles[2], bottomRadiusHandles[3] }
                    }
                    ;
                    if (definition.type != CylinderShapeType.Cone)
                    {
                        if (topHandles == null || topHandles.Length != 5)
                        {
                            topHandles = new IChiselHandle[] { topHandle, topRadiusHandles[0], topRadiusHandles[1], topRadiusHandles[2], topRadiusHandles[3] }
                        }
                        ;
                    }
                    else
                    {
                        if (topHandles == null || topHandles.Length != 1)
                        {
                            topHandles = new IChiselHandle[] { topHandle }
                        }
                        ;
                    }
                }
                else
                {
                    if (bottomRadiusHandles == null || bottomRadiusHandles.Length != 1)
                    {
                        bottomRadiusHandles = new IChiselEllipsoidHandle[] { fullBottomCircleHandle }
                    }
                    ;
                    if (topRadiusHandles == null || topRadiusHandles.Length != 1)
                    {
                        topRadiusHandles = new IChiselEllipsoidHandle[] { fullTopCircleHandle }
                    }
                    ;

                    if (bottomHandles == null || bottomHandles.Length != 2)
                    {
                        bottomHandles = new IChiselHandle[] { bottomHandle, bottomRadiusHandles[0] }
                    }
                    ;
                    if (definition.type != CylinderShapeType.Cone)
                    {
                        if (topHandles == null || topHandles.Length != 2)
                        {
                            topHandles = new IChiselHandle[] { topHandle, topRadiusHandles[0] }
                        }
                        ;
                    }
                    else
                    {
                        if (topHandles == null || topHandles.Length != 1)
                        {
                            topHandles = new IChiselHandle[] { topHandle }
                        }
                        ;
                    }
                }
            }
        }
Exemple #10
0
        public static bool GenerateTorusAsset(CSGBrushMeshAsset brushMeshAsset, CSGTorusDefinition definition)
        {
            Vector3[] vertices = null;
            if (!GenerateTorusVertices(definition, ref vertices))
            {
                brushMeshAsset.Clear();
                return(false);
            }

            definition.Validate();
            var surfaces     = definition.surfaceAssets;
            var descriptions = definition.surfaceDescriptions;
            var tubeRadiusX  = (definition.tubeWidth * 0.5f);
            var tubeRadiusY  = (definition.tubeHeight * 0.5f);
            var torusRadius  = (definition.outerDiameter * 0.5f) - tubeRadiusX;


            var horzSegments = definition.horizontalSegments;
            var vertSegments = definition.verticalSegments;

            var horzDegreePerSegment = (definition.totalAngle / horzSegments);
            var vertDegreePerSegment = (360.0f / vertSegments) * Mathf.Deg2Rad;
            var descriptionIndex     = new int[2 + vertSegments];

            descriptionIndex[0] = 0;
            descriptionIndex[1] = 1;

            var circleVertices = new Vector2[vertSegments];

            var min             = new Vector2(float.PositiveInfinity, float.PositiveInfinity);
            var max             = new Vector2(float.NegativeInfinity, float.NegativeInfinity);
            var tubeAngleOffset = ((((vertSegments & 1) == 1) ? 0.0f : ((360.0f / vertSegments) * 0.5f)) + definition.tubeRotation) * Mathf.Deg2Rad;

            for (int v = 0; v < vertSegments; v++)
            {
                var vRad = tubeAngleOffset + (v * vertDegreePerSegment);
                circleVertices[v] = new Vector2((Mathf.Cos(vRad) * tubeRadiusX) - torusRadius,
                                                (Mathf.Sin(vRad) * tubeRadiusY));
                min.x = Mathf.Min(min.x, circleVertices[v].x);
                min.y = Mathf.Min(min.y, circleVertices[v].y);
                max.x = Mathf.Max(max.x, circleVertices[v].x);
                max.y = Mathf.Max(max.y, circleVertices[v].y);
                descriptionIndex[v + 2] = 2;
            }

            if (definition.fitCircle)
            {
                var center = (max + min) * 0.5f;
                var size   = (max - min) * 0.5f;
                size.x = tubeRadiusX / size.x;
                size.y = tubeRadiusY / size.y;
                for (int v = 0; v < vertSegments; v++)
                {
                    circleVertices[v].x  = (circleVertices[v].x - center.x) * size.x;
                    circleVertices[v].y  = (circleVertices[v].y - center.y) * size.y;
                    circleVertices[v].x -= torusRadius;
                }
            }

            var subMeshes  = new CSGBrushSubMesh[horzSegments];
            var horzOffset = definition.startAngle;

            for (int h = 1, p = 0; h < horzSegments + 1; p = h, h++)
            {
                var hDegree0        = (p * horzDegreePerSegment) + horzOffset;
                var hDegree1        = (h * horzDegreePerSegment) + horzOffset;
                var rotation0       = Quaternion.AngleAxis(hDegree0, Vector3.up);
                var rotation1       = Quaternion.AngleAxis(hDegree1, Vector3.up);
                var subMeshVertices = new Vector3[vertSegments * 2];
                for (int v = 0; v < vertSegments; v++)
                {
                    subMeshVertices[v + vertSegments] = rotation0 * circleVertices[v];
                    subMeshVertices[v] = rotation1 * circleVertices[v];
                }

                var subMesh = new CSGBrushSubMesh();
                CreateExtrudedSubMesh(subMesh, vertSegments, descriptionIndex, descriptionIndex, 0, 1, subMeshVertices, surfaces, descriptions);
                if (!subMesh.Validate())
                {
                    brushMeshAsset.Clear();
                    return(false);
                }
                subMeshes[h - 1] = subMesh;
            }

            brushMeshAsset.SubMeshes = subMeshes;

            brushMeshAsset.CalculatePlanes();
            brushMeshAsset.SetDirty();
            return(true);
        }
Exemple #11
0
        public static bool GenerateTorusVertices(CSGTorusDefinition definition, ref Vector3[] vertices)
        {
            definition.Validate();
            //var surfaces		= definition.surfaceAssets;
            //var descriptions	= definition.surfaceDescriptions;
            var tubeRadiusX = (definition.tubeWidth * 0.5f);
            var tubeRadiusY = (definition.tubeHeight * 0.5f);
            var torusRadius = (definition.outerDiameter * 0.5f) - tubeRadiusX;


            var horzSegments = definition.horizontalSegments;
            var vertSegments = definition.verticalSegments;

            var horzDegreePerSegment = (definition.totalAngle / horzSegments);
            var vertDegreePerSegment = (360.0f / vertSegments) * Mathf.Deg2Rad;

            var circleVertices = new Vector2[vertSegments];

            var min             = new Vector2(float.PositiveInfinity, float.PositiveInfinity);
            var max             = new Vector2(float.NegativeInfinity, float.NegativeInfinity);
            var tubeAngleOffset = ((((vertSegments & 1) == 1) ? 0.0f : ((360.0f / vertSegments) * 0.5f)) + definition.tubeRotation) * Mathf.Deg2Rad;

            for (int v = 0; v < vertSegments; v++)
            {
                var vRad = tubeAngleOffset + (v * vertDegreePerSegment);
                circleVertices[v] = new Vector2((Mathf.Cos(vRad) * tubeRadiusX) - torusRadius,
                                                (Mathf.Sin(vRad) * tubeRadiusY));
                min.x = Mathf.Min(min.x, circleVertices[v].x);
                min.y = Mathf.Min(min.y, circleVertices[v].y);
                max.x = Mathf.Max(max.x, circleVertices[v].x);
                max.y = Mathf.Max(max.y, circleVertices[v].y);
            }

            if (definition.fitCircle)
            {
                var center = (max + min) * 0.5f;
                var size   = (max - min) * 0.5f;
                size.x = tubeRadiusX / size.x;
                size.y = tubeRadiusY / size.y;
                for (int v = 0; v < vertSegments; v++)
                {
                    circleVertices[v].x  = (circleVertices[v].x - center.x) * size.x;
                    circleVertices[v].y  = (circleVertices[v].y - center.y) * size.y;
                    circleVertices[v].x -= torusRadius;
                }
            }

            if (definition.totalAngle != 360)
            {
                horzSegments++;
            }

            var horzOffset  = definition.startAngle;
            var vertexCount = vertSegments * horzSegments;

            if (vertices == null ||
                vertices.Length != vertexCount)
            {
                vertices = new Vector3[vertexCount];
            }
            for (int h = 0, v = 0; h < horzSegments; h++)
            {
                var hDegree1  = (h * horzDegreePerSegment) + horzOffset;
                var rotation1 = Quaternion.AngleAxis(hDegree1, Vector3.up);
                for (int i = 0; i < vertSegments; i++, v++)
                {
                    vertices[v] = rotation1 * circleVertices[i];
                }
            }
            return(true);
        }