Exemple #1
0
        SimpleCityCell CreateCell(int x, int z, SimpleCityCellType cellType)
        {
            var cell = new SimpleCityCell();

            cell.Position = new IntVector(x, 0, z);
            cell.CellType = cellType;
            cell.Rotation = Quaternion.identity;
            return(cell);
        }
Exemple #2
0
        /// <summary>
        /// Generate a layout and save it in the model
        /// </summary>
        void GenerateCityLayout()
        {
            var width  = random.Range(demoConfig.minSize, demoConfig.maxSize);
            var length = random.Range(demoConfig.minSize, demoConfig.maxSize);

            demoModel.CityWidth  = width;
            demoModel.CityHeight = length;

            demoModel.Cells = new SimpleCityCell[width, length];

            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    var cell = new SimpleCityCell();
                    cell.Position         = new IntVector(x, 0, z);
                    cell.CellType         = SimpleCityCellType.House;
                    cell.Rotation         = GetRandomRotation();
                    demoModel.Cells[x, z] = cell;
                }
            }


            // Build a road network by removing some houses
            // First build roads along the edge of the map
            for (int x = 0; x < width; x++)
            {
                MakeRoad(x, 0);
                MakeRoad(x, length - 1);
            }
            for (int z = 0; z < length; z++)
            {
                MakeRoad(0, z);
                MakeRoad(width - 1, z);
            }

            // Create roads in-between
            for (int x = GetRandomBlockSize() + 1; x < width; x += GetRandomBlockSize() + 1)
            {
                if (width - x <= 2)
                {
                    continue;
                }
                for (int z = 0; z < length; z++)
                {
                    MakeRoad(x, z);
                }
            }
            for (int z = GetRandomBlockSize() + 1; z < length; z += GetRandomBlockSize() + 1)
            {
                if (length - z <= 2)
                {
                    continue;
                }
                for (int x = 0; x < width; x++)
                {
                    MakeRoad(x, z);
                }
            }

            // Insert 2x houses (bigger houses)
            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    if (CanContainBiggerHouse(x, z))
                    {
                        if (random.NextFloat() < demoConfig.biggerHouseProbability)
                        {
                            InsertBiggerHouse(x, z);
                        }
                    }
                }
            }

            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    var cell = demoModel.Cells[x, z];
                    if (cell.CellType == SimpleCityCellType.House)
                    {
                        FaceHouseTowardsRoad(cell);
                    }
                }
            }


            // Create padding cells

            var padding     = demoConfig.cityWallPadding;
            var paddedCells = new List <SimpleCityCell>();

            for (int p = 1; p <= padding; p++)
            {
                var currentPadding = p;

                var sx = -currentPadding;
                var sz = -currentPadding;
                var ex = width + currentPadding - 1;
                var ez = length + currentPadding - 1;

                // Fill it with city wall padding marker
                for (int x = sx; x < ex; x++)
                {
                    SimpleCityCellType cellType = SimpleCityCellType.CityWallPadding;

                    paddedCells.Add(CreateCell(x, sz, cellType));
                    paddedCells.Add(CreateCell(x, ez, cellType));
                }

                for (int z = sz; z < ez; z++)
                {
                    SimpleCityCellType cellType = SimpleCityCellType.CityWallPadding;

                    paddedCells.Add(CreateCell(sx, z, cellType));
                    paddedCells.Add(CreateCell(ex, z, cellType));
                }
            }
            demoModel.WallPaddingCells = paddedCells.ToArray();
        }
        void UpdateBaseTexture(SimpleCityDungeonModel model, float[,,] map)
        {
            if (terrain == null)
            {
                return;
            }
            int fillIndex = GetTextureIndex(SimpleCityLandscapeTextureType.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;
                    }
                }
            }

            var activeTextureTypes = new SimpleCityLandscapeTextureType[] {
                SimpleCityLandscapeTextureType.Park,
                SimpleCityLandscapeTextureType.Road,
                SimpleCityLandscapeTextureType.CityWallPadding,
            };

            var activeCellTypes = new SimpleCityCellType[] {
                SimpleCityCellType.Park,
                SimpleCityCellType.Road,
                SimpleCityCellType.CityWallPadding,
            };

            var dataMaps = new List <float[, ]>();

            for (int i = 0; i < activeTextureTypes.Length; i++)
            {
                dataMaps.Add(new float[map.GetLength(0), map.GetLength(1)]);
            }

            var gridSize2D = model.Config.CellSize;
            var gridSize   = new Vector3(gridSize2D.x, 0, gridSize2D.y);
            var cells      = new List <SimpleCityCell>();

            foreach (var cell in model.Cells)
            {
                cells.Add(cell);
            }
            cells.AddRange(model.WallPaddingCells);

            foreach (var cell in cells)
            {
                var locationGrid = cell.Position;
                var location = locationGrid * gridSize - gridSize / 2.0f;
                var 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 (int i = 0; i < activeTextureTypes.Length; i++)
                {
                    //SimpleCityLandscapeTextureType activeTexType = activeTextureTypes[i];
                    SimpleCityCellType activeCellType = activeCellTypes[i];
                    //int textureIndex = GetTextureIndex(activeTexType);
                    var dataMap = dataMaps[i];

                    for (var gx = gx1; gx <= gx2; gx++)
                    {
                        for (var gy = gy1; gy <= gy2; gy++)
                        {
                            dataMap[gy, gx] = (cell.CellType == activeCellType) ? 1 : 0;
                        }
                    }
                }
            }

            // Blur the layout data
            var filter = new BlurFilter(roadBlurDistance);

            for (int i = 0; i < dataMaps.Count; i++)
            {
                dataMaps[i] = filter.ApplyFilter(dataMaps[i]);
            }

            for (int i = 0; i < dataMaps.Count; i++)
            {
                var dataMap      = dataMaps[i];
                int textureIndex = GetTextureIndex(activeTextureTypes[i]);
                if (textureIndex < 0)
                {
                    continue;
                }
                for (var y = 0; y < data.alphamapHeight; y++)
                {
                    for (var x = 0; x < data.alphamapWidth; x++)
                    {
                        map[y, x, textureIndex] = dataMap[y, x];
                        if (textureIndex != fillIndex)
                        {
                            map[y, x, fillIndex] -= dataMap[y, x];
                            map[y, x, fillIndex]  = Mathf.Clamp01(map[y, x, fillIndex]);
                        }
                    }
                }
            }

            // Normalize
            for (var y = 0; y < data.alphamapHeight; y++)
            {
                for (var x = 0; x < data.alphamapWidth; x++)
                {
                    // Apply the curves
                    for (int t = 0; t < textures.Length; t++)
                    {
                        var curve = textures[t].curve;
                        if (curve != null && curve.keys.Length > 0)
                        {
                            map[y, x, t] = curve.Evaluate(map[y, x, t]);
                        }
                    }

                    float sum = 0;
                    for (int t = 0; t < textures.Length; t++)
                    {
                        sum += map[y, x, t];
                    }

                    for (int t = 0; t < textures.Length; t++)
                    {
                        map[y, x, t] /= sum;
                    }
                }
            }

            for (int layer = 0; layer < data.detailPrototypes.Length; layer++)
            {
                var foliageMap = data.GetDetailLayer(0, 0, data.detailWidth, data.detailHeight, layer);

                for (int x = 0; x < data.detailWidth; x++)
                {
                    float nx      = x / (float)(data.detailWidth - 1);
                    int   sampleX = Mathf.RoundToInt(nx * (data.alphamapWidth - 1));
                    for (int y = 0; y < data.detailHeight; y++)
                    {
                        float ny      = y / (float)(data.detailHeight - 1);
                        int   sampleY = Mathf.RoundToInt(ny * (data.alphamapHeight - 1));

                        float influence = 0;
                        foreach (var foliageTheme in foliage)
                        {
                            var textureIndex = GetTextureIndex(foliageTheme.textureType);
                            if (textureIndex < 0)
                            {
                                continue;
                            }
                            foreach (var entry in foliageTheme.foliageEntries)
                            {
                                if (entry.grassIndex == layer)
                                {
                                    float mapData = map[sampleY, sampleX, textureIndex];
                                    if (foliageTheme.curve != null && foliageTheme.curve.length > 0)
                                    {
                                        mapData = foliageTheme.curve.Evaluate(mapData);
                                    }
                                    float alpha = mapData * entry.density * foliageTheme.density;
                                    influence += alpha;
                                }
                            }
                        }

                        int   value = Mathf.FloorToInt(influence);
                        float frac  = influence - value;
                        if (Random.value < frac)
                        {
                            value++;
                        }
                        foliageMap[y, x] = value;
                    }
                }

                data.SetDetailLayer(0, 0, layer, foliageMap);
            }

            /*
             * // Update foliage
             * foreach (var foliageTheme in foliage)
             * {
             *  var textureIndex = GetTextureIndex(foliageTheme.textureType);
             *  if (textureIndex < 0) continue;
             *  foreach (var entry in foliageTheme.foliageEntries)
             *  {
             *      int layer = entry.grassIndex;
             *      var foliageMap = data.GetDetailLayer(0, 0, data.detailWidth, data.detailHeight, layer);
             *      for (int x = 0; x < data.detailWidth; x++)
             *      {
             *          float nx = x / (float)(data.detailWidth - 1);
             *          int sampleX = Mathf.RoundToInt(nx * (data.alphamapWidth - 1));
             *          for (int y = 0; y < data.detailHeight; y++)
             *          {
             *              float ny = y / (float)(data.detailHeight - 1);
             *              int sampleY = Mathf.RoundToInt(ny * (data.alphamapHeight - 1));
             *
             *              float alpha = map[sampleY, sampleX, textureIndex] * entry.density * foliageTheme.density;
             *              int value = Mathf.FloorToInt(alpha);
             *              float frac = alpha - value;
             *              if (Random.value < frac) value++;
             *              foliageMap[y, x] = value;
             *          }
             *      }
             *
             *      data.SetDetailLayer(0, 0, layer, foliageMap);
             *  }
             * }
             */
        }
        /// <summary>
        /// Generate a layout and save it in the model
        /// </summary>
        void GenerateCityLayout()
        {
            var width  = random.Range(demoConfig.minSize, demoConfig.maxSize);
            var length = random.Range(demoConfig.minSize, demoConfig.maxSize);

            demoModel.CityWidth  = width;
            demoModel.CityHeight = length;

            demoModel.Cells = new SimpleCityCell[width, length];

            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    var cell = new SimpleCityCell();
                    cell.Position         = new IntVector(x, 0, z);
                    cell.CellType         = SimpleCityCellType.House;
                    cell.Rotation         = GetRandomRotation();
                    demoModel.Cells[x, z] = cell;
                }
            }


            // Build a road network by removing some houses
            // First build roads along the edge of the map
            for (int x = 0; x < width; x++)
            {
                MakeRoad(x, 0);
                MakeRoad(x, length - 1);
            }
            for (int z = 0; z < length; z++)
            {
                MakeRoad(0, z);
                MakeRoad(width - 1, z);
            }

            // Create roads in-between
            for (int x = GetRandomBlockSize() + 1; x < width; x += GetRandomBlockSize() + 1)
            {
                if (width - x <= 2)
                {
                    continue;
                }
                for (int z = 0; z < length; z++)
                {
                    MakeRoad(x, z);
                }
            }
            for (int z = GetRandomBlockSize() + 1; z < length; z += GetRandomBlockSize() + 1)
            {
                if (length - z <= 2)
                {
                    continue;
                }
                for (int x = 0; x < width; x++)
                {
                    MakeRoad(x, z);
                }
            }

            RemoveRoadEdges();


            // Insert bigger houses
            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    foreach (var blockDimension in demoConfig.customBlockDimensions)
                    {
                        bool bProcess = random.NextFloat() < blockDimension.probability;
                        if (!bProcess)
                        {
                            continue;
                        }

                        int BlockWidth  = blockDimension.sizeX;
                        int BlockHeight = blockDimension.sizeZ;

                        InsertHouseDelegate InsertHouse = delegate() {
                            if (CanContainBiggerHouse(x, z, BlockWidth, BlockHeight))
                            {
                                if (random.NextFloat() < demoConfig.biggerHouseProbability)
                                {
                                    InsertBiggerHouse(x, z, BlockWidth, BlockHeight, 0, blockDimension.markerName);
                                }
                            }
                        };


                        InsertHouseDelegate InsertHouse90 = delegate()
                        {
                            // Try the 90 degrees rotated version
                            if (CanContainBiggerHouse(x, z, BlockHeight, BlockWidth))
                            {
                                if (random.NextFloat() < demoConfig.biggerHouseProbability)
                                {
                                    InsertBiggerHouse(x, z, BlockHeight, BlockWidth, 90, blockDimension.markerName);
                                }
                            }
                        };

                        if (random.NextFloat() < 0.5f)
                        {
                            InsertHouse();
                            InsertHouse90();
                        }
                        else
                        {
                            InsertHouse90();
                            InsertHouse();
                        }
                    }
                }
            }


            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    var cell = demoModel.Cells[x, z];
                    if (cell.CellType == SimpleCityCellType.House)
                    {
                        FaceHouseTowardsRoad(cell);
                    }
                }
            }


            // Create padding cells

            var padding     = demoConfig.cityWallPadding;
            var paddedCells = new List <SimpleCityCell>();

            for (int p = 1; p <= padding; p++)
            {
                var currentPadding = p;

                var sx = -currentPadding;
                var sz = -currentPadding;
                var ex = width + currentPadding - 1;
                var ez = length + currentPadding - 1;

                // Fill it with city wall padding marker
                for (int x = sx; x < ex; x++)
                {
                    SimpleCityCellType cellType = SimpleCityCellType.CityWallPadding;

                    paddedCells.Add(CreateCell(x, sz, cellType));
                    paddedCells.Add(CreateCell(x, ez, cellType));
                }

                for (int z = sz; z < ez; z++)
                {
                    SimpleCityCellType cellType = SimpleCityCellType.CityWallPadding;

                    paddedCells.Add(CreateCell(sx, z, cellType));
                    paddedCells.Add(CreateCell(ex, z, cellType));
                }
            }
            demoModel.WallPaddingCells = paddedCells.ToArray();
        }