void UpdateHeights(GridDungeonModel model)
        {
            if (terrain == null || terrain.terrainData == null)
            {
                return;
            }
            var rasterizer = new LandscapeDataRasterizer(terrain, groundLevelHeight);

            rasterizer.LoadData();
            var gridSize = model.Config.GridCellSize;

            // Raise the terrain
            foreach (var cell in model.Cells)
            {
                var locationGrid = cell.Bounds.Location;
                var location     = locationGrid * gridSize;
                var size         = cell.Bounds.Size * gridSize;
                var cellY        = location.y + layoutLevelOffset;
                rasterizer.DrawCell(location.x, location.z, size.x, size.z, cellY);
            }

            // Smooth the terrain
            ApplySmoothing(model, rasterizer);

            rasterizer.SaveData();
        }
예제 #2
0
        public static bool AreAdjacentCellsReachable(GridDungeonModel gridModel, int cellIdA, int cellIdB)
        {
            var cellA = gridModel.GetCell(cellIdA);
            var cellB = gridModel.GetCell(cellIdB);

            if (cellA == null || cellB == null)
            {
                return(false);
            }


            // If any one is a room, make sure we have a door between them
            if (cellA.CellType == CellType.Room || cellB.CellType == CellType.Room)
            {
                if (!gridModel.DoorManager.ContainsDoorBetweenCells(cellIdA, cellIdB))
                {
                    // We don't have a door between them and is blocked by a room wall
                    return(false);
                }
            }

            // if their height is different, make sure we have a stair between them
            if (cellA.Bounds.Location.y != cellB.Bounds.Location.y)
            {
                if (!gridModel.ContainsStair(cellIdA, cellIdB))
                {
                    // Height difference with no stairs. not reachable
                    return(false);
                }
            }

            // reachable
            return(true);
        }
예제 #3
0
        /// <summary>
        /// Finds all the nearby tiles that belong to the same cluster
        /// </summary>
        /// <param name="gridModel"></param>
        /// <param name="corridorTileCellId"></param>
        /// <returns></returns>
        public static int[] GetCellCluster(GridDungeonModel gridModel, int sampleCellId)
        {
            var clusters = new List <int>();

            // Check if we are in a room.  Rooms don't need to be clustered as they form a single group
            var startCell = gridModel.GetCell(sampleCellId);

            if (startCell == null || startCell.CellType == CellType.Room)
            {
                clusters.Add(sampleCellId);
                return(clusters.ToArray());
            }

            var visited = new HashSet <int>();
            var stack   = new Stack <int>();

            stack.Push(sampleCellId);

            while (stack.Count > 0)
            {
                var topId = stack.Pop();
                if (visited.Contains(topId))
                {
                    continue;
                }
                visited.Add(topId);

                var top = gridModel.GetCell(topId);
                if (top == null)
                {
                    continue;
                }
                if (top.CellType == CellType.Unknown || top.CellType == CellType.Room)
                {
                    continue;
                }

                if (IsCorridor(top.CellType))
                {
                    clusters.Add(topId);
                }

                // search adjacent cells
                foreach (var adjacentId in top.AdjacentCells)
                {
                    // make sure the adjacent cell is reachable
                    if (AreAdjacentCellsReachable(gridModel, topId, adjacentId))
                    {
                        stack.Push(adjacentId);
                    }
                }
            }

            return(clusters.ToArray());
        }
        void EmitCornerMarker(DungeonBuilder builder, GridDungeonModel model, IntVector point, string markerName)
        {
            // Add an empty marker here
            var gridSize = model.Config.GridCellSize;
            var position = point * gridSize;

            position += Vector3.Scale(new Vector3(0.5f, 0, 0.5f), gridSize);
            var transform = Matrix4x4.TRS(position, Quaternion.identity, Vector3.one);

            builder.EmitMarker(markerName, transform, point, -1);
        }
 void EmitForPoint(DungeonBuilder builder, GridDungeonModel model, IntVector point)
 {
     foreach (var config in CornerConfigs)
     {
         if (ConfigMatches(model, point, config))
         {
             EmitCornerMarker(builder, model, point, config.markerName);
             break;
         }
     }
 }
        public GridDungeonModel GetDungeonModelGrid()
        {
            var model = base.GetDungeonModel();

            gridModel = model as GridDungeonModel;
            if (gridModel == null)
            {
                Debug.LogWarning("Invalid dungeon model type for this type of paint tool.  Expected DungeonModelGrid.  Received:" + (model != null ? model.GetType().ToString() : "null"));
            }

            return(gridModel);
        }
