src/tgp.cpp
changeset 11109 3a53e7dcff4c
parent 11091 6b5352725f43
child 11113 3cb24f59d83e
equal deleted inserted replaced
11107:6db1c5112e97 11109:3a53e7dcff4c
   172 	uint     dim_x;      //< height map size_x MapSizeX() + 1
   172 	uint     dim_x;      //< height map size_x MapSizeX() + 1
   173 	uint     total_size; //< height map total size
   173 	uint     total_size; //< height map total size
   174 	uint     size_x;     //< MapSizeX()
   174 	uint     size_x;     //< MapSizeX()
   175 	uint     size_y;     //< MapSizeY()
   175 	uint     size_y;     //< MapSizeY()
   176 
   176 
       
   177 	/**
       
   178 	 * Height map accessor
       
   179 	 * @param x X position
       
   180 	 * @param y Y position
       
   181 	 * @return height as fixed point number
       
   182 	 */
   177 	inline height_t &height(uint x, uint y) {
   183 	inline height_t &height(uint x, uint y) {
   178 		return h[x + y * dim_x];
   184 		return h[x + y * dim_x];
   179 	}
   185 	}
   180 };
   186 };
   181 
   187 
   232 {
   238 {
   233 	return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y;
   239 	return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y;
   234 }
   240 }
   235 
   241 
   236 
   242 
   237 /** Allocate array of (MapSizeX()+1)*(MapSizeY()+1) heights and init the _height_map structure members */
   243 /**
       
   244  * Allocate array of (MapSizeX()+1)*(MapSizeY()+1) heights and init the _height_map structure members
       
   245  * @return true on success
       
   246  */
   238 static inline bool AllocHeightMap()
   247 static inline bool AllocHeightMap()
   239 {
   248 {
   240 	height_t *h;
   249 	height_t *h;
   241 
   250 
   242 	_height_map.size_x = MapSizeX();
   251 	_height_map.size_x = MapSizeX();
   260 	if (_height_map.h == NULL) return;
   269 	if (_height_map.h == NULL) return;
   261 	free(_height_map.h);
   270 	free(_height_map.h);
   262 	_height_map.h = NULL;
   271 	_height_map.h = NULL;
   263 }
   272 }
   264 
   273 
   265 /** RandomHeight() generator */
   274 /**
       
   275  * Generates new random height in given amplitude (generated numbers will range from - amplitude to + amplitude)
       
   276  * @param rMax Limit of result
       
   277  * @return generated height
       
   278  */
   266 static inline height_t RandomHeight(amplitude_t rMax)
   279 static inline height_t RandomHeight(amplitude_t rMax)
   267 {
   280 {
   268 	amplitude_t ra = (Random() << 16) | (Random() & 0x0000FFFF);
   281 	amplitude_t ra = (Random() << 16) | (Random() & 0x0000FFFF);
   269 	height_t rh;
   282 	height_t rh;
   270 	/* Spread height into range -rMax..+rMax */
   283 	/* Spread height into range -rMax..+rMax */
   271 	rh = A2H(ra % (2 * rMax + 1) - rMax);
   284 	rh = A2H(ra % (2 * rMax + 1) - rMax);
   272 	return rh;
   285 	return rh;
   273 }
   286 }
   274 
   287 
   275 /** One interpolation and noise round */
   288 /**
       
   289  * One interpolation and noise round
       
   290  *
       
   291  * The heights on the map are generated in an iterative process.
       
   292  * We start off with a frequency of 1 (log_frequency == 0), and generate heights only for corners on the most coarsly mesh
       
   293  * (i.e. only for x/y coordinates which are multiples of the minimum edge length).
       
   294  *
       
   295  * After this initial step the frequency is doubled (log_frequency incremented) each iteration to generate corners on the next finer mesh.
       
   296  * The heights of the newly added corners are first set by interpolating the heights from the previous iteration.
       
   297  * Finally noise with the given amplitude is applied to all corners of the new mesh.
       
   298  *
       
   299  * Generation terminates, when the frequency has reached the map size. I.e. the mesh is as fine as the map, and every corner height
       
   300  * has been set.
       
   301  *
       
   302  * @param log_frequency frequency (logarithmic) to apply noise for
       
   303  * @param amplitude Amplitude for the noise
       
   304  * @return false if we are finished (reached the minimal step size / highest frequency)
       
   305  */
   276 static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
   306 static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
   277 {
   307 {
   278 	uint size_min = min(_height_map.size_x, _height_map.size_y);
   308 	uint size_min = min(_height_map.size_x, _height_map.size_y);
   279 	uint step = size_min >> log_frequency;
   309 	uint step = size_min >> log_frequency;
   280 	uint x, y;
   310 	uint x, y;
   281 
   311 
       
   312 	/* Trying to apply noise to uninitialized height map */
   282 	assert(_height_map.h != NULL);
   313 	assert(_height_map.h != NULL);
   283 
   314 
   284 	/* Are we finished? */
   315 	/* Are we finished? */
   285 	if (step == 0) return false;
   316 	if (step == 0) return false;
   286 
   317 
   314 			height_t h10 = (h00 + h20) / 2;
   345 			height_t h10 = (h00 + h20) / 2;
   315 			_height_map.height(x, y + 1 * step) = h10;
   346 			_height_map.height(x, y + 1 * step) = h10;
   316 		}
   347 		}
   317 	}
   348 	}
   318 
   349 
       
   350 	/* Add noise for next higher frequency (smaller steps) */
   319 	for (y = 0; y <= _height_map.size_y; y += step) {
   351 	for (y = 0; y <= _height_map.size_y; y += step) {
   320 		for (x = 0; x <= _height_map.size_x; x += step) {
   352 		for (x = 0; x <= _height_map.size_x; x += step) {
   321 			_height_map.height(x, y) += RandomHeight(amplitude);
   353 			_height_map.height(x, y) += RandomHeight(amplitude);
   322 		}
   354 		}
   323 	}
   355 	}
       
   356 
   324 	return (step > 1);
   357 	return (step > 1);
   325 }
   358 }
   326 
   359 
   327 /** Base Perlin noise generator - fills height map with raw Perlin noise */
   360 /** Base Perlin noise generator - fills height map with raw Perlin noise */
   328 static void HeightMapGenerate()
   361 static void HeightMapGenerate()
   336 
   369 
   337 	/* Find first power of two that fits */
   370 	/* Find first power of two that fits */
   338 	for (log_size_min = 6; (1U << log_size_min) < size_min; log_size_min++) { }
   371 	for (log_size_min = 6; (1U << log_size_min) < size_min; log_size_min++) { }
   339 	log_frequency_min = log_size_min - 6;
   372 	log_frequency_min = log_size_min - 6;
   340 
   373 
       
   374 	/* Keep increasing the frequency until we reach the step size equal to one tile */
   341 	do {
   375 	do {
   342 		log_frequency = iteration_round - log_frequency_min;
   376 		log_frequency = iteration_round - log_frequency_min;
   343 		if (log_frequency >= 0) {
   377 		if (log_frequency >= 0) {
       
   378 			/* Apply noise for the next frequency */
   344 			amplitude = _amplitudes_by_smoothness_and_frequency[_settings_game.game_creation.tgen_smoothness][log_frequency];
   379 			amplitude = _amplitudes_by_smoothness_and_frequency[_settings_game.game_creation.tgen_smoothness][log_frequency];
   345 		} else {
   380 		} else {
       
   381 			/* Amplitude for the low frequencies on big maps is 0, i.e. initialise with zero height */
   346 			amplitude = 0;
   382 			amplitude = 0;
   347 		}
   383 		}
   348 		continue_iteration = ApplyNoise(iteration_round, amplitude);
   384 		continue_iteration = ApplyNoise(iteration_round, amplitude);
   349 		iteration_round++;
   385 		iteration_round++;
   350 	} while(continue_iteration);
   386 	} while (continue_iteration);
   351 }
   387 }
   352 
   388 
   353 /** Returns min, max and average height from height map */
   389 /** Returns min, max and average height from height map */
   354 static void HeightMapGetMinMaxAvg(height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr)
   390 static void HeightMapGetMinMaxAvg(height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr)
   355 {
   391 {
   377 static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf)
   413 static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf)
   378 {
   414 {
   379 	int *hist = hist_buf - h_min;
   415 	int *hist = hist_buf - h_min;
   380 	height_t *h;
   416 	height_t *h;
   381 
   417 
   382 	/* Fill histogram */
   418 	/* Count the heights and fill the histogram */
   383 	FOR_ALL_TILES_IN_HEIGHT(h) {
   419 	FOR_ALL_TILES_IN_HEIGHT(h) {
   384 		assert(*h >= h_min);
   420 		assert(*h >= h_min);
   385 		assert(*h <= h_max);
   421 		assert(*h <= h_max);
   386 		hist[*h]++;
   422 		hist[*h]++;
   387 	}
   423 	}
   767 
   803 
   768 	return total;
   804 	return total;
   769 }
   805 }
   770 
   806 
   771 
   807 
   772 /** A small helper function */
   808 /** A small helper function to initialize the terrain */
   773 static void TgenSetTileHeight(TileIndex tile, int height)
   809 static void TgenSetTileHeight(TileIndex tile, int height)
   774 {
   810 {
   775 	SetTileHeight(tile, height);
   811 	SetTileHeight(tile, height);
   776 	MakeClear(tile, CLEAR_GRASS, 3);
   812 	MakeClear(tile, CLEAR_GRASS, 3);
   777 }
   813 }