00001
00002
00005 #include "stdafx.h"
00006 #include <math.h>
00007 #include "clear_map.h"
00008 #include "void_map.h"
00009 #include "genworld.h"
00010 #include "core/alloc_func.hpp"
00011 #include "core/random_func.hpp"
00012 #include "landscape_type.h"
00013 #include "settings_type.h"
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 #ifndef M_PI_2
00149 #define M_PI_2 1.57079632679489661923
00150 #define M_PI 3.14159265358979323846
00151 #endif
00152
00154 typedef int16 height_t;
00155 static const int height_decimal_bits = 4;
00156 static const height_t _invalid_height = -32768;
00157
00159 typedef int amplitude_t;
00160 static const int amplitude_decimal_bits = 10;
00161
00163 struct HeightMap
00164 {
00165 height_t *h;
00166 uint dim_x;
00167 uint total_size;
00168 uint size_x;
00169 uint size_y;
00170
00177 inline height_t &height(uint x, uint y) {
00178 return h[x + y * dim_x];
00179 }
00180 };
00181
00183 static HeightMap _height_map = {NULL, 0, 0, 0, 0};
00184
00186 #define I2H(i) ((i) << height_decimal_bits)
00187
00188 #define H2I(i) ((i) >> height_decimal_bits)
00189
00191 #define I2A(i) ((i) << amplitude_decimal_bits)
00192
00193 #define A2I(i) ((i) >> amplitude_decimal_bits)
00194
00196 #define A2H(a) ((a) >> (amplitude_decimal_bits - height_decimal_bits))
00197
00198
00200 #define FOR_ALL_TILES_IN_HEIGHT(h) for (h = _height_map.h; h < &_height_map.h[_height_map.total_size]; h++)
00201
00203 static const int TGP_FREQUENCY_MAX = 6;
00204
00207 static const amplitude_t _amplitudes_by_smoothness_and_frequency[4][TGP_FREQUENCY_MAX + 1] = {
00208
00209
00210 {16000, 5600, 1968, 688, 240, 16, 16},
00211
00212 {16000, 16000, 6448, 3200, 1024, 128, 16},
00213
00214 {16000, 19200, 12800, 8000, 3200, 256, 64},
00215
00216 {24000, 16000, 19200, 16000, 8000, 512, 320},
00217 };
00218
00220 static const amplitude_t _water_percent[4] = {20, 80, 250, 400};
00221
00223 static const int8 _max_height[4] = {
00224 6,
00225 9,
00226 12,
00227 15
00228 };
00229
00235 static inline bool IsValidXY(uint x, uint y)
00236 {
00237 return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y;
00238 }
00239
00240
00245 static inline bool AllocHeightMap()
00246 {
00247 height_t *h;
00248
00249 _height_map.size_x = MapSizeX();
00250 _height_map.size_y = MapSizeY();
00251
00252
00253 _height_map.total_size = (_height_map.size_x + 1) * (_height_map.size_y + 1);
00254 _height_map.dim_x = _height_map.size_x + 1;
00255 _height_map.h = CallocT<height_t>(_height_map.total_size);
00256 if (_height_map.h == NULL) return false;
00257
00258
00259 FOR_ALL_TILES_IN_HEIGHT(h) *h = _invalid_height;
00260
00261 return true;
00262 }
00263
00265 static inline void FreeHeightMap()
00266 {
00267 if (_height_map.h == NULL) return;
00268 free(_height_map.h);
00269 _height_map.h = NULL;
00270 }
00271
00277 static inline height_t RandomHeight(amplitude_t rMax)
00278 {
00279 amplitude_t ra = (Random() << 16) | (Random() & 0x0000FFFF);
00280 height_t rh;
00281
00282 rh = A2H(ra % (2 * rMax + 1) - rMax);
00283 return rh;
00284 }
00285
00304 static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
00305 {
00306 uint size_min = min(_height_map.size_x, _height_map.size_y);
00307 uint step = size_min >> log_frequency;
00308 uint x, y;
00309
00310
00311 assert(_height_map.h != NULL);
00312
00313
00314 if (step == 0) return false;
00315
00316 if (log_frequency == 0) {
00317
00318 for (y = 0; y <= _height_map.size_y; y += step) {
00319 for (x = 0; x <= _height_map.size_x; x += step) {
00320 height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0;
00321 _height_map.height(x, y) = height;
00322 }
00323 }
00324 return true;
00325 }
00326
00327
00328
00329 for (y = 0; y <= _height_map.size_y; y += 2 * step) {
00330 for (x = 0; x < _height_map.size_x; x += 2 * step) {
00331 height_t h00 = _height_map.height(x + 0 * step, y);
00332 height_t h02 = _height_map.height(x + 2 * step, y);
00333 height_t h01 = (h00 + h02) / 2;
00334 _height_map.height(x + 1 * step, y) = h01;
00335 }
00336 }
00337
00338
00339 for (y = 0; y < _height_map.size_y; y += 2 * step) {
00340 for (x = 0; x <= _height_map.size_x; x += step) {
00341 height_t h00 = _height_map.height(x, y + 0 * step);
00342 height_t h20 = _height_map.height(x, y + 2 * step);
00343 height_t h10 = (h00 + h20) / 2;
00344 _height_map.height(x, y + 1 * step) = h10;
00345 }
00346 }
00347
00348
00349 for (y = 0; y <= _height_map.size_y; y += step) {
00350 for (x = 0; x <= _height_map.size_x; x += step) {
00351 _height_map.height(x, y) += RandomHeight(amplitude);
00352 }
00353 }
00354
00355 return (step > 1);
00356 }
00357
00359 static void HeightMapGenerate()
00360 {
00361 uint size_min = min(_height_map.size_x, _height_map.size_y);
00362 uint iteration_round = 0;
00363 amplitude_t amplitude;
00364 bool continue_iteration;
00365 int log_size_min, log_frequency_min;
00366 int log_frequency;
00367
00368
00369 for (log_size_min = TGP_FREQUENCY_MAX; (1U << log_size_min) < size_min; log_size_min++) { }
00370 log_frequency_min = log_size_min - TGP_FREQUENCY_MAX;
00371
00372
00373 assert(log_frequency_min >= 0);
00374
00375
00376 do {
00377 log_frequency = iteration_round - log_frequency_min;
00378 if (log_frequency >= 0) {
00379
00380 assert(log_frequency <= TGP_FREQUENCY_MAX);
00381 amplitude = _amplitudes_by_smoothness_and_frequency[_settings_game.game_creation.tgen_smoothness][log_frequency];
00382 } else {
00383
00384 amplitude = 0;
00385 }
00386 continue_iteration = ApplyNoise(iteration_round, amplitude);
00387 iteration_round++;
00388 } while (continue_iteration);
00389 assert(log_frequency == TGP_FREQUENCY_MAX);
00390 }
00391
00393 static void HeightMapGetMinMaxAvg(height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr)
00394 {
00395 height_t h_min, h_max, h_avg, *h;
00396 int64 h_accu = 0;
00397 h_min = h_max = _height_map.height(0, 0);
00398
00399
00400 FOR_ALL_TILES_IN_HEIGHT(h) {
00401 if (*h < h_min) h_min = *h;
00402 if (*h > h_max) h_max = *h;
00403 h_accu += *h;
00404 }
00405
00406
00407 h_avg = (height_t)(h_accu / (_height_map.size_x * _height_map.size_y));
00408
00409
00410 if (min_ptr != NULL) *min_ptr = h_min;
00411 if (max_ptr != NULL) *max_ptr = h_max;
00412 if (avg_ptr != NULL) *avg_ptr = h_avg;
00413 }
00414
00416 static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf)
00417 {
00418 int *hist = hist_buf - h_min;
00419 height_t *h;
00420
00421
00422 FOR_ALL_TILES_IN_HEIGHT(h) {
00423 assert(*h >= h_min);
00424 assert(*h <= h_max);
00425 hist[*h]++;
00426 }
00427 return hist;
00428 }
00429
00431 static void HeightMapSineTransform(height_t h_min, height_t h_max)
00432 {
00433 height_t *h;
00434
00435 FOR_ALL_TILES_IN_HEIGHT(h) {
00436 double fheight;
00437
00438 if (*h < h_min) continue;
00439
00440
00441 fheight = (double)(*h - h_min) / (double)(h_max - h_min);
00442
00443 switch(_settings_game.game_creation.landscape) {
00444 case LT_TOYLAND:
00445 case LT_TEMPERATE:
00446
00447 fheight = 2 * fheight - 1;
00448
00449 fheight = sin(fheight * M_PI_2);
00450
00451 fheight = 0.5 * (fheight + 1);
00452 break;
00453
00454 case LT_ARCTIC:
00455 {
00456
00457
00458 double sine_upper_limit = 0.75;
00459 double linear_compression = 2;
00460 if (fheight >= sine_upper_limit) {
00461
00462 fheight = 1.0 - (1.0 - fheight) / linear_compression;
00463 } else {
00464 double m = 1.0 - (1.0 - sine_upper_limit) / linear_compression;
00465
00466 fheight = 2.0 * fheight / sine_upper_limit - 1.0;
00467
00468 fheight = sin(fheight * M_PI_2);
00469
00470 fheight = 0.5 * (fheight + 1.0) * m;
00471 }
00472 }
00473 break;
00474
00475 case LT_TROPIC:
00476 {
00477
00478
00479 double sine_lower_limit = 0.5;
00480 double linear_compression = 2;
00481 if (fheight <= sine_lower_limit) {
00482
00483 fheight = fheight / linear_compression;
00484 } else {
00485 double m = sine_lower_limit / linear_compression;
00486
00487 fheight = 2.0 * ((fheight - sine_lower_limit) / (1.0 - sine_lower_limit)) - 1.0;
00488
00489 fheight = sin(fheight * M_PI_2);
00490
00491 fheight = 0.5 * ((1.0 - m) * fheight + (1.0 + m));
00492 }
00493 }
00494 break;
00495
00496 default:
00497 NOT_REACHED();
00498 break;
00499 }
00500
00501 *h = (height_t)(fheight * (h_max - h_min) + h_min);
00502 if (*h < 0) *h = I2H(0);
00503 if (*h >= h_max) *h = h_max - 1;
00504 }
00505 }
00506
00508 static void HeightMapAdjustWaterLevel(amplitude_t water_percent, height_t h_max_new)
00509 {
00510 height_t h_min, h_max, h_avg, h_water_level;
00511 int water_tiles, desired_water_tiles;
00512 height_t *h;
00513 int *hist;
00514
00515 HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg);
00516
00517
00518 int *hist_buf = CallocT<int>(h_max - h_min + 1);
00519
00520 hist = HeightMapMakeHistogram(h_min, h_max, hist_buf);
00521
00522
00523 desired_water_tiles = (int)(((int64)water_percent) * (int64)(_height_map.size_x * _height_map.size_y)) >> amplitude_decimal_bits;
00524
00525
00526 for (h_water_level = h_min, water_tiles = 0; h_water_level < h_max; h_water_level++) {
00527 water_tiles += hist[h_water_level];
00528 if (water_tiles >= desired_water_tiles) break;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537 FOR_ALL_TILES_IN_HEIGHT(h) {
00538
00539 *h = (height_t)(((int)h_max_new) * (*h - h_water_level) / (h_max - h_water_level)) + I2H(1);
00540
00541 if (*h < 0) *h = I2H(0);
00542 if (*h >= h_max_new) *h = h_max_new - 1;
00543 }
00544
00545 free(hist_buf);
00546 }
00547
00548 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime);
00549
00570 static void HeightMapCoastLines(uint8 water_borders)
00571 {
00572 int smallest_size = min(_settings_game.game_creation.map_x, _settings_game.game_creation.map_y);
00573 const int margin = 4;
00574 uint y, x;
00575 double max_x;
00576 double max_y;
00577
00578
00579 for (y = 0; y <= _height_map.size_y; y++) {
00580 if (HasBit(water_borders, BORDER_NE)) {
00581
00582 max_x = abs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.9, 53) + 0.25) * 5 + (perlin_coast_noise_2D(y, y, 0.35, 179) + 1) * 12);
00583 max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
00584 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00585 for (x = 0; x < max_x; x++) {
00586 _height_map.height(x, y) = 0;
00587 }
00588 }
00589
00590 if (HasBit(water_borders, BORDER_SW)) {
00591
00592 max_x = abs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.85, 101) + 0.3) * 6 + (perlin_coast_noise_2D(y, y, 0.45, 67) + 0.75) * 8);
00593 max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
00594 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00595 for (x = _height_map.size_x; x > (_height_map.size_x - 1 - max_x); x--) {
00596 _height_map.height(x, y) = 0;
00597 }
00598 }
00599 }
00600
00601
00602 for (x = 0; x <= _height_map.size_x; x++) {
00603 if (HasBit(water_borders, BORDER_NW)) {
00604
00605 max_y = abs((perlin_coast_noise_2D(x, _height_map.size_y / 2, 0.9, 167) + 0.4) * 5 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.4, 211) + 0.7) * 9);
00606 max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
00607 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00608 for (y = 0; y < max_y; y++) {
00609 _height_map.height(x, y) = 0;
00610 }
00611 }
00612
00613 if (HasBit(water_borders, BORDER_SE)) {
00614
00615 max_y = abs((perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.85, 71) + 0.25) * 6 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.35, 193) + 0.75) * 12);
00616 max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
00617 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00618 for (y = _height_map.size_y; y > (_height_map.size_y - 1 - max_y); y--) {
00619 _height_map.height(x, y) = 0;
00620 }
00621 }
00622 }
00623 }
00624
00626 static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int dir_y)
00627 {
00628 const int max_coast_dist_from_edge = 35;
00629 const int max_coast_Smooth_depth = 35;
00630
00631 int x, y;
00632 int ed;
00633 int depth;
00634
00635 height_t h_prev = 16;
00636 height_t h;
00637
00638 assert(IsValidXY(org_x, org_y));
00639
00640
00641 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++) {
00642
00643 if (_height_map.height(x, y) > 15) break;
00644
00645
00646 if (IsValidXY(x + dir_y, y + dir_x) && _height_map.height(x + dir_y, y + dir_x) > 0) break;
00647
00648
00649 if (IsValidXY(x - dir_y, y - dir_x) && _height_map.height(x - dir_y, y - dir_x) > 0) break;
00650 }
00651
00652
00653
00654 for (depth = 0; IsValidXY(x, y) && depth <= max_coast_Smooth_depth; depth++, x += dir_x, y += dir_y) {
00655 h = _height_map.height(x, y);
00656 h = min(h, h_prev + (4 + depth));
00657 _height_map.height(x, y) = h;
00658 h_prev = h;
00659 }
00660 }
00661
00663 static void HeightMapSmoothCoasts(uint8 water_borders)
00664 {
00665 uint x, y;
00666
00667 for (x = 0; x < _height_map.size_x; x++) {
00668 if (HasBit(water_borders, BORDER_NW)) HeightMapSmoothCoastInDirection(x, 0, 0, 1);
00669 if (HasBit(water_borders, BORDER_SE)) HeightMapSmoothCoastInDirection(x, _height_map.size_y - 1, 0, -1);
00670 }
00671
00672 for (y = 0; y < _height_map.size_y; y++) {
00673 if (HasBit(water_borders, BORDER_NE)) HeightMapSmoothCoastInDirection(0, y, 1, 0);
00674 if (HasBit(water_borders, BORDER_SW)) HeightMapSmoothCoastInDirection(_height_map.size_x - 1, y, -1, 0);
00675 }
00676 }
00677
00685 static void HeightMapSmoothSlopes(height_t dh_max)
00686 {
00687 int x, y;
00688 for (y = 0; y <= (int)_height_map.size_y; y++) {
00689 for (x = 0; x <= (int)_height_map.size_x; x++) {
00690 height_t h_max = min(_height_map.height(x > 0 ? x - 1 : x, y), _height_map.height(x, y > 0 ? y - 1 : y)) + dh_max;
00691 if (_height_map.height(x, y) > h_max) _height_map.height(x, y) = h_max;
00692 }
00693 }
00694 for (y = _height_map.size_y; y >= 0; y--) {
00695 for (x = _height_map.size_x; x >= 0; x--) {
00696 height_t h_max = min(_height_map.height((uint)x < _height_map.size_x ? x + 1 : x, y), _height_map.height(x, (uint)y < _height_map.size_y ? y + 1 : y)) + dh_max;
00697 if (_height_map.height(x, y) > h_max) _height_map.height(x, y) = h_max;
00698 }
00699 }
00700 }
00701
00707 static void HeightMapNormalize()
00708 {
00709 const amplitude_t water_percent = _water_percent[_settings_game.difficulty.quantity_sea_lakes];
00710 const height_t h_max_new = I2H(_max_height[_settings_game.difficulty.terrain_type]);
00711 const height_t roughness = 7 + 3 * _settings_game.game_creation.tgen_smoothness;
00712
00713 HeightMapAdjustWaterLevel(water_percent, h_max_new);
00714
00715 byte water_borders = _settings_game.construction.freeform_edges ? _settings_game.game_creation.water_borders : 0xF;
00716 if (water_borders == BORDERS_RANDOM) water_borders = GB(Random(), 0, 4);
00717
00718 HeightMapCoastLines(water_borders);
00719 HeightMapSmoothSlopes(roughness);
00720
00721 HeightMapSmoothCoasts(water_borders);
00722 HeightMapSmoothSlopes(roughness);
00723
00724 HeightMapSineTransform(12, h_max_new);
00725 HeightMapSmoothSlopes(16);
00726 }
00727
00735 static double int_noise(const long x, const long y, const int prime)
00736 {
00737 long n = x + y * prime + _settings_game.game_creation.generation_seed;
00738
00739 n = (n << 13) ^ n;
00740
00741
00742 return 1.0 - (double)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0;
00743 }
00744
00745
00752 static double smoothed_noise(const int x, const int y, const int prime)
00753 {
00754 #if 0
00755
00756 const double sides = int_noise(x - 1, y) + int_noise(x + 1, y) + int_noise(x, y - 1) + int_noise(x, y + 1);
00757 const double center = int_noise(x, y);
00758 return (sides + sides + center * 4) / 8.0;
00759 #endif
00760
00761
00762 return int_noise(x, y, prime);
00763 }
00764
00765
00769 static inline double linear_interpolate(const double a, const double b, const double x)
00770 {
00771 return a + x * (b - a);
00772 }
00773
00774
00779 static double interpolated_noise(const double x, const double y, const int prime)
00780 {
00781 const int integer_X = (int)x;
00782 const int integer_Y = (int)y;
00783
00784 const double fractional_X = x - (double)integer_X;
00785 const double fractional_Y = y - (double)integer_Y;
00786
00787 const double v1 = smoothed_noise(integer_X, integer_Y, prime);
00788 const double v2 = smoothed_noise(integer_X + 1, integer_Y, prime);
00789 const double v3 = smoothed_noise(integer_X, integer_Y + 1, prime);
00790 const double v4 = smoothed_noise(integer_X + 1, integer_Y + 1, prime);
00791
00792 const double i1 = linear_interpolate(v1, v2, fractional_X);
00793 const double i2 = linear_interpolate(v3, v4, fractional_X);
00794
00795 return linear_interpolate(i1, i2, fractional_Y);
00796 }
00797
00798
00805 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime)
00806 {
00807 double total = 0.0;
00808 int i;
00809
00810 for (i = 0; i < 6; i++) {
00811 const double frequency = (double)(1 << i);
00812 const double amplitude = pow(p, (double)i);
00813
00814 total += interpolated_noise((x * frequency) / 64.0, (y * frequency) / 64.0, prime) * amplitude;
00815 }
00816
00817 return total;
00818 }
00819
00820
00822 static void TgenSetTileHeight(TileIndex tile, int height)
00823 {
00824 SetTileHeight(tile, height);
00825
00826
00827 if (TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY() &&
00828 (!_settings_game.construction.freeform_edges || (TileX(tile) != 0 && TileY(tile) != 0))) {
00829 MakeClear(tile, CLEAR_GRASS, 3);
00830 }
00831 }
00832
00840 void GenerateTerrainPerlin()
00841 {
00842 uint x, y;
00843
00844 if (!AllocHeightMap()) return;
00845 GenerateWorldSetAbortCallback(FreeHeightMap);
00846
00847 HeightMapGenerate();
00848
00849 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00850
00851 HeightMapNormalize();
00852
00853 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00854
00855
00856 if (_settings_game.construction.freeform_edges) {
00857 for (y = 0; y < _height_map.size_y - 1; y++) MakeVoid(_height_map.size_x * y);
00858 for (x = 0; x < _height_map.size_x; x++) MakeVoid(x);
00859 }
00860
00861
00862 for (y = 0; y < _height_map.size_y; y++) {
00863 for (x = 0; x < _height_map.size_x; x++) {
00864 int height = H2I(_height_map.height(x, y));
00865 if (height < 0) height = 0;
00866 if (height > 15) height = 15;
00867 TgenSetTileHeight(TileXY(x, y), height);
00868 }
00869 }
00870
00871 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00872
00873 FreeHeightMap();
00874 GenerateWorldSetAbortCallback(NULL);
00875 }