PocketMine-MP  1.4 - API 1.10.0
 All Classes Namespaces Functions Variables Pages
Simplex.php
1 <?php
2 
3 /*
4  *
5  * ____ _ _ __ __ _ __ __ ____
6  * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7  * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8  * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9  * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * @author PocketMine Team
17  * @link http://www.pocketmine.net/
18  *
19  *
20 */
21 
22 namespace pocketmine\level\generator\noise;
23 
25 
33 class Simplex extends Perlin{
34  protected static $SQRT_3;
35  protected static $SQRT_5;
36  protected static $F2;
37  protected static $G2;
38  protected static $G22;
39  protected static $F3;
40  protected static $G3;
41  protected static $F4;
42  protected static $G4;
43  protected static $G42;
44  protected static $G43;
45  protected static $G44;
46  protected static $grad4 = [[0, 1, 1, 1], [0, 1, 1, -1], [0, 1, -1, 1], [0, 1, -1, -1],
47  [0, -1, 1, 1], [0, -1, 1, -1], [0, -1, -1, 1], [0, -1, -1, -1],
48  [1, 0, 1, 1], [1, 0, 1, -1], [1, 0, -1, 1], [1, 0, -1, -1],
49  [-1, 0, 1, 1], [-1, 0, 1, -1], [-1, 0, -1, 1], [-1, 0, -1, -1],
50  [1, 1, 0, 1], [1, 1, 0, -1], [1, -1, 0, 1], [1, -1, 0, -1],
51  [-1, 1, 0, 1], [-1, 1, 0, -1], [-1, -1, 0, 1], [-1, -1, 0, -1],
52  [1, 1, 1, 0], [1, 1, -1, 0], [1, -1, 1, 0], [1, -1, -1, 0],
53  [-1, 1, 1, 0], [-1, 1, -1, 0], [-1, -1, 1, 0], [-1, -1, -1, 0]];
54  protected static $simplex = [
55  [0, 1, 2, 3], [0, 1, 3, 2], [0, 0, 0, 0], [0, 2, 3, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 2, 3, 0],
56  [0, 2, 1, 3], [0, 0, 0, 0], [0, 3, 1, 2], [0, 3, 2, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 3, 2, 0],
57  [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0],
58  [1, 2, 0, 3], [0, 0, 0, 0], [1, 3, 0, 2], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [2, 3, 0, 1], [2, 3, 1, 0],
59  [1, 0, 2, 3], [1, 0, 3, 2], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [2, 0, 3, 1], [0, 0, 0, 0], [2, 1, 3, 0],
60  [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0],
61  [2, 0, 1, 3], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3, 0, 1, 2], [3, 0, 2, 1], [0, 0, 0, 0], [3, 1, 2, 0],
62  [2, 1, 0, 3], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3, 1, 0, 2], [0, 0, 0, 0], [3, 2, 0, 1], [3, 2, 1, 0]];
63  protected $offsetW;
64 
65 
66  public function __construct(Random $random, $octaves, $frequency, $amplitude){
67  parent::__construct($random, $octaves, $frequency, $amplitude);
68  $this->offsetW = $random->nextFloat() * 256;
69  self::$SQRT_3 = sqrt(3);
70  self::$SQRT_5 = sqrt(5);
71  self::$F2 = 0.5 * (self::$SQRT_3 - 1);
72  self::$G2 = (3 - self::$SQRT_3) / 6;
73  self::$G22 = self::$G2 * 2.0 - 1;
74  self::$F3 = 1.0 / 3.0;
75  self::$G3 = 1.0 / 6.0;
76  self::$F4 = (self::$SQRT_5 - 1.0) / 4.0;
77  self::$G4 = (5.0 - self::$SQRT_5) / 20.0;
78  self::$G42 = self::$G4 * 2.0;
79  self::$G43 = self::$G4 * 3.0;
80  self::$G44 = self::$G4 * 4.0 - 1.0;
81  }
82 
83  protected static function dot2D($g, $x, $y){
84  return $g[0] * $x + $g[1] * $y;
85  }
86 
87  protected static function dot3D($g, $x, $y, $z){
88  return $g[0] * $x + $g[1] * $y + $g[2] * $z;
89  }
90 
91  protected static function dot4D($g, $x, $y, $z, $w){
92  return $g[0] * $x + $g[1] * $y + $g[2] * $z + $g[3] * $w;
93  }
94 
95  public function getNoise3D($x, $y, $z){
96  $x += $this->offsetX;
97  $y += $this->offsetY;
98  $z += $this->offsetZ;
99 
100  // Skew the input space to determine which simplex cell we're in
101  $s = ($x + $y + $z) * self::$F3; // Very nice and simple skew factor for 3D
102  $i = (int) floor($x + $s);
103  $j = (int) floor($y + $s);
104  $k = (int) floor($z + $s);
105  $t = ($i + $j + $k) * self::$G3;
106  $X0 = $i - $t; // Unskew the cell origin back to (x,y,z) space
107  $Y0 = $j - $t;
108  $Z0 = $k - $t;
109  $x0 = $x - $X0; // The x,y,z distances from the cell origin
110  $y0 = $y - $Y0;
111  $z0 = $z - $Z0;
112 
113  // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
114 
115  // Determine which simplex we are in.
116  if($x0 >= $y0){
117  if($y0 >= $z0){
118  $i1 = 1;
119  $j1 = 0;
120  $k1 = 0;
121  $i2 = 1;
122  $j2 = 1;
123  $k2 = 0;
124  } // X Y Z order
125  elseif($x0 >= $z0){
126  $i1 = 1;
127  $j1 = 0;
128  $k1 = 0;
129  $i2 = 1;
130  $j2 = 0;
131  $k2 = 1;
132  } // X Z Y order
133  else{
134  $i1 = 0;
135  $j1 = 0;
136  $k1 = 1;
137  $i2 = 1;
138  $j2 = 0;
139  $k2 = 1;
140  }
141  // Z X Y order
142  }else{ // x0<y0
143  if($y0 < $z0){
144  $i1 = 0;
145  $j1 = 0;
146  $k1 = 1;
147  $i2 = 0;
148  $j2 = 1;
149  $k2 = 1;
150  } // Z Y X order
151  elseif($x0 < $z0){
152  $i1 = 0;
153  $j1 = 1;
154  $k1 = 0;
155  $i2 = 0;
156  $j2 = 1;
157  $k2 = 1;
158  } // Y Z X order
159  else{
160  $i1 = 0;
161  $j1 = 1;
162  $k1 = 0;
163  $i2 = 1;
164  $j2 = 1;
165  $k2 = 0;
166  }
167  // Y X Z order
168  }
169 
170  // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
171  // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
172  // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
173  // c = 1/6.
174  $x1 = $x0 - $i1 + self::$G3; // Offsets for second corner in (x,y,z) coords
175  $y1 = $y0 - $j1 + self::$G3;
176  $z1 = $z0 - $k1 + self::$G3;
177  $x2 = $x0 - $i2 + 2.0 * self::$G3; // Offsets for third corner in (x,y,z) coords
178  $y2 = $y0 - $j2 + 2.0 * self::$G3;
179  $z2 = $z0 - $k2 + 2.0 * self::$G3;
180  $x3 = $x0 - 1.0 + 3.0 * self::$G3; // Offsets for last corner in (x,y,z) coords
181  $y3 = $y0 - 1.0 + 3.0 * self::$G3;
182  $z3 = $z0 - 1.0 + 3.0 * self::$G3;
183 
184  // Work out the hashed gradient indices of the four simplex corners
185  $ii = $i & 255;
186  $jj = $j & 255;
187  $kk = $k & 255;
188  $gi0 = $this->perm[$ii + $this->perm[$jj + $this->perm[$kk]]] % 12;
189  $gi1 = $this->perm[$ii + $i1 + $this->perm[$jj + $j1 + $this->perm[$kk + $k1]]] % 12;
190  $gi2 = $this->perm[$ii + $i2 + $this->perm[$jj + $j2 + $this->perm[$kk + $k2]]] % 12;
191  $gi3 = $this->perm[$ii + 1 + $this->perm[$jj + 1 + $this->perm[$kk + 1]]] % 12;
192 
193  // Calculate the contribution from the four corners
194  $t0 = 0.6 - $x0 ** 2 - $y0 ** 2 - $z0 ** 2;
195  if($t0 < 0){
196  $n0 = 0.0;
197  }else{
198  $t0 **= 2;
199  $n0 = $t0 ** 2 * self::dot3D(self::$grad3[$gi0], $x0, $y0, $z0);
200  }
201 
202  $t1 = 0.6 - $x1 ** 2 - $y1 ** 2 - $z1 ** 2;
203  if($t1 < 0){
204  $n1 = 0.0;
205  }else{
206  $t1 **= 2;
207  $n1 = $t1 ** 2 * self::dot3D(self::$grad3[$gi1], $x1, $y1, $z1);
208  }
209 
210  $t2 = 0.6 - $x2 ** 2 - $y2 ** 2 - $z2 ** 2;
211  if($t2 < 0){
212  $n2 = 0.0;
213  }else{
214  $t2 **= 2;
215  $n2 = $t2 ** 2 * self::dot3D(self::$grad3[$gi2], $x2, $y2, $z2);
216  }
217 
218  $t3 = 0.6 - $x3 ** 2 - $y3 ** 2 - $z3 ** 2;
219  if($t3 < 0){
220  $n3 = 0.0;
221  }else{
222  $t3 **= 2;
223  $n3 = $t3 ** 2 * self::dot3D(self::$grad3[$gi3], $x3, $y3, $z3);
224  }
225 
226  // Add contributions from each corner to get the noise value.
227  // The result is scaled to stay just inside [-1,1]
228  return 32.0 * ($n0 + $n1 + $n2 + $n3);
229  }
230 
231  public function getNoise2D($x, $y){
232  $x += $this->offsetX;
233  $y += $this->offsetY;
234 
235  // Skew the input space to determine which simplex cell we're in
236  $s = ($x + $y) * self::$F2; // Hairy factor for 2D
237  $i = (int) floor($x + $s);
238  $j = (int) floor($y + $s);
239  $t = ($i + $j) * self::$G2;
240  $X0 = $i - $t; // Unskew the cell origin back to (x,y) space
241  $Y0 = $j - $t;
242  $x0 = $x - $X0; // The x,y distances from the cell origin
243  $y0 = $y - $Y0;
244 
245  // For the 2D case, the simplex shape is an equilateral triangle.
246 
247  // Determine which simplex we are in.
248  if($x0 > $y0){
249  $i1 = 1;
250  $j1 = 0;
251  } // lower triangle, XY order: (0,0)->(1,0)->(1,1)
252  else{
253  $i1 = 0;
254  $j1 = 1;
255  }
256  // upper triangle, YX order: (0,0)->(0,1)->(1,1)
257 
258  // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
259  // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
260  // c = (3-sqrt(3))/6
261 
262  $x1 = $x0 - $i1 + self::$G2; // Offsets for middle corner in (x,y) unskewed coords
263  $y1 = $y0 - $j1 + self::$G2;
264  $x2 = $x0 + self::$G22; // Offsets for last corner in (x,y) unskewed coords
265  $y2 = $y0 + self::$G22;
266 
267  // Work out the hashed gradient indices of the three simplex corners
268  $ii = $i & 255;
269  $jj = $j & 255;
270  $gi0 = $this->perm[$ii + $this->perm[$jj]] % 12;
271  $gi1 = $this->perm[$ii + $i1 + $this->perm[$jj + $j1]] % 12;
272  $gi2 = $this->perm[$ii + 1 + $this->perm[$jj + 1]] % 12;
273 
274  $n = 0;
275 
276  // Calculate the contribution from the three corners
277  $t = 0.5 - $x0 ** 2 - $y0 ** 2;
278  if($t > 0){
279  $n += $t ** 4 * self::dot2D(self::$grad3[$gi0], $x0, $y0); // (x,y) of grad3 used for 2D gradient
280  }
281 
282  $t = 0.5 - $x1 ** 2 - $y1 ** 2;
283  if($t > 0){
284  $n += $t ** 4 * self::dot2D(self::$grad3[$gi1], $x1, $y1);
285  }
286 
287  $t = 0.5 - $x2 ** 2 - $y2 ** 2;
288  if($t > 0){
289  $n += $t ** 4 * self::dot2D(self::$grad3[$gi2], $x2, $y2);
290  }
291 
292  // Add contributions from each corner to get the noise value.
293  // The result is scaled to return values in the interval [-1,1].
294  return 70.0 * $n;
295  }
296 
308  /*public function getNoise4D($x, $y, $z, $w){
309  x += offsetX;
310  y += offsetY;
311  z += offsetZ;
312  w += offsetW;
313 
314  n0, n1, n2, n3, n4; // Noise contributions from the five corners
315 
316  // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
317  s = (x + y + z + w) * self::$F4; // Factor for 4D skewing
318  i = floor(x + s);
319  j = floor(y + s);
320  k = floor(z + s);
321  l = floor(w + s);
322 
323  t = (i + j + k + l) * self::$G4; // Factor for 4D unskewing
324  X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
325  Y0 = j - t;
326  Z0 = k - t;
327  W0 = l - t;
328  x0 = x - X0; // The x,y,z,w distances from the cell origin
329  y0 = y - Y0;
330  z0 = z - Z0;
331  w0 = w - W0;
332 
333  // For the 4D case, the simplex is a 4D shape I won't even try to describe.
334  // To find out which of the 24 possible simplices we're in, we need to
335  // determine the magnitude ordering of x0, y0, z0 and w0.
336  // The method below is a good way of finding the ordering of x,y,z,w and
337  // then find the correct traversal order for the simplex we’re in.
338  // First, six pair-wise comparisons are performed between each possible pair
339  // of the four coordinates, and the results are used to add up binary bits
340  // for an integer index.
341  c1 = (x0 > y0) ? 32 : 0;
342  c2 = (x0 > z0) ? 16 : 0;
343  c3 = (y0 > z0) ? 8 : 0;
344  c4 = (x0 > w0) ? 4 : 0;
345  c5 = (y0 > w0) ? 2 : 0;
346  c6 = (z0 > w0) ? 1 : 0;
347  c = c1 + c2 + c3 + c4 + c5 + c6;
348  i1, j1, k1, l1; // The integer offsets for the second simplex corner
349  i2, j2, k2, l2; // The integer offsets for the third simplex corner
350  i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
351 
352  // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
353  // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
354  // impossible. Only the 24 indices which have non-zero entries make any sense.
355  // We use a thresholding to set the coordinates in turn from the largest magnitude.
356 
357  // The number 3 in the "simplex" array is at the position of the largest coordinate.
358  i1 = simplex[c][0] >= 3 ? 1 : 0;
359  j1 = simplex[c][1] >= 3 ? 1 : 0;
360  k1 = simplex[c][2] >= 3 ? 1 : 0;
361  l1 = simplex[c][3] >= 3 ? 1 : 0;
362 
363  // The number 2 in the "simplex" array is at the second largest coordinate.
364  i2 = simplex[c][0] >= 2 ? 1 : 0;
365  j2 = simplex[c][1] >= 2 ? 1 : 0;
366  k2 = simplex[c][2] >= 2 ? 1 : 0;
367  l2 = simplex[c][3] >= 2 ? 1 : 0;
368 
369  // The number 1 in the "simplex" array is at the second smallest coordinate.
370  i3 = simplex[c][0] >= 1 ? 1 : 0;
371  j3 = simplex[c][1] >= 1 ? 1 : 0;
372  k3 = simplex[c][2] >= 1 ? 1 : 0;
373  l3 = simplex[c][3] >= 1 ? 1 : 0;
374 
375  // The fifth corner has all coordinate offsets = 1, so no need to look that up.
376 
377  x1 = x0 - i1 + self::$G4; // Offsets for second corner in (x,y,z,w) coords
378  y1 = y0 - j1 + self::$G4;
379  z1 = z0 - k1 + self::$G4;
380  w1 = w0 - l1 + self::$G4;
381 
382  x2 = x0 - i2 + self::$G42; // Offsets for third corner in (x,y,z,w) coords
383  y2 = y0 - j2 + self::$G42;
384  z2 = z0 - k2 + self::$G42;
385  w2 = w0 - l2 + self::$G42;
386 
387  x3 = x0 - i3 + self::$G43; // Offsets for fourth corner in (x,y,z,w) coords
388  y3 = y0 - j3 + self::$G43;
389  z3 = z0 - k3 + self::$G43;
390  w3 = w0 - l3 + self::$G43;
391 
392  x4 = x0 + self::$G44; // Offsets for last corner in (x,y,z,w) coords
393  y4 = y0 + self::$G44;
394  z4 = z0 + self::$G44;
395  w4 = w0 + self::$G44;
396 
397  // Work out the hashed gradient indices of the five simplex corners
398  ii = i & 255;
399  jj = j & 255;
400  kk = k & 255;
401  ll = l & 255;
402 
403  gi0 = $this->perm[ii + $this->perm[jj + $this->perm[kk + $this->perm[ll]]]] % 32;
404  gi1 = $this->perm[ii + i1 + $this->perm[jj + j1 + $this->perm[kk + k1 + $this->perm[ll + l1]]]] % 32;
405  gi2 = $this->perm[ii + i2 + $this->perm[jj + j2 + $this->perm[kk + k2 + $this->perm[ll + l2]]]] % 32;
406  gi3 = $this->perm[ii + i3 + $this->perm[jj + j3 + $this->perm[kk + k3 + $this->perm[ll + l3]]]] % 32;
407  gi4 = $this->perm[ii + 1 + $this->perm[jj + 1 + $this->perm[kk + 1 + $this->perm[ll + 1]]]] % 32;
408 
409  // Calculate the contribution from the five corners
410  t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
411  if(t0 < 0){
412  n0 = 0.0;
413  }else{
414  t0 *= t0;
415  n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0);
416  }
417 
418  t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
419  if(t1 < 0){
420  n1 = 0.0;
421  }else{
422  t1 *= t1;
423  n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1);
424  }
425 
426  t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
427  if(t2 < 0){
428  n2 = 0.0;
429  }else{
430  t2 *= t2;
431  n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2);
432  }
433 
434  t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
435  if(t3 < 0){
436  n3 = 0.0;
437  }else{
438  t3 *= t3;
439  n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3);
440  }
441 
442  t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
443  if(t4 < 0){
444  n4 = 0.0;
445  }else{
446  t4 *= t4;
447  n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4);
448  }
449 
450  // Sum up and scale the result to cover the range [-1,1]
451  return 27.0 * (n0 + n1 + n2 + n3 + n4);
452  }*/
453 }