diff options
-rw-r--r-- | src/tgp.cpp | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/src/tgp.cpp b/src/tgp.cpp index 1816130e9..e26242875 100644 --- a/src/tgp.cpp +++ b/src/tgp.cpp @@ -174,6 +174,12 @@ struct HeightMap uint size_x; //< MapSizeX() uint size_y; //< MapSizeY() + /** + * Height map accessor + * @param x X position + * @param y Y position + * @return height as fixed point number + */ inline height_t &height(uint x, uint y) { return h[x + y * dim_x]; } @@ -234,7 +240,10 @@ static inline bool IsValidXY(uint x, uint y) } -/** Allocate array of (MapSizeX()+1)*(MapSizeY()+1) heights and init the _height_map structure members */ +/** + * Allocate array of (MapSizeX()+1)*(MapSizeY()+1) heights and init the _height_map structure members + * @return true on success + */ static inline bool AllocHeightMap() { height_t *h; @@ -262,7 +271,11 @@ static inline void FreeHeightMap() _height_map.h = NULL; } -/** RandomHeight() generator */ +/** + * Generates new random height in given amplitude (generated numbers will range from - amplitude to + amplitude) + * @param rMax Limit of result + * @return generated height + */ static inline height_t RandomHeight(amplitude_t rMax) { amplitude_t ra = (Random() << 16) | (Random() & 0x0000FFFF); @@ -272,13 +285,31 @@ static inline height_t RandomHeight(amplitude_t rMax) return rh; } -/** One interpolation and noise round */ +/** + * One interpolation and noise round + * + * The heights on the map are generated in an iterative process. + * We start off with a frequency of 1 (log_frequency == 0), and generate heights only for corners on the most coarsly mesh + * (i.e. only for x/y coordinates which are multiples of the minimum edge length). + * + * After this initial step the frequency is doubled (log_frequency incremented) each iteration to generate corners on the next finer mesh. + * The heights of the newly added corners are first set by interpolating the heights from the previous iteration. + * Finally noise with the given amplitude is applied to all corners of the new mesh. + * + * Generation terminates, when the frequency has reached the map size. I.e. the mesh is as fine as the map, and every corner height + * has been set. + * + * @param log_frequency frequency (logarithmic) to apply noise for + * @param amplitude Amplitude for the noise + * @return false if we are finished (reached the minimal step size / highest frequency) + */ static bool ApplyNoise(uint log_frequency, amplitude_t amplitude) { uint size_min = min(_height_map.size_x, _height_map.size_y); uint step = size_min >> log_frequency; uint x, y; + /* Trying to apply noise to uninitialized height map */ assert(_height_map.h != NULL); /* Are we finished? */ @@ -316,11 +347,13 @@ static bool ApplyNoise(uint log_frequency, amplitude_t amplitude) } } + /* Add noise for next higher frequency (smaller steps) */ for (y = 0; y <= _height_map.size_y; y += step) { for (x = 0; x <= _height_map.size_x; x += step) { _height_map.height(x, y) += RandomHeight(amplitude); } } + return (step > 1); } @@ -338,16 +371,19 @@ static void HeightMapGenerate() for (log_size_min = 6; (1U << log_size_min) < size_min; log_size_min++) { } log_frequency_min = log_size_min - 6; + /* Keep increasing the frequency until we reach the step size equal to one tile */ do { log_frequency = iteration_round - log_frequency_min; if (log_frequency >= 0) { + /* Apply noise for the next frequency */ amplitude = _amplitudes_by_smoothness_and_frequency[_settings_game.game_creation.tgen_smoothness][log_frequency]; } else { + /* Amplitude for the low frequencies on big maps is 0, i.e. initialise with zero height */ amplitude = 0; } continue_iteration = ApplyNoise(iteration_round, amplitude); iteration_round++; - } while(continue_iteration); + } while (continue_iteration); } /** Returns min, max and average height from height map */ @@ -379,7 +415,7 @@ static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf int *hist = hist_buf - h_min; height_t *h; - /* Fill histogram */ + /* Count the heights and fill the histogram */ FOR_ALL_TILES_IN_HEIGHT(h) { assert(*h >= h_min); assert(*h <= h_max); @@ -769,7 +805,7 @@ static double perlin_coast_noise_2D(const double x, const double y, const double } -/** A small helper function */ +/** A small helper function to initialize the terrain */ static void TgenSetTileHeight(TileIndex tile, int height) { SetTileHeight(tile, height); |