163 /** Fixed point array for amplitudes (and percent values) */ |
163 /** Fixed point array for amplitudes (and percent values) */ |
164 typedef int amplitude_t; |
164 typedef int amplitude_t; |
165 static const int amplitude_decimal_bits = 10; |
165 static const int amplitude_decimal_bits = 10; |
166 |
166 |
167 /** Height map - allocated array of heights (MapSizeX() + 1) x (MapSizeY() + 1) */ |
167 /** Height map - allocated array of heights (MapSizeX() + 1) x (MapSizeY() + 1) */ |
168 typedef struct HeightMap |
168 struct HeightMap |
169 { |
169 { |
170 height_t *h; //! array of heights |
170 height_t *h; //! array of heights |
171 uint dim_x; //! height map size_x MapSizeX() + 1 |
171 uint dim_x; //! height map size_x MapSizeX() + 1 |
172 uint total_size; //! height map total size |
172 uint total_size; //! height map total size |
173 uint size_x; //! MapSizeX() |
173 uint size_x; //! MapSizeX() |
174 uint size_y; //! MapSizeY() |
174 uint size_y; //! MapSizeY() |
175 } HeightMap; |
175 }; |
176 |
176 |
177 /** Global height map instance */ |
177 /** Global height map instance */ |
178 static HeightMap _height_map = {NULL, 0, 0, 0, 0}; |
178 static HeightMap _height_map = {NULL, 0, 0, 0, 0}; |
179 |
179 |
180 /** Height map accessors */ |
180 /** Height map accessors */ |
227 return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y; |
227 return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y; |
228 } |
228 } |
229 |
229 |
230 |
230 |
231 /** Allocate array of (MapSizeX()+1)*(MapSizeY()+1) heights and init the _height_map structure members */ |
231 /** Allocate array of (MapSizeX()+1)*(MapSizeY()+1) heights and init the _height_map structure members */ |
232 static inline bool AllocHeightMap(void) |
232 static inline bool AllocHeightMap() |
233 { |
233 { |
234 height_t *h; |
234 height_t *h; |
235 |
235 |
236 _height_map.size_x = MapSizeX(); |
236 _height_map.size_x = MapSizeX(); |
237 _height_map.size_y = MapSizeY(); |
237 _height_map.size_y = MapSizeY(); |
319 } |
319 } |
320 return (step > 1); |
320 return (step > 1); |
321 } |
321 } |
322 |
322 |
323 /** Base Perlin noise generator - fills height map with raw Perlin noise */ |
323 /** Base Perlin noise generator - fills height map with raw Perlin noise */ |
324 static void HeightMapGenerate(void) |
324 static void HeightMapGenerate() |
325 { |
325 { |
326 uint size_min = min(_height_map.size_x, _height_map.size_y); |
326 uint size_min = min(_height_map.size_x, _height_map.size_y); |
327 uint iteration_round = 0; |
327 uint iteration_round = 0; |
328 amplitude_t amplitude; |
328 amplitude_t amplitude; |
329 bool continue_iteration; |
329 bool continue_iteration; |
522 * a larger map. |
522 * a larger map. |
523 * |
523 * |
524 * Please note that all the small numbers; 53, 101, 167, etc. are small primes |
524 * Please note that all the small numbers; 53, 101, 167, etc. are small primes |
525 * to help give the perlin noise a bit more of a random feel. |
525 * to help give the perlin noise a bit more of a random feel. |
526 */ |
526 */ |
527 static void HeightMapCoastLines(void) |
527 static void HeightMapCoastLines() |
528 { |
528 { |
529 int smallest_size = min(_patches.map_x, _patches.map_y); |
529 int smallest_size = min(_patches.map_x, _patches.map_y); |
530 const int margin = 4; |
530 const int margin = 4; |
531 uint y, x; |
531 uint y, x; |
532 double max_x; |
532 double max_x; |
608 h_prev = h; |
608 h_prev = h; |
609 } |
609 } |
610 } |
610 } |
611 |
611 |
612 /** Smooth coasts by modulating height of tiles close to map edges with cosine of distance from edge */ |
612 /** Smooth coasts by modulating height of tiles close to map edges with cosine of distance from edge */ |
613 static void HeightMapSmoothCoasts(void) |
613 static void HeightMapSmoothCoasts() |
614 { |
614 { |
615 uint x, y; |
615 uint x, y; |
616 /* First Smooth NW and SE coasts (y close to 0 and y close to size_y) */ |
616 /* First Smooth NW and SE coasts (y close to 0 and y close to size_y) */ |
617 for (x = 0; x < _height_map.size_x; x++) { |
617 for (x = 0; x < _height_map.size_x; x++) { |
618 HeightMapSmoothCoastInDirection(x, 0, 0, 1); |
618 HeightMapSmoothCoastInDirection(x, 0, 0, 1); |
652 /** Height map terraform post processing: |
652 /** Height map terraform post processing: |
653 * - water level adjusting |
653 * - water level adjusting |
654 * - coast Smoothing |
654 * - coast Smoothing |
655 * - slope Smoothing |
655 * - slope Smoothing |
656 * - height histogram redistribution by sine wave transform */ |
656 * - height histogram redistribution by sine wave transform */ |
657 static void HeightMapNormalize(void) |
657 static void HeightMapNormalize() |
658 { |
658 { |
659 const amplitude_t water_percent = _water_percent[_opt.diff.quantity_sea_lakes]; |
659 const amplitude_t water_percent = _water_percent[_opt.diff.quantity_sea_lakes]; |
660 const height_t h_max_new = I2H(_max_height[_opt.diff.terrain_type]); |
660 const height_t h_max_new = I2H(_max_height[_opt.diff.terrain_type]); |
661 const height_t roughness = 7 + 3 * _patches.tgen_smoothness; |
661 const height_t roughness = 7 + 3 * _patches.tgen_smoothness; |
662 |
662 |
791 * different to all others to give a desert valley between two high mountains. |
791 * different to all others to give a desert valley between two high mountains. |
792 * Clearly if a low height terrain (flat/very flat) is chosen, then the tropic |
792 * Clearly if a low height terrain (flat/very flat) is chosen, then the tropic |
793 * areas wont be high enough, and there will be very little tropic on the map. |
793 * areas wont be high enough, and there will be very little tropic on the map. |
794 * Thus Tropic works best on Hilly or Mountainous. |
794 * Thus Tropic works best on Hilly or Mountainous. |
795 */ |
795 */ |
796 void GenerateTerrainPerlin(void) |
796 void GenerateTerrainPerlin() |
797 { |
797 { |
798 uint x, y; |
798 uint x, y; |
799 |
799 |
800 if (!AllocHeightMap()) return; |
800 if (!AllocHeightMap()) return; |
801 GenerateWorldSetAbortCallback(FreeHeightMap); |
801 GenerateWorldSetAbortCallback(FreeHeightMap); |