예제 #7
0
        public static void GetAdjacentCorridors(GridDungeonModel gridModel, int startCellId, ref List <int> OutConnectedCorridors, ref List <int> OutConnectedRooms)
        {
            OutConnectedCorridors.Clear();
            OutConnectedRooms.Clear();

            // search all nearby cells till we reach a dead end (or a room)
            var visited = new HashSet <int>();
            var stack   = new Stack <int>();

            stack.Push(startCellId);

            while (stack.Count > 0)
            {
                var topId = stack.Pop();
                if (visited.Contains(topId))
                {
                    continue;
                }
                visited.Add(topId);

                var top = gridModel.GetCell(topId);
                if (top == null)
                {
                    continue;
                }
                if (top.CellType == CellType.Unknown)
                {
                    continue;
                }

                if (top.CellType == CellType.Room && top.Id != startCellId)
                {
                    OutConnectedRooms.Add(topId);
                    continue;
                }

                if (IsCorridor(top.CellType))
                {
                    OutConnectedCorridors.Add(topId);
                }

                // search adjacent cells
                foreach (var adjacentId in top.AdjacentCells)
                {
                    // make sure the adjacent cell is reachable
                    if (AreAdjacentCellsReachable(gridModel, topId, adjacentId))
                    {
                        stack.Push(adjacentId);
                    }
                }
            }
        }
        protected virtual void ApplySmoothing(GridDungeonModel model, LandscapeDataRasterizer rasterizer)
        {
            var gridSize = model.Config.GridCellSize;

            foreach (var cell in model.Cells)
            {
                var locationGrid = cell.Bounds.Location;
                var location     = locationGrid * gridSize;
                var size         = cell.Bounds.Size * gridSize;
                var cellY        = location.y + layoutLevelOffset;
                var curve        = (cell.CellType == CellType.Room) ? roomElevationCurve : corridorElevationCurve;
                rasterizer.SmoothCell(location.x, location.z, size.x, size.z, cellY, smoothingDistance, curve);
            }
        }
        public static Cell[] FindFurthestRooms(GridDungeonModel model)
        {
            var bestLength = 0;
            var result     = new Cell[2];

            foreach (var startCell in model.Cells)
            {
                var queue     = new Queue <LongestPathBFSData>();
                var visited   = new HashSet <int>();
                var startData = new LongestPathBFSData {
                    cell = startCell, length = 0
                };
                LongestPathBFSData endData = startData;

                queue.Enqueue(startData);
                while (queue.Count > 0)
                {
                    var front = queue.Dequeue();
                    visited.Add(front.cell.Id);

                    foreach (var childId in front.cell.FixedRoomConnections)
                    {
                        if (visited.Contains(childId))
                        {
                            continue;
                        }
                        var child     = model.GetCell(childId);
                        var childData = new LongestPathBFSData {
                            cell = child, length = front.length + 1
                        };
                        queue.Enqueue(childData);
                    }

                    if (queue.Count == 0)
                    {
                        endData = front;
                    }
                }

                if (endData.length > bestLength)
                {
                    bestLength = endData.length;
                    result[0]  = startData.cell;
                    result[1]  = endData.cell;
                }
            }

            return(result);
        }
        void UpdateTerrainTextures(GridDungeonModel model)
        {
            if (terrain == null || terrain.terrainData == null)
            {
                return;
            }

            var numTextures = textures.Length;
            var data        = terrain.terrainData;
            var map         = new float[data.alphamapWidth, data.alphamapHeight, numTextures];

            UpdateBaseTexture(model, map);
            UpdateCliffTexture(map);

            data.SetAlphamaps(0, 0, map);
        }
        CellType GetCellTypeFromId(int cellId, GridDungeonModel model)
        {
            if (!model.CellLookup.ContainsKey(cellId))
            {
                return(CellType.Unknown);
            }
            var cell = model.CellLookup[cellId];

            if (cell == null)
            {
                return(CellType.Unknown);
            }
            if (cell.CellType == CellType.CorridorPadding)
            {
                return(CellType.Corridor);
            }
            return(cell.CellType);
        }
