00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include <math.h>
00014 #include "clear_map.h"
00015 #include "void_map.h"
00016 #include "genworld.h"
00017 #include "core/alloc_func.hpp"
00018 #include "core/random_func.hpp"
00019 #include "landscape_type.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
00183 inline height_t &height(uint x, uint y)
00184 {
00185 return h[x + y * dim_x];
00186 }
00187 };
00188
00190 static HeightMap _height_map = {NULL, 0, 0, 0, 0};
00191
00193 #define I2H(i) ((i) << height_decimal_bits)
00194
00195 #define H2I(i) ((i) >> height_decimal_bits)
00196
00198 #define I2A(i) ((i) << amplitude_decimal_bits)
00199
00200 #define A2I(i) ((i) >> amplitude_decimal_bits)
00201
00203 #define A2H(a) ((a) >> (amplitude_decimal_bits - height_decimal_bits))
00204
00205
00207 #define FOR_ALL_TILES_IN_HEIGHT(h) for (h = _height_map.h; h < &_height_map.h[_height_map.total_size]; h++)
00208
00210 static const int TGP_FREQUENCY_MAX = 6;
00211
00214 static const amplitude_t _amplitudes_by_smoothness_and_frequency[4][TGP_FREQUENCY_MAX + 1] = {
00215
00216
00217 {16000, 5600, 1968, 688, 240, 16, 16},
00218
00219 {16000, 16000, 6448, 3200, 1024, 128, 16},
00220
00221 {16000, 19200, 12800, 8000, 3200, 256, 64},
00222
00223 {24000, 16000, 19200, 16000, 8000, 512, 320},
00224 };
00225
00227 static const amplitude_t _water_percent[4] = {20, 80, 250, 400};
00228
00230 static const int8 _max_height[4] = {
00231 6,
00232 9,
00233 12,
00234 15
00235 };
00236
00242 static inline bool IsValidXY(uint x, uint y)
00243 {
00244 return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y;
00245 }
00246
00247
00252 static inline bool AllocHeightMap()
00253 {
00254 height_t *h;
00255
00256 _height_map.size_x = MapSizeX();
00257 _height_map.size_y = MapSizeY();
00258
00259
00260 _height_map.total_size = (_height_map.size_x + 1) * (_height_map.size_y + 1);
00261 _height_map.dim_x = _height_map.size_x + 1;
00262 _height_map.h = CallocT<height_t>(_height_map.total_size);
00263
00264
00265 FOR_ALL_TILES_IN_HEIGHT(h) *h = _invalid_height;
00266
00267 return true;
00268 }
00269
00271 static inline void FreeHeightMap()
00272 {
00273 if (_height_map.h == NULL) return;
00274 free(_height_map.h);
00275 _height_map.h = NULL;
00276 }
00277
00283 static inline height_t RandomHeight(amplitude_t rMax)
00284 {
00285 amplitude_t ra = (Random() << 16) | (Random() & 0x0000FFFF);
00286 height_t rh;
00287
00288 rh = A2H(ra % (2 * rMax + 1) - rMax);
00289 return rh;
00290 }
00291
00310 static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
00311 {
00312 uint size_min = min(_height_map.size_x, _height_map.size_y);
00313 uint step = size_min >> log_frequency;
00314 uint x, y;
00315
00316
00317 assert(_height_map.h != NULL);
00318
00319
00320 if (step == 0) return false;
00321
00322 if (log_frequency == 0) {
00323
00324 for (y = 0; y <= _height_map.size_y; y += step) {
00325 for (x = 0; x <= _height_map.size_x; x += step) {
00326 height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0;
00327 _height_map.height(x, y) = height;
00328 }
00329 }
00330 return true;
00331 }
00332
00333
00334
00335 for (y = 0; y <= _height_map.size_y; y += 2 * step) {
00336 for (x = 0; x < _height_map.size_x; x += 2 * step) {
00337 height_t h00 = _height_map.height(x + 0 * step, y);
00338 height_t h02 = _height_map.height(x + 2 * step, y);
00339 height_t h01 = (h00 + h02) / 2;
00340 _height_map.height(x + 1 * step, y) = h01;
00341 }
00342 }
00343
00344
00345 for (y = 0; y < _height_map.size_y; y += 2 * step) {
00346 for (x = 0; x <= _height_map.size_x; x += step) {
00347 height_t h00 = _height_map.height(x, y + 0 * step);
00348 height_t h20 = _height_map.height(x, y + 2 * step);
00349 height_t h10 = (h00 + h20) / 2;
00350 _height_map.height(x, y + 1 * step) = h10;
00351 }
00352 }
00353
00354
00355 for (y = 0; y <= _height_map.size_y; y += step) {
00356 for (x = 0; x <= _height_map.size_x; x += step) {
00357 _height_map.height(x, y) += RandomHeight(amplitude);
00358 }
00359 }
00360
00361 return (step > 1);
00362 }
00363
00365 static void HeightMapGenerate()
00366 {
00367 uint size_min = min(_height_map.size_x, _height_map.size_y);
00368 uint iteration_round = 0;
00369 amplitude_t amplitude;
00370 bool continue_iteration;
00371 int log_size_min, log_frequency_min;
00372 int log_frequency;
00373
00374
00375 for (log_size_min = TGP_FREQUENCY_MAX; (1U << log_size_min) < size_min; log_size_min++) { }
00376 log_frequency_min = log_size_min - TGP_FREQUENCY_MAX;
00377
00378
00379 assert(log_frequency_min >= 0);
00380
00381
00382 do {
00383 log_frequency = iteration_round - log_frequency_min;
00384 if (log_frequency >= 0) {
00385
00386 assert(log_frequency <= TGP_FREQUENCY_MAX);
00387 amplitude = _amplitudes_by_smoothness_and_frequency[_settings_game.game_creation.tgen_smoothness][log_frequency];
00388 } else {
00389
00390 amplitude = 0;
00391 }
00392 continue_iteration = ApplyNoise(iteration_round, amplitude);
00393 iteration_round++;
00394 } while (continue_iteration);
00395 assert(log_frequency == TGP_FREQUENCY_MAX);
00396 }
00397
00399 static void HeightMapGetMinMaxAvg(height_t *min_ptr, height_t *max_ptr, height_t *avg_ptr)
00400 {
00401 height_t h_min, h_max, h_avg, *h;
00402 int64 h_accu = 0;
00403 h_min = h_max = _height_map.height(0, 0);
00404
00405
00406 FOR_ALL_TILES_IN_HEIGHT(h) {
00407 if (*h < h_min) h_min = *h;
00408 if (*h > h_max) h_max = *h;
00409 h_accu += *h;
00410 }
00411
00412
00413 h_avg = (height_t)(h_accu / (_height_map.size_x * _height_map.size_y));
00414
00415
00416 if (min_ptr != NULL) *min_ptr = h_min;
00417 if (max_ptr != NULL) *max_ptr = h_max;
00418 if (avg_ptr != NULL) *avg_ptr = h_avg;
00419 }
00420
00422 static int *HeightMapMakeHistogram(height_t h_min, height_t h_max, int *hist_buf)
00423 {
00424 int *hist = hist_buf - h_min;
00425 height_t *h;
00426
00427
00428 FOR_ALL_TILES_IN_HEIGHT(h) {
00429 assert(*h >= h_min);
00430 assert(*h <= h_max);
00431 hist[*h]++;
00432 }
00433 return hist;
00434 }
00435
00437 static void HeightMapSineTransform(height_t h_min, height_t h_max)
00438 {
00439 height_t *h;
00440
00441 FOR_ALL_TILES_IN_HEIGHT(h) {
00442 double fheight;
00443
00444 if (*h < h_min) continue;
00445
00446
00447 fheight = (double)(*h - h_min) / (double)(h_max - h_min);
00448
00449 switch (_settings_game.game_creation.landscape) {
00450 case LT_TOYLAND:
00451 case LT_TEMPERATE:
00452
00453 fheight = 2 * fheight - 1;
00454
00455 fheight = sin(fheight * M_PI_2);
00456
00457 fheight = 0.5 * (fheight + 1);
00458 break;
00459
00460 case LT_ARCTIC:
00461 {
00462
00463
00464 double sine_upper_limit = 0.75;
00465 double linear_compression = 2;
00466 if (fheight >= sine_upper_limit) {
00467
00468 fheight = 1.0 - (1.0 - fheight) / linear_compression;
00469 } else {
00470 double m = 1.0 - (1.0 - sine_upper_limit) / linear_compression;
00471
00472 fheight = 2.0 * fheight / sine_upper_limit - 1.0;
00473
00474 fheight = sin(fheight * M_PI_2);
00475
00476 fheight = 0.5 * (fheight + 1.0) * m;
00477 }
00478 }
00479 break;
00480
00481 case LT_TROPIC:
00482 {
00483
00484
00485 double sine_lower_limit = 0.5;
00486 double linear_compression = 2;
00487 if (fheight <= sine_lower_limit) {
00488
00489 fheight = fheight / linear_compression;
00490 } else {
00491 double m = sine_lower_limit / linear_compression;
00492
00493 fheight = 2.0 * ((fheight - sine_lower_limit) / (1.0 - sine_lower_limit)) - 1.0;
00494
00495 fheight = sin(fheight * M_PI_2);
00496
00497 fheight = 0.5 * ((1.0 - m) * fheight + (1.0 + m));
00498 }
00499 }
00500 break;
00501
00502 default:
00503 NOT_REACHED();
00504 break;
00505 }
00506
00507 *h = (height_t)(fheight * (h_max - h_min) + h_min);
00508 if (*h < 0) *h = I2H(0);
00509 if (*h >= h_max) *h = h_max - 1;
00510 }
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 struct control_point_t {
00531 height_t x;
00532 height_t y;
00533 };
00534
00535 struct control_point_list_t {
00536 size_t length;
00537 const control_point_t *list;
00538 };
00539
00540 static const control_point_t _curve_map_1[] = {
00541 { 0, 0 }, { 48, 24 }, { 192, 32 }, { 240, 96 }
00542 };
00543
00544 static const control_point_t _curve_map_2[] = {
00545 { 0, 0 }, { 16, 24 }, { 128, 32 }, { 192, 64 }, { 240, 144 }
00546 };
00547
00548 static const control_point_t _curve_map_3[] = {
00549 { 0, 0 }, { 16, 24 }, { 128, 64 }, { 192, 144 }, { 240, 192 }
00550 };
00551
00552 static const control_point_t _curve_map_4[] = {
00553 { 0, 0 }, { 16, 24 }, { 96, 72 }, { 160, 192 }, { 220, 239 }, { 240, 239 }
00554 };
00555
00556 static const control_point_list_t _curve_maps[] = {
00557 { lengthof(_curve_map_1), _curve_map_1 },
00558 { lengthof(_curve_map_2), _curve_map_2 },
00559 { lengthof(_curve_map_3), _curve_map_3 },
00560 { lengthof(_curve_map_4), _curve_map_4 },
00561 };
00562
00563 static void HeightMapCurves(uint level)
00564 {
00565 height_t ht[lengthof(_curve_maps)];
00566
00567
00568 uint sx = Clamp(1 << level, 2, 32);
00569 uint sy = Clamp(1 << level, 2, 32);
00570 byte *c = (byte *)alloca(sx * sy);
00571
00572 for (uint i = 0; i < sx * sy; i++) {
00573 c[i] = Random() % lengthof(_curve_maps);
00574 }
00575
00576
00577 for (uint x = 0; x < _height_map.size_x; x++) {
00578
00579
00580 float fx = (float)(sx * x) / _height_map.size_x + 0.5f;
00581 uint x1 = (uint)fx;
00582 uint x2 = x1;
00583 float xr = 2.0f * (fx - x1) - 1.0f;
00584 xr = sin(xr * M_PI_2);
00585 xr = sin(xr * M_PI_2);
00586 xr = 0.5f * (xr + 1.0f);
00587 float xri = 1.0f - xr;
00588
00589 if (x1 > 0) {
00590 x1--;
00591 if (x2 >= sx) x2--;
00592 }
00593
00594 for (uint y = 0; y < _height_map.size_y; y++) {
00595
00596
00597 float fy = (float)(sy * y) / _height_map.size_y + 0.5f;
00598 uint y1 = (uint)fy;
00599 uint y2 = y1;
00600 float yr = 2.0f * (fy - y1) - 1.0f;
00601 yr = sin(yr * M_PI_2);
00602 yr = sin(yr * M_PI_2);
00603 yr = 0.5f * (yr + 1.0f);
00604 float yri = 1.0f - yr;
00605
00606 if (y1 > 0) {
00607 y1--;
00608 if (y2 >= sy) y2--;
00609 }
00610
00611 uint corner_a = c[x1 + sx * y1];
00612 uint corner_b = c[x1 + sx * y2];
00613 uint corner_c = c[x2 + sx * y1];
00614 uint corner_d = c[x2 + sx * y2];
00615
00616
00617
00618 uint corner_bits = 0;
00619 corner_bits |= 1 << corner_a;
00620 corner_bits |= 1 << corner_b;
00621 corner_bits |= 1 << corner_c;
00622 corner_bits |= 1 << corner_d;
00623
00624 height_t *h = &_height_map.height(x, y);
00625
00626
00627 for (uint t = 0; t < lengthof(_curve_maps); t++) {
00628 if (!HasBit(corner_bits, t)) continue;
00629
00630 const control_point_t *cm = _curve_maps[t].list;
00631 for (uint i = 0; i < _curve_maps[t].length - 1; i++) {
00632 const control_point_t &p1 = cm[i];
00633 const control_point_t &p2 = cm[i + 1];
00634
00635 if (*h >= p1.x && *h < p2.x) {
00636 ht[t] = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
00637 break;
00638 }
00639 }
00640 }
00641
00642
00643 *h = (height_t)((ht[corner_a] * yri + ht[corner_b] * yr) * xri + (ht[corner_c] * yri + ht[corner_d] * yr) * xr);
00644 }
00645 }
00646 }
00647
00649 static void HeightMapAdjustWaterLevel(amplitude_t water_percent, height_t h_max_new)
00650 {
00651 height_t h_min, h_max, h_avg, h_water_level;
00652 int water_tiles, desired_water_tiles;
00653 height_t *h;
00654 int *hist;
00655
00656 HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg);
00657
00658
00659 int *hist_buf = CallocT<int>(h_max - h_min + 1);
00660
00661 hist = HeightMapMakeHistogram(h_min, h_max, hist_buf);
00662
00663
00664 desired_water_tiles = (int)(((int64)water_percent) * (int64)(_height_map.size_x * _height_map.size_y)) >> amplitude_decimal_bits;
00665
00666
00667 for (h_water_level = h_min, water_tiles = 0; h_water_level < h_max; h_water_level++) {
00668 water_tiles += hist[h_water_level];
00669 if (water_tiles >= desired_water_tiles) break;
00670 }
00671
00672
00673
00674
00675
00676
00677
00678 FOR_ALL_TILES_IN_HEIGHT(h) {
00679
00680 *h = (height_t)(((int)h_max_new) * (*h - h_water_level) / (h_max - h_water_level)) + I2H(1);
00681
00682 if (*h < 0) *h = I2H(0);
00683 if (*h >= h_max_new) *h = h_max_new - 1;
00684 }
00685
00686 free(hist_buf);
00687 }
00688
00689 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime);
00690
00711 static void HeightMapCoastLines(uint8 water_borders)
00712 {
00713 int smallest_size = min(_settings_game.game_creation.map_x, _settings_game.game_creation.map_y);
00714 const int margin = 4;
00715 uint y, x;
00716 double max_x;
00717 double max_y;
00718
00719
00720 for (y = 0; y <= _height_map.size_y; y++) {
00721 if (HasBit(water_borders, BORDER_NE)) {
00722
00723 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);
00724 max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
00725 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00726 for (x = 0; x < max_x; x++) {
00727 _height_map.height(x, y) = 0;
00728 }
00729 }
00730
00731 if (HasBit(water_borders, BORDER_SW)) {
00732
00733 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);
00734 max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
00735 if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
00736 for (x = _height_map.size_x; x > (_height_map.size_x - 1 - max_x); x--) {
00737 _height_map.height(x, y) = 0;
00738 }
00739 }
00740 }
00741
00742
00743 for (x = 0; x <= _height_map.size_x; x++) {
00744 if (HasBit(water_borders, BORDER_NW)) {
00745
00746 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);
00747 max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
00748 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00749 for (y = 0; y < max_y; y++) {
00750 _height_map.height(x, y) = 0;
00751 }
00752 }
00753
00754 if (HasBit(water_borders, BORDER_SE)) {
00755
00756 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);
00757 max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
00758 if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
00759 for (y = _height_map.size_y; y > (_height_map.size_y - 1 - max_y); y--) {
00760 _height_map.height(x, y) = 0;
00761 }
00762 }
00763 }
00764 }
00765
00767 static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int dir_y)
00768 {
00769 const int max_coast_dist_from_edge = 35;
00770 const int max_coast_Smooth_depth = 35;
00771
00772 int x, y;
00773 int ed;
00774 int depth;
00775
00776 height_t h_prev = 16;
00777 height_t h;
00778
00779 assert(IsValidXY(org_x, org_y));
00780
00781
00782 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++) {
00783
00784 if (_height_map.height(x, y) > 15) break;
00785
00786
00787 if (IsValidXY(x + dir_y, y + dir_x) && _height_map.height(x + dir_y, y + dir_x) > 0) break;
00788
00789
00790 if (IsValidXY(x - dir_y, y - dir_x) && _height_map.height(x - dir_y, y - dir_x) > 0) break;
00791 }
00792
00793
00794
00795 for (depth = 0; IsValidXY(x, y) && depth <= max_coast_Smooth_depth; depth++, x += dir_x, y += dir_y) {
00796 h = _height_map.height(x, y);
00797 h = min(h, h_prev + (4 + depth));
00798 _height_map.height(x, y) = h;
00799 h_prev = h;
00800 }
00801 }
00802
00804 static void HeightMapSmoothCoasts(uint8 water_borders)
00805 {
00806 uint x, y;
00807
00808 for (x = 0; x < _height_map.size_x; x++) {
00809 if (HasBit(water_borders, BORDER_NW)) HeightMapSmoothCoastInDirection(x, 0, 0, 1);
00810 if (HasBit(water_borders, BORDER_SE)) HeightMapSmoothCoastInDirection(x, _height_map.size_y - 1, 0, -1);
00811 }
00812
00813 for (y = 0; y < _height_map.size_y; y++) {
00814 if (HasBit(water_borders, BORDER_NE)) HeightMapSmoothCoastInDirection(0, y, 1, 0);
00815 if (HasBit(water_borders, BORDER_SW)) HeightMapSmoothCoastInDirection(_height_map.size_x - 1, y, -1, 0);
00816 }
00817 }
00818
00826 static void HeightMapSmoothSlopes(height_t dh_max)
00827 {
00828 int x, y;
00829 for (y = 0; y <= (int)_height_map.size_y; y++) {
00830 for (x = 0; x <= (int)_height_map.size_x; x++) {
00831 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;
00832 if (_height_map.height(x, y) > h_max) _height_map.height(x, y) = h_max;
00833 }
00834 }
00835 for (y = _height_map.size_y; y >= 0; y--) {
00836 for (x = _height_map.size_x; x >= 0; x--) {
00837 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;
00838 if (_height_map.height(x, y) > h_max) _height_map.height(x, y) = h_max;
00839 }
00840 }
00841 }
00842
00848 static void HeightMapNormalize()
00849 {
00850 const amplitude_t water_percent = _water_percent[_settings_game.difficulty.quantity_sea_lakes];
00851 const height_t h_max_new = I2H(_max_height[_settings_game.difficulty.terrain_type]);
00852 const height_t roughness = 7 + 3 * _settings_game.game_creation.tgen_smoothness;
00853
00854 HeightMapAdjustWaterLevel(water_percent, h_max_new);
00855
00856 byte water_borders = _settings_game.construction.freeform_edges ? _settings_game.game_creation.water_borders : 0xF;
00857 if (water_borders == BORDERS_RANDOM) water_borders = GB(Random(), 0, 4);
00858
00859 HeightMapCoastLines(water_borders);
00860 HeightMapSmoothSlopes(roughness);
00861
00862 HeightMapSmoothCoasts(water_borders);
00863 HeightMapSmoothSlopes(roughness);
00864
00865 HeightMapSineTransform(12, h_max_new);
00866
00867 if (_settings_game.game_creation.variety > 0) {
00868 HeightMapCurves(_settings_game.game_creation.variety);
00869 }
00870
00871 HeightMapSmoothSlopes(16);
00872 }
00873
00881 static double int_noise(const long x, const long y, const int prime)
00882 {
00883 long n = x + y * prime + _settings_game.game_creation.generation_seed;
00884
00885 n = (n << 13) ^ n;
00886
00887
00888 return 1.0 - (double)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0;
00889 }
00890
00891
00898 static double smoothed_noise(const int x, const int y, const int prime)
00899 {
00900 #if 0
00901
00902 const double sides = int_noise(x - 1, y) + int_noise(x + 1, y) + int_noise(x, y - 1) + int_noise(x, y + 1);
00903 const double center = int_noise(x, y);
00904 return (sides + sides + center * 4) / 8.0;
00905 #endif
00906
00907
00908 return int_noise(x, y, prime);
00909 }
00910
00911
00915 static inline double linear_interpolate(const double a, const double b, const double x)
00916 {
00917 return a + x * (b - a);
00918 }
00919
00920
00925 static double interpolated_noise(const double x, const double y, const int prime)
00926 {
00927 const int integer_X = (int)x;
00928 const int integer_Y = (int)y;
00929
00930 const double fractional_X = x - (double)integer_X;
00931 const double fractional_Y = y - (double)integer_Y;
00932
00933 const double v1 = smoothed_noise(integer_X, integer_Y, prime);
00934 const double v2 = smoothed_noise(integer_X + 1, integer_Y, prime);
00935 const double v3 = smoothed_noise(integer_X, integer_Y + 1, prime);
00936 const double v4 = smoothed_noise(integer_X + 1, integer_Y + 1, prime);
00937
00938 const double i1 = linear_interpolate(v1, v2, fractional_X);
00939 const double i2 = linear_interpolate(v3, v4, fractional_X);
00940
00941 return linear_interpolate(i1, i2, fractional_Y);
00942 }
00943
00944
00951 static double perlin_coast_noise_2D(const double x, const double y, const double p, const int prime)
00952 {
00953 double total = 0.0;
00954 int i;
00955
00956 for (i = 0; i < 6; i++) {
00957 const double frequency = (double)(1 << i);
00958 const double amplitude = pow(p, (double)i);
00959
00960 total += interpolated_noise((x * frequency) / 64.0, (y * frequency) / 64.0, prime) * amplitude;
00961 }
00962
00963 return total;
00964 }
00965
00966
00968 static void TgenSetTileHeight(TileIndex tile, int height)
00969 {
00970 SetTileHeight(tile, height);
00971
00972
00973 if (TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY() &&
00974 (!_settings_game.construction.freeform_edges || (TileX(tile) != 0 && TileY(tile) != 0))) {
00975 MakeClear(tile, CLEAR_GRASS, 3);
00976 }
00977 }
00978
00986 void GenerateTerrainPerlin()
00987 {
00988 uint x, y;
00989
00990 if (!AllocHeightMap()) return;
00991 GenerateWorldSetAbortCallback(FreeHeightMap);
00992
00993 HeightMapGenerate();
00994
00995 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00996
00997 HeightMapNormalize();
00998
00999 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
01000
01001
01002 if (_settings_game.construction.freeform_edges) {
01003 for (y = 0; y < _height_map.size_y - 1; y++) MakeVoid(_height_map.size_x * y);
01004 for (x = 0; x < _height_map.size_x; x++) MakeVoid(x);
01005 }
01006
01007
01008 for (y = 0; y < _height_map.size_y; y++) {
01009 for (x = 0; x < _height_map.size_x; x++) {
01010 int height = H2I(_height_map.height(x, y));
01011 if (height < 0) height = 0;
01012 if (height > 15) height = 15;
01013 TgenSetTileHeight(TileXY(x, y), height);
01014 }
01015 }
01016
01017 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
01018
01019 FreeHeightMap();
01020 GenerateWorldSetAbortCallback(NULL);
01021 }