mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2026-07-25 08:22:17 +00:00
Feature: Add worldgen setting for average height (#14989)
This commit is contained in:
+92
-56
@@ -215,7 +215,7 @@ static const int64_t _water_percent[4] = {70, 170, 270, 420};
|
||||
*/
|
||||
static Height TGPGetMaxHeight()
|
||||
{
|
||||
if (_settings_game.difficulty.terrain_type == TT_CUSTOM) {
|
||||
if (_settings_game.difficulty.terrain_type == GenworldMaxHeight::Custom) {
|
||||
/* TGP never reaches this height; this means that if a user inputs "2",
|
||||
* it would create a flat map without the "+ 1". But that would
|
||||
* overflow on "255". So we reduce it by 1 to get back in range. */
|
||||
@@ -242,7 +242,7 @@ static Height TGPGetMaxHeight()
|
||||
};
|
||||
|
||||
int map_size_bucket = std::min(Map::LogX(), Map::LogY()) - MIN_MAP_SIZE_BITS;
|
||||
int max_height_from_table = max_height[_settings_game.difficulty.terrain_type][map_size_bucket];
|
||||
int max_height_from_table = max_height[to_underlying(_settings_game.difficulty.terrain_type)][map_size_bucket];
|
||||
|
||||
/* If there is a manual map height limit, clamp to it. */
|
||||
if (_settings_game.construction.map_height_limit != 0) {
|
||||
@@ -455,6 +455,81 @@ static int *HeightMapMakeHistogram(Height h_min, [[maybe_unused]] Height h_max,
|
||||
return hist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the landscape to create lowlands on average (tropic landscape).
|
||||
* @param fheight The height to adjust.
|
||||
* @return The adjusted height.
|
||||
*/
|
||||
static double SineTransformLowlands(double fheight)
|
||||
{
|
||||
double height = fheight;
|
||||
|
||||
/* Half of tiles should be at lowest (0..25%) heights */
|
||||
double sine_lower_limit = 0.5;
|
||||
double linear_compression = 2;
|
||||
if (height <= sine_lower_limit) {
|
||||
/* Under the limit we do linear compression down */
|
||||
height = height / linear_compression;
|
||||
} else {
|
||||
double m = sine_lower_limit / linear_compression;
|
||||
/* Get sine_lower_limit..1 into -1..1 */
|
||||
height = 2.0 * ((height - sine_lower_limit) / (1.0 - sine_lower_limit)) - 1.0;
|
||||
/* Sine wave transform */
|
||||
height = sin(height * M_PI_2);
|
||||
/* Get -1..1 back to (sine_lower_limit / linear_compression)..1.0 */
|
||||
height = 0.5 * ((1.0 - m) * height + (1.0 + m));
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the landscape to create normal average height (temperate and toyland landscapes).
|
||||
* @param fheight The height to adjust.
|
||||
* @return The adjusted height.
|
||||
*/
|
||||
static double SineTransformNormal(double &fheight)
|
||||
{
|
||||
double height = fheight;
|
||||
|
||||
/* Move and scale 0..1 into -1..+1 */
|
||||
height = 2 * height - 1;
|
||||
/* Sine transform */
|
||||
height = sin(height * M_PI_2);
|
||||
/* Transform it back from -1..1 into 0..1 space */
|
||||
height = 0.5 * (height + 1);
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the landscape to create plateaus on average (arctic landscape).
|
||||
* @param fheight The height to adjust.
|
||||
* @return The adjusted height.
|
||||
*/
|
||||
static double SineTransformPlateaus(double &fheight)
|
||||
{
|
||||
double height = fheight;
|
||||
|
||||
/* Redistribute heights to have more tiles at highest (75%..100%) range */
|
||||
double sine_upper_limit = 0.75;
|
||||
double linear_compression = 2;
|
||||
if (height >= sine_upper_limit) {
|
||||
/* Over the limit we do linear compression up */
|
||||
height = 1.0 - (1.0 - height) / linear_compression;
|
||||
} else {
|
||||
double m = 1.0 - (1.0 - sine_upper_limit) / linear_compression;
|
||||
/* Get 0..sine_upper_limit into -1..1 */
|
||||
height = 2.0 * height / sine_upper_limit - 1.0;
|
||||
/* Sine wave transform */
|
||||
height = sin(height * M_PI_2);
|
||||
/* Get -1..1 back to 0..(1 - (1 - sine_upper_limit) / linear_compression) == 0.0..m */
|
||||
height = 0.5 * (height + 1.0) * m;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
/** Applies sine wave redistribution onto height map */
|
||||
static void HeightMapSineTransform(Height h_min, Height h_max)
|
||||
{
|
||||
@@ -465,66 +540,27 @@ static void HeightMapSineTransform(Height h_min, Height h_max)
|
||||
|
||||
/* Transform height into 0..1 space */
|
||||
fheight = (double)(h - h_min) / (double)(h_max - h_min);
|
||||
/* Apply sine transform depending on landscape type */
|
||||
switch (_settings_game.game_creation.landscape) {
|
||||
case LandscapeType::Toyland:
|
||||
case LandscapeType::Temperate:
|
||||
/* Move and scale 0..1 into -1..+1 */
|
||||
fheight = 2 * fheight - 1;
|
||||
/* Sine transform */
|
||||
fheight = sin(fheight * M_PI_2);
|
||||
/* Transform it back from -1..1 into 0..1 space */
|
||||
fheight = 0.5 * (fheight + 1);
|
||||
break;
|
||||
|
||||
case LandscapeType::Arctic:
|
||||
{
|
||||
/* Arctic terrain needs special height distribution.
|
||||
* Redistribute heights to have more tiles at highest (75%..100%) range */
|
||||
double sine_upper_limit = 0.75;
|
||||
double linear_compression = 2;
|
||||
if (fheight >= sine_upper_limit) {
|
||||
/* Over the limit we do linear compression up */
|
||||
fheight = 1.0 - (1.0 - fheight) / linear_compression;
|
||||
} else {
|
||||
double m = 1.0 - (1.0 - sine_upper_limit) / linear_compression;
|
||||
/* Get 0..sine_upper_limit into -1..1 */
|
||||
fheight = 2.0 * fheight / sine_upper_limit - 1.0;
|
||||
/* Sine wave transform */
|
||||
fheight = sin(fheight * M_PI_2);
|
||||
/* Get -1..1 back to 0..(1 - (1 - sine_upper_limit) / linear_compression) == 0.0..m */
|
||||
fheight = 0.5 * (fheight + 1.0) * m;
|
||||
}
|
||||
switch (_settings_game.game_creation.average_height) {
|
||||
case GenworldAverageHeight::Auto:
|
||||
/* Apply sine transform depending on landscape type */
|
||||
switch (_settings_game.game_creation.landscape) {
|
||||
case LandscapeType::Temperate: fheight = SineTransformNormal(fheight); break;
|
||||
case LandscapeType::Tropic: fheight = SineTransformLowlands(fheight); break;
|
||||
case LandscapeType::Arctic: fheight = SineTransformPlateaus(fheight); break;
|
||||
case LandscapeType::Toyland: fheight = SineTransformNormal(fheight); break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
break;
|
||||
|
||||
case LandscapeType::Tropic:
|
||||
{
|
||||
/* Desert terrain needs special height distribution.
|
||||
* Half of tiles should be at lowest (0..25%) heights */
|
||||
double sine_lower_limit = 0.5;
|
||||
double linear_compression = 2;
|
||||
if (fheight <= sine_lower_limit) {
|
||||
/* Under the limit we do linear compression down */
|
||||
fheight = fheight / linear_compression;
|
||||
} else {
|
||||
double m = sine_lower_limit / linear_compression;
|
||||
/* Get sine_lower_limit..1 into -1..1 */
|
||||
fheight = 2.0 * ((fheight - sine_lower_limit) / (1.0 - sine_lower_limit)) - 1.0;
|
||||
/* Sine wave transform */
|
||||
fheight = sin(fheight * M_PI_2);
|
||||
/* Get -1..1 back to (sine_lower_limit / linear_compression)..1.0 */
|
||||
fheight = 0.5 * ((1.0 - m) * fheight + (1.0 + m));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
break;
|
||||
case GenworldAverageHeight::Lowlands: fheight = SineTransformLowlands(fheight); break;
|
||||
case GenworldAverageHeight::Normal: fheight = SineTransformNormal(fheight); break;
|
||||
case GenworldAverageHeight::Plateaus: fheight = SineTransformPlateaus(fheight); break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
||||
/* Transform it back into h_min..h_max space */
|
||||
h = (Height)(fheight * (h_max - h_min) + h_min);
|
||||
h = static_cast<Height>(fheight * (h_max - h_min) + h_min);
|
||||
if (h < 0) h = I2H(0);
|
||||
if (h >= h_max) h = h_max - 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user