예제 #12
0
        public static void DrawAdjacentCells(Cell cell, GridDungeonModel model, Color color, bool mode2D)
        {
            if (model == null)
            {
                return;
            }
            var gridConfig = model.Config as GridDungeonConfig;

            if (gridConfig == null)
            {
                return;
            }

            foreach (var adjacentId in cell.AdjacentCells)
            {
                var adjacentCell = model.GetCell(adjacentId);
                if (adjacentCell == null)
                {
                    return;
                }
                var centerA = Vector3.Scale(cell.Bounds.CenterF(), gridConfig.GridCellSize);
                var centerB = Vector3.Scale(adjacentCell.Bounds.CenterF(), gridConfig.GridCellSize);
                DebugDrawUtils.DrawLine(centerA, centerB, color, 0, false, mode2D);
            }

            foreach (var adjacentId in cell.FixedRoomConnections)
            {
                var adjacentCell = model.GetCell(adjacentId);
                if (adjacentCell == null)
                {
                    return;
                }
                var centerA = Vector3.Scale(cell.Bounds.CenterF(), gridConfig.GridCellSize) + new Vector3(0, 0.2f, 0);
                var centerB = Vector3.Scale(adjacentCell.Bounds.CenterF(), gridConfig.GridCellSize) + new Vector3(0, 0.2f, 0);
                DebugDrawUtils.DrawLine(centerA, centerB, Color.red, 0, false, mode2D);
            }
        }
        bool ConfigMatches(GridDungeonModel model, IntVector point, CellSpatialConfig config)
        {
            var neighbors = config.neighborConfig;

            for (int i = 0; i < neighbors.Length; i++)
            {
                var code = neighbors[i];
                if (code == 0)
                {
                    // Don't care about this cell
                    continue;
                }
                var dx = i % 3;
                var dz = i / 3;
                dx--; dz--;                      // bring to -1..1 range (from previous 0..2)
                dz *= -1;
                var x = point.x + dx;
                var z = point.z + dz;

                var  cellInfo = model.GetGridCellLookup(x, z);
                bool empty    = cellInfo.CellType == CellType.Unknown;
                if (code == 1 && empty)
                {
                    // We were expecting a non-empty space here, but it is empty
                    return(false);
                }
                else if (code == 2 && !empty)
                {
                    // We were expecting a empty space here, but it is not empty
                    return(false);
                }
            }

            // Matches, all tests have passed
            return(true);
        }
 void BuildTerrain(GridDungeonModel model)
 {
     SetupTextures();
     UpdateHeights(model);
     UpdateTerrainTextures(model);
 }
        void UpdateBaseTexture(GridDungeonModel model, float[,,] map)
        {
            if (terrain == null)
            {
                return;
            }
            int fillIndex = GetTextureIndex(LandscapeTextureType.Fill);

            if (fillIndex < 0)
            {
                return;
            }

            var data = terrain.terrainData;

            // Fill up the entire space with the fill texture
            for (var y = 0; y < data.alphamapHeight; y++)
            {
                for (var x = 0; x < data.alphamapWidth; x++)
                {
                    for (int t = 0; t < textures.Length; t++)
                    {
                        var ratio = (t == fillIndex) ? 1 : 0;
                        map[y, x, t] = ratio;
                    }
                }
            }

            int corridorIndex = GetTextureIndex(LandscapeTextureType.Corridor);
            int roomIndex     = GetTextureIndex(LandscapeTextureType.Room);

            if (roomIndex < 0 && corridorIndex < 0)
            {
                // Both corridor and room textures were not provided.  Fill them up with the fill index
                roomIndex     = fillIndex;
                corridorIndex = fillIndex;
            }
            else if (roomIndex < 0)
            {
                // Use the same texture for the room used by the corridor
                roomIndex = corridorIndex;
            }
            else if (corridorIndex < 0)
            {
                // Use the same texture for the corridor used by the room
                corridorIndex = roomIndex;
            }

            // Apply the room/corridor texture
            {
                var gridSize    = model.Config.GridCellSize;
                var roomMap     = new float[map.GetLength(0), map.GetLength(1)];
                var corridorMap = new float[map.GetLength(0), map.GetLength(1)];
                foreach (var cell in model.Cells)
                {
                    var bounds = cell.Bounds;
                    var locationGrid = bounds.Location;
                    var location = locationGrid * gridSize;
                    var size = bounds.Size * gridSize;
                    int gx1, gy1, gx2, gy2;
                    LandscapeDataRasterizer.WorldToTerrainTextureCoord(terrain, location.x, location.z, out gx1, out gy1);
                    LandscapeDataRasterizer.WorldToTerrainTextureCoord(terrain, location.x + size.x, location.z + size.z, out gx2, out gy2);
                    for (var gx = gx1; gx <= gx2; gx++)
                    {
                        for (var gy = gy1; gy <= gy2; gy++)
                        {
                            if (cell.CellType == CellType.Unknown)
                            {
                                continue;
                            }
                            if (cell.CellType == CellType.Room)
                            {
                                roomMap[gy, gx] = 1;
                            }
                            else
                            {
                                corridorMap[gy, gx] = 1;
                            }
                        }
                    }
                }

                // Blur the layout data
                var filter = new BlurFilter(roadBlurDistance);
                roomMap     = filter.ApplyFilter(roomMap);
                corridorMap = filter.ApplyFilter(corridorMap);

                // Fill up the inner region with corridor index
                for (var y = 0; y < data.alphamapHeight; y++)
                {
                    for (var x = 0; x < data.alphamapWidth; x++)
                    {
                        bool corridor = (corridorMap[y, x] > corridorBlurThreshold);
                        if (corridor)
                        {
                            map[y, x, fillIndex]     = 0;
                            map[y, x, roomIndex]     = 0;
                            map[y, x, corridorIndex] = 1;
                        }

                        bool room = (roomMap[y, x] > roomBlurThreshold);
                        if (room)
                        {
                            map[y, x, fillIndex]     = 0;
                            map[y, x, corridorIndex] = 0;
                            map[y, x, roomIndex]     = 1;
                        }
                    }
                }
            }
        }