hedgewars/uLandGenPerlin.pas
branchsdl2transition
changeset 11362 ed5a6478e710
parent 10702 528d899443ab
child 15011 bea068dd9356
equal deleted inserted replaced
11361:31570b766315 11362:ed5a6478e710
       
     1 {$INCLUDE "options.inc"}
       
     2 
       
     3 unit uLandGenPerlin;
       
     4 interface
       
     5 
       
     6 procedure GenPerlin;
       
     7 
       
     8 implementation
       
     9 uses uVariables
       
    10     , uConsts
       
    11     , uRandom
       
    12     , uLandOutline // FillLand
       
    13     , uUtils
       
    14     ;
       
    15 
       
    16 var p: array[0..511] of LongInt;
       
    17 
       
    18 const fadear: array[byte] of LongInt =
       
    19 (0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 6, 7, 9, 10, 12,
       
    20 14, 17, 19, 22, 25, 29, 32, 36, 40, 45, 49, 54, 60, 65, 71,
       
    21 77, 84, 91, 98, 105, 113, 121, 130, 139, 148, 158, 167, 178,
       
    22 188, 199, 211, 222, 234, 247, 259, 273, 286, 300, 314, 329, 344,
       
    23 359, 374, 390, 407, 424, 441, 458, 476, 494, 512, 531, 550,
       
    24 570, 589, 609, 630, 651, 672, 693, 715, 737, 759, 782, 805, 828,
       
    25 851, 875, 899, 923, 948, 973, 998, 1023, 1049, 1074, 1100, 1127,
       
    26 1153, 1180, 1207, 1234, 1261, 1289, 1316, 1344, 1372, 1400, 1429,
       
    27 1457, 1486, 1515, 1543, 1572, 1602, 1631, 1660, 1690, 1719, 1749,
       
    28 1778, 1808, 1838, 1868, 1898, 1928, 1958, 1988, 2018, 2048, 2077,
       
    29 2107, 2137, 2167, 2197, 2227, 2257, 2287, 2317, 2346, 2376, 2405,
       
    30 2435, 2464, 2493, 2523, 2552, 2580, 2609, 2638, 2666, 2695, 2723,
       
    31 2751, 2779, 2806, 2834, 2861, 2888, 2915, 2942, 2968, 2995, 3021,
       
    32 3046, 3072, 3097, 3122, 3147, 3172, 3196, 3220, 3244, 3267, 3290,
       
    33 3313, 3336, 3358, 3380, 3402, 3423, 3444, 3465, 3486, 3506, 3525,
       
    34 3545, 3564, 3583, 3601, 3619, 3637, 3654, 3672, 3688, 3705, 3721,
       
    35 3736, 3751, 3766, 3781, 3795, 3809, 3822, 3836, 3848, 3861, 3873,
       
    36 3884, 3896, 3907, 3917, 3928, 3937, 3947, 3956, 3965, 3974, 3982,
       
    37 3990, 3997, 4004, 4011, 4018, 4024, 4030, 4035, 4041, 4046, 4050,
       
    38 4055, 4059, 4063, 4066, 4070, 4073, 4076, 4078, 4081, 4083, 4085,
       
    39 4086, 4088, 4089, 4091, 4092, 4092, 4093, 4094, 4094, 4095, 4095,
       
    40 4095, 4095, 4095, 4095, 4095);
       
    41 
       
    42 function fade(t: LongInt) : LongInt; inline;
       
    43 var t0, t1: LongInt;
       
    44 begin
       
    45     t0:= fadear[t shr 8];
       
    46 
       
    47     if t0 = fadear[255] then
       
    48         t1:= t0
       
    49     else
       
    50         t1:= fadear[t shr 8 + 1];
       
    51 
       
    52     fade:= t0 + ((t and 255) * (t1 - t0) shr 8)
       
    53 end;
       
    54 
       
    55 
       
    56 function lerp(t, a, b: LongInt) : LongInt; inline;
       
    57 begin
       
    58     lerp:= a + ((Int64(b) - a) * t shr 12)
       
    59 end;
       
    60 
       
    61 
       
    62 function grad(hash, x, y: LongInt) : LongInt; inline;
       
    63 var h, v, u: LongInt;
       
    64 begin
       
    65     h:= hash and 15;
       
    66     if h < 8 then u:= x else u:= y;
       
    67     if h < 4 then v:= y else
       
    68         if (h = 12) or (h = 14) then v:= x else v:= 0;
       
    69 
       
    70     if (h and 1) <> 0 then u:= -u;
       
    71     if (h and 2) <> 0 then v:= -v;
       
    72 
       
    73     grad:= u + v
       
    74 end;
       
    75 
       
    76 
       
    77 function inoise(x, y: LongInt) : LongInt; inline;
       
    78 const N = $10000;
       
    79 var xx, yy, u, v, A, AA, AB, B, BA, BB: LongInt;
       
    80 begin
       
    81     xx:= (x shr 16) and 255;
       
    82     yy:= (y shr 16) and 255;
       
    83 
       
    84     x:= x and $FFFF;
       
    85     y:= y and $FFFF;
       
    86 
       
    87     u:= fade(x);
       
    88     v:= fade(y);
       
    89 
       
    90     A:= p[xx    ] + yy; AA:= p[A]; AB:= p[A + 1];
       
    91     B:= p[xx + 1] + yy; BA:= p[B]; BB:= p[B + 1];
       
    92 
       
    93     inoise:=
       
    94             lerp(v, lerp(u, grad(p[AA  ], x   , y  ),
       
    95                             grad(p[BA  ], x-N , y  )),
       
    96                     lerp(u, grad(p[AB  ], x   , y-N),
       
    97                             grad(p[BB  ], x-N , y-N)));
       
    98 end;
       
    99 
       
   100 procedure inoise_setup();
       
   101 var i, ii, t: Longword;
       
   102 begin
       
   103     for i:= 0 to 254 do
       
   104         p[i]:= i + 1;
       
   105     p[255]:= 0;
       
   106 
       
   107     for i:= 0 to 254 do
       
   108     begin
       
   109         ii:= GetRandom(256 - i) + i;
       
   110         t:= p[i];
       
   111         p[i]:= p[ii];
       
   112         p[ii]:= t
       
   113     end;
       
   114 
       
   115     for i:= 0 to 255 do
       
   116         p[256 + i]:= p[i];
       
   117 end;
       
   118 
       
   119 const width = 4096;
       
   120       height = 2048;
       
   121       minY = 500;
       
   122 
       
   123     //bottomPlateHeight = 90;
       
   124     //bottomPlateMargin = 1200;
       
   125     margin = 200;
       
   126 
       
   127 procedure GenPerlin;
       
   128 var y, x, di, dj, r, param1, param2, rCutoff, detail: LongInt;
       
   129 var df: Int64;
       
   130 begin
       
   131     param1:= cTemplateFilter div 3;
       
   132     param2:= cTemplateFilter mod 3;
       
   133     rCutoff:= min(max((26-cFeatureSize)*4,15),85);
       
   134     detail:= (26-cFeatureSize)*16000+50000; // feature size is a slider from 1-25 at present. flip it for perlin
       
   135 
       
   136     df:= detail * (6 - param2 * 2);
       
   137 
       
   138     inoise_setup();
       
   139 
       
   140     for y:= minY to pred(height) do
       
   141     begin
       
   142         di:= df * y div height;
       
   143         for x:= 0 to pred(width) do
       
   144         begin
       
   145             dj:= df * x div width;
       
   146 
       
   147             r:= ((abs(inoise(di, dj)) + y*4) mod 65536 - (height - y) * 8) div 256;
       
   148 
       
   149             //r:= (abs(inoise(di, dj))) shr 8 and $ff;
       
   150             if (x < margin) or (x > width - margin) then r:= r - abs(x - width div 2) + width div 2 - margin; // fade on edges
       
   151 
       
   152             //r:= r - max(0, - abs(x - width div 2) + width * 2 div 100); // split vertically in the middle
       
   153             //r:= r + (trunc(1000 - sqrt(sqr(x - (width div 2)) * 4 + sqr(y - height * 5 div 4) * 22))) div 600 * 20; // ellipse
       
   154             //r:= r + 1 - ((abs(x - (width div 2)) + abs(y - height) * 2)) div 32; // manhattan length ellipse
       
   155 
       
   156             {
       
   157             if (y > height - bottomPlateHeight) and (x > bottomPlateMargin) and (x + bottomPlateMargin < width) then
       
   158             begin
       
   159                 dy:= (y - height + bottomPlateHeight);
       
   160                 r:= r + dy;
       
   161 
       
   162                 if x < bottomPlateMargin + bottomPlateHeight then
       
   163                     r:= r + (x - bottomPlateMargin - bottomPlateHeight)
       
   164                 else
       
   165                 if x + bottomPlateMargin + bottomPlateHeight > width then
       
   166                     r:= r - (x - width + bottomPlateMargin + bottomPlateHeight);
       
   167             end;
       
   168             }
       
   169 
       
   170             if r < rCutoff then
       
   171                 Land[y, x]:= 0
       
   172             else if param1 = 0 then
       
   173                 Land[y, x]:= lfObjMask
       
   174             else
       
   175                 Land[y, x]:= lfBasic
       
   176         end;
       
   177     end;
       
   178 
       
   179     if param1 = 0 then
       
   180         begin
       
   181         for x:= 0 to width do
       
   182             if Land[height - 1, x] = lfObjMask then FillLand(x, height - 1, 0, lfBasic);
       
   183 
       
   184         // strip all lfObjMask pixels
       
   185         for y:= minY to LAND_HEIGHT - 1 do
       
   186             for x:= 0 to LAND_WIDTH - 1 do
       
   187                 if Land[y, x] = lfObjMask then
       
   188                     Land[y, x]:= 0;
       
   189         end;
       
   190 
       
   191     leftX:= 0;
       
   192     rightX:= 4095;
       
   193     topY:= 0;
       
   194     hasBorder:= false;
       
   195 end;
       
   196 
       
   197 end.