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