summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tgp.cpp48
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);