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
00257
00258 FOR_ALL_TILES_IN_HEIGHT(h) *h = _invalid_height;
00259
00260 return true;
00261 }
00262
00264 static inline void FreeHeightMap()
00265 {
00266 if (_height_map.h == NULL) return;
00267 free(_height_map.h);
00268 _height_map.h = NULL;
00269 }
00270
00276 static inline height_t RandomHeight(amplitude_t rMax)
00277 {
00278 amplitude_t ra = (Random() << 16) | (Random() & 0x0000FFFF);
00279 height_t rh;
00280
00281 rh = A2H(ra % (2 * rMax + 1) - rMax);
00282 return rh;
00283 }
00284
00303 static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
00304 {
00305 uint size_min = min(_height_map.size_x, _height_map.size_y);
00306 uint step = size_min >> log_frequency;
00307 uint x, y;
00308
00309
00310 assert(_height_map.h != NULL);
00311
00312
00313 if (step == 0) return false;
00314
00315 if (log_frequency == 0) {
00316
00317 for (y = 0; y <= _height_map.size_y; y += step) {
00318 for (x = 0; x <= _height_map.size_x; x += step) {
00319 height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0;
00320 _height_map.height(x, y) = height;
00321 }
00322 }
00323 return true;
00324 }
00325
00326
00327
00328 for (y = 0; y <= _height_map.size_y; y += 2 * step) {
00329 for (x = 0; x < _height_map.size_x; x += 2 * step) {
00330 height_t h00 = _height_map.height(x + 0 * step, y);
00331 height_t h02 = _height_map.height(x + 2 * step, y);
00332 height_t h01 = (h00 + h02) / 2;
00333 _height_map.height(x + 1 * step, y) = h01;
00334 }
00335 }
00336
00337
00338 for (y = 0; y < _height_map.size_y; y += 2 * step) {
00339 for (x = 0; x <= _height_map.size_x; x += step) {
00340 height_t h00 = _height_map.height(x, y + 0 * step);
00341 height_t h20 = _height_map.height(x, y + 2 * step);
00342 height_t h10 = (h00 + h20) / 2;
00343 _height_map.height(x, y + 1 * step) = h10;
00344 }
00345 }
00346
00347
00348 for (y = 0; y <= _height_map.size_y; y += step) {
00349 for (x = 0; x <= _height_map.size_x; x += step) {
00350 _height_map.height(x, y) += RandomHeight(amplitude);
00351 }
00352 }
00353
00354 return (step > 1);
00355 }
00356
00358 static void HeightMapGenerate()
00359 {
00360 uint size_min = min(_height_map.size_x, _height_map.size_y);
00361 uint iteration_round = 0;
00362 amplitude_t amplitude;
00363 bool continue_iteration;
00364 int log_size_min, log_frequency_min;
00365 int log_frequency;
00366
00367
00368 for (log_size_min = TGP_FREQUENCY_MAX; (1U << log_size_min) < size_min; log_size_min++) { }
00369 log_frequency_min = log_size_min - TGP_FREQUENCY_MAX;
00370
00371
00372 assert(log_frequency_min >= 0);
00373
00374
00375 do {
00376 log_frequency = iteration_round - log_frequency_min;
00377 if (log_frequency >= 0) {
00378
00379 assert(log_frequency <= TGP_FREQUENCY_MAX);
00380 amplitude = _amplitudes_by_smoothness_and_frequency[_settings_game.game_creation.tgen_smoothness][log_frequency];
00381 } else {
00382
00383 amplitude = 0;
00384 }
00385 continue_iteration = ApplyNoise(iteration_round, amplitude);
00386 iteration_round++;
00387 } while (continue_iteration);
00388 assert(log_frequency == TGP_FREQUENCY_MAX);
00389 }
00390
00392 static void HeightMapGetMinMaxAvg(height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr)
00393 {
00394 height_t h_min, h_max, h_avg, *h;
00395 int64 h_accu = 0;
00396 h_min = h_max = _height_map.height(0, 0);
00397
00398
00399 FOR_ALL_TILES_IN_HEIGHT(h) {
00400 if (*h < h_min) h_min = *h;
00401 if (*h > h_max) h_max = *h;
00402 h_accu += *h;
00403 }
00404
00405
00406 h_avg = (height_t)(h_accu / (_height_map.size_x * _height_map.size_y));
00407
00408
00409 if (min_ptr != NULL) *min_ptr = h_min;
00410 if (max_ptr != NULL) *max_ptr = h_max;
00411 if (avg_ptr != NULL) *avg_ptr = h_avg;
00412 }
00413
00415 static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf)
00416 {
00417 int *hist = hist_buf - h_min;
00418 height_t *h;
00419
00420
00421 FOR_ALL_TILES_IN_HEIGHT(h) {
00422 assert(*h >= h_min);
00423 assert(*h <= h_max);
00424 hist[*h]++;
00425 }
00426 return hist;
00427 }
00428
00430 static void HeightMapSineTransform(height_t h_min, height_t h_max)
00431 {
00432 height_t *h;
00433
00434 FOR_ALL_TILES_IN_HEIGHT(h) {
00435 double fheight;
00436
00437 if (*h < h_min) continue;
00438
00439
00440 fheight = (double)(*h - h_min) / (double)(h_max - h_min);
00441
00442 switch(_settings_game.game_creation.landscape) {
00443 case LT_TOYLAND:
00444 case LT_TEMPERATE:
00445
00446 fheight = 2 * fheight - 1;
00447
00448 fheight = sin(fheight * M_PI_2);
00449
00450 fheight = 0.5 * (fheight + 1);
00451 break;
00452
00453 case LT_ARCTIC:
00454 {
00455
00456
00457 double sine_upper_limit = 0.75;
00458 double linear_compression = 2;
00459 if (fheight >= sine_upper_limit) {
00460
00461 fheight = 1.0 - (1.0 - fheight) / linear_compression;
00462 } else {
00463 double m = 1.0 - (1.0 - sine_upper_limit) / linear_compression;
00464
00465 fheight = 2.0 * fheight / sine_upper_limit - 1.0;
00466
00467 fheight = sin(fheight * M_PI_2);
00468
00469 fheight = 0.5 * (fheight + 1.0) * m;
00470 }
00471 }
00472 break;
00473
00474 case LT_TROPIC:
00475 {
00476
00477
00478 double sine_lower_limit = 0.5;
00479 double linear_compression = 2;
00480 if (fheight <= sine_lower_limit) {
00481
00482 fheight = fheight / linear_compression;
00483 } else {
00484 double m = sine_lower_limit / linear_compression;
00485
00486 fheight = 2.0 * ((fheight - sine_lower_limit) / (1.0 - sine_lower_limit)) - 1.0;
00487
00488 fheight = sin(fheight * M_PI_2);
00489
00490 fheight = 0.5 * ((1.0 - m) * fheight + (1.0 + m));
00491 }
00492 }
00493 break;
00494
00495 default:
00496 NOT_REACHED();
00497 break;
00498 }
00499
00500 *h = (height_t)(fheight * (h_max - h_min) + h_min);
00501 if (*h < 0) *h = I2H(0);
00502 if (*h >= h_max) *h = h_max - 1;
00503 }
00504 }
00505
00507 static void HeightMapAdjustWaterLevel(amplitude_t water_percent, height_t h_max_new)
00508 {
00509 height_t h_min, h_max, h_avg, h_water_level;
00510 int water_tiles, desired_water_tiles;
00511 height_t *h;
00512 int *hist;
00513
00514 HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg);
00515
00516
00517 int *hist_buf = CallocT<int>(h_max - h_min + 1);
00518
00519 hist = HeightMapMakeHistogram(h_min, h_max, hist_buf);
00520
00521
00522 desired_water_tiles = (int)(((int64)water_percent) * (int64)(_height_map.size_x * _height_map.size_y)) >> amplitude_decimal_bits;
00523
00524
00525 for (h_water_level = h_min, water_tiles = 0; h_water_level < h_max; h_water_level++) {
00526 water_tiles += hist[h_water_level];
00527 if (water_tiles >= desired_water_tiles) break;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536 FOR_ALL_TILES_IN_HEIGHT(h) {
00537
00538 *h = (height_t)(((int)h_max_new) * (*h - h_water_level) / (h_max - h_water_level)) + I2H(1);
00539
00540 if (*h < 0) *h = I2H(0);
00541 if (*h >= h_max_new) *h = h_max_new - 1;
00542 }
00543
00544 free(hist_buf);
00545 }
00546
00547 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime);
00548
00569 static void HeightMapCoastLines(uint8 water_borders)
00570 {
00571 int smallest_size = min(_settings_game.game_creation.map_x, _settings_game.game_creation.map_y);
00572 const int margin = 4;
00573 uint y, x;
00574 double max_x;
00575 double max_y;
00576
00577
00578 for (y = 0; y <= _height_map.size_y; y++) {
00579 if (HasBit(water_borders, BORDER_NE)) {
00580
00581 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);
00582 max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
00583 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00584 for (x = 0; x < max_x; x++) {
00585 _height_map.height(x, y) = 0;
00586 }
00587 }
00588
00589 if (HasBit(water_borders, BORDER_SW)) {
00590
00591 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);
00592 max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
00593 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00594 for (x = _height_map.size_x; x > (_height_map.size_x - 1 - max_x); x--) {
00595 _height_map.height(x, y) = 0;
00596 }
00597 }
00598 }
00599
00600
00601 for (x = 0; x <= _height_map.size_x; x++) {
00602 if (HasBit(water_borders, BORDER_NW)) {
00603
00604 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);
00605 max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
00606 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00607 for (y = 0; y < max_y; y++) {
00608 _height_map.height(x, y) = 0;
00609 }
00610 }
00611
00612 if (HasBit(water_borders, BORDER_SE)) {
00613
00614 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);
00615 max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
00616 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00617 for (y = _height_map.size_y; y > (_height_map.size_y - 1 - max_y); y--) {
00618 _height_map.height(x, y) = 0;
00619 }
00620 }
00621 }
00622 }
00623
00625 static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int dir_y)
00626 {
00627 const int max_coast_dist_from_edge = 35;
00628 const int max_coast_Smooth_depth = 35;
00629
00630 int x, y;
00631 int ed;
00632 int depth;
00633
00634 height_t h_prev = 16;
00635 height_t h;
00636
00637 assert(IsValidXY(org_x, org_y));
00638
00639
00640 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++) {
00641
00642 if (_height_map.height(x, y) > 15) break;
00643
00644
00645 if (IsValidXY(x + dir_y, y + dir_x) && _height_map.height(x + dir_y, y + dir_x) > 0) break;
00646
00647
00648 if (IsValidXY(x - dir_y, y - dir_x) && _height_map.height(x - dir_y, y - dir_x) > 0) break;
00649 }
00650
00651
00652
00653 for (depth = 0; IsValidXY(x, y) && depth <= max_coast_Smooth_depth; depth++, x += dir_x, y += dir_y) {
00654 h = _height_map.height(x, y);
00655 h = min(h, h_prev + (4 + depth));
00656 _height_map.height(x, y) = h;
00657 h_prev = h;
00658 }
00659 }
00660
00662 static void HeightMapSmoothCoasts(uint8 water_borders)
00663 {
00664 uint x, y;
00665
00666 for (x = 0; x < _height_map.size_x; x++) {
00667 if (HasBit(water_borders, BORDER_NW)) HeightMapSmoothCoastInDirection(x, 0, 0, 1);
00668 if (HasBit(water_borders, BORDER_SE)) HeightMapSmoothCoastInDirection(x, _height_map.size_y - 1, 0, -1);
00669 }
00670
00671 for (y = 0; y < _height_map.size_y; y++) {
00672 if (HasBit(water_borders, BORDER_NE)) HeightMapSmoothCoastInDirection(0, y, 1, 0);
00673 if (HasBit(water_borders, BORDER_SW)) HeightMapSmoothCoastInDirection(_height_map.size_x - 1, y, -1, 0);
00674 }
00675 }
00676
00684 static void HeightMapSmoothSlopes(height_t dh_max)
00685 {
00686 int x, y;
00687 for (y = 0; y <= (int)_height_map.size_y; y++) {
00688 for (x = 0; x <= (int)_height_map.size_x; x++) {
00689 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;
00690 if (_height_map.height(x, y) > h_max) _height_map.height(x, y) = h_max;
00691 }
00692 }
00693 for (y = _height_map.size_y; y >= 0; y--) {
00694 for (x = _height_map.size_x; x >= 0; x--) {
00695 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;
00696 if (_height_map.height(x, y) > h_max) _height_map.height(x, y) = h_max;
00697 }
00698 }
00699 }
00700
00706 static void HeightMapNormalize()
00707 {
00708 const amplitude_t water_percent = _water_percent[_settings_game.difficulty.quantity_sea_lakes];
00709 const height_t h_max_new = I2H(_max_height[_settings_game.difficulty.terrain_type]);
00710 const height_t roughness = 7 + 3 * _settings_game.game_creation.tgen_smoothness;
00711
00712 HeightMapAdjustWaterLevel(water_percent, h_max_new);
00713
00714 byte water_borders = _settings_game.construction.freeform_edges ? _settings_game.game_creation.water_borders : 0xF;
00715 if (water_borders == BORDERS_RANDOM) water_borders = GB(Random(), 0, 4);
00716
00717 HeightMapCoastLines(water_borders);
00718 HeightMapSmoothSlopes(roughness);
00719
00720 HeightMapSmoothCoasts(water_borders);
00721 HeightMapSmoothSlopes(roughness);
00722
00723 HeightMapSineTransform(12, h_max_new);
00724 HeightMapSmoothSlopes(16);
00725 }
00726
00734 static double int_noise(const long x, const long y, const int prime)
00735 {
00736 long n = x + y * prime + _settings_game.game_creation.generation_seed;
00737
00738 n = (n << 13) ^ n;
00739
00740
00741 return 1.0 - (double)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0;
00742 }
00743
00744
00751 static double smoothed_noise(const int x, const int y, const int prime)
00752 {
00753 #if 0
00754
00755 const double sides = int_noise(x - 1, y) + int_noise(x + 1, y) + int_noise(x, y - 1) + int_noise(x, y + 1);
00756 const double center = int_noise(x, y);
00757 return (sides + sides + center * 4) / 8.0;
00758 #endif
00759
00760
00761 return int_noise(x, y, prime);
00762 }
00763
00764
00768 static inline double linear_interpolate(const double a, const double b, const double x)
00769 {
00770 return a + x * (b - a);
00771 }
00772
00773
00778 static double interpolated_noise(const double x, const double y, const int prime)
00779 {
00780 const int integer_X = (int)x;
00781 const int integer_Y = (int)y;
00782
00783 const double fractional_X = x - (double)integer_X;
00784 const double fractional_Y = y - (double)integer_Y;
00785
00786 const double v1 = smoothed_noise(integer_X, integer_Y, prime);
00787 const double v2 = smoothed_noise(integer_X + 1, integer_Y, prime);
00788 const double v3 = smoothed_noise(integer_X, integer_Y + 1, prime);
00789 const double v4 = smoothed_noise(integer_X + 1, integer_Y + 1, prime);
00790
00791 const double i1 = linear_interpolate(v1, v2, fractional_X);
00792 const double i2 = linear_interpolate(v3, v4, fractional_X);
00793
00794 return linear_interpolate(i1, i2, fractional_Y);
00795 }
00796
00797
00804 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime)
00805 {
00806 double total = 0.0;
00807 int i;
00808
00809 for (i = 0; i < 6; i++) {
00810 const double frequency = (double)(1 << i);
00811 const double amplitude = pow(p, (double)i);
00812
00813 total += interpolated_noise((x * frequency) / 64.0, (y * frequency) / 64.0, prime) * amplitude;
00814 }
00815
00816 return total;
00817 }
00818
00819
00821 static void TgenSetTileHeight(TileIndex tile, int height)
00822 {
00823 SetTileHeight(tile, height);
00824
00825
00826 if (TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY() &&
00827 (!_settings_game.construction.freeform_edges || (TileX(tile) != 0 && TileY(tile) != 0))) {
00828 MakeClear(tile, CLEAR_GRASS, 3);
00829 }
00830 }
00831
00839 void GenerateTerrainPerlin()
00840 {
00841 uint x, y;
00842
00843 if (!AllocHeightMap()) return;
00844 GenerateWorldSetAbortCallback(FreeHeightMap);
00845
00846 HeightMapGenerate();
00847
00848 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00849
00850 HeightMapNormalize();
00851
00852 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00853
00854
00855 if (_settings_game.construction.freeform_edges) {
00856 for (y = 0; y < _height_map.size_y - 1; y++) MakeVoid(_height_map.size_x * y);
00857 for (x = 0; x < _height_map.size_x; x++) MakeVoid(x);
00858 }
00859
00860
00861 for (y = 0; y < _height_map.size_y; y++) {
00862 for (x = 0; x < _height_map.size_x; x++) {
00863 int height = H2I(_height_map.height(x, y));
00864 if (height < 0) height = 0;
00865 if (height > 15) height = 15;
00866 TgenSetTileHeight(TileXY(x, y), height);
00867 }
00868 }
00869
00870 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00871
00872 FreeHeightMap();
00873 GenerateWorldSetAbortCallback(NULL);
00874 }