00001
00002
00005 #include "stdafx.h"
00006 #include <math.h>
00007 #include "openttd.h"
00008 #include "clear_map.h"
00009 #include "clear_map.h"
00010 #include "variables.h"
00011 #include "void_map.h"
00012 #include "tgp.h"
00013 #include "console.h"
00014 #include "genworld.h"
00015 #include "core/alloc_func.hpp"
00016 #include "core/random_func.hpp"
00017 #include "settings_type.h"
00018
00019 #include "table/strings.h"
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
00149
00150
00151
00152
00153
00154 #ifndef M_PI_2
00155 #define M_PI_2 1.57079632679489661923
00156 #define M_PI 3.14159265358979323846
00157 #endif
00158
00160 typedef int16 height_t;
00161 static const int height_decimal_bits = 4;
00162 static const height_t _invalid_height = -32768;
00163
00165 typedef int amplitude_t;
00166 static const int amplitude_decimal_bits = 10;
00167
00169 struct HeightMap
00170 {
00171 height_t *h;
00172 uint dim_x;
00173 uint total_size;
00174 uint size_x;
00175 uint size_y;
00176 };
00177
00179 static HeightMap _height_map = {NULL, 0, 0, 0, 0};
00180
00182 #define HeightMapXY(x, y) _height_map.h[(x) + (y) * _height_map.dim_x]
00183
00185 #define I2H(i) ((i) << height_decimal_bits)
00186
00187 #define H2I(i) ((i) >> height_decimal_bits)
00188
00190 #define I2A(i) ((i) << amplitude_decimal_bits)
00191
00192 #define A2I(i) ((i) >> amplitude_decimal_bits)
00193
00195 #define A2H(a) ((a) >> (amplitude_decimal_bits - height_decimal_bits))
00196
00197
00199 #define FOR_ALL_TILES_IN_HEIGHT(h) for (h = _height_map.h; h < &_height_map.h[_height_map.total_size]; h++)
00200
00203 static const amplitude_t _amplitudes_by_smoothness_and_frequency[4][12] = {
00204
00205 {1000, 350, 123, 43, 15, 1, 1, 0, 0, 0, 0, 0},
00206
00207 {1000, 1000, 403, 200, 64, 8, 1, 0, 0, 0, 0, 0},
00208
00209 {1000, 1200, 800, 500, 200, 16, 4, 0, 0, 0, 0, 0},
00210
00211 {1500, 1000, 1200, 1000, 500, 32, 20, 0, 0, 0, 0, 0},
00212 };
00213
00215 static const amplitude_t _water_percent[4] = {20, 80, 250, 400};
00216
00218 static const int8 _max_height[4] = {
00219 6,
00220 9,
00221 12,
00222 15
00223 };
00224
00230 static inline bool IsValidXY(uint x, uint y)
00231 {
00232 return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y;
00233 }
00234
00235
00237 static inline bool AllocHeightMap()
00238 {
00239 height_t *h;
00240
00241 _height_map.size_x = MapSizeX();
00242 _height_map.size_y = MapSizeY();
00243
00244
00245 _height_map.total_size = (_height_map.size_x + 1) * (_height_map.size_y + 1);
00246 _height_map.dim_x = _height_map.size_x + 1;
00247 _height_map.h = CallocT<height_t>(_height_map.total_size);
00248 if (_height_map.h == NULL) return false;
00249
00250
00251 FOR_ALL_TILES_IN_HEIGHT(h) *h = _invalid_height;
00252
00253 return true;
00254 }
00255
00257 static inline void FreeHeightMap()
00258 {
00259 if (_height_map.h == NULL) return;
00260 free(_height_map.h);
00261 _height_map.h = NULL;
00262 }
00263
00265 static inline height_t RandomHeight(amplitude_t rMax)
00266 {
00267 amplitude_t ra = (Random() << 16) | (Random() & 0x0000FFFF);
00268 height_t rh;
00269
00270 rMax *= 16;
00271
00272 rh = A2H(ra % (2 * rMax + 1) - rMax);
00273 return rh;
00274 }
00275
00277 static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
00278 {
00279 uint size_min = min(_height_map.size_x, _height_map.size_y);
00280 uint step = size_min >> log_frequency;
00281 uint x, y;
00282
00283 assert(_height_map.h != NULL);
00284
00285
00286 if (step == 0) return false;
00287
00288 if (log_frequency == 0) {
00289
00290 for (y = 0; y <= _height_map.size_y; y += step) {
00291 for (x = 0; x <= _height_map.size_x; x += step) {
00292 height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0;
00293 HeightMapXY(x, y) = height;
00294 }
00295 }
00296 return true;
00297 }
00298
00299
00300
00301 for (y = 0; y <= _height_map.size_y; y += 2 * step) {
00302 for (x = 0; x < _height_map.size_x; x += 2 * step) {
00303 height_t h00 = HeightMapXY(x + 0 * step, y);
00304 height_t h02 = HeightMapXY(x + 2 * step, y);
00305 height_t h01 = (h00 + h02) / 2;
00306 HeightMapXY(x + 1 * step, y) = h01;
00307 }
00308 }
00309
00310
00311 for (y = 0; y < _height_map.size_y; y += 2 * step) {
00312 for (x = 0; x <= _height_map.size_x; x += step) {
00313 height_t h00 = HeightMapXY(x, y + 0 * step);
00314 height_t h20 = HeightMapXY(x, y + 2 * step);
00315 height_t h10 = (h00 + h20) / 2;
00316 HeightMapXY(x, y + 1 * step) = h10;
00317 }
00318 }
00319
00320 for (y = 0; y <= _height_map.size_y; y += step) {
00321 for (x = 0; x <= _height_map.size_x; x += step) {
00322 HeightMapXY(x, y) += RandomHeight(amplitude);
00323 }
00324 }
00325 return (step > 1);
00326 }
00327
00329 static void HeightMapGenerate()
00330 {
00331 uint size_min = min(_height_map.size_x, _height_map.size_y);
00332 uint iteration_round = 0;
00333 amplitude_t amplitude;
00334 bool continue_iteration;
00335 uint log_size_min, log_frequency_min;
00336 int log_frequency;
00337
00338
00339 for (log_size_min = 6; (1U << log_size_min) < size_min; log_size_min++) { }
00340 log_frequency_min = log_size_min - 6;
00341
00342 do {
00343 log_frequency = iteration_round - log_frequency_min;
00344 if (log_frequency >= 0) {
00345 amplitude = _amplitudes_by_smoothness_and_frequency[_patches.tgen_smoothness][log_frequency];
00346 } else {
00347 amplitude = 0;
00348 }
00349 continue_iteration = ApplyNoise(iteration_round, amplitude);
00350 iteration_round++;
00351 } while(continue_iteration);
00352 }
00353
00355 static void HeightMapGetMinMaxAvg(height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr)
00356 {
00357 height_t h_min, h_max, h_avg, *h;
00358 int64 h_accu = 0;
00359 h_min = h_max = HeightMapXY(0, 0);
00360
00361
00362 FOR_ALL_TILES_IN_HEIGHT(h) {
00363 if (*h < h_min) h_min = *h;
00364 if (*h > h_max) h_max = *h;
00365 h_accu += *h;
00366 }
00367
00368
00369 h_avg = (height_t)(h_accu / (_height_map.size_x * _height_map.size_y));
00370
00371
00372 if (min_ptr != NULL) *min_ptr = h_min;
00373 if (max_ptr != NULL) *max_ptr = h_max;
00374 if (avg_ptr != NULL) *avg_ptr = h_avg;
00375 }
00376
00378 static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf)
00379 {
00380 int *hist = hist_buf - h_min;
00381 height_t *h;
00382
00383
00384 FOR_ALL_TILES_IN_HEIGHT(h) {
00385 assert(*h >= h_min);
00386 assert(*h <= h_max);
00387 hist[*h]++;
00388 }
00389 return hist;
00390 }
00391
00393 static void HeightMapSineTransform(height_t h_min, height_t h_max)
00394 {
00395 height_t *h;
00396
00397 FOR_ALL_TILES_IN_HEIGHT(h) {
00398 double fheight;
00399
00400 if (*h < h_min) continue;
00401
00402
00403 fheight = (double)(*h - h_min) / (double)(h_max - h_min);
00404
00405 switch(_opt.landscape) {
00406 case LT_TOYLAND:
00407 case LT_TEMPERATE:
00408
00409 fheight = 2 * fheight - 1;
00410
00411 fheight = sin(fheight * M_PI_2);
00412
00413 fheight = 0.5 * (fheight + 1);
00414 break;
00415
00416 case LT_ARCTIC:
00417 {
00418
00419
00420 double sine_upper_limit = 0.75;
00421 double linear_compression = 2;
00422 if (fheight >= sine_upper_limit) {
00423
00424 fheight = 1.0 - (1.0 - fheight) / linear_compression;
00425 } else {
00426 double m = 1.0 - (1.0 - sine_upper_limit) / linear_compression;
00427
00428 fheight = 2.0 * fheight / sine_upper_limit - 1.0;
00429
00430 fheight = sin(fheight * M_PI_2);
00431
00432 fheight = 0.5 * (fheight + 1.0) * m;
00433 }
00434 }
00435 break;
00436
00437 case LT_TROPIC:
00438 {
00439
00440
00441 double sine_lower_limit = 0.5;
00442 double linear_compression = 2;
00443 if (fheight <= sine_lower_limit) {
00444
00445 fheight = fheight / linear_compression;
00446 } else {
00447 double m = sine_lower_limit / linear_compression;
00448
00449 fheight = 2.0 * ((fheight - sine_lower_limit) / (1.0 - sine_lower_limit)) - 1.0;
00450
00451 fheight = sin(fheight * M_PI_2);
00452
00453 fheight = 0.5 * ((1.0 - m) * fheight + (1.0 + m));
00454 }
00455 }
00456 break;
00457
00458 default:
00459 NOT_REACHED();
00460 break;
00461 }
00462
00463 *h = (height_t)(fheight * (h_max - h_min) + h_min);
00464 if (*h < 0) *h = I2H(0);
00465 if (*h >= h_max) *h = h_max - 1;
00466 }
00467 }
00468
00470 static void HeightMapAdjustWaterLevel(amplitude_t water_percent, height_t h_max_new)
00471 {
00472 height_t h_min, h_max, h_avg, h_water_level;
00473 int water_tiles, desired_water_tiles;
00474 height_t *h;
00475 int *hist;
00476
00477 HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg);
00478
00479
00480 int *hist_buf = CallocT<int>(h_max - h_min + 1);
00481
00482 hist = HeightMapMakeHistogram(h_min, h_max, hist_buf);
00483
00484
00485 desired_water_tiles = (int)(((int64)water_percent) * (int64)(_height_map.size_x * _height_map.size_y)) >> amplitude_decimal_bits;
00486
00487
00488 for (h_water_level = h_min, water_tiles = 0; h_water_level < h_max; h_water_level++) {
00489 water_tiles += hist[h_water_level];
00490 if (water_tiles >= desired_water_tiles) break;
00491 }
00492
00493
00494
00495
00496
00497
00498
00499 FOR_ALL_TILES_IN_HEIGHT(h) {
00500
00501 *h = (height_t)(((int)h_max_new) * (*h - h_water_level) / (h_max - h_water_level)) + I2H(1);
00502
00503 if (*h < 0) *h = I2H(0);
00504 if (*h >= h_max_new) *h = h_max_new - 1;
00505 }
00506
00507 free(hist_buf);
00508 }
00509
00510 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime);
00511
00532 static void HeightMapCoastLines()
00533 {
00534 int smallest_size = min(_patches.map_x, _patches.map_y);
00535 const int margin = 4;
00536 uint y, x;
00537 double max_x;
00538 double max_y;
00539
00540
00541 for (y = 0; y <= _height_map.size_y; y++) {
00542
00543 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);
00544 max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
00545 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00546 for (x = 0; x < max_x; x++) {
00547 HeightMapXY(x, y) = 0;
00548 }
00549
00550
00551 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);
00552 max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
00553 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00554 for (x = _height_map.size_x; x > (_height_map.size_x - 1 - max_x); x--) {
00555 HeightMapXY(x, y) = 0;
00556 }
00557 }
00558
00559
00560 for (x = 0; x <= _height_map.size_x; x++) {
00561
00562 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);
00563 max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
00564 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00565 for (y = 0; y < max_y; y++) {
00566 HeightMapXY(x, y) = 0;
00567 }
00568
00569
00570
00571 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);
00572 max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
00573 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00574 for (y = _height_map.size_y; y > (_height_map.size_y - 1 - max_y); y--) {
00575 HeightMapXY(x, y) = 0;
00576 }
00577 }
00578 }
00579
00581 static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int dir_y)
00582 {
00583 const int max_coast_dist_from_edge = 35;
00584 const int max_coast_Smooth_depth = 35;
00585
00586 int x, y;
00587 int ed;
00588 int depth;
00589
00590 height_t h_prev = 16;
00591 height_t h;
00592
00593 assert(IsValidXY(org_x, org_y));
00594
00595
00596 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++) {
00597
00598 if (HeightMapXY(x, y) > 15) break;
00599
00600
00601 if (IsValidXY(x + dir_y, y + dir_x) && HeightMapXY(x + dir_y, y + dir_x) > 0) break;
00602
00603
00604 if (IsValidXY(x - dir_y, y - dir_x) && HeightMapXY(x - dir_y, y - dir_x) > 0) break;
00605 }
00606
00607
00608
00609 for (depth = 0; IsValidXY(x, y) && depth <= max_coast_Smooth_depth; depth++, x += dir_x, y += dir_y) {
00610 h = HeightMapXY(x, y);
00611 h = min(h, h_prev + (4 + depth));
00612 HeightMapXY(x, y) = h;
00613 h_prev = h;
00614 }
00615 }
00616
00618 static void HeightMapSmoothCoasts()
00619 {
00620 uint x, y;
00621
00622 for (x = 0; x < _height_map.size_x; x++) {
00623 HeightMapSmoothCoastInDirection(x, 0, 0, 1);
00624 HeightMapSmoothCoastInDirection(x, _height_map.size_y - 1, 0, -1);
00625 }
00626
00627 for (y = 0; y < _height_map.size_y; y++) {
00628 HeightMapSmoothCoastInDirection(0, y, 1, 0);
00629 HeightMapSmoothCoastInDirection(_height_map.size_x - 1, y, -1, 0);
00630 }
00631 }
00632
00640 static void HeightMapSmoothSlopes(height_t dh_max)
00641 {
00642 int x, y;
00643 for (y = 1; y <= (int)_height_map.size_y; y++) {
00644 for (x = 1; x <= (int)_height_map.size_x; x++) {
00645 height_t h_max = min(HeightMapXY(x - 1, y), HeightMapXY(x, y - 1)) + dh_max;
00646 if (HeightMapXY(x, y) > h_max) HeightMapXY(x, y) = h_max;
00647 }
00648 }
00649 for (y = _height_map.size_y - 1; y >= 0; y--) {
00650 for (x = _height_map.size_x - 1; x >= 0; x--) {
00651 height_t h_max = min(HeightMapXY(x + 1, y), HeightMapXY(x, y + 1)) + dh_max;
00652 if (HeightMapXY(x, y) > h_max) HeightMapXY(x, y) = h_max;
00653 }
00654 }
00655 }
00656
00662 static void HeightMapNormalize()
00663 {
00664 const amplitude_t water_percent = _water_percent[_opt.diff.quantity_sea_lakes];
00665 const height_t h_max_new = I2H(_max_height[_opt.diff.terrain_type]);
00666 const height_t roughness = 7 + 3 * _patches.tgen_smoothness;
00667
00668 HeightMapAdjustWaterLevel(water_percent, h_max_new);
00669
00670 HeightMapCoastLines();
00671 HeightMapSmoothSlopes(roughness);
00672
00673 HeightMapSmoothCoasts();
00674 HeightMapSmoothSlopes(roughness);
00675
00676 HeightMapSineTransform(12, h_max_new);
00677 HeightMapSmoothSlopes(16);
00678 }
00679
00680 static inline int perlin_landXY(uint x, uint y)
00681 {
00682 return HeightMapXY(x, y);
00683 }
00684
00685
00686
00687 static const double _perlin_p_values[][7] = {
00688 { 0.35, 0.35, 0.35, 0.35, 0.35, 0.25, 0.539 },
00689 { 0.45, 0.55, 0.45, 0.45, 0.35, 0.25, 0.89 },
00690 { 0.85, 0.80, 0.70, 0.45, 0.45, 0.35, 1.825 },
00691 { 0.95, 0.85, 0.80, 0.55, 0.55, 0.45, 2.245 }
00692 };
00693
00701 static double int_noise(const long x, const long y, const int prime)
00702 {
00703 long n = x + y * prime + _patches.generation_seed;
00704
00705 n = (n << 13) ^ n;
00706
00707
00708 return 1.0 - (double)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0;
00709 }
00710
00711
00718 static double smoothed_noise(const int x, const int y, const int prime)
00719 {
00720 #if 0
00721
00722 const double sides = int_noise(x - 1, y) + int_noise(x + 1, y) + int_noise(x, y - 1) + int_noise(x, y + 1);
00723 const double center = int_noise(x, y);
00724 return (sides + sides + center * 4) / 8.0;
00725 #endif
00726
00727
00728 return int_noise(x, y, prime);
00729 }
00730
00731
00735 static inline double linear_interpolate(const double a, const double b, const double x)
00736 {
00737 return a + x * (b - a);
00738 }
00739
00740
00745 static double interpolated_noise(const double x, const double y, const int prime)
00746 {
00747 const int integer_X = (int)x;
00748 const int integer_Y = (int)y;
00749
00750 const double fractional_X = x - (double)integer_X;
00751 const double fractional_Y = y - (double)integer_Y;
00752
00753 const double v1 = smoothed_noise(integer_X, integer_Y, prime);
00754 const double v2 = smoothed_noise(integer_X + 1, integer_Y, prime);
00755 const double v3 = smoothed_noise(integer_X, integer_Y + 1, prime);
00756 const double v4 = smoothed_noise(integer_X + 1, integer_Y + 1, prime);
00757
00758 const double i1 = linear_interpolate(v1, v2, fractional_X);
00759 const double i2 = linear_interpolate(v3, v4, fractional_X);
00760
00761 return linear_interpolate(i1, i2, fractional_Y);
00762 }
00763
00764
00771 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime)
00772 {
00773 double total = 0.0;
00774 int i;
00775
00776 for (i = 0; i < 6; i++) {
00777 const double frequency = (double)(1 << i);
00778 const double amplitude = pow(p, (double)i);
00779
00780 total += interpolated_noise((x * frequency) / 64.0, (y * frequency) / 64.0, prime) * amplitude;
00781 }
00782
00783 return total;
00784 }
00785
00786
00788 static void TgenSetTileHeight(TileIndex tile, int height)
00789 {
00790 SetTileHeight(tile, height);
00791 MakeClear(tile, CLEAR_GRASS, 3);
00792 }
00793
00801 void GenerateTerrainPerlin()
00802 {
00803 uint x, y;
00804
00805 if (!AllocHeightMap()) return;
00806 GenerateWorldSetAbortCallback(FreeHeightMap);
00807
00808 HeightMapGenerate();
00809
00810 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00811
00812 HeightMapNormalize();
00813
00814 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00815
00816
00817 for (y = 2; y < _height_map.size_y - 2; y++) {
00818 for (x = 2; x < _height_map.size_x - 2; x++) {
00819 int height = H2I(HeightMapXY(x, y));
00820 if (height < 0) height = 0;
00821 if (height > 15) height = 15;
00822 TgenSetTileHeight(TileXY(x, y), height);
00823 }
00824 }
00825
00826 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00827
00828
00829 for (y = 0; y < _height_map.size_y - 1; y++) MakeVoid(_height_map.size_x * y + _height_map.size_x - 1);
00830 for (x = 0; x < _height_map.size_x; x++) MakeVoid(_height_map.size_x * y + x);
00831
00832 FreeHeightMap();
00833 GenerateWorldSetAbortCallback(NULL);
00834 }