PocketMine-MP 5.18.2 git-00e39821f06a4b6d728d35053c2621dbb19369ff
Noise.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
22declare(strict_types=1);
23
28
29use function array_fill;
30use function assert;
31
32abstract class Noise{
33
43 public static function linearLerp($x, $x1, $x2, $q0, $q1){
44 return (($x2 - $x) / ($x2 - $x1)) * $q0 + (($x - $x1) / ($x2 - $x1)) * $q1;
45 }
46
61 public static function bilinearLerp($x, $y, $q00, $q01, $q10, $q11, $x1, $x2, $y1, $y2){
62 $dx1 = (($x2 - $x) / ($x2 - $x1));
63 $dx2 = (($x - $x1) / ($x2 - $x1));
64
65 return (($y2 - $y) / ($y2 - $y1)) * (
66 $dx1 * $q00 + $dx2 * $q10
67 ) + (($y - $y1) / ($y2 - $y1)) * (
68 $dx1 * $q01 + $dx2 * $q11
69 );
70 }
71
93 public static function trilinearLerp($x, $y, $z, $q000, $q001, $q010, $q011, $q100, $q101, $q110, $q111, $x1, $x2, $y1, $y2, $z1, $z2){
94 $dx1 = (($x2 - $x) / ($x2 - $x1));
95 $dx2 = (($x - $x1) / ($x2 - $x1));
96 $dy1 = (($y2 - $y) / ($y2 - $y1));
97 $dy2 = (($y - $y1) / ($y2 - $y1));
98
99 return (($z2 - $z) / ($z2 - $z1)) * (
100 $dy1 * (
101 $dx1 * $q000 + $dx2 * $q100
102 ) + $dy2 * (
103 $dx1 * $q001 + $dx2 * $q101
104 )
105 ) + (($z - $z1) / ($z2 - $z1)) * (
106 $dy1 * (
107 $dx1 * $q010 + $dx2 * $q110
108 ) + $dy2 * (
109 $dx1 * $q011 + $dx2 * $q111
110 )
111 );
112 }
113
114 public function __construct(
115 protected int $octaves,
116 protected float $persistence,
117 protected float $expansion
118 ){}
119
126 abstract public function getNoise2D($x, $z);
127
135 abstract public function getNoise3D($x, $y, $z);
136
144 public function noise2D($x, $z, $normalized = false){
145 $result = 0;
146 $amp = 1;
147 $freq = 1;
148 $max = 0;
149
150 $x *= $this->expansion;
151 $z *= $this->expansion;
152
153 for($i = 0; $i < $this->octaves; ++$i){
154 $result += $this->getNoise2D($x * $freq, $z * $freq) * $amp;
155 $max += $amp;
156 $freq *= 2;
157 $amp *= $this->persistence;
158 }
159
160 if($normalized === true){
161 $result /= $max;
162 }
163
164 return $result;
165 }
166
175 public function noise3D($x, $y, $z, $normalized = false){
176 $result = 0;
177 $amp = 1;
178 $freq = 1;
179 $max = 0;
180
181 $x *= $this->expansion;
182 $y *= $this->expansion;
183 $z *= $this->expansion;
184
185 for($i = 0; $i < $this->octaves; ++$i){
186 $result += $this->getNoise3D($x * $freq, $y * $freq, $z * $freq) * $amp;
187 $max += $amp;
188 $freq *= 2;
189 $amp *= $this->persistence;
190 }
191
192 if($normalized === true){
193 $result /= $max;
194 }
195
196 return $result;
197 }
198
203 public function getFastNoise1D(int $xSize, int $samplingRate, int $x, int $y, int $z) : \SplFixedArray{
204 if($samplingRate === 0){
205 throw new \InvalidArgumentException("samplingRate cannot be 0");
206 }
207 if($xSize % $samplingRate !== 0){
208 throw new \InvalidArgumentException("xSize % samplingRate must return 0");
209 }
210
212 $noiseArray = new \SplFixedArray($xSize + 1);
213
214 for($xx = 0; $xx <= $xSize; $xx += $samplingRate){
215 $noiseArray[$xx] = $this->noise3D($xx + $x, $y, $z);
216 }
217
218 for($xx = 0; $xx < $xSize; ++$xx){
219 if($xx % $samplingRate !== 0){
220 $nx = (int) ($xx / $samplingRate) * $samplingRate;
221 $noiseArray[$xx] = self::linearLerp(
222 x: $xx,
223 x1: $nx,
224 x2: $nx + $samplingRate,
225 q0: $noiseArray[$nx],
226 q1: $noiseArray[$nx + $samplingRate]
227 );
228 }
229 }
230
231 return $noiseArray;
232 }
233
238 public function getFastNoise2D(int $xSize, int $zSize, int $samplingRate, int $x, int $y, int $z) : \SplFixedArray{
239 assert($samplingRate !== 0, new \InvalidArgumentException("samplingRate cannot be 0"));
240
241 assert($xSize % $samplingRate === 0, new \InvalidArgumentException("xSize % samplingRate must return 0"));
242 assert($zSize % $samplingRate === 0, new \InvalidArgumentException("zSize % samplingRate must return 0"));
243
245 $noiseArray = new \SplFixedArray($xSize + 1);
246
247 for($xx = 0; $xx <= $xSize; $xx += $samplingRate){
248 $noiseArray[$xx] = new \SplFixedArray($zSize + 1);
249 for($zz = 0; $zz <= $zSize; $zz += $samplingRate){
250 $noiseArray[$xx][$zz] = $this->noise3D($x + $xx, $y, $z + $zz);
251 }
252 }
253
254 for($xx = 0; $xx < $xSize; ++$xx){
255 if($xx % $samplingRate !== 0){
256 $noiseArray[$xx] = new \SplFixedArray($zSize + 1);
257 }
258
259 for($zz = 0; $zz < $zSize; ++$zz){
260 if($xx % $samplingRate !== 0 || $zz % $samplingRate !== 0){
261 $nx = (int) ($xx / $samplingRate) * $samplingRate;
262 $nz = (int) ($zz / $samplingRate) * $samplingRate;
263 $noiseArray[$xx][$zz] = Noise::bilinearLerp(
264 x: $xx,
265 y: $zz,
266 q00: $noiseArray[$nx][$nz],
267 q01: $noiseArray[$nx][$nz + $samplingRate],
268 q10: $noiseArray[$nx + $samplingRate][$nz],
269 q11: $noiseArray[$nx + $samplingRate][$nz + $samplingRate],
270 x1: $nx,
271 x2: $nx + $samplingRate,
272 y1: $nz,
273 y2: $nz + $samplingRate
274 );
275 }
276 }
277 }
278
279 return $noiseArray;
280 }
281
285 public function getFastNoise3D(int $xSize, int $ySize, int $zSize, int $xSamplingRate, int $ySamplingRate, int $zSamplingRate, int $x, int $y, int $z) : array{
286
287 assert($xSamplingRate !== 0, new \InvalidArgumentException("xSamplingRate cannot be 0"));
288 assert($zSamplingRate !== 0, new \InvalidArgumentException("zSamplingRate cannot be 0"));
289 assert($ySamplingRate !== 0, new \InvalidArgumentException("ySamplingRate cannot be 0"));
290
291 assert($xSize % $xSamplingRate === 0, new \InvalidArgumentException("xSize % xSamplingRate must return 0"));
292 assert($zSize % $zSamplingRate === 0, new \InvalidArgumentException("zSize % zSamplingRate must return 0"));
293 assert($ySize % $ySamplingRate === 0, new \InvalidArgumentException("ySize % ySamplingRate must return 0"));
294
295 $noiseArray = array_fill(0, $xSize + 1, array_fill(0, $zSize + 1, []));
296
297 for($xx = 0; $xx <= $xSize; $xx += $xSamplingRate){
298 for($zz = 0; $zz <= $zSize; $zz += $zSamplingRate){
299 for($yy = 0; $yy <= $ySize; $yy += $ySamplingRate){
300 $noiseArray[$xx][$zz][$yy] = $this->noise3D($x + $xx, $y + $yy, $z + $zz, true);
301 }
302 }
303 }
304
316 for($xx = 0; $xx < $xSize; ++$xx){
317 $nx = (int) ($xx / $xSamplingRate) * $xSamplingRate;
318 $nnx = $nx + $xSamplingRate;
319
320 $dx1 = (($nnx - $xx) / ($nnx - $nx));
321 $dx2 = (($xx - $nx) / ($nnx - $nx));
322
323 for($zz = 0; $zz < $zSize; ++$zz){
324 $nz = (int) ($zz / $zSamplingRate) * $zSamplingRate;
325 $nnz = $nz + $zSamplingRate;
326
327 $dz1 = ($nnz - $zz) / ($nnz - $nz);
328 $dz2 = ($zz - $nz) / ($nnz - $nz);
329
330 for($yy = 0; $yy < $ySize; ++$yy){
331 if($xx % $xSamplingRate !== 0 || $zz % $zSamplingRate !== 0 || $yy % $ySamplingRate !== 0){
332 $ny = (int) ($yy / $ySamplingRate) * $ySamplingRate;
333 $nny = $ny + $ySamplingRate;
334
335 $dy1 = (($nny - $yy) / ($nny - $ny));
336 $dy2 = (($yy - $ny) / ($nny - $ny));
337
338 $noiseArray[$xx][$zz][$yy] = $dz1 * (
339 $dy1 * (
340 $dx1 * $noiseArray[$nx][$nz][$ny] + $dx2 * $noiseArray[$nnx][$nz][$ny]
341 ) + $dy2 * (
342 $dx1 * $noiseArray[$nx][$nz][$nny] + $dx2 * $noiseArray[$nnx][$nz][$nny]
343 )
344 ) + $dz2 * (
345 $dy1 * (
346 $dx1 * $noiseArray[$nx][$nnz][$ny] + $dx2 * $noiseArray[$nnx][$nnz][$ny]
347 ) + $dy2 * (
348 $dx1 * $noiseArray[$nx][$nnz][$nny] + $dx2 * $noiseArray[$nnx][$nnz][$nny]
349 )
350 );
351 }
352 }
353 }
354 }
355
356 return $noiseArray;
357 }
358}
noise3D($x, $y, $z, $normalized=false)
Definition: Noise.php:175
getFastNoise3D(int $xSize, int $ySize, int $zSize, int $xSamplingRate, int $ySamplingRate, int $zSamplingRate, int $x, int $y, int $z)
Definition: Noise.php:285
static linearLerp($x, $x1, $x2, $q0, $q1)
Definition: Noise.php:43
static trilinearLerp($x, $y, $z, $q000, $q001, $q010, $q011, $q100, $q101, $q110, $q111, $x1, $x2, $y1, $y2, $z1, $z2)
Definition: Noise.php:93
static bilinearLerp($x, $y, $q00, $q01, $q10, $q11, $x1, $x2, $y1, $y2)
Definition: Noise.php:61
getFastNoise1D(int $xSize, int $samplingRate, int $x, int $y, int $z)
Definition: Noise.php:203
getFastNoise2D(int $xSize, int $zSize, int $samplingRate, int $x, int $y, int $z)
Definition: Noise.php:238
noise2D($x, $z, $normalized=false)
Definition: Noise.php:144