mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 11:03:00 +01:00
Add smoothing height map option
This commit is contained in:
committed by
Michał Janiszewski
parent
edfe997e78
commit
26989ea8f6
@@ -86,8 +86,8 @@ enum {
|
||||
WIDX_SIMPLEX_FLOOR_TEXTURE,
|
||||
WIDX_SIMPLEX_WALL_TEXTURE,
|
||||
|
||||
WIDX_HEIGHTMAP_SMOOTH = TAB_BEGIN,
|
||||
WIDX_HEIGHTMAP_STRONG,
|
||||
WIDX_HEIGHTMAP_SMOOTH_HEIGHTMAP = TAB_BEGIN,
|
||||
WIDX_HEIGHTMAP_SMOOTH_TILES,
|
||||
WIDX_HEIGHTMAP_NORMALIZE,
|
||||
WIDX_HEIGHTMAP_LOW,
|
||||
WIDX_HEIGHTMAP_LOW_UP,
|
||||
@@ -201,10 +201,10 @@ static rct_widget HeightmapWidgets[] = {
|
||||
|
||||
{ WWT_DROPDOWN_BUTTON, 1, 104, 198, 52, 63, STR_MAPGEN_ACTION_GENERATE, STR_NONE }, // WIDX_GENERATE
|
||||
|
||||
{ WWT_CHECKBOX, 1, 4, 103, 52, 63, STR_MAPGEN_SMOOTH_TILE, STR_NONE }, // WIDX_HEIGHTMAP_SMOOTH
|
||||
{ WWT_CHECKBOX, 1, 4, 103, 70, 81, STR_MAPGEN_SMOOTH_STRONG, STR_NONE }, // WIDX_HEIGHTMAP_STRONG
|
||||
{ WWT_CHECKBOX, 1, 4, 103, 52, 63, STR_MAPGEN_SMOOTH_HEIGHTMAP,STR_NONE }, // WIDX_HEIGHTMAP_SMOOTH_HEIGHTMAP
|
||||
{ WWT_CHECKBOX, 1, 4, 103, 70, 81, STR_MAPGEN_SMOOTH_TILE, STR_NONE }, // WIDX_HEIGHTMAP_SMOOTH_TILES
|
||||
|
||||
{ WWT_CHECKBOX, 1, 4, 103, 88, 99, STR_MAPGEN_NORMALIZE, STR_NONE }, // WIDX_HEIGHTMAP_NORMALIZE
|
||||
{ WWT_CHECKBOX, 1, 4, 103, 88, 99, STR_MAPGEN_NORMALIZE, STR_NONE }, // WIDX_HEIGHTMAP_NORMALIZE
|
||||
|
||||
{ WWT_SPINNER, 1, 104, 198, 106, 117, STR_NONE, STR_NONE }, // WIDX_HEIGHTMAP_LOW
|
||||
{ WWT_DROPDOWN_BUTTON, 1, 187, 197, 107, 111, STR_NUMERIC_UP, STR_NONE }, // WIDX_HEIGHTMAP_LOW_UP
|
||||
@@ -235,7 +235,7 @@ static uint64 PressedWidgets[] = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(1ULL << WIDX_HEIGHTMAP_SMOOTH)
|
||||
(1ULL << WIDX_HEIGHTMAP_SMOOTH_TILES)
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
@@ -464,8 +464,8 @@ static uint32 PageEnabledWidgets[] = {
|
||||
(1ULL << WIDX_TAB_3) |
|
||||
(1ULL << WIDX_TAB_4) |
|
||||
(1ULL << WIDX_GENERATE) |
|
||||
(1ULL << WIDX_HEIGHTMAP_SMOOTH) |
|
||||
(1ULL << WIDX_HEIGHTMAP_STRONG) |
|
||||
(1ULL << WIDX_HEIGHTMAP_SMOOTH_HEIGHTMAP) |
|
||||
(1ULL << WIDX_HEIGHTMAP_SMOOTH_TILES) |
|
||||
(1ULL << WIDX_HEIGHTMAP_NORMALIZE) |
|
||||
(1ULL << WIDX_HEIGHTMAP_LOW) |
|
||||
(1ULL << WIDX_HEIGHTMAP_LOW_UP) |
|
||||
@@ -551,7 +551,7 @@ static sint32 _simplex_octaves = 4;
|
||||
|
||||
static bool _heightmapNormalize = true;
|
||||
static sint32 _heightmapLow = 10;
|
||||
static sint32 _heightmapHigh = 14;
|
||||
static sint32 _heightmapHigh = 40;
|
||||
|
||||
rct_window *window_mapgen_open()
|
||||
{
|
||||
@@ -1147,22 +1147,21 @@ static void window_mapgen_heightmap_mouseup(rct_window *w, sint32 widgetIndex)
|
||||
break;
|
||||
case WIDX_GENERATE:
|
||||
mapgenSettings.water_level = _waterLevel;
|
||||
mapgenSettings.smooth = widget_is_pressed(w, WIDX_HEIGHTMAP_SMOOTH);
|
||||
mapgenSettings.strong_smooth = widget_is_pressed(w, WIDX_HEIGHTMAP_STRONG);
|
||||
mapgenSettings.smooth = widget_is_pressed(w, WIDX_HEIGHTMAP_SMOOTH_TILES);
|
||||
mapgenSettings.smooth_height_map = widget_is_pressed(w, WIDX_HEIGHTMAP_SMOOTH_HEIGHTMAP);
|
||||
mapgenSettings.normalize_height = _heightmapNormalize;
|
||||
mapgenSettings.simplex_low = _heightmapLow;
|
||||
mapgenSettings.simplex_high = _heightmapHigh;
|
||||
mapgen_generate_from_heightmap(&mapgenSettings);
|
||||
gfx_invalidate_screen();
|
||||
break;
|
||||
case WIDX_HEIGHTMAP_SMOOTH:
|
||||
widget_set_checkbox_value(w, WIDX_HEIGHTMAP_SMOOTH, !widget_is_pressed(w, WIDX_HEIGHTMAP_SMOOTH));
|
||||
widget_set_enabled(w, WIDX_HEIGHTMAP_STRONG, widget_is_pressed(w, WIDX_HEIGHTMAP_SMOOTH));
|
||||
widget_invalidate(w, WIDX_HEIGHTMAP_SMOOTH);
|
||||
widget_invalidate(w, WIDX_HEIGHTMAP_STRONG);
|
||||
case WIDX_HEIGHTMAP_SMOOTH_HEIGHTMAP:
|
||||
widget_set_checkbox_value(w, WIDX_HEIGHTMAP_SMOOTH_HEIGHTMAP, !widget_is_pressed(w, WIDX_HEIGHTMAP_SMOOTH_HEIGHTMAP));
|
||||
widget_invalidate(w, WIDX_HEIGHTMAP_SMOOTH_HEIGHTMAP);
|
||||
break;
|
||||
case WIDX_HEIGHTMAP_STRONG:
|
||||
widget_set_checkbox_value(w, WIDX_HEIGHTMAP_STRONG, !widget_is_pressed(w, WIDX_HEIGHTMAP_STRONG));
|
||||
case WIDX_HEIGHTMAP_SMOOTH_TILES:
|
||||
widget_set_checkbox_value(w, WIDX_HEIGHTMAP_SMOOTH_TILES, !widget_is_pressed(w, WIDX_HEIGHTMAP_SMOOTH_TILES));
|
||||
widget_invalidate(w, WIDX_HEIGHTMAP_SMOOTH_TILES);
|
||||
break;
|
||||
case WIDX_HEIGHTMAP_NORMALIZE:
|
||||
_heightmapNormalize = !_heightmapNormalize;
|
||||
|
||||
@@ -766,7 +766,61 @@ static void mapgen_simplex(mapgen_settings *settings)
|
||||
|
||||
#pragma region Heightmap
|
||||
|
||||
#pragma optimize("", off)
|
||||
/**
|
||||
* Applies box Gaussian blur to the surface
|
||||
*/
|
||||
void mapgen_smooth_heightmap(SDL_Surface *surface)
|
||||
{
|
||||
SDL_LockSurface(surface);
|
||||
|
||||
// Apply box Gaussian blur
|
||||
const uint32 width = surface->w;
|
||||
const uint32 height = surface->h;
|
||||
const uint32 numChannels = surface->format->BytesPerPixel;
|
||||
const size_t pitch = surface->pitch;
|
||||
|
||||
// Create buffer to store one channel
|
||||
uint8 *dest = (uint8*)malloc(width * height);
|
||||
uint8 *src = surface->pixels;
|
||||
|
||||
// Calculate box Gaussian blur value to all pixels of the surface
|
||||
for (uint32 y = 0; y < height; y++)
|
||||
{
|
||||
for (uint32 x = 0; x < width; x++)
|
||||
{
|
||||
uint32 sum = 0;
|
||||
|
||||
// Loop over neightbour pixels, all of them have the same weight
|
||||
for (sint8 offsetX = -1; offsetX <= 1; offsetX++)
|
||||
{
|
||||
for (sint8 offsetY = -1; offsetY <= 1; offsetY++)
|
||||
{
|
||||
// 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(x + offsetX, 0, width - 1);
|
||||
const sint32 readY = clamp(y + offsetY, 0, height - 1);
|
||||
sum += src[readX * numChannels + readY * pitch];
|
||||
}
|
||||
}
|
||||
|
||||
// Take average
|
||||
dest[x + y * width] = sum / 9;
|
||||
}
|
||||
}
|
||||
|
||||
// Now apply the Gaussian blur to the real pixels
|
||||
for (uint32 y = 0; y < height; y++)
|
||||
{
|
||||
for (uint32 x = 0; x < width; x++)
|
||||
{
|
||||
src[x * numChannels + y * pitch] = dest[x + y * width];
|
||||
}
|
||||
}
|
||||
|
||||
free(dest);
|
||||
SDL_UnlockSurface(surface);
|
||||
}
|
||||
|
||||
void mapgen_generate_from_heightmap(mapgen_settings *settings)
|
||||
{
|
||||
openrct2_assert(settings->simplex_high != settings->simplex_low, "Low and high setting cannot be the same");
|
||||
@@ -778,15 +832,21 @@ void mapgen_generate_from_heightmap(mapgen_settings *settings)
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 width = bitmap->w;
|
||||
uint32 height = bitmap->h;
|
||||
uint8 numChannels = bitmap->format->BytesPerPixel;
|
||||
const uint32 width = bitmap->w;
|
||||
const uint32 height = bitmap->h;
|
||||
const uint8 numChannels = bitmap->format->BytesPerPixel;
|
||||
|
||||
map_init(width + 2); // + 2 for the black tiles around the map
|
||||
|
||||
uint8 maxValue = 255;
|
||||
uint8 minValue = 0;
|
||||
|
||||
if (settings->smooth_height_map)
|
||||
{
|
||||
// Smooth height map
|
||||
mapgen_smooth_heightmap(bitmap);
|
||||
}
|
||||
|
||||
SDL_LockSurface(bitmap);
|
||||
uint8 *src = (uint8*)bitmap->pixels;
|
||||
if (settings->normalize_height)
|
||||
@@ -846,33 +906,25 @@ void mapgen_generate_from_heightmap(mapgen_settings *settings)
|
||||
// Smooth map
|
||||
if (settings->smooth)
|
||||
{
|
||||
if (settings->strong_smooth)
|
||||
// Keep smoothing the entire map until no tiles are changed anymore
|
||||
while (true)
|
||||
{
|
||||
map_smooth(1, 1, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep smoothing the entire map until no tiles are changed anymore
|
||||
while (true)
|
||||
sint32 numTilesChanged = 0;
|
||||
for (uint32 y = 1; y <= height; y++)
|
||||
{
|
||||
sint32 numTilesChanged = 0;
|
||||
for (uint32 y = 1; y <= height; y++)
|
||||
for (uint32 x = 1; x <= width; x++)
|
||||
{
|
||||
for (uint32 x = 1; x <= width; x++)
|
||||
{
|
||||
numTilesChanged += tile_smooth(x, y);
|
||||
}
|
||||
numTilesChanged += tile_smooth(x, y);
|
||||
}
|
||||
|
||||
if (numTilesChanged == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (numTilesChanged == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(bitmap);
|
||||
SDL_FreeSurface(bitmap);
|
||||
}
|
||||
#pragma optimize("", on)
|
||||
|
||||
#pragma endregion
|
||||
|
||||
@@ -36,7 +36,7 @@ typedef struct mapgen_settings {
|
||||
|
||||
// Height map settings
|
||||
bool smooth;
|
||||
bool strong_smooth;
|
||||
bool smooth_height_map;
|
||||
bool normalize_height;
|
||||
} mapgen_settings;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user