153static const int HEIGHT_DECIMAL_BITS = 4;
157static const int AMPLITUDE_DECIMAL_BITS = 10;
162 std::vector<Height>
h;
191 return i << HEIGHT_DECIMAL_BITS;
201 return i >> HEIGHT_DECIMAL_BITS;
211 return i >> (AMPLITUDE_DECIMAL_BITS - HEIGHT_DECIMAL_BITS);
217static constexpr int WATER_PERCENT_FACTOR = 1024;
230 if (
_settings_game.difficulty.terrain_type == GenworldMaxHeight::Custom) {
249 { 3, 3, 3, 3, 4, 5, 7 },
250 { 5, 7, 8, 9, 14, 19, 31 },
251 { 8, 9, 10, 15, 23, 37, 61 },
252 { 10, 11, 17, 19, 49, 63, 73 },
253 { 12, 19, 25, 31, 67, 75, 87 },
261 max_height_from_table = std::min<uint>(max_height_from_table,
_settings_game.construction.map_height_limit);
264 return I2H(max_height_from_table);
285 static const Amplitude amplitudes[][7] = {
287 {16000, 5600, 1968, 688, 240, 16, 16},
288 {24000, 12800, 6400, 2700, 1024, 128, 16},
289 {32000, 19200, 12800, 8000, 3200, 256, 64},
290 {48000, 24000, 19200, 16000, 8000, 512, 320},
302 static const double extrapolation_factors[] = { 3.3, 2.8, 2.3, 1.8 };
307 int index = frequency -
MAX_TGP_FREQUENCIES +
static_cast<int>(std::size(amplitudes[smoothness]));
308 Amplitude amplitude = amplitudes[smoothness][std::max(0, index)];
309 if (index >= 0)
return amplitude;
312 double extrapolation_factor = extrapolation_factors[smoothness];
313 int height_range =
I2H(16);
315 amplitude = (
Amplitude)(extrapolation_factor * (
double)amplitude);
388 if (amplitude == 0)
continue;
394 for (
int y = 0; y <=
_height_map.size_y; y += step) {
395 for (
int x = 0; x <=
_height_map.size_x; x += step) {
406 for (
int y = 0; y <=
_height_map.size_y; y += 2 * step) {
407 for (
int x = 0; x <=
_height_map.size_x - 2 * step; x += 2 * step) {
410 Height h01 = (h00 + h02) / 2;
416 for (
int y = 0; y <=
_height_map.size_y - 2 * step; y += 2 * step) {
417 for (
int x = 0; x <=
_height_map.size_x; x += step) {
420 Height h10 = (h00 + h20) / 2;
426 for (
int y = 0; y <=
_height_map.size_y; y += step) {
427 for (
int x = 0; x <=
_height_map.size_x; x += step) {
443 int *hist = hist_buf - h_min;
461 double height = fheight;
464 double sine_lower_limit = 0.5;
465 double linear_compression = 2;
466 if (height <= sine_lower_limit) {
468 height = height / linear_compression;
470 double m = sine_lower_limit / linear_compression;
472 height = 2.0 * ((height - sine_lower_limit) / (1.0 - sine_lower_limit)) - 1.0;
474 height = sin(height * M_PI_2);
476 height = 0.5 * ((1.0 - m) * height + (1.0 + m));
489 double height = fheight;
492 height = 2 * height - 1;
494 height = sin(height * M_PI_2);
496 height = 0.5 * (height + 1);
508 double height = fheight;
511 double sine_upper_limit = 0.75;
512 double linear_compression = 2;
513 if (height >= sine_upper_limit) {
515 height = 1.0 - (1.0 - height) / linear_compression;
517 double m = 1.0 - (1.0 - sine_upper_limit) / linear_compression;
519 height = 2.0 * height / sine_upper_limit - 1.0;
521 height = sin(height * M_PI_2);
523 height = 0.5 * (height + 1.0) * m;
539 if (h < h_min)
continue;
542 fheight = (double)(h - h_min) / (double)(h_max - h_min);
545 case GenworldAverageHeight::Auto:
552 default: NOT_REACHED();
559 default: NOT_REACHED();
563 h =
static_cast<Height>(fheight * (h_max - h_min) + h_min);
564 if (h < 0) h =
I2H(0);
565 if (h >= h_max) h = h_max - 1;
590 struct ControlPoint {
595#define F(fraction) ((Height)(fraction * mh))
596 const ControlPoint curve_map_1[] = { { F(0.0), F(0.0) }, { F(0.8), F(0.13) }, { F(1.0), F(0.4) } };
597 const ControlPoint curve_map_2[] = { { F(0.0), F(0.0) }, { F(0.53), F(0.13) }, { F(0.8), F(0.27) }, { F(1.0), F(0.6) } };
598 const ControlPoint curve_map_3[] = { { F(0.0), F(0.0) }, { F(0.53), F(0.27) }, { F(0.8), F(0.57) }, { F(1.0), F(0.8) } };
599 const ControlPoint curve_map_4[] = { { F(0.0), F(0.0) }, { F(0.4), F(0.3) }, { F(0.7), F(0.8) }, { F(0.92), F(0.99) }, { F(1.0), F(0.99) } };
602 const std::span<const ControlPoint> curve_maps[] = { curve_map_1, curve_map_2, curve_map_3, curve_map_4 };
604 std::array<
Height, std::size(curve_maps)> ht{};
608 uint sx =
Clamp((
int)(((1 << level) * factor) + 0.5), 1, 128);
609 uint sy =
Clamp((
int)(((1 << level) / factor) + 0.5), 1, 128);
610 std::vector<uint8_t> c(
static_cast<size_t>(sx) * sy);
612 for (uint i = 0; i < sx * sy; i++) {
613 c[i] =
RandomRange(
static_cast<uint32_t
>(std::size(curve_maps)));
620 float fx = (float)(sx * x) /
_height_map.size_x + 1.0f;
623 float xr = 2.0f * (fx - x1) - 1.0f;
624 xr = sin(xr * M_PI_2);
625 xr = sin(xr * M_PI_2);
626 xr = 0.5f * (xr + 1.0f);
627 float xri = 1.0f - xr;
637 float fy = (float)(sy * y) /
_height_map.size_y + 1.0f;
640 float yr = 2.0f * (fy - y1) - 1.0f;
641 yr = sin(yr * M_PI_2);
642 yr = sin(yr * M_PI_2);
643 yr = 0.5f * (yr + 1.0f);
644 float yri = 1.0f - yr;
651 uint corner_a = c[x1 + sx * y1];
652 uint corner_b = c[x1 + sx * y2];
653 uint corner_c = c[x2 + sx * y1];
654 uint corner_d = c[x2 + sx * y2];
658 uint corner_bits = 0;
659 corner_bits |= 1 << corner_a;
660 corner_bits |= 1 << corner_b;
661 corner_bits |= 1 << corner_c;
662 corner_bits |= 1 << corner_d;
667 if (*h <
I2H(1))
continue;
673 for (
size_t t = 0; t < std::size(curve_maps); t++) {
674 if (!
HasBit(corner_bits,
static_cast<uint8_t
>(t)))
continue;
676 [[maybe_unused]]
bool found =
false;
677 auto &cm = curve_maps[t];
678 for (
size_t i = 0; i < cm.size() - 1; i++) {
679 const ControlPoint &p1 = cm[i];
680 const ControlPoint &p2 = cm[i + 1];
682 if (*h >= p1.x && *h < p2.x) {
683 ht[t] = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
694 *h = (
Height)((ht[corner_a] * yri + ht[corner_b] * yr) * xri + (ht[corner_c] * yri + ht[corner_d] * yr) * xr);
710 int64_t water_tiles, desired_water_tiles;
713 auto [h_min, h_max] = std::ranges::minmax(
_height_map.h);
716 std::vector<int> hist_buf(h_max - h_min + 1);
724 for (h_water_level = h_min, water_tiles = 0; h_water_level < h_max; h_water_level++) {
725 water_tiles += hist[h_water_level];
726 if (water_tiles >= desired_water_tiles)
break;
737 h = (
Height)(((
int)h_max_new) * (h - h_water_level) / (h_max - h_water_level)) +
I2H(1);
739 if (h < 0) h =
I2H(0);
740 if (h >= h_max_new) h = h_max_new - 1;
744static double PerlinCoastNoise2D(
const double x,
const double y,
const double p,
const int prime);
771 const int jagged_distance = std::min(12 + (smallest_size * smallest_size / 4096) + std::min(map_ratio, 16), 64);
774 const int smooth_distance = std::min(smallest_size / 32, 32);
779 auto get_depth = [&](
int x,
int p1,
int p2,
int p3) {
792 for (x = 0; x < get_depth(y, 67, 179, 53); x++) {
809 for (y = 0; y < get_depth(x, 179, 211, 167); y++) {
832 const int max_coast_dist_from_edge = 100;
833 const int max_coast_smooth_depth = 35;
845 for (x = org_x, y = org_y, ed = 0;
IsValidXY(x, y) && ed < max_coast_dist_from_edge; x += dir_x, y += dir_y, ed++) {
858 for (depth = 0;
IsValidXY(x, y) && depth <= max_coast_smooth_depth; depth++, x += dir_x, y += dir_y) {
860 h =
static_cast<Height>(std::min<uint>(h, h_prev + (4 + depth)));
895 for (
int y = 0; y <= (int)
_height_map.size_y; y++) {
896 for (
int x = 0; x <= (int)
_height_map.size_x; x++) {
925 if (water_borders ==
BorderFlag::Random) water_borders =
static_cast<BorderFlags
>(
GB(Random(), 0, 4));
951static double IntNoise(
const long x,
const long y,
const int prime)
953 long n = x + y * prime +
_settings_game.game_creation.generation_seed;
958 return 1.0 - (double)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0;
971 return a + x * (b - a);
985 const int integer_x = (int)x;
986 const int integer_y = (int)y;
988 const double fractional_x = x - (double)integer_x;
989 const double fractional_y = y - (double)integer_y;
991 const double v1 =
IntNoise(integer_x, integer_y, prime);
992 const double v2 =
IntNoise(integer_x + 1, integer_y, prime);
993 const double v3 =
IntNoise(integer_x, integer_y + 1, prime);
994 const double v4 =
IntNoise(integer_x + 1, integer_y + 1, prime);
1015 constexpr int OCTAVES = 6;
1016 constexpr double INITIAL_FREQUENCY = 1 << OCTAVES;
1019 double max_value = 0.0;
1020 double frequency = 1.0 / INITIAL_FREQUENCY;
1021 double amplitude = 1.0;
1022 for (
int i = 0; i < OCTAVES; i++) {
1024 max_value += amplitude;
1031 return total / max_value;
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Map accessors for 'clear' tiles.
@ Grass
Plain grass with dirt transition (0-3).
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
void GenerateWorldSetAbortCallback(GWAbortProc *proc)
Set here the function, if any, that you want to be called when landscape generation is aborted.
Functions related to world/map generation.
void IncreaseGeneratingWorldProgress(GenWorldProgress cls)
Increases the current stage of the world generation with one.
static const uint CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY
Value for custom sea level in difficulty settings.
@ GWP_LANDSCAPE
Create the landscape.
Types related to the landscape.
static constexpr BorderFlags BORDERFLAGS_ALL
Border on all sides.
@ Arctic
Landscape with snow levels.
@ Toyland
Landscape with funky industries and vehicles.
@ Tropic
Landscape with distinct rainforests and deserts,.
@ Temperate
Base landscape.
@ NorthWest
Border on North West.
@ Random
Randomise borders.
@ NorthEast
Border on North East.
@ SouthEast
Border on South East.
@ SouthWest
Border on South West.
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
static const uint MIN_MAP_SIZE_BITS
Minimal and maximal map width and height.
static const uint MAX_MAP_SIZE_BITS
Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Pseudo random number generator.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition of base types and functions in a cross-platform compatible way.
Height map - allocated array of heights (Map::SizeX() + 1) * (Map::SizeY() + 1).
std::vector< Height > h
array of heights
int dim_x
height map size_x Map::SizeX() + 1
Height & height(uint x, uint y)
Height map accessor.
static uint SizeX()
Get the size of the map along the X.
static uint SizeY()
Get the size of the map along the Y.
static uint LogX()
Logarithm of the map size along the X side.
static uint LogY()
Logarithm of the map size along the y side.
static double SineTransformNormal(double &fheight)
Adjust the landscape to create normal average height (temperate and toyland landscapes).
static Height RandomHeight(Amplitude r_max)
Generates new random height in given amplitude (generated numbers will range from - amplitude to + am...
static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int dir_y)
Start at given point, move in given direction, find and Smooth coast in that direction.
static Height A2H(Amplitude i)
Convert Amplitude to fixed point Height.
static void HeightMapGenerate()
Base Perlin noise generator - fills height map with raw Perlin noise.
static Height TGPGetMaxHeight()
Gets the maximum allowed height while generating a map based on mapsize, terraintype,...
static double LinearInterpolate(const double a, const double b, const double x)
This routine determines the interpolated value between a and b.
static void HeightMapCoastLines(BorderFlags water_borders)
This routine sculpts in from the edge a random amount, again from Perlin sequences,...
static Height I2H(int i)
Convert tile height to fixed point Height.
static int H2I(Height i)
Convert fixed point Height to tile height.
static double SineTransformPlateaus(double &fheight)
Adjust the landscape to create plateaus on average (arctic landscape).
static void HeightMapSmoothSlopes(Height dh_max)
This routine provides the essential cleanup necessary before OTTD can display the terrain.
static double PerlinCoastNoise2D(const double x, const double y, const double p, const int prime)
This is a similar function to the main perlin noise calculation, but uses the value p passed as a par...
static const int64_t _water_percent[4]
Desired water percentage (100% == 1024) - indexed by _settings_game.difficulty.quantity_sea_lakes.
int16_t Height
Fixed point type for heights.
static Amplitude GetAmplitude(int frequency)
Get the amplitude associated with the currently selected smoothness and maximum height level.
static int * HeightMapMakeHistogram(Height h_min, Height h_max, int *hist_buf)
Create histogram and return pointer to its base point - to the count of zero heights.
static void FreeHeightMap()
Free height map.
int Amplitude
Fixed point array for amplitudes.
uint GetEstimationTGPMapHeight()
Get an overestimation of the highest peak TGP wants to generate.
static void HeightMapAdjustWaterLevel(int64_t water_percent, Height h_max_new)
Adjusts heights in height map to contain required amount of water tiles.
static double IntNoise(const long x, const long y, const int prime)
The Perlin Noise calculation using large primes The initial number is adjusted by two values; the gen...
static double InterpolatedNoise(const double x, const double y, const int prime)
This routine returns the smoothed interpolated noise for an x and y, using the values from the surrou...
static void HeightMapSineTransform(Height h_min, Height h_max)
Applies sine wave redistribution onto height map.
static HeightMap _height_map
Global height map instance.
static void HeightMapNormalize()
Height map terraform post processing:
static void HeightMapSmoothCoasts(BorderFlags water_borders)
Smooth coasts by modulating height of tiles close to map edges with cosine of distance from edge.
static bool IsValidXY(int x, int y)
Check if a X/Y set are within the map.
static const int MAX_TGP_FREQUENCIES
Maximum number of TGP noise frequencies.
static void TgenSetTileHeight(TileIndex tile, int height)
A small helper function to initialize the terrain.
void GenerateTerrainPerlin()
The main new land generator using Perlin noise.
static double SineTransformLowlands(double fheight)
Adjust the landscape to create lowlands on average (tropic landscape).
static void HeightMapCurves(uint level)
Additional map variety is provided by applying different curve maps to different parts of the map.
static void AllocHeightMap()
Allocate array of (Map::SizeX() + 1) * (Map::SizeY() + 1) heights and init the _height_map structure ...
bool IsInnerTile(Tile tile)
Check if a tile is within the map (not a border).
void SetTileHeight(Tile tile, uint height)
Sets the height of a tile.
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Map accessors for void tiles.
void MakeVoid(Tile t)
Make a nice void tile ;).