From a292917e50ad1de760dbda8d0e58c3fc3f53725c Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Fri, 17 Nov 2017 10:22:54 +0100 Subject: [PATCH] Compile mapgen.c as C++ --- OpenRCT2.xcodeproj/project.pbxproj | 14 +- src/openrct2-ui/windows/MapGen.cpp | 2 +- src/openrct2/world/{mapgen.c => MapGen.cpp} | 615 ++++++++------------ src/openrct2/world/{mapgen.h => MapGen.h} | 26 +- 4 files changed, 259 insertions(+), 398 deletions(-) rename src/openrct2/world/{mapgen.c => MapGen.cpp} (54%) rename src/openrct2/world/{mapgen.h => MapGen.h} (73%) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index f47c8aa3c8..a6d8fe1c2e 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 4C31B2E41FB6115600F6A38A /* MapGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C31B2E21FB6115600F6A38A /* MapGen.cpp */; }; 4C4C1E981F58226500560300 /* TrackDesign.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C4C1E971F58226500560300 /* TrackDesign.cpp */; }; 4C5DFF421FAC69D200CB093A /* Date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C5DFF401FAC69D200CB093A /* Date.cpp */; }; 4C6AC20F1F9E1693004324AA /* Station.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AC20D1F9E1693004324AA /* Station.cpp */; }; @@ -455,7 +456,6 @@ F76C87A01EC4E88400FA49E2 /* map.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C85681EC4E7CD00FA49E2 /* map.c */; }; F76C87A21EC4E88400FA49E2 /* map_animation.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C856A1EC4E7CD00FA49E2 /* map_animation.c */; }; F76C87A41EC4E88500FA49E2 /* map_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C856C1EC4E7CD00FA49E2 /* map_helpers.c */; }; - F76C87A61EC4E88500FA49E2 /* mapgen.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C856E1EC4E7CD00FA49E2 /* mapgen.c */; }; F76C87A81EC4E88500FA49E2 /* money_effect.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C85701EC4E7CD00FA49E2 /* money_effect.c */; }; F76C87A91EC4E88500FA49E2 /* park.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C85711EC4E7CD00FA49E2 /* park.c */; }; F76C87AB1EC4E88500FA49E2 /* particle.c in Sources */ = {isa = PBXBuildFile; fileRef = F76C85731EC4E7CD00FA49E2 /* particle.c */; }; @@ -613,6 +613,9 @@ /* Begin PBXFileReference section */ 4C31B2E61FB7352900F6A38A /* Scenery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scenery.h; sourceTree = ""; }; + 4C31B2E21FB6115600F6A38A /* MapGen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MapGen.cpp; sourceTree = ""; }; + 4C31B2E31FB6115600F6A38A /* MapGen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapGen.h; sourceTree = ""; }; + 4C31B2E51FB6116100F6A38A /* Location.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Location.h; sourceTree = ""; }; 4C4C1E971F58226500560300 /* TrackDesign.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackDesign.cpp; sourceTree = ""; }; 4C4C1E991F5832AA00560300 /* TrackDesign.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackDesign.h; sourceTree = ""; }; 4C5DFF401FAC69D200CB093A /* Date.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Date.cpp; sourceTree = ""; }; @@ -1367,8 +1370,6 @@ F76C856B1EC4E7CD00FA49E2 /* map_animation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = map_animation.h; sourceTree = ""; }; F76C856C1EC4E7CD00FA49E2 /* map_helpers.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = map_helpers.c; sourceTree = ""; }; F76C856D1EC4E7CD00FA49E2 /* map_helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = map_helpers.h; sourceTree = ""; }; - F76C856E1EC4E7CD00FA49E2 /* mapgen.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mapgen.c; sourceTree = ""; }; - F76C856F1EC4E7CD00FA49E2 /* mapgen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mapgen.h; sourceTree = ""; }; F76C85701EC4E7CD00FA49E2 /* money_effect.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = money_effect.c; sourceTree = ""; }; F76C85711EC4E7CD00FA49E2 /* park.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = park.c; sourceTree = ""; }; F76C85721EC4E7CD00FA49E2 /* park.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = park.h; sourceTree = ""; }; @@ -2554,14 +2555,15 @@ F76C85651EC4E7CD00FA49E2 /* footpath.h */, F76C85661EC4E7CD00FA49E2 /* Fountain.cpp */, F76C85671EC4E7CD00FA49E2 /* Fountain.h */, + 4C31B2E51FB6116100F6A38A /* Location.h */, F76C85681EC4E7CD00FA49E2 /* map.c */, F76C85691EC4E7CD00FA49E2 /* map.h */, F76C856A1EC4E7CD00FA49E2 /* map_animation.c */, F76C856B1EC4E7CD00FA49E2 /* map_animation.h */, F76C856C1EC4E7CD00FA49E2 /* map_helpers.c */, F76C856D1EC4E7CD00FA49E2 /* map_helpers.h */, - F76C856E1EC4E7CD00FA49E2 /* mapgen.c */, - F76C856F1EC4E7CD00FA49E2 /* mapgen.h */, + 4C31B2E21FB6115600F6A38A /* MapGen.cpp */, + 4C31B2E31FB6115600F6A38A /* MapGen.h */, F76C85701EC4E7CD00FA49E2 /* money_effect.c */, F76C85711EC4E7CD00FA49E2 /* park.c */, F76C85721EC4E7CD00FA49E2 /* park.h */, @@ -3312,6 +3314,7 @@ 4C93F1911F8B747A00A9330D /* SwingingInverterShip.cpp in Sources */, 4C93F1461F8B744400A9330D /* LayDownRollerCoaster.cpp in Sources */, 4C93F1991F8B748200A9330D /* Chairlift.cpp in Sources */, + 4C31B2E41FB6115600F6A38A /* MapGen.cpp in Sources */, 4C6AC20F1F9E1693004324AA /* Station.cpp in Sources */, C64644FE1F3FA4120026AC2D /* Main.cpp in Sources */, 4C93F16B1F8B745700A9330D /* CircusShow.cpp in Sources */, @@ -3533,7 +3536,6 @@ F76C87A01EC4E88400FA49E2 /* map.c in Sources */, F76C87A21EC4E88400FA49E2 /* map_animation.c in Sources */, F76C87A41EC4E88500FA49E2 /* map_helpers.c in Sources */, - F76C87A61EC4E88500FA49E2 /* mapgen.c in Sources */, F76C87A81EC4E88500FA49E2 /* money_effect.c in Sources */, F76C87A91EC4E88500FA49E2 /* park.c in Sources */, F76C87AB1EC4E88500FA49E2 /* particle.c in Sources */, diff --git a/src/openrct2-ui/windows/MapGen.cpp b/src/openrct2-ui/windows/MapGen.cpp index 65b56b07a8..30f69e2b67 100644 --- a/src/openrct2-ui/windows/MapGen.cpp +++ b/src/openrct2-ui/windows/MapGen.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include enum { diff --git a/src/openrct2/world/mapgen.c b/src/openrct2/world/MapGen.cpp similarity index 54% rename from src/openrct2/world/mapgen.c rename to src/openrct2/world/MapGen.cpp index b8ed288532..239fdf2a50 100644 --- a/src/openrct2/world/mapgen.c +++ b/src/openrct2/world/MapGen.cpp @@ -16,36 +16,41 @@ #include "../common.h" #include +#include #include "../Context.h" -#include "../Imaging.h" #include "../core/Guard.hpp" +#include "../core/Math.hpp" +#include "../core/String.hpp" +#include "../core/Util.hpp" #include "../game.h" +#include "../Imaging.h" #include "../localisation/string_ids.h" #include "../object.h" #include "../platform/platform.h" #include "../util/util.h" #include "map.h" #include "map_helpers.h" -#include "mapgen.h" +#include "MapGen.h" #include "scenery.h" #pragma region Height map struct -static struct { +static struct +{ uint32 width, height; - uint8 *mono_bitmap; + uint8 * mono_bitmap; } _heightMapData = { - .width = 0, - .height = 0, - .mono_bitmap = NULL + 0, + 0, + nullptr }; #pragma endregion Height map struct #pragma region Random objects -static const char *GrassTrees[] = { +static const char * GrassTrees[] = { // Dark "TCF ", // Caucasian Fir Tree "TRF ", // Red Fir Tree @@ -61,7 +66,7 @@ static const char *GrassTrees[] = { "TEL ", // European Larch Tree }; -static const char *DesertTrees[] = { +static const char * DesertTrees[] = { "TMP ", // Monkey-Puzzle Tree "THL ", // Honey Locust Tree "TH1 ", // Canary Palm Tree @@ -72,7 +77,7 @@ static const char *DesertTrees[] = { "TSC ", // Cactus }; -static const char *SnowTrees[] = { +static const char * SnowTrees[] = { "TCFS ", // Snow-covered Caucasian Fir Tree "TNSS ", // Snow-covered Norway Spruce Tree "TRF3 ", // Snow-covered Red Fir Tree @@ -82,21 +87,19 @@ static const char *SnowTrees[] = { #pragma endregion // Randomly chosen base terrains. We rarely want a whole map made out of chequerboard or rock. -static const uint8 BaseTerrain[] = { TERRAIN_GRASS, TERRAIN_SAND, TERRAIN_SAND_LIGHT, TERRAIN_DIRT, TERRAIN_ICE }; +static const uint8 BaseTerrain[] = {TERRAIN_GRASS, TERRAIN_SAND, TERRAIN_SAND_LIGHT, TERRAIN_DIRT, TERRAIN_ICE}; #define BLOB_HEIGHT 255 static void mapgen_place_trees(); static void mapgen_set_water_level(sint32 waterLevel); -static void mapgen_blobs(sint32 count, sint32 lowSize, sint32 highSize, sint32 lowHeight, sint32 highHeight); -static void mapgen_blob(sint32 cx, sint32 cy, sint32 size, sint32 height); static void mapgen_smooth_height(sint32 iterations); static void mapgen_set_height(); -static void mapgen_simplex(mapgen_settings *settings); +static void mapgen_simplex(mapgen_settings * settings); -static sint32 _heightSize; -static uint8 *_height; +static sint32 _heightSize; +static uint8 * _height; static sint32 get_height(sint32 x, sint32 y) { @@ -112,20 +115,22 @@ static void set_height(sint32 x, sint32 y, sint32 height) _height[x + y * _heightSize] = height; } -void mapgen_generate_blank(mapgen_settings *settings) +void mapgen_generate_blank(mapgen_settings * settings) { sint32 x, y; - rct_tile_element *tileElement; + rct_tile_element * tileElement; map_clear_all_elements(); map_init(settings->mapSize); - for (y = 1; y < settings->mapSize - 1; y++) { - for (x = 1; x < settings->mapSize - 1; x++) { + for (y = 1; y < settings->mapSize - 1; y++) + { + for (x = 1; x < settings->mapSize - 1; x++) + { tileElement = map_get_surface_element_at(x, y); tile_element_set_terrain(tileElement, settings->floor); tile_element_set_terrain_edge(tileElement, settings->wall); - tileElement->base_height = settings->height; + tileElement->base_height = settings->height; tileElement->clearance_height = settings->height; } } @@ -133,24 +138,26 @@ void mapgen_generate_blank(mapgen_settings *settings) mapgen_set_water_level(settings->water_level); } -void mapgen_generate(mapgen_settings *settings) +void mapgen_generate(mapgen_settings * settings) { sint32 x, y, mapSize, floorTexture, wallTexture, waterLevel; - rct_tile_element *tileElement; + rct_tile_element * tileElement; - util_srand((sint32)platform_get_ticks()); + util_srand((sint32) platform_get_ticks()); - mapSize = settings->mapSize; + mapSize = settings->mapSize; floorTexture = settings->floor; - wallTexture = settings->wall; - waterLevel = settings->water_level; + wallTexture = settings->wall; + waterLevel = settings->water_level; if (floorTexture == -1) - floorTexture = BaseTerrain[util_rand() % countof(BaseTerrain)]; + floorTexture = BaseTerrain[util_rand() % Util::CountOf(BaseTerrain)]; - if (wallTexture == -1) { + if (wallTexture == -1) + { // Base edge type on surface type - switch (floorTexture) { + switch (floorTexture) + { case TERRAIN_DIRT: wallTexture = TERRAIN_EDGE_WOOD_RED; break; @@ -167,52 +174,42 @@ void mapgen_generate(mapgen_settings *settings) // Initialise the base map map_init(mapSize); - for (y = 1; y < mapSize - 1; y++) { - for (x = 1; x < mapSize - 1; x++) { + for (y = 1; y < mapSize - 1; y++) + { + for (x = 1; x < mapSize - 1; x++) + { tileElement = map_get_surface_element_at(x, y); tile_element_set_terrain(tileElement, floorTexture); tile_element_set_terrain_edge(tileElement, wallTexture); - tileElement->base_height = settings->height; + tileElement->base_height = settings->height; tileElement->clearance_height = settings->height; } } // Create the temporary height map and initialise _heightSize = mapSize * 2; - _height = (uint8*)malloc(_heightSize * _heightSize * sizeof(uint8)); + _height = new uint8[_heightSize * _heightSize]; memset(_height, 0, _heightSize * _heightSize * sizeof(uint8)); - if (1) { - mapgen_simplex(settings); - mapgen_smooth_height(2 + (util_rand() % 6)); - } else { - // Keep overwriting the map with rough circular blobs of different sizes and heights. - // This procedural method can produce intersecting contour like land and lakes. - // Large blobs, general shape of map - mapgen_blobs(6, _heightSize / 2, _heightSize * 4, 4, 16); - // Medium blobs - mapgen_blobs(12, _heightSize / 16, _heightSize / 8, 4, 18); - // Small blobs, small hills and lakes - mapgen_blobs(32, _heightSize / 32, _heightSize / 16, 4, 18); - - // Smooth the land so that there aren't cliffs round every blob. - mapgen_smooth_height(2); - } + mapgen_simplex(settings); + mapgen_smooth_height(2 + (util_rand() % 6)); // Set the game map to the height map mapgen_set_height(); - free(_height); + delete[] _height; // Set the tile slopes so that there are no cliffs - while (map_smooth(1, 1, mapSize - 1, mapSize - 1)) { } + while (map_smooth(1, 1, mapSize - 1, mapSize - 1)) {} // Add the water mapgen_set_water_level(waterLevel); // Add sandy beaches sint32 beachTexture = floorTexture; - if (settings->floor == -1 && floorTexture == TERRAIN_GRASS) { - switch (util_rand() % 4) { + if (settings->floor == -1 && floorTexture == TERRAIN_GRASS) + { + switch (util_rand() % 4) + { case 0: beachTexture = TERRAIN_SAND; break; @@ -221,8 +218,10 @@ void mapgen_generate(mapgen_settings *settings) break; } } - for (y = 1; y < mapSize - 1; y++) { - for (x = 1; x < mapSize - 1; x++) { + for (y = 1; y < mapSize - 1; y++) + { + for (x = 1; x < mapSize - 1; x++) + { tileElement = map_get_surface_element_at(x, y); if (tileElement->base_height < waterLevel + 6) @@ -240,17 +239,17 @@ void mapgen_generate(mapgen_settings *settings) static void mapgen_place_tree(sint32 type, sint32 x, sint32 y) { sint32 surfaceZ; - rct_tile_element *tileElement; - rct_scenery_entry *sceneryEntry = get_small_scenery_entry(type); + rct_tile_element * tileElement; + rct_scenery_entry * sceneryEntry = get_small_scenery_entry(type); - surfaceZ = tile_element_height(x * 32 + 16, y * 32 + 16) / 8; + surfaceZ = tile_element_height(x * 32 + 16, y * 32 + 16) / 8; tileElement = tile_element_insert(x, y, surfaceZ, (1 | 2 | 4 | 8)); - assert(tileElement != NULL); + assert(tileElement != nullptr); tileElement->clearance_height = surfaceZ + (sceneryEntry->small_scenery.height >> 3); - tileElement->type = TILE_ELEMENT_TYPE_SCENERY | (util_rand() & 3); + tileElement->type = TILE_ELEMENT_TYPE_SCENERY | (util_rand() & 3); tileElement->properties.scenery.type = type; - tileElement->properties.scenery.age = 0; + tileElement->properties.scenery.age = 0; scenery_small_set_primary_colour(tileElement, COLOUR_YELLOW); } @@ -259,119 +258,129 @@ static void mapgen_place_tree(sint32 type, sint32 x, sint32 y) */ static void mapgen_place_trees() { - sint32 numGrassTreeIds = 0, numDesertTreeIds = 0, numSnowTreeIds = 0; - sint32 *grassTreeIds = (sint32*)malloc(countof(GrassTrees) * sizeof(sint32)); - sint32 *desertTreeIds = (sint32*)malloc(countof(DesertTrees) * sizeof(sint32)); - sint32 *snowTreeIds = (sint32*)malloc(countof(SnowTrees) * sizeof(sint32)); + std::vector grassTreeIds(Util::CountOf(GrassTrees), 0); + std::vector desertTreeIds(Util::CountOf(DesertTrees), 0); + std::vector snowTreeIds(Util::CountOf(SnowTrees), 0); - for (sint32 i = 0; i < object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]; i++) { - rct_scenery_entry *sceneryEntry = get_small_scenery_entry(i); - rct_object_entry_extended *entry = &object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[i]; + for (sint32 i = 0; i < object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]; i++) + { + rct_scenery_entry * sceneryEntry = get_small_scenery_entry(i); + rct_object_entry_extended * entry = &object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[i]; - if (sceneryEntry == NULL) + if (sceneryEntry == nullptr) continue; - sint32 j; - for (j = 0; j < countof(GrassTrees); j++) + uint32 j; + for (j = 0; j < Util::CountOf(GrassTrees); j++) + { if (strncmp(GrassTrees[j], entry->name, 8) == 0) break; - if (j != countof(GrassTrees)) { - grassTreeIds[numGrassTreeIds++] = i; + } + if (j != Util::CountOf(GrassTrees)) + { + grassTreeIds.push_back(i); continue; } - for (j = 0; j < countof(DesertTrees); j++) + for (j = 0; j < Util::CountOf(DesertTrees); j++) + { if (strncmp(DesertTrees[j], entry->name, 8) == 0) break; - if (j != countof(DesertTrees)) { - desertTreeIds[numDesertTreeIds++] = i; + } + if (j != Util::CountOf(DesertTrees)) + { + desertTreeIds.push_back(i); continue; } - for (j = 0; j < countof(SnowTrees); j++) + for (j = 0; j < Util::CountOf(SnowTrees); j++) + { if (strncmp(SnowTrees[j], entry->name, 8) == 0) break; - if (j != countof(SnowTrees)) { - snowTreeIds[numSnowTreeIds++] = i; + } + if (j != Util::CountOf(SnowTrees)) + { + snowTreeIds.push_back(i); continue; } } - sint32 availablePositionsCount = 0; - struct { sint32 x; sint32 y; } tmp, *pos, *availablePositions; - availablePositions = malloc(MAXIMUM_MAP_SIZE_TECHNICAL * MAXIMUM_MAP_SIZE_TECHNICAL * sizeof(tmp)); + LocationXY32 tmp, pos; + + std::vector availablePositions; // Create list of available tiles - for (sint32 y = 1; y < gMapSize - 1; y++) { - for (sint32 x = 1; x < gMapSize - 1; x++) { - rct_tile_element *tileElement = map_get_surface_element_at(x, y); + for (sint32 y = 1; y < gMapSize - 1; y++) + { + for (sint32 x = 1; x < gMapSize - 1; x++) + { + rct_tile_element * tileElement = map_get_surface_element_at(x, y); // Exclude water tiles if (map_get_water_height(tileElement) > 0) continue; - pos = &availablePositions[availablePositionsCount++]; - pos->x = x; - pos->y = y; + pos.x = x; + pos.y = y; + availablePositions.push_back(pos); + } } // Shuffle list - for (sint32 i = 0; i < availablePositionsCount; i++) { - sint32 rindex = util_rand() % availablePositionsCount; + for (uint32 i = 0; i < availablePositions.size(); i++) + { + uint32 rindex = util_rand() % availablePositions.size(); if (rindex == i) continue; tmp = availablePositions[i]; - availablePositions[i] = availablePositions[rindex]; + availablePositions[i] = availablePositions[rindex]; availablePositions[rindex] = tmp; } // Place trees - float treeToLandRatio = (10 + (util_rand() % 30)) / 100.0f; - sint32 numTrees = max(4, (sint32)(availablePositionsCount * treeToLandRatio)); + float treeToLandRatio = (10 + (util_rand() % 30)) / 100.0f; + sint32 numTrees = Math::Max(4, (sint32) (availablePositions.size() * treeToLandRatio)); - for (sint32 i = 0; i < numTrees; i++) { - pos = &availablePositions[i]; + for (sint32 i = 0; i < numTrees; i++) + { + pos = availablePositions[i]; sint32 type = -1; - rct_tile_element *tileElement = map_get_surface_element_at(pos->x, pos->y); - switch (tile_element_get_terrain(tileElement)) { + rct_tile_element * tileElement = map_get_surface_element_at(pos.x, pos.y); + switch (tile_element_get_terrain(tileElement)) + { case TERRAIN_GRASS: case TERRAIN_DIRT: case TERRAIN_GRASS_CLUMPS: - if (numGrassTreeIds == 0) + if (grassTreeIds.size() == 0) break; - type = grassTreeIds[util_rand() % numGrassTreeIds]; + type = grassTreeIds[util_rand() % grassTreeIds.size()]; break; case TERRAIN_SAND: case TERRAIN_SAND_DARK: case TERRAIN_SAND_LIGHT: - if (numDesertTreeIds == 0) + if (desertTreeIds.size() == 0) break; if (util_rand() % 4 == 0) - type = desertTreeIds[util_rand() % numDesertTreeIds]; + type = desertTreeIds[util_rand() % desertTreeIds.size()]; break; case TERRAIN_ICE: - if (numSnowTreeIds == 0) + if (snowTreeIds.size() == 0) break; - type = snowTreeIds[util_rand() % numSnowTreeIds]; + type = snowTreeIds[util_rand() % snowTreeIds.size()]; break; } if (type != -1) - mapgen_place_tree(type, pos->x, pos->y); + mapgen_place_tree(type, pos.x, pos.y); } - - free(availablePositions); - free(grassTreeIds); - free(desertTreeIds); - free(snowTreeIds); } /** @@ -380,207 +389,21 @@ static void mapgen_place_trees() static void mapgen_set_water_level(sint32 waterLevel) { sint32 x, y, mapSize; - rct_tile_element *tileElement; + rct_tile_element * tileElement; mapSize = gMapSize; - for (y = 1; y < mapSize - 1; y++) { - for (x = 1; x < mapSize - 1; x++) { + for (y = 1; y < mapSize - 1; y++) + { + for (x = 1; x < mapSize - 1; x++) + { tileElement = map_get_surface_element_at(x, y); if (tileElement->base_height < waterLevel) - tileElement->properties.surface.terrain |= (waterLevel / 2); + tileElement->properties.surface.terrain |= (waterLevel / 2); } } } -static void mapgen_blobs(sint32 count, sint32 lowSize, sint32 highSize, sint32 lowHeight, sint32 highHeight) -{ - sint32 i; - sint32 sizeRange = highSize - lowSize; - sint32 heightRange = highHeight - lowHeight; - - sint32 border = 2 + (util_rand() % 24); - sint32 borderRange = _heightSize - (border * 2); - for (i = 0; i < count; i++) { - sint32 radius = lowSize + (util_rand() % sizeRange); - mapgen_blob( - border + (util_rand() % borderRange), - border + (util_rand() % borderRange), - (sint32)(M_PI * radius * radius), - lowHeight + (util_rand() % heightRange) - ); - } -} - -/** - * Sets any holes within a new created blob to the specified height. - */ -static void mapgen_blob_fill(sint32 height) -{ - // For each square find out whether it is landlocked by BLOB_HEIGHT and then fill it if it is - sint32 left = 0, - top = 0, - right = _heightSize - 1, - bottom = _heightSize - 1; - - uint8 *landX = (uint8*)malloc(_heightSize * _heightSize * sizeof(uint8)); - sint32 firstLand, lastLand; - - // Check each row and see if each tile is between first land x and last land x - for (sint32 y = top; y <= bottom; y++) { - // Calculate first land - firstLand = -1; - for (sint32 xx = left; xx <= right; xx++) { - if (get_height(xx, y) == BLOB_HEIGHT) { - firstLand = xx; - break; - } - } - - lastLand = -1; - if (firstLand >= 0) { - // Calculate last land - for (sint32 xx = right; xx >= left; xx--) { - if (get_height(xx, y) == BLOB_HEIGHT) { - lastLand = xx; - break; - } - } - } else { - // No land on this row - continue; - } - - for (sint32 x = left; x <= right; x++) - if (x >= firstLand && x <= lastLand) - landX[x * _heightSize + y] = 1; - } - - // Do the same for Y - for (sint32 x = left; x <= right; x++) { - // Calculate first land - firstLand = -1; - for (sint32 yy = top; yy <= bottom; yy++) { - if (get_height(x, yy) == BLOB_HEIGHT) { - firstLand = yy; - break; - } - } - - lastLand = -1; - if (firstLand >= 0) { - // Calculate last land - for (sint32 yy = bottom; yy >= top; yy--) { - if (get_height(x, yy) == BLOB_HEIGHT) { - lastLand = yy; - break; - } - } - } else { - // No land on this row - continue; - } - - for (sint32 y = top; y <= bottom; y++) { - if (y >= firstLand && y <= lastLand && landX[x * _heightSize + y]) { - // Not only do we know it's landlocked to both x and y - // we can change the land too - set_height(x, y, BLOB_HEIGHT); - } - } - } - - // Replace all the BLOB_HEIGHT with the actual land height - for (sint32 x = left; x <= right; x++) - for (sint32 y = top; y <= bottom; y++) - if (get_height(x, y) == BLOB_HEIGHT) - set_height(x, y, height); - - free(landX); -} - -/** - * Sets a rough circular blob of tiles of the specified size to the specified height. - */ -static void mapgen_blob(sint32 cx, sint32 cy, sint32 size, sint32 height) -{ - sint32 x, y, currentSize, direction; - - x = cx; - y = cy; - currentSize = 1; - direction = 0; - set_height(x, y, BLOB_HEIGHT); - - while (currentSize < size) { - if (util_rand() % 2 == 0) { - set_height(x, y, BLOB_HEIGHT); - currentSize++; - } - - switch (direction) { - case 0: - if (y == 0) { - currentSize = size; - break; - } - - y--; - if (get_height(x + 1, y) != BLOB_HEIGHT) - direction = 1; - else if (get_height(x, y - 1) != BLOB_HEIGHT) - direction = 0; - else if (get_height(x - 1, y) != BLOB_HEIGHT) - direction = 3; - break; - case 1: - if (x == _heightSize - 1) { - currentSize = size; - break; - } - - x++; - if (get_height(x, y + 1) != BLOB_HEIGHT) - direction = 2; - else if (get_height(x + 1, y) != BLOB_HEIGHT) - direction = 1; - else if (get_height(x, y - 1) != BLOB_HEIGHT) - direction = 0; - break; - case 2: - if (y == _heightSize - 1) { - currentSize = size; - break; - } - - y++; - if (get_height(x - 1, y) != BLOB_HEIGHT) - direction = 3; - else if (get_height(x, y + 1) != BLOB_HEIGHT) - direction = 2; - else if (get_height(x + 1, y) != BLOB_HEIGHT) - direction = 1; - break; - case 3: - if (x == 0) { - currentSize = size; - break; - } - - x--; - if (get_height(x, y - 1) != BLOB_HEIGHT) - direction = 0; - else if (get_height(x - 1, y) != BLOB_HEIGHT) - direction = 3; - else if (get_height(x, y + 1) != BLOB_HEIGHT) - direction = 2; - break; - } - } - - mapgen_blob_fill(height); -} - /** * Smooths the height map. */ @@ -588,23 +411,30 @@ static void mapgen_smooth_height(sint32 iterations) { sint32 i, x, y, xx, yy, avg; sint32 arraySize = _heightSize * _heightSize * sizeof(uint8); - uint8 *copyHeight = malloc(arraySize); + uint8 * copyHeight = new uint8[arraySize]; - for (i = 0; i < iterations; i++) { + for (i = 0; i < iterations; i++) + { memcpy(copyHeight, _height, arraySize); - for (y = 1; y < _heightSize - 1; y++) { - for (x = 1; x < _heightSize - 1; x++) { - avg = 0; + for (y = 1; y < _heightSize - 1; y++) + { + for (x = 1; x < _heightSize - 1; x++) + { + avg = 0; for (yy = -1; yy <= 1; yy++) + { for (xx = -1; xx <= 1; xx++) + { avg += copyHeight[(y + yy) * _heightSize + (x + xx)]; + } + } avg /= 9; set_height(x, y, avg); } } } - free(copyHeight); + delete[] copyHeight; } /** @@ -613,11 +443,13 @@ static void mapgen_smooth_height(sint32 iterations) static void mapgen_set_height() { sint32 x, y, heightX, heightY, mapSize; - rct_tile_element *tileElement; + rct_tile_element * tileElement; mapSize = _heightSize / 2; - for (y = 1; y < mapSize - 1; y++) { - for (x = 1; x < mapSize - 1; x++) { + for (y = 1; y < mapSize - 1; y++) + { + for (x = 1; x < mapSize - 1; x++) + { heightX = x * 2; heightY = y * 2; @@ -629,7 +461,7 @@ static void mapgen_set_height() uint8 baseHeight = (q00 + q01 + q10 + q11) / 4; tileElement = map_get_surface_element_at(x, y); - tileElement->base_height = max(2, baseHeight * 2); + tileElement->base_height = Math::Max(2, baseHeight * 2); tileElement->clearance_height = tileElement->base_height; if (q00 > baseHeight) @@ -661,15 +493,18 @@ static uint8 perm[512]; static void noise_rand() { - for (sint32 i = 0; i < countof(perm); i++) + for (uint32 i = 0; i < Util::CountOf(perm); i++) + { perm[i] = util_rand() & 0xFF; + } } static float fractal_noise(sint32 x, sint32 y, float frequency, sint32 octaves, float lacunarity, float persistence) { - float total = 0.0f; - float amplitude = persistence; - for (sint32 i = 0; i < octaves; i++) { + float total = 0.0f; + float amplitude = persistence; + for (sint32 i = 0; i < octaves; i++) + { total += generate(x * frequency, y * frequency) * amplitude; frequency *= lacunarity; amplitude *= persistence; @@ -685,13 +520,13 @@ static float generate(float x, float y) float n0, n1, n2; // Noise contributions from the three corners // Skew the input space to determine which simplex cell we're in - float s = (x + y) * F2; // Hairy factor for 2D - float xs = x + s; - float ys = y + s; - sint32 i = fast_floor(xs); - sint32 j = fast_floor(ys); + float s = (x + y) * F2; // Hairy factor for 2D + float xs = x + s; + float ys = y + s; + sint32 i = fast_floor(xs); + sint32 j = fast_floor(ys); - float t = (float)(i + j) * G2; + float t = (float) (i + j) * G2; float X0 = i - t; // Unskew the cell origin back to (x,y) space float Y0 = j - t; float x0 = x - X0; // The x,y distances from the cell origin @@ -700,8 +535,16 @@ static float generate(float x, float y) // For the 2D case, the simplex shape is an equilateral triangle. // Determine which simplex we are in. sint32 i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords - if (x0 > y0) { i1 = 1; j1 = 0; } // lower triangle, XY order: (0,0)->(1,0)->(1,1) - else { i1 = 0; j1 = 1; } // upper triangle, YX order: (0,0)->(0,1)->(1,1) + if (x0 > y0) + { + i1 = 1; + j1 = 0; + } // lower triangle, XY order: (0,0)->(1,0)->(1,1) + else + { + i1 = 0; + j1 = 1; + } // upper triangle, YX order: (0,0)->(0,1)->(1,1) // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where @@ -718,22 +561,34 @@ static float generate(float x, float y) // Calculate the contribution from the three corners float t0 = 0.5f - x0 * x0 - y0 * y0; - if (t0 < 0.0f) n0 = 0.0f; - else { + if (t0 < 0.0f) + { + n0 = 0.0f; + } + else + { t0 *= t0; n0 = t0 * t0 * grad(perm[ii + perm[jj]], x0, y0); } float t1 = 0.5f - x1 * x1 - y1 * y1; - if (t1 < 0.0f) n1 = 0.0f; - else { + if (t1 < 0.0f) + { + n1 = 0.0f; + } + else + { t1 *= t1; n1 = t1 * t1 * grad(perm[ii + i1 + perm[jj + j1]], x1, y1); } float t2 = 0.5f - x2 * x2 - y2 * y2; - if (t2 < 0.0f) n2 = 0.0f; - else { + if (t2 < 0.0f) + { + n2 = 0.0f; + } + else + { t2 *= t2; n2 = t2 * t2 * grad(perm[ii + 1 + perm[jj + 1]], x2, y2); } @@ -745,34 +600,36 @@ static float generate(float x, float y) static sint32 fast_floor(float x) { - return (x > 0) ? ((sint32)x) : (((sint32)x) - 1); + return (x > 0) ? ((sint32) x) : (((sint32) x) - 1); } static float grad(sint32 hash, float x, float y) { sint32 h = hash & 7; // Convert low 3 bits of hash code - float u = h < 4 ? x : y; // into 8 simple gradient directions, - float v = h < 4 ? y : x; // and compute the dot product with (x,y). + float u = h < 4 ? x : y; // into 8 simple gradient directions, + float v = h < 4 ? y : x; // and compute the dot product with (x,y). return ((h & 1) != 0 ? -u : u) + ((h & 2) != 0 ? -2.0f * v : 2.0f * v); } -static void mapgen_simplex(mapgen_settings *settings) +static void mapgen_simplex(mapgen_settings * settings) { sint32 x, y; - float freq = settings->simplex_base_freq * (1.0f / _heightSize); + float freq = settings->simplex_base_freq * (1.0f / _heightSize); sint32 octaves = settings->simplex_octaves; - sint32 low = settings->simplex_low; + sint32 low = settings->simplex_low; sint32 high = settings->simplex_high; noise_rand(); - for (y = 0; y < _heightSize; y++) { - for (x = 0; x < _heightSize; x++) { - float noiseValue = clamp(-1.0f, fractal_noise(x, y, freq, octaves, 2.0f, 0.65f), 1.0f); + for (y = 0; y < _heightSize; y++) + { + for (x = 0; x < _heightSize; x++) + { + float noiseValue = Math::Clamp(-1.0f, fractal_noise(x, y, freq, octaves, 2.0f, 0.65f), 1.0f); float normalisedNoiseValue = (noiseValue + 1.0f) / 2.0f; - set_height(x, y, low + (sint32)(normalisedNoiseValue * high)); + set_height(x, y, low + (sint32) (normalisedNoiseValue * high)); } } } @@ -781,15 +638,16 @@ static void mapgen_simplex(mapgen_settings *settings) #pragma region Heightmap -bool mapgen_load_heightmap(const utf8 *path) +bool mapgen_load_heightmap(const utf8 * path) { - const char* extension = path_get_extension(path); - uint8 *pixels; + const char * extension = path_get_extension(path); + uint8 * pixels; size_t pitch; uint32 numChannels; uint32 width, height; - if (strcicmp(extension, ".png") == 0) { + if (String::Equals(extension, ".png", false)) + { sint32 bitDepth; if (!image_io_png_read(&pixels, &width, &height, true, path, &bitDepth)) { @@ -799,16 +657,18 @@ bool mapgen_load_heightmap(const utf8 *path) } numChannels = 4; - pitch = width * numChannels; + pitch = width * numChannels; } - else if (strcicmp(extension, ".bmp") == 0) { - if (!context_read_bmp((void *)&pixels, &width, &height, path)) { + else if (strcicmp(extension, ".bmp") == 0) + { + if (!context_read_bmp((void **) &pixels, &width, &height, path)) + { // ReadBMP contains context_show_error calls return false; } numChannels = 4; - pitch = width * numChannels; + pitch = width * numChannels; } else { @@ -816,31 +676,33 @@ bool mapgen_load_heightmap(const utf8 *path) return false; } - if (width != height) { + if (width != height) + { context_show_error(STR_HEIGHT_MAP_ERROR, STR_ERROR_WIDTH_AND_HEIGHT_DO_NOT_MATCH); free(pixels); return false; } - if (width > MAXIMUM_MAP_SIZE_PRACTICAL) { + if (width > MAXIMUM_MAP_SIZE_PRACTICAL) + { context_show_error(STR_HEIGHT_MAP_ERROR, STR_ERROR_HEIHGT_MAP_TOO_BIG); - width = height = min(height, MAXIMUM_MAP_SIZE_PRACTICAL); + width = height = Math::Min(height, (uint32)MAXIMUM_MAP_SIZE_PRACTICAL); } // Allocate memory for the height map values, one byte pixel - free(_heightMapData.mono_bitmap); - _heightMapData.mono_bitmap = (uint8*)malloc(width * height); - _heightMapData.width = width; - _heightMapData.height = height; + delete[] _heightMapData.mono_bitmap; + _heightMapData.mono_bitmap = new uint8[width * height]; + _heightMapData.width = width; + _heightMapData.height = height; // Copy average RGB value to mono bitmap for (uint32 x = 0; x < _heightMapData.width; x++) { for (uint32 y = 0; y < _heightMapData.height; y++) { - const uint8 red = pixels[x * numChannels + y * pitch]; + const uint8 red = pixels[x * numChannels + y * pitch]; const uint8 green = pixels[x * numChannels + y * pitch + 1]; - const uint8 blue = pixels[x * numChannels + y * pitch + 2]; + const uint8 blue = pixels[x * numChannels + y * pitch + 2]; _heightMapData.mono_bitmap[x + y * _heightMapData.width] = (red + green + blue) / 3; } } @@ -854,19 +716,18 @@ bool mapgen_load_heightmap(const utf8 *path) */ void mapgen_unload_heightmap() { - free(_heightMapData.mono_bitmap); - _heightMapData.mono_bitmap = NULL; - _heightMapData.width = 0; - _heightMapData.height = 0; + SafeDeleteArray(_heightMapData.mono_bitmap); + _heightMapData.width = 0; + _heightMapData.height = 0; } /** * Applies box blur to the surface N times */ -static void mapgen_smooth_heightmap(uint8 *src, sint32 strength) +static void mapgen_smooth_heightmap(uint8 * src, sint32 strength) { // Create buffer to store one channel - uint8 *dest = (uint8*)malloc(_heightMapData.width * _heightMapData.height); + uint8 * dest = new uint8[_heightMapData.width * _heightMapData.height]; for (sint32 i = 0; i < strength; i++) { @@ -884,8 +745,8 @@ static void mapgen_smooth_heightmap(uint8 *src, sint32 strength) { // Clamp x and y so they stay within the image // This assumes the height map is not tiled, and increases the weight of the edges - const sint32 readX = clamp((sint32)x + offsetX, 0, (sint32)_heightMapData.width - 1); - const sint32 readY = clamp((sint32)y + offsetY, 0, (sint32)_heightMapData.height - 1); + const sint32 readX = Math::Clamp((sint32) x + offsetX, 0, (sint32) _heightMapData.width - 1); + const sint32 readY = Math::Clamp((sint32) y + offsetY, 0, (sint32) _heightMapData.height - 1); heightSum += src[readX + readY * _heightMapData.width]; } } @@ -905,17 +766,17 @@ static void mapgen_smooth_heightmap(uint8 *src, sint32 strength) } } - free(dest); + delete[] dest; } -void mapgen_generate_from_heightmap(mapgen_settings *settings) +void mapgen_generate_from_heightmap(mapgen_settings * settings) { openrct2_assert(_heightMapData.width == _heightMapData.height, "Invalid height map size"); - openrct2_assert(_heightMapData.mono_bitmap != NULL, "No height map loaded"); + openrct2_assert(_heightMapData.mono_bitmap != nullptr, "No height map loaded"); openrct2_assert(settings->simplex_high != settings->simplex_low, "Low and high setting cannot be the same"); // Make a copy of the original height map that we can edit - uint8 *dest = (uint8*)malloc(_heightMapData.width * _heightMapData.height); + uint8 * dest = new uint8[_heightMapData.width * _heightMapData.height]; memcpy(dest, _heightMapData.mono_bitmap, _heightMapData.width * _heightMapData.width); map_init(_heightMapData.width + 2); // + 2 for the black tiles around the map @@ -938,15 +799,15 @@ void mapgen_generate_from_heightmap(mapgen_settings *settings) for (uint32 x = 0; x < _heightMapData.width; x++) { uint8 value = dest[x + y * _heightMapData.width]; - maxValue = max(maxValue, value); - minValue = min(minValue, value); + maxValue = Math::Max(maxValue, value); + minValue = Math::Min(minValue, value); } } if (minValue == maxValue) { context_show_error(STR_HEIGHT_MAP_ERROR, STR_ERROR_CANNOT_NORMALIZE); - free(dest); + delete[] dest; return; } } @@ -954,7 +815,7 @@ void mapgen_generate_from_heightmap(mapgen_settings *settings) openrct2_assert(maxValue > minValue, "Input range is invalid"); openrct2_assert(settings->simplex_high > settings->simplex_low, "Output range is invalid"); - const uint8 rangeIn = maxValue - minValue; + const uint8 rangeIn = maxValue - minValue; const uint8 rangeOut = settings->simplex_high - settings->simplex_low; for (uint32 y = 0; y < _heightMapData.height; y++) @@ -962,12 +823,12 @@ void mapgen_generate_from_heightmap(mapgen_settings *settings) for (uint32 x = 0; x < _heightMapData.width; x++) { // The x and y axis are flipped in the world, so this uses y for x and x for y. - rct_tile_element *const surfaceElement = map_get_surface_element_at(y + 1, x + 1); + rct_tile_element * const surfaceElement = map_get_surface_element_at(y + 1, x + 1); // Read value from bitmap, and convert its range uint8 value = dest[x + y * _heightMapData.width]; - value = (uint8)((float)(value - minValue) / rangeIn * rangeOut) + settings->simplex_low; - surfaceElement->base_height = value; + value = (uint8) ((float) (value - minValue) / rangeIn * rangeOut) + settings->simplex_low; + surfaceElement->base_height = value; // Floor to even number surfaceElement->base_height /= 2; @@ -1003,7 +864,7 @@ void mapgen_generate_from_heightmap(mapgen_settings *settings) } // Clean up - free(dest); + delete[] dest; } #pragma endregion diff --git a/src/openrct2/world/mapgen.h b/src/openrct2/world/MapGen.h similarity index 73% rename from src/openrct2/world/mapgen.h rename to src/openrct2/world/MapGen.h index 54d17c2d83..e252ec73ca 100644 --- a/src/openrct2/world/mapgen.h +++ b/src/openrct2/world/MapGen.h @@ -14,12 +14,12 @@ *****************************************************************************/ #pragma endregion -#ifndef _MAPGEN_H_ -#define _MAPGEN_H_ +#pragma once #include "../common.h" -typedef struct mapgen_settings { +typedef struct mapgen_settings +{ // Base sint32 mapSize; sint32 height; @@ -33,29 +33,27 @@ typedef struct mapgen_settings { // Simplex Noise Parameters sint32 simplex_low; sint32 simplex_high; - float simplex_base_freq; + float simplex_base_freq; sint32 simplex_octaves; // Height map settings - bool smooth; - bool smooth_height_map; + bool smooth; + bool smooth_height_map; uint32 smooth_strength; - bool normalize_height; + bool normalize_height; } mapgen_settings; #ifdef __cplusplus extern "C" { #endif -void mapgen_generate_blank(mapgen_settings *settings); -void mapgen_generate(mapgen_settings *settings); -void mapgen_generate_custom_simplex(mapgen_settings *settings); -bool mapgen_load_heightmap(const utf8 *path); +void mapgen_generate_blank(mapgen_settings * settings); +void mapgen_generate(mapgen_settings * settings); +void mapgen_generate_custom_simplex(mapgen_settings * settings); +bool mapgen_load_heightmap(const utf8 * path); void mapgen_unload_heightmap(); -void mapgen_generate_from_heightmap(mapgen_settings *settings); +void mapgen_generate_from_heightmap(mapgen_settings * settings); #ifdef __cplusplus } #endif - -#endif