mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-20 05:23:04 +01:00
Add tile_smooth function to smooth generated map
This commit is contained in:
committed by
Michał Janiszewski
parent
702d99e1e3
commit
d2113514a0
@@ -320,3 +320,96 @@ static sint32 map_smooth_wavy(sint32 l, sint32 t, sint32 r, sint32 b)
|
||||
|
||||
return raisedLand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raises the corners based on the height offset of neightbour tiles.
|
||||
* This does not change the base height, unless all corners have been raised.
|
||||
* @returns 0 if no edits were made, 1 otherwise
|
||||
*/
|
||||
sint32 tile_smooth(sint32 x, sint32 y)
|
||||
{
|
||||
rct_map_element *const surfaceElement = map_get_surface_element_at(x, y);
|
||||
|
||||
// +-----+-----+-----+
|
||||
// | NW | N | NE |
|
||||
// | 2 | 1 | 0 |
|
||||
// +-----+-----+-----+
|
||||
// | W | _ | E |
|
||||
// | 4 | | 3 |
|
||||
// +-----+-----+-----+
|
||||
// | SW | S | SE |
|
||||
// | 7 | 6 | 5 |
|
||||
// +-----+-----+-----+
|
||||
union
|
||||
{
|
||||
sint32 baseheight[8];
|
||||
struct { sint32 NE, N, NW, E, W, SE, S, SW; };
|
||||
} neighbourHeightOffset = { 0 };
|
||||
|
||||
// Find the neighbour base heights
|
||||
for (sint32 index = 0, y_offset = -1; y_offset <= 1; y_offset++)
|
||||
{
|
||||
for (sint32 x_offset = -1; x_offset <= 1; x_offset++)
|
||||
{
|
||||
// Skip self
|
||||
if (y_offset == 0 && x_offset == 0)
|
||||
continue;
|
||||
|
||||
// Get neightbour height. If the element is not valid (outside of map) assume the same height
|
||||
rct_map_element *neightbour_element = map_get_surface_element_at(x + x_offset, y + y_offset);
|
||||
neighbourHeightOffset.baseheight[index] = neightbour_element ? neightbour_element->base_height : surfaceElement->base_height;
|
||||
|
||||
// Make the height relative to the current surface element
|
||||
neighbourHeightOffset.baseheight[index] -= surfaceElement->base_height;
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// Count number from the three tiles that is currently higher
|
||||
sint8 thresholdNW = clamp(neighbourHeightOffset.W, 0, 1) + clamp(neighbourHeightOffset.NW, 0, 1) + clamp(neighbourHeightOffset.N, 0, 1);
|
||||
sint8 thresholdNE = clamp(neighbourHeightOffset.N, 0, 1) + clamp(neighbourHeightOffset.NE, 0, 1) + clamp(neighbourHeightOffset.E, 0, 1);
|
||||
sint8 thresholdSE = clamp(neighbourHeightOffset.E, 0, 1) + clamp(neighbourHeightOffset.SE, 0, 1) + clamp(neighbourHeightOffset.S, 0, 1);
|
||||
sint8 thresholdSW = clamp(neighbourHeightOffset.S, 0, 1) + clamp(neighbourHeightOffset.SW, 0, 1) + clamp(neighbourHeightOffset.W, 0, 1);
|
||||
|
||||
uint8 slope = 0;
|
||||
slope |= (thresholdNW >= 1) << 1;
|
||||
slope |= (thresholdNE >= 1) << 2;
|
||||
slope |= (thresholdSE >= 1) << 3;
|
||||
slope |= (thresholdSW >= 1) << 0;
|
||||
|
||||
// Set diagonal when three corners have been raised, and the middle one can be raised one more
|
||||
if ((slope == 0b0111 && neighbourHeightOffset.NW >= 4) || (slope == 0b1011 && neighbourHeightOffset.SW >= 4) ||
|
||||
(slope == 0b1101 && neighbourHeightOffset.SE >= 4) || (slope == 0b1110 && neighbourHeightOffset.NE >= 4))
|
||||
{
|
||||
slope |= 1 << 4;
|
||||
}
|
||||
|
||||
// Check if the calculated slope is the same already
|
||||
uint8 currentSlope = surfaceElement->properties.surface.slope & 0x1F;
|
||||
if (currentSlope == slope)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Remove old slope value
|
||||
surfaceElement->properties.surface.slope &= ~0x1F;
|
||||
if ((slope & 0xF) == 0xF)
|
||||
{
|
||||
// All corners are raised, raise the entire tile instead.
|
||||
surfaceElement->base_height = (surfaceElement->clearance_height += 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply the slope to this tile
|
||||
surfaceElement->properties.surface.slope |= slope;
|
||||
|
||||
// Set correct clearance height
|
||||
if (slope & 0x10)
|
||||
surfaceElement->clearance_height = surfaceElement->base_height + 4;
|
||||
else if (slope & 0x0F)
|
||||
surfaceElement->clearance_height = surfaceElement->base_height + 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -18,5 +18,6 @@
|
||||
#define _MAP_HELPERS_H_
|
||||
|
||||
sint32 map_smooth(sint32 l, sint32 t, sint32 r, sint32 b);
|
||||
sint32 tile_smooth(sint32 x, sint32 y);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -767,10 +767,9 @@ static void mapgen_simplex(mapgen_settings *settings)
|
||||
|
||||
#pragma region Heightmap
|
||||
|
||||
#pragma optimize("", off)
|
||||
void mapgen_generate_from_heightmap()
|
||||
{
|
||||
SDL_Surface *bitmap = SDL_LoadBMP("test.bmp");
|
||||
SDL_Surface *bitmap = SDL_LoadBMP("test_blurry.bmp");
|
||||
if (bitmap == NULL)
|
||||
{
|
||||
printf("Failed to load bitmap: %s\n", SDL_GetError());
|
||||
@@ -804,9 +803,17 @@ void mapgen_generate_from_heightmap()
|
||||
}
|
||||
}
|
||||
|
||||
// smooth the entire map
|
||||
for (uint32 y = 1; y <= height; y++)
|
||||
{
|
||||
for (uint32 x = 1; x <= width; x++)
|
||||
{
|
||||
tile_smooth(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(bitmap);
|
||||
SDL_FreeSurface(bitmap);
|
||||
}
|
||||
#pragma optimize("", on)
|
||||
|
||||
#pragma endregion
|
||||
#pragma endregion
|
||||
|
||||
Reference in New Issue
Block a user