Example #1
0
        public void Reset()
        {
            // TODO: set defaults using attributes?
            stepHeight  = kDefaultStepHeight;
            stepDepth   = kDefaultStepDepth;
            treadHeight = kDefaultTreadHeight;
            nosingDepth = kDefaultNosingDepth;
            nosingWidth = kDefaultNosingWidth;

            width  = kDefaultWidth;
            height = kDefaultHeight;
            depth  = kDefaultDepth;

            plateauHeight = kDefaultPlateauHeight;

            riserType  = StairsRiserType.ThinRiser;
            leftSide   = StairsSideType.None;
            rightSide  = StairsSideType.None;
            riserDepth = kDefaultRiserDepth;
            sideDepth  = kDefaultSideDepth;
            sideWidth  = kDefaultSideWidth;
            sideHeight = kDefaultSideHeight;

            if (surfaceDefinition != null)
            {
                surfaceDefinition.Reset();
            }
        }
Example #2
0
        public static int CountPathedStairBrushes(UnsafeList <SegmentVertex> shapeVertices,
                                                  bool closedLoop,

                                                  ChiselAABB bounds,

                                                  float stepHeight,
                                                  float stepDepth,

                                                  float treadHeight,

                                                  float nosingDepth,

                                                  float plateauHeight,

                                                  StairsRiserType riserType,
                                                  float riserDepth,

                                                  StairsSideType leftSide,
                                                  StairsSideType rightSide,

                                                  float sideWidth,
                                                  float sideHeight,
                                                  float sideDepth)
        {
            var totalSubMeshCount = 0;

            for (int i = 0; i < shapeVertices.Length; i++)
            {
                if (i == 0 && !closedLoop)
                {
                    continue;
                }

                var segmentLeftSide  = (!closedLoop && i == 1) ? leftSide : StairsSideType.None;
                var segmentRightSide = (!closedLoop && i == shapeVertices.Length - 1) ? rightSide : StairsSideType.None;

                var description = new LineairStairsData(bounds, stepHeight, stepDepth, treadHeight,
                                                        nosingDepth, nosingWidth: 0, plateauHeight,
                                                        riserType, riserDepth,
                                                        segmentLeftSide, segmentRightSide,
                                                        sideWidth, sideHeight, sideDepth);
                totalSubMeshCount += description.subMeshCount;
            }
            return(totalSubMeshCount);
        }
Example #3
0
        // TODO: kind of broken, needs fixing
        public static bool GeneratePathedStairs(NativeList <ChiselBlobAssetReference <BrushMeshBlob> > brushMeshes,
                                                UnsafeList <SegmentVertex> shapeVertices,
                                                bool closedLoop,
                                                ChiselAABB bounds,

                                                float stepHeight,
                                                float stepDepth,

                                                float treadHeight,

                                                float nosingDepth,

                                                float plateauHeight,

                                                StairsRiserType riserType,
                                                float riserDepth,

                                                StairsSideType leftSide,
                                                StairsSideType rightSide,

                                                float sideWidth,
                                                float sideHeight,
                                                float sideDepth,
                                                in ChiselBlobAssetReference <NativeChiselSurfaceDefinition> surfaceDefinitionBlob,
        public static bool GenerateLinearStairsSubMeshes(CSGBrushSubMesh[] subMeshes, CSGLinearStairsDefinition definition, StairsSideType leftSideDefinition, StairsSideType rightSideDefinition, int subMeshOffset = 0)
        {
            // TODO: properly assign all materials

            //const int Top		= (int)CSGLinearStairsDefinition.SurfaceSides.Top;
            //const int Bottom	= (int)CSGLinearStairsDefinition.SurfaceSides.Bottom;
            const int Left  = (int)CSGLinearStairsDefinition.SurfaceSides.Left;
            const int Right = (int)CSGLinearStairsDefinition.SurfaceSides.Right;
            //const int Forward	= (int)CSGLinearStairsDefinition.SurfaceSides.Forward;
            //const int Back	= (int)CSGLinearStairsDefinition.SurfaceSides.Back;
            const int Tread = (int)CSGLinearStairsDefinition.SurfaceSides.Tread;
            const int Step  = (int)CSGLinearStairsDefinition.SurfaceSides.Step;

            CSGSurfaceAsset[]    surfaceAssets       = definition.surfaceAssets;
            SurfaceDescription[] surfaceDescriptions = definition.surfaceDescriptions;
            if (surfaceAssets.Length != (int)CSGLinearStairsDefinition.SurfaceSides.TotalSides ||
                surfaceDescriptions.Length != 6)
            {
                return(false);
            }

            // TODO: implement smooth riser-type

            const float kEpsilon = 0.001f;

            // TODO: put these values in a shared location since they need to match in multiple locations

            var treadHeight   = (definition.treadHeight < kEpsilon) ? 0 : definition.treadHeight;
            var riserType     = (treadHeight == 0 && definition.riserType == StairsRiserType.ThinRiser) ? StairsRiserType.ThickRiser : definition.riserType;
            var leftSideType  = (riserType == StairsRiserType.None && definition.leftSide == StairsSideType.Up) ? StairsSideType.DownAndUp : leftSideDefinition;
            var rightSideType = (riserType == StairsRiserType.None && definition.rightSide == StairsSideType.Up) ? StairsSideType.DownAndUp : rightSideDefinition;

            if (riserType == StairsRiserType.Smooth)
            {
                switch (leftSideType)
                {
                case StairsSideType.Up:   leftSideType = StairsSideType.DownAndUp; break;

                case StairsSideType.None: leftSideType = StairsSideType.Down; break;
                }
                switch (rightSideType)
                {
                case StairsSideType.Up:   rightSideType = StairsSideType.DownAndUp; break;

                case StairsSideType.None: rightSideType = StairsSideType.Down; break;
                }
            }
            var boundsMin = definition.bounds.min;
            var boundsMax = definition.bounds.max;

            if (boundsMin.y > boundsMax.y)
            {
                var t = boundsMin.y; boundsMin.y = boundsMax.y; boundsMax.y = t;
            }
            if (boundsMin.x > boundsMax.x)
            {
                var t = boundsMin.x; boundsMin.x = boundsMax.x; boundsMax.x = t;
            }
            if (boundsMin.z > boundsMax.z)
            {
                var t = boundsMin.z; boundsMin.z = boundsMax.z; boundsMax.z = t;
            }

            var haveRiser        = riserType != StairsRiserType.None;
            var haveLeftSideDown = riserType != StairsRiserType.FillDown &&
                                   (leftSideType == StairsSideType.Down || leftSideType == StairsSideType.DownAndUp);
            var haveLeftSideUp    = (leftSideType == StairsSideType.Up || leftSideType == StairsSideType.DownAndUp);
            var haveRightSideDown = riserType != StairsRiserType.FillDown &&
                                    (rightSideType == StairsSideType.Down || rightSideType == StairsSideType.DownAndUp);
            var haveRightSideUp = (rightSideType == StairsSideType.Up || rightSideType == StairsSideType.DownAndUp);
            var sideWidth       = definition.sideWidth;
            var sideHeight      = definition.sideHeight;
            var leftSideDepth   = (haveLeftSideDown) ? definition.sideDepth : 0;
            var rightSideDepth  = (haveRightSideDown) ? definition.sideDepth : 0;
            var thickRiser      = riserType == StairsRiserType.ThickRiser || riserType == StairsRiserType.Smooth;
            var riserDepth      = (haveRiser && !thickRiser) ? definition.riserDepth : 0;

            var stepCount   = definition.StepCount;
            var offsetZ     = (definition.StepDepthOffset < kEpsilon) ? 0 : definition.StepDepthOffset;
            var offsetY     = definition.plateauHeight;
            var nosingDepth = definition.nosingDepth;

            var haveTread   = (treadHeight >= kEpsilon);
            var haveTopSide = (sideHeight > kEpsilon);

            var leftNosingWidth     = haveLeftSideUp  ? -sideWidth : definition.nosingWidth;
            var rightNosingWidth    = haveRightSideUp ? -sideWidth : definition.nosingWidth;
            var leftTopNosingWidth  = (haveLeftSideUp && (!haveTopSide)) ? definition.nosingWidth : leftNosingWidth;
            var rightTopNosingWidth = (haveRightSideUp && (!haveTopSide)) ? definition.nosingWidth : rightNosingWidth;

            var subMeshCount = 0;                    if (haveRiser)
            {
                subMeshCount = stepCount;
            }
            var startTread = subMeshCount; if (haveTread)
            {
                subMeshCount += stepCount;
            }
            var startLeftSideDown = subMeshCount; if (haveLeftSideDown)
            {
                subMeshCount += stepCount;
            }
            var startRightSideDown = subMeshCount; if (haveRightSideDown)
            {
                subMeshCount += stepCount;
            }
            var startLeftSideUp = subMeshCount; if (haveLeftSideUp)
            {
                subMeshCount += (stepCount - 1) + (haveTopSide ? 1 : 0) + 1;                                                                        //(haveLeftSideDown  ? 0 : 1);
            }
            var startRightSideUp = subMeshCount; if (haveRightSideUp)
            {
                subMeshCount += (stepCount - 1) + (haveTopSide ? 1 : 0) + 1;                                                                //(haveRightSideDown ? 0 : 1);
            }
            var stepOffset = new Vector3(0, -definition.stepHeight, definition.stepDepth);

            if (stepCount > 0)
            {
                if (haveRiser)
                {
                    var min = boundsMin;
                    var max = boundsMax;
                    max.z = min.z + definition.StepDepthOffset + definition.stepDepth;
                    if (riserType != StairsRiserType.FillDown)
                    {
                        if (riserType == StairsRiserType.ThinRiser)
                        {
                            min.z = max.z - riserDepth;
                        }
                        else
                        {
                            min.z = min.z + definition.StepDepthOffset;
                        }
                        if (thickRiser)
                        {
                            min.z -= offsetZ;
                        }
                    }
                    min.y  = max.y - definition.stepHeight;
                    min.y -= treadHeight;
                    max.y -= treadHeight;
                    min.x += haveRightSideUp ? sideWidth : 0;
                    max.x -= haveLeftSideUp  ? sideWidth : 0;
                    var extrusion = new Vector3(max.x - min.x, 0, 0);
                    for (int i = 0; i < stepCount; i++)
                    {
                        if (i == 1 &&
                            thickRiser)
                        {
                            min.z += offsetZ;
                        }
                        if (i == stepCount - 1)
                        {
                            min.y += treadHeight - offsetY;
                        }

                        Vector3[] vertices;
                        if (i == 0 || riserType != StairsRiserType.Smooth)
                        {
                            vertices = new[] {
                                new Vector3(min.x, min.y, min.z),                   // 0
                                new Vector3(min.x, min.y, max.z),                   // 1
                                new Vector3(min.x, max.y, max.z),                   // 2
                                new Vector3(min.x, max.y, min.z),                   // 3
                            };
                        }
                        else
                        {
                            vertices = new[] {
                                new Vector3(min.x, min.y, min.z),                        // 0
                                new Vector3(min.x, min.y, max.z),                        // 1
                                new Vector3(min.x, max.y, max.z),                        // 2
                                new Vector3(min.x, max.y, min.z - definition.stepDepth), // 3
                            };
                        }

                        CreateExtrudedSubMesh(subMeshes[subMeshOffset + i], vertices, extrusion,
                                              new int[] { 0, 1, 2, 3, 3, 3 },                      // TODO: fix this
                                              new int[] { Left, Right, Step, Tread, Step, Tread }, // TODO: fix this
                                              surfaceAssets, surfaceDescriptions);

                        if (riserType != StairsRiserType.FillDown)
                        {
                            min.z += definition.stepDepth;
                        }
                        max.z += definition.stepDepth;
                        min.y -= definition.stepHeight;
                        max.y -= definition.stepHeight;
                    }
                }
                if (haveTread)
                {
                    var min = new Vector3(boundsMin.x + sideWidth, boundsMax.y - definition.treadHeight, boundsMin.z);
                    var max = new Vector3(boundsMax.x - sideWidth, boundsMax.y, boundsMin.z + definition.StepDepthOffset + definition.stepDepth + nosingDepth);
                    for (int i = 0; i < stepCount; i++)
                    {
                        min.x = boundsMin.x - ((i == 0) ? rightTopNosingWidth : rightNosingWidth);
                        max.x = boundsMax.x + ((i == 0) ? leftTopNosingWidth  : leftNosingWidth);
                        if (i == 1)
                        {
                            min.z = max.z - (definition.stepDepth + nosingDepth);
                        }
                        var vertices = new[] {
                            new Vector3(min.x, min.y, min.z),                       // 0
                            new Vector3(min.x, min.y, max.z),                       // 1
                            new Vector3(min.x, max.y, max.z),                       // 2
                            new Vector3(min.x, max.y, min.z),                       // 3
                        };
                        var extrusion = new Vector3(max.x - min.x, 0, 0);
                        CreateExtrudedSubMesh(subMeshes[subMeshOffset + startTread + i], vertices, extrusion,
                                              new int[] { 0, 1, 2, 2, 2, 2 },                        // TODO: fix this
                                              new int[] { Left, Right, Tread, Tread, Tread, Tread }, // TODO: fix this
                                              surfaceAssets, surfaceDescriptions);
                        min += stepOffset;
                        max += stepOffset;
                    }
                }
                if (haveLeftSideDown)
                {
                    var min = new Vector3(boundsMax.x - sideWidth, boundsMax.y - definition.stepHeight - definition.treadHeight, boundsMin.z + definition.StepDepthOffset);
                    var max = new Vector3(boundsMax.x, boundsMax.y - definition.treadHeight, boundsMin.z + definition.StepDepthOffset + definition.stepDepth);

                    var extrusion  = new Vector3(sideWidth, 0, 0);
                    var extraDepth = (thickRiser ? definition.stepDepth : riserDepth) + leftSideDepth;
                    var maxDepth   = boundsMin.z;

                    GenerateBottomRamp(subMeshes, subMeshOffset + startLeftSideDown, stepCount, min, max, extrusion, riserType, definition.stepDepth - riserDepth, extraDepth, maxDepth, definition, surfaceAssets, surfaceDescriptions);
                }
                if (haveRightSideDown)
                {
                    var min = new Vector3(boundsMin.x, boundsMax.y - definition.stepHeight - definition.treadHeight, boundsMin.z + definition.StepDepthOffset);
                    var max = new Vector3(boundsMin.x + sideWidth, boundsMax.y - definition.treadHeight, boundsMin.z + definition.StepDepthOffset + definition.stepDepth);

                    var extrusion  = new Vector3(sideWidth, 0, 0);
                    var extraDepth = (thickRiser ? definition.stepDepth : riserDepth) + rightSideDepth;
                    var maxDepth   = boundsMin.z;

                    GenerateBottomRamp(subMeshes, subMeshOffset + startRightSideDown, stepCount, min, max, extrusion, riserType, definition.stepDepth - riserDepth, extraDepth, maxDepth, definition, surfaceAssets, surfaceDescriptions);
                }
                if (haveLeftSideUp)
                {
                    var min        = new Vector3(boundsMax.x - sideWidth, boundsMax.y - definition.treadHeight - definition.stepHeight, boundsMin.z + definition.StepDepthOffset + definition.stepDepth);
                    var max        = new Vector3(boundsMax.x, boundsMax.y - definition.treadHeight, boundsMin.z + definition.StepDepthOffset + definition.stepDepth + definition.stepDepth);
                    var extrusion  = new Vector3(sideWidth, 0, 0);
                    var extraDepth = (thickRiser ? definition.stepDepth : riserDepth) + leftSideDepth;
                    var maxDepth   = boundsMin.z;

                    GenerateTopRamp(subMeshes, subMeshOffset + startLeftSideUp, stepCount - 1, min, max, extrusion, sideHeight, extraDepth, maxDepth, riserType, definition, surfaceAssets, surfaceDescriptions);

                    if (haveTopSide)
                    {
                        var vertices = new[] {
                            new Vector3(min.x, max.y + sideHeight + definition.treadHeight, min.z),                             // 0
                            new Vector3(min.x, max.y + sideHeight + definition.treadHeight, boundsMin.z),                       // 1
                            new Vector3(min.x, max.y, boundsMin.z),                                                             // 2
                            new Vector3(min.x, max.y, min.z),                                                                   // 3
                        };

                        CreateExtrudedSubMesh(subMeshes[subMeshOffset + startLeftSideUp + (stepCount - 1)], vertices, extrusion,
                                              new int[] { 0, 1, 2, 3, 3, 3 }, // TODO: fix this
                                              new int[] { 0, 1, 2, 2, 2, 2 }, // TODO: fix this
                                              surfaceAssets, surfaceDescriptions);
                    }
                    //if (!haveLeftSideDown)
                    {
                        var       stepHeight = definition.stepHeight;
                        Vector3[] vertices;
                        if (riserType == StairsRiserType.FillDown)
                        {
                            vertices = new[] {
                                new Vector3(min.x, boundsMin.y + stepHeight, boundsMax.z),              // 0
                                new Vector3(min.x, boundsMin.y + stepHeight, boundsMin.z),              // 1
                                new Vector3(min.x, boundsMin.y, boundsMin.z),                           // 2
                                new Vector3(min.x, boundsMin.y, boundsMax.z),                           // 3
                            };
                        }
                        else
                        {
                            vertices = new[] {
                                new Vector3(min.x, boundsMin.y + stepHeight, boundsMax.z),                      // 0
                                new Vector3(min.x, boundsMin.y + stepHeight, boundsMax.z - extraDepth),         // 1
                                new Vector3(min.x, boundsMin.y, boundsMax.z - extraDepth),                      // 2
                                new Vector3(min.x, boundsMin.y, boundsMax.z),                                   // 3
                            };
                        }

                        CreateExtrudedSubMesh(subMeshes[subMeshOffset + startLeftSideUp + stepCount], vertices, extrusion,
                                              new int[] { 0, 1, 2, 3, 3, 3 }, // TODO: fix this
                                              new int[] { 0, 1, 2, 2, 2, 2 }, // TODO: fix this
                                              surfaceAssets, surfaceDescriptions);
                    }
                }
                if (haveRightSideUp)
                {
                    var min        = new Vector3(boundsMin.x, boundsMax.y - definition.treadHeight - definition.stepHeight, boundsMin.z + definition.StepDepthOffset + definition.stepDepth);
                    var max        = new Vector3(boundsMin.x + sideWidth, boundsMax.y - definition.treadHeight, boundsMin.z + definition.StepDepthOffset + definition.stepDepth + definition.stepDepth);
                    var extrusion  = new Vector3(sideWidth, 0, 0);
                    var extraDepth = (thickRiser ? definition.stepDepth : riserDepth) + rightSideDepth;
                    var maxDepth   = boundsMin.z;

                    GenerateTopRamp(subMeshes, subMeshOffset + startRightSideUp, stepCount - 1, min, max, extrusion, sideHeight, extraDepth, maxDepth, riserType, definition, surfaceAssets, surfaceDescriptions);

                    if (haveTopSide)
                    {
                        var vertices = new[] {
                            new Vector3(min.x, max.y + sideHeight + definition.treadHeight, min.z),                         // 0
                            new Vector3(min.x, max.y + sideHeight + definition.treadHeight, boundsMin.z),                   // 1
                            new Vector3(min.x, max.y, boundsMin.z),                                                         // 2
                            new Vector3(min.x, max.y, min.z),                                                               // 3
                        };

                        CreateExtrudedSubMesh(subMeshes[subMeshOffset + startRightSideUp + (stepCount - 1)], vertices, extrusion,
                                              new int[] { 0, 1, 2, 3, 3, 3 }, // TODO: fix this
                                              new int[] { 0, 1, 2, 2, 2, 2 }, // TODO: fix this
                                              surfaceAssets, surfaceDescriptions);
                    }
                    //if (!haveRightSideDown)
                    {
                        var       stepHeight = definition.stepHeight;
                        Vector3[] vertices;
                        if (riserType == StairsRiserType.FillDown)
                        {
                            vertices = new[] {
                                new Vector3(min.x, boundsMin.y + stepHeight, boundsMax.z),               // 0
                                new Vector3(min.x, boundsMin.y + stepHeight, boundsMin.z),               // 1
                                new Vector3(min.x, boundsMin.y, boundsMin.z),                            // 2
                                new Vector3(min.x, boundsMin.y, boundsMax.z),                            // 3
                            };
                        }
                        else
                        {
                            vertices = new[] {
                                new Vector3(min.x, boundsMin.y + stepHeight, boundsMax.z),                      // 0
                                new Vector3(min.x, boundsMin.y + stepHeight, boundsMax.z - extraDepth),         // 1
                                new Vector3(min.x, boundsMin.y, boundsMax.z - extraDepth),                      // 2
                                new Vector3(min.x, boundsMin.y, boundsMax.z),                                   // 3
                            };
                        }

                        CreateExtrudedSubMesh(subMeshes[subMeshOffset + startRightSideUp + stepCount], vertices, extrusion,
                                              new int[] { 0, 1, 2, 3, 3, 3 }, // TODO: fix this
                                              new int[] { 0, 1, 2, 2, 2, 2 }, // TODO: fix this
                                              surfaceAssets, surfaceDescriptions);
                    }
                }
            }
            return(true);
        }
        public static int GetLinearStairsSubMeshCount(CSGLinearStairsDefinition definition, StairsSideType leftSideDefinition, StairsSideType rightSideDefinition)
        {
            CSGSurfaceAsset[]    surfaceAssets       = definition.surfaceAssets;
            SurfaceDescription[] surfaceDescriptions = definition.surfaceDescriptions;
            if (surfaceAssets.Length != (int)CSGLinearStairsDefinition.SurfaceSides.TotalSides ||
                surfaceDescriptions.Length != 6)
            {
                return(0);
            }

            // TODO: implement smooth riser-type

            const float kEpsilon = 0.001f;

            // TODO: put these values in a shared location since they need to match in multiple locations

            var treadHeight   = (definition.treadHeight < kEpsilon) ? 0 : definition.treadHeight;
            var riserType     = (treadHeight == 0 && definition.riserType == StairsRiserType.ThinRiser) ? StairsRiserType.ThickRiser : definition.riserType;
            var leftSideType  = (riserType == StairsRiserType.None && definition.leftSide == StairsSideType.Up) ? StairsSideType.DownAndUp : leftSideDefinition;
            var rightSideType = (riserType == StairsRiserType.None && definition.rightSide == StairsSideType.Up) ? StairsSideType.DownAndUp : rightSideDefinition;

            if (riserType == StairsRiserType.Smooth)
            {
                switch (leftSideType)
                {
                case StairsSideType.Up:   leftSideType = StairsSideType.DownAndUp; break;

                case StairsSideType.None: leftSideType = StairsSideType.Down; break;
                }
                switch (rightSideType)
                {
                case StairsSideType.Up:   rightSideType = StairsSideType.DownAndUp; break;

                case StairsSideType.None: rightSideType = StairsSideType.Down; break;
                }
            }

            var haveRiser        = riserType != StairsRiserType.None;
            var haveLeftSideDown = riserType != StairsRiserType.FillDown &&
                                   (leftSideType == StairsSideType.Down || leftSideType == StairsSideType.DownAndUp);
            var haveLeftSideUp    = (leftSideType == StairsSideType.Up || leftSideType == StairsSideType.DownAndUp);
            var haveRightSideDown = riserType != StairsRiserType.FillDown &&
                                    (rightSideType == StairsSideType.Down || rightSideType == StairsSideType.DownAndUp);
            var haveRightSideUp = (rightSideType == StairsSideType.Up || rightSideType == StairsSideType.DownAndUp);
            var sideHeight      = definition.sideHeight;


            var stepCount   = definition.StepCount;
            var haveTread   = (treadHeight >= kEpsilon);
            var haveTopSide = (sideHeight > kEpsilon);

            var subMeshCount = 0;

            if (haveRiser)
            {
                subMeshCount = stepCount;
            }
            if (haveTread)
            {
                subMeshCount += stepCount;
            }
            if (haveLeftSideDown)
            {
                subMeshCount += stepCount;
            }
            if (haveRightSideDown)
            {
                subMeshCount += stepCount;
            }
            if (haveLeftSideUp)
            {
                subMeshCount += (stepCount - 1) + (haveTopSide ? 1 : 0) + 1;                        //(haveLeftSideDown  ? 0 : 1);
            }
            if (haveRightSideUp)
            {
                subMeshCount += (stepCount - 1) + (haveTopSide ? 1 : 0) + 1;                        //(haveRightSideDown ? 0 : 1);
            }
            return(subMeshCount);
        }