[READ-ONLY] Mirror of https://github.com/flo-bit/every-noise. javascript noise class with lots of features
flo-bit.github.io/every-noise/
javascript
noise
procedural-generation
46 kB
1477 lines
1import Vector from "../js-utils/vector.js";
2
3/** Srand
4 * @param {number} seed
5 */
6(function () {
7 function r(e, n, t) {
8 function o(i, f) {
9 if (!n[i]) {
10 if (!e[i]) {
11 var c = "function" == typeof require && require;
12 if (!f && c) return c(i, !0);
13 if (u) return u(i, !0);
14 var a = new Error("Cannot find module '" + i + "'");
15 throw ((a.code = "MODULE_NOT_FOUND"), a);
16 }
17 var p = (n[i] = { exports: {} });
18 e[i][0].call(
19 p.exports,
20 function (r) {
21 var n = e[i][1][r];
22 return o(n || r);
23 },
24 p,
25 p.exports,
26 r,
27 e,
28 n,
29 t
30 );
31 }
32 return n[i].exports;
33 }
34 for (
35 var u = "function" == typeof require && require, i = 0;
36 i < t.length;
37 i++
38 )
39 o(t[i]);
40 return o;
41 }
42 return r;
43})()(
44 {
45 1: [
46 function (require, module, exports) {
47 /*!
48 * jsrand - https://github.com/DomenicoDeFelice/jsrand
49 *
50 * Copyright (c) 2014-2020 Domenico De Felice
51 * Released under the MIT License
52 *
53 * @license
54 */ "use strict";
55 function _toConsumableArray(a) {
56 return (
57 _arrayWithoutHoles(a) ||
58 _iterableToArray(a) ||
59 _unsupportedIterableToArray(a) ||
60 _nonIterableSpread()
61 );
62 }
63 function _nonIterableSpread() {
64 throw new TypeError(
65 "Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
66 );
67 }
68 function _unsupportedIterableToArray(a, b) {
69 if (a) {
70 if ("string" == typeof a) return _arrayLikeToArray(a, b);
71 var c = Object.prototype.toString.call(a).slice(8, -1);
72 return (
73 "Object" === c && a.constructor && (c = a.constructor.name),
74 "Map" === c || "Set" === c
75 ? Array.from(a)
76 : "Arguments" === c ||
77 /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c)
78 ? _arrayLikeToArray(a, b)
79 : void 0
80 );
81 }
82 }
83 function _iterableToArray(a) {
84 if ("undefined" != typeof Symbol && Symbol.iterator in Object(a))
85 return Array.from(a);
86 }
87 function _arrayWithoutHoles(a) {
88 if (Array.isArray(a)) return _arrayLikeToArray(a);
89 }
90 function _arrayLikeToArray(a, b) {
91 (null == b || b > a.length) && (b = a.length);
92 for (var c = 0, d = Array(b); c < b; c++) d[c] = a[c];
93 return d;
94 }
95 function _typeof(a) {
96 "@babel/helpers - typeof";
97 return (
98 (_typeof =
99 "function" == typeof Symbol && "symbol" == typeof Symbol.iterator
100 ? function (a) {
101 return typeof a;
102 }
103 : function (a) {
104 return a &&
105 "function" == typeof Symbol &&
106 a.constructor === Symbol &&
107 a !== Symbol.prototype
108 ? "symbol"
109 : typeof a;
110 }),
111 _typeof(a)
112 );
113 }
114 function Srand(a) {
115 null == a ? this.randomize() : this.seed(a);
116 }
117 (Srand.prototype = {}),
118 (Srand.seed = Srand.prototype.seed =
119 function (a) {
120 return null == a
121 ? this._seed
122 : ((this._mz = 123456789), (this._mw = this._seed = a));
123 }),
124 (Srand.randomize = Srand.prototype.randomize =
125 function () {
126 return this.seed(1 + Math.floor(4294967295 * Math.random()));
127 }),
128 (Srand.getState = Srand.prototype.getState =
129 function () {
130 return { seed: this._seed, mz: this._mz, mw: this._mw };
131 }),
132 (Srand.setState = Srand.prototype.setState =
133 function (a) {
134 if (
135 null == a ||
136 "object" !== _typeof(a) ||
137 "number" != typeof a.seed ||
138 "number" != typeof a.mz ||
139 "number" != typeof a.mw
140 )
141 throw new Error("Invalid state.");
142 (this._seed = a.seed), (this._mz = a.mz), (this._mw = a.mw);
143 }),
144 (Srand.random = Srand.prototype.random =
145 function () {
146 null == this._seed && this.randomize();
147 var a = this._mz,
148 b = this._mw;
149 (a = 4294967295 & (36969 * (65535 & a) + (a >> 16))),
150 (b = 4294967295 & (18e3 * (65535 & b) + (b >> 16))),
151 (this._mz = a),
152 (this._mw = b);
153 var c = (4294967295 & ((a << 16) + b)) / 4294967296;
154 return 0.5 + c;
155 }),
156 (Srand.inRange = Srand.prototype.inRange =
157 function (c, a) {
158 return c + this.random() * (a - c);
159 }),
160 (Srand.intInRange = Srand.prototype.intInRange =
161 function (a, b) {
162 return a + Math.floor(this.random() * (b - a + 1));
163 }),
164 (Srand.choice = Srand.prototype.choice =
165 function (a) {
166 if (0 === a.length)
167 throw new Error(
168 "Cannot choose random element from empty array."
169 );
170 var b = this.intInRange(0, a.length - 1);
171 return a[b];
172 }),
173 (Srand.choices = Srand.prototype.choices =
174 function (a, b) {
175 for (var c = Array(b), d = 0; d < b; d++) c[d] = this.choice(a);
176 return c;
177 }),
178 (Srand.sample = Srand.prototype.sample =
179 function (a, b) {
180 if (b > a.length)
181 throw new Error("Sample size cannot exceed population size.");
182 if (b === a.length) return _toConsumableArray(a);
183 for (
184 var c, d = a.length - 1, e = Array(b), f = {}, g = 0;
185 g < b;
186 g++
187 ) {
188 do c = this.intInRange(0, d);
189 while (f[c]);
190 (e[g] = a[c]), (f[c] = !0);
191 }
192 return e;
193 }),
194 (Srand.shuffle = Srand.prototype.shuffle =
195 function (a) {
196 for (var d = a.length - 1; 0 < d; d--) {
197 var b = this.intInRange(0, d - 1),
198 c = a[d];
199 (a[d] = a[b]), (a[b] = c);
200 }
201 return a;
202 }),
203 (Srand._oldSrand = void 0),
204 (Srand.noConflict = function () {
205 return Srand;
206 }),
207 (module.exports = Srand);
208 },
209 {},
210 ],
211 2: [
212 function (require, module, exports) {
213 "use strict";
214 var _jsrand = _interopRequireDefault(require("./jsrand.js"));
215 function _interopRequireDefault(a) {
216 return a && a.__esModule ? a : { default: a };
217 }
218 (_jsrand.default._oldSrand = window.Srand),
219 (_jsrand.default.noConflict = function () {
220 return (window.Srand = _jsrand.default._oldSrand), _jsrand.default;
221 }),
222 (window.Srand = _jsrand.default);
223 },
224 { "./jsrand.js": 1 },
225 ],
226 },
227 {},
228 [2]
229);
230
231/**
232 * every-noise.js
233 */
234class Noise {
235 static defaultUp = new Vector(0, 1, 0);
236
237 /*
238 * simplex-noise.js by Jonas Wagner
239 *
240 * version 4.0.1 slightly modified
241 */
242 static Simplex = (function () {
243 /*
244 * A fast javascript implementation of simplex noise by Jonas Wagner
245
246Based on a speed-improved simplex noise algorithm for 2D, 3D and 4D in Java.
247Which is based on example code by Stefan Gustavson (stegu@itn.liu.se).
248With Optimisations by Peter Eastman (peastman@drizzle.stanford.edu).
249Better rank ordering method by Stefan Gustavson in 2012.
250
251 Copyright (c) 2022 Jonas Wagner
252
253 Permission is hereby granted, free of charge, to any person obtaining a copy
254 of this software and associated documentation files (the "Software"), to deal
255 in the Software without restriction, including without limitation the rights
256 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
257 copies of the Software, and to permit persons to whom the Software is
258 furnished to do so, subject to the following conditions:
259
260 The above copyright notice and this permission notice shall be included in all
261 copies or substantial portions of the Software.
262
263 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
264 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
265 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
266 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
267 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
268 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
269 SOFTWARE.
270 */
271 // these #__PURE__ comments help uglifyjs with dead code removal
272 //
273 const F2 = /*#__PURE__*/ 0.5 * (Math.sqrt(3.0) - 1.0);
274 const G2 = /*#__PURE__*/ (3.0 - Math.sqrt(3.0)) / 6.0;
275 const F3 = 1.0 / 3.0;
276 const G3 = 1.0 / 6.0;
277 const F4 = /*#__PURE__*/ (Math.sqrt(5.0) - 1.0) / 4.0;
278 const G4 = /*#__PURE__*/ (5.0 - Math.sqrt(5.0)) / 20.0;
279 // I'm really not sure why this | 0 (basically a coercion to int)
280 // is making this faster but I get ~5 million ops/sec more on the
281 // benchmarks across the board or a ~10% speedup.
282 const fastFloor = (x) => Math.floor(x) | 0;
283 const grad2 = /*#__PURE__*/ new Float64Array([
284 1, 1, -1, 1, 1, -1, -1, -1, 1, 0, -1, 0, 1, 0, -1, 0, 0, 1, 0, -1, 0, 1,
285 0, -1,
286 ]);
287 // double seems to be faster than single or int's
288 // probably because most operations are in double precision
289 const grad3 = /*#__PURE__*/ new Float64Array([
290 1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1, 0, 1, 0, 1, -1, 0, 1, 1, 0, -1, -1,
291 0, -1, 0, 1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1,
292 ]);
293 // double is a bit quicker here as well
294 const grad4 = /*#__PURE__*/ new Float64Array([
295 0, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1, 0, -1, 1, 1, 0, -1, 1,
296 -1, 0, -1, -1, 1, 0, -1, -1, -1, 1, 0, 1, 1, 1, 0, 1, -1, 1, 0, -1, 1, 1,
297 0, -1, -1, -1, 0, 1, 1, -1, 0, 1, -1, -1, 0, -1, 1, -1, 0, -1, -1, 1, 1,
298 0, 1, 1, 1, 0, -1, 1, -1, 0, 1, 1, -1, 0, -1, -1, 1, 0, 1, -1, 1, 0, -1,
299 -1, -1, 0, 1, -1, -1, 0, -1, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1,
300 -1, 0, -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1, 0,
301 ]);
302 /**
303 * Creates a 2D noise function
304 * @param random the random function that will be used to build the permutation table
305 * @returns {NoiseFunction2D}
306 */
307 function createNoise2D(random = Math.random) {
308 const perm = buildPermutationTable(random);
309 // precalculating this yields a little ~3% performance improvement.
310 const permGrad2x = new Float64Array(perm).map((v) => grad2[(v % 12) * 2]);
311 const permGrad2y = new Float64Array(perm).map(
312 (v) => grad2[(v % 12) * 2 + 1]
313 );
314 return function noise2D(x, y) {
315 // if(!isFinite(x) || !isFinite(y)) return 0;
316 let n0 = 0; // Noise contributions from the three corners
317 let n1 = 0;
318 let n2 = 0;
319 // Skew the input space to determine which simplex cell we're in
320 const s = (x + y) * F2; // Hairy factor for 2D
321 const i = fastFloor(x + s);
322 const j = fastFloor(y + s);
323 const t = (i + j) * G2;
324 const X0 = i - t; // Unskew the cell origin back to (x,y) space
325 const Y0 = j - t;
326 const x0 = x - X0; // The x,y distances from the cell origin
327 const y0 = y - Y0;
328 // For the 2D case, the simplex shape is an equilateral triangle.
329 // Determine which simplex we are in.
330 let i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
331 if (x0 > y0) {
332 i1 = 1;
333 j1 = 0;
334 } // lower triangle, XY order: (0,0)->(1,0)->(1,1)
335 else {
336 i1 = 0;
337 j1 = 1;
338 } // upper triangle, YX order: (0,0)->(0,1)->(1,1)
339 // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
340 // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
341 // c = (3-sqrt(3))/6
342 const x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
343 const y1 = y0 - j1 + G2;
344 const x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
345 const y2 = y0 - 1.0 + 2.0 * G2;
346 // Work out the hashed gradient indices of the three simplex corners
347 const ii = i & 255;
348 const jj = j & 255;
349 // Calculate the contribution from the three corners
350 let t0 = 0.5 - x0 * x0 - y0 * y0;
351 if (t0 >= 0) {
352 const gi0 = ii + perm[jj];
353 const g0x = permGrad2x[gi0];
354 const g0y = permGrad2y[gi0];
355 t0 *= t0;
356 // n0 = t0 * t0 * (grad2[gi0] * x0 + grad2[gi0 + 1] * y0); // (x,y) of grad3 used for 2D gradient
357 n0 = t0 * t0 * (g0x * x0 + g0y * y0);
358 }
359 let t1 = 0.5 - x1 * x1 - y1 * y1;
360 if (t1 >= 0) {
361 const gi1 = ii + i1 + perm[jj + j1];
362 const g1x = permGrad2x[gi1];
363 const g1y = permGrad2y[gi1];
364 t1 *= t1;
365 // n1 = t1 * t1 * (grad2[gi1] * x1 + grad2[gi1 + 1] * y1);
366 n1 = t1 * t1 * (g1x * x1 + g1y * y1);
367 }
368 let t2 = 0.5 - x2 * x2 - y2 * y2;
369 if (t2 >= 0) {
370 const gi2 = ii + 1 + perm[jj + 1];
371 const g2x = permGrad2x[gi2];
372 const g2y = permGrad2y[gi2];
373 t2 *= t2;
374 // n2 = t2 * t2 * (grad2[gi2] * x2 + grad2[gi2 + 1] * y2);
375 n2 = t2 * t2 * (g2x * x2 + g2y * y2);
376 }
377 // Add contributions from each corner to get the final noise value.
378 // The result is scaled to return values in the interval [-1,1].
379 return 70.0 * (n0 + n1 + n2);
380 };
381 }
382 /**
383 * Creates a 3D noise function
384 * @param random the random function that will be used to build the permutation table
385 * @returns {NoiseFunction3D}
386 */
387 function createNoise3D(random = Math.random) {
388 const perm = buildPermutationTable(random);
389 // precalculating these seems to yield a speedup of over 15%
390 const permGrad3x = new Float64Array(perm).map((v) => grad3[(v % 12) * 3]);
391 const permGrad3y = new Float64Array(perm).map(
392 (v) => grad3[(v % 12) * 3 + 1]
393 );
394 const permGrad3z = new Float64Array(perm).map(
395 (v) => grad3[(v % 12) * 3 + 2]
396 );
397 return function noise3D(x, y, z) {
398 let n0, n1, n2, n3; // Noise contributions from the four corners
399 // Skew the input space to determine which simplex cell we're in
400 const s = (x + y + z) * F3; // Very nice and simple skew factor for 3D
401 const i = fastFloor(x + s);
402 const j = fastFloor(y + s);
403 const k = fastFloor(z + s);
404 const t = (i + j + k) * G3;
405 const X0 = i - t; // Unskew the cell origin back to (x,y,z) space
406 const Y0 = j - t;
407 const Z0 = k - t;
408 const x0 = x - X0; // The x,y,z distances from the cell origin
409 const y0 = y - Y0;
410 const z0 = z - Z0;
411 // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
412 // Determine which simplex we are in.
413 let i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
414 let i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
415 if (x0 >= y0) {
416 if (y0 >= z0) {
417 i1 = 1;
418 j1 = 0;
419 k1 = 0;
420 i2 = 1;
421 j2 = 1;
422 k2 = 0;
423 } // X Y Z order
424 else if (x0 >= z0) {
425 i1 = 1;
426 j1 = 0;
427 k1 = 0;
428 i2 = 1;
429 j2 = 0;
430 k2 = 1;
431 } // X Z Y order
432 else {
433 i1 = 0;
434 j1 = 0;
435 k1 = 1;
436 i2 = 1;
437 j2 = 0;
438 k2 = 1;
439 } // Z X Y order
440 } else {
441 // x0<y0
442 if (y0 < z0) {
443 i1 = 0;
444 j1 = 0;
445 k1 = 1;
446 i2 = 0;
447 j2 = 1;
448 k2 = 1;
449 } // Z Y X order
450 else if (x0 < z0) {
451 i1 = 0;
452 j1 = 1;
453 k1 = 0;
454 i2 = 0;
455 j2 = 1;
456 k2 = 1;
457 } // Y Z X order
458 else {
459 i1 = 0;
460 j1 = 1;
461 k1 = 0;
462 i2 = 1;
463 j2 = 1;
464 k2 = 0;
465 } // Y X Z order
466 }
467 // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
468 // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
469 // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
470 // c = 1/6.
471 const x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
472 const y1 = y0 - j1 + G3;
473 const z1 = z0 - k1 + G3;
474 const x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
475 const y2 = y0 - j2 + 2.0 * G3;
476 const z2 = z0 - k2 + 2.0 * G3;
477 const x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
478 const y3 = y0 - 1.0 + 3.0 * G3;
479 const z3 = z0 - 1.0 + 3.0 * G3;
480 // Work out the hashed gradient indices of the four simplex corners
481 const ii = i & 255;
482 const jj = j & 255;
483 const kk = k & 255;
484 // Calculate the contribution from the four corners
485 let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
486 if (t0 < 0) n0 = 0.0;
487 else {
488 const gi0 = ii + perm[jj + perm[kk]];
489 t0 *= t0;
490 n0 =
491 t0 *
492 t0 *
493 (permGrad3x[gi0] * x0 +
494 permGrad3y[gi0] * y0 +
495 permGrad3z[gi0] * z0);
496 }
497 let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
498 if (t1 < 0) n1 = 0.0;
499 else {
500 const gi1 = ii + i1 + perm[jj + j1 + perm[kk + k1]];
501 t1 *= t1;
502 n1 =
503 t1 *
504 t1 *
505 (permGrad3x[gi1] * x1 +
506 permGrad3y[gi1] * y1 +
507 permGrad3z[gi1] * z1);
508 }
509 let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
510 if (t2 < 0) n2 = 0.0;
511 else {
512 const gi2 = ii + i2 + perm[jj + j2 + perm[kk + k2]];
513 t2 *= t2;
514 n2 =
515 t2 *
516 t2 *
517 (permGrad3x[gi2] * x2 +
518 permGrad3y[gi2] * y2 +
519 permGrad3z[gi2] * z2);
520 }
521 let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
522 if (t3 < 0) n3 = 0.0;
523 else {
524 const gi3 = ii + 1 + perm[jj + 1 + perm[kk + 1]];
525 t3 *= t3;
526 n3 =
527 t3 *
528 t3 *
529 (permGrad3x[gi3] * x3 +
530 permGrad3y[gi3] * y3 +
531 permGrad3z[gi3] * z3);
532 }
533 // Add contributions from each corner to get the final noise value.
534 // The result is scaled to stay just inside [-1,1]
535 return 32.0 * (n0 + n1 + n2 + n3);
536 };
537 }
538 /**
539 * Creates a 4D noise function
540 * @param random the random function that will be used to build the permutation table
541 * @returns {NoiseFunction4D}
542 */
543 function createNoise4D(random = Math.random) {
544 const perm = buildPermutationTable(random);
545 // precalculating these leads to a ~10% speedup
546 const permGrad4x = new Float64Array(perm).map((v) => grad4[(v % 32) * 4]);
547 const permGrad4y = new Float64Array(perm).map(
548 (v) => grad4[(v % 32) * 4 + 1]
549 );
550 const permGrad4z = new Float64Array(perm).map(
551 (v) => grad4[(v % 32) * 4 + 2]
552 );
553 const permGrad4w = new Float64Array(perm).map(
554 (v) => grad4[(v % 32) * 4 + 3]
555 );
556 return function noise4D(x, y, z, w) {
557 let n0, n1, n2, n3, n4; // Noise contributions from the five corners
558 // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
559 const s = (x + y + z + w) * F4; // Factor for 4D skewing
560 const i = fastFloor(x + s);
561 const j = fastFloor(y + s);
562 const k = fastFloor(z + s);
563 const l = fastFloor(w + s);
564 const t = (i + j + k + l) * G4; // Factor for 4D unskewing
565 const X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
566 const Y0 = j - t;
567 const Z0 = k - t;
568 const W0 = l - t;
569 const x0 = x - X0; // The x,y,z,w distances from the cell origin
570 const y0 = y - Y0;
571 const z0 = z - Z0;
572 const w0 = w - W0;
573 // For the 4D case, the simplex is a 4D shape I won't even try to describe.
574 // To find out which of the 24 possible simplices we're in, we need to
575 // determine the magnitude ordering of x0, y0, z0 and w0.
576 // Six pair-wise comparisons are performed between each possible pair
577 // of the four coordinates, and the results are used to rank the numbers.
578 let rankx = 0;
579 let ranky = 0;
580 let rankz = 0;
581 let rankw = 0;
582 if (x0 > y0) rankx++;
583 else ranky++;
584 if (x0 > z0) rankx++;
585 else rankz++;
586 if (x0 > w0) rankx++;
587 else rankw++;
588 if (y0 > z0) ranky++;
589 else rankz++;
590 if (y0 > w0) ranky++;
591 else rankw++;
592 if (z0 > w0) rankz++;
593 else rankw++;
594 // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
595 // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
596 // impossible. Only the 24 indices which have non-zero entries make any sense.
597 // We use a thresholding to set the coordinates in turn from the largest magnitude.
598 // Rank 3 denotes the largest coordinate.
599 // Rank 2 denotes the second largest coordinate.
600 // Rank 1 denotes the second smallest coordinate.
601 // The integer offsets for the second simplex corner
602 const i1 = rankx >= 3 ? 1 : 0;
603 const j1 = ranky >= 3 ? 1 : 0;
604 const k1 = rankz >= 3 ? 1 : 0;
605 const l1 = rankw >= 3 ? 1 : 0;
606 // The integer offsets for the third simplex corner
607 const i2 = rankx >= 2 ? 1 : 0;
608 const j2 = ranky >= 2 ? 1 : 0;
609 const k2 = rankz >= 2 ? 1 : 0;
610 const l2 = rankw >= 2 ? 1 : 0;
611 // The integer offsets for the fourth simplex corner
612 const i3 = rankx >= 1 ? 1 : 0;
613 const j3 = ranky >= 1 ? 1 : 0;
614 const k3 = rankz >= 1 ? 1 : 0;
615 const l3 = rankw >= 1 ? 1 : 0;
616 // The fifth corner has all coordinate offsets = 1, so no need to compute that.
617 const x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
618 const y1 = y0 - j1 + G4;
619 const z1 = z0 - k1 + G4;
620 const w1 = w0 - l1 + G4;
621 const x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords
622 const y2 = y0 - j2 + 2.0 * G4;
623 const z2 = z0 - k2 + 2.0 * G4;
624 const w2 = w0 - l2 + 2.0 * G4;
625 const x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords
626 const y3 = y0 - j3 + 3.0 * G4;
627 const z3 = z0 - k3 + 3.0 * G4;
628 const w3 = w0 - l3 + 3.0 * G4;
629 const x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords
630 const y4 = y0 - 1.0 + 4.0 * G4;
631 const z4 = z0 - 1.0 + 4.0 * G4;
632 const w4 = w0 - 1.0 + 4.0 * G4;
633 // Work out the hashed gradient indices of the five simplex corners
634 const ii = i & 255;
635 const jj = j & 255;
636 const kk = k & 255;
637 const ll = l & 255;
638 // Calculate the contribution from the five corners
639 let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
640 if (t0 < 0) n0 = 0.0;
641 else {
642 const gi0 = ii + perm[jj + perm[kk + perm[ll]]];
643 t0 *= t0;
644 n0 =
645 t0 *
646 t0 *
647 (permGrad4x[gi0] * x0 +
648 permGrad4y[gi0] * y0 +
649 permGrad4z[gi0] * z0 +
650 permGrad4w[gi0] * w0);
651 }
652 let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
653 if (t1 < 0) n1 = 0.0;
654 else {
655 const gi1 = ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]];
656 t1 *= t1;
657 n1 =
658 t1 *
659 t1 *
660 (permGrad4x[gi1] * x1 +
661 permGrad4y[gi1] * y1 +
662 permGrad4z[gi1] * z1 +
663 permGrad4w[gi1] * w1);
664 }
665 let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
666 if (t2 < 0) n2 = 0.0;
667 else {
668 const gi2 = ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]];
669 t2 *= t2;
670 n2 =
671 t2 *
672 t2 *
673 (permGrad4x[gi2] * x2 +
674 permGrad4y[gi2] * y2 +
675 permGrad4z[gi2] * z2 +
676 permGrad4w[gi2] * w2);
677 }
678 let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
679 if (t3 < 0) n3 = 0.0;
680 else {
681 const gi3 = ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]];
682 t3 *= t3;
683 n3 =
684 t3 *
685 t3 *
686 (permGrad4x[gi3] * x3 +
687 permGrad4y[gi3] * y3 +
688 permGrad4z[gi3] * z3 +
689 permGrad4w[gi3] * w3);
690 }
691 let t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
692 if (t4 < 0) n4 = 0.0;
693 else {
694 const gi4 = ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]];
695 t4 *= t4;
696 n4 =
697 t4 *
698 t4 *
699 (permGrad4x[gi4] * x4 +
700 permGrad4y[gi4] * y4 +
701 permGrad4z[gi4] * z4 +
702 permGrad4w[gi4] * w4);
703 }
704 // Sum up and scale the result to cover the range [-1,1]
705 return 27.0 * (n0 + n1 + n2 + n3 + n4);
706 };
707 }
708 /**
709 * Builds a random permutation table.
710 * This is exported only for (internal) testing purposes.
711 * Do not rely on this export.
712 * @private
713 */
714 function buildPermutationTable(random) {
715 const tableSize = 512;
716 const p = new Uint8Array(tableSize);
717 for (let i = 0; i < tableSize / 2; i++) {
718 p[i] = i;
719 }
720 for (let i = 0; i < tableSize / 2 - 1; i++) {
721 const r = i + ~~(random() * (256 - i));
722 const aux = p[i];
723 p[i] = p[r];
724 p[r] = aux;
725 }
726 for (let i = 256; i < tableSize; i++) {
727 p[i] = p[i - 256];
728 }
729 return p;
730 }
731
732 return {
733 createNoise2D: createNoise2D,
734 createNoise3D: createNoise3D,
735 createNoise4D: createNoise4D,
736 };
737 })();
738
739 static firstDefined(...arr) {
740 for (let i = 0; i < arr.length; i++) {
741 if (arr[i] !== undefined) return arr[i];
742 }
743 }
744
745 /**
746 * create new Noise object
747 *
748 * @param {object} opts
749 *
750 * @property {number} seed - seed for the noise, if not provided, Math.random() will be used,
751 * currently same results can only be guaranteed for newly created noise objects with same seed
752 * (as opposed to an old noise object where you changed the seed)
753 *
754 * @property {number} min - minimun value of noise
755 * @property {number} max - maximum value of noise
756 *
757 * @property {number} scale - scale of the noise
758 * @property {number} power - power of the noise (1 = linear, 2 = quadratic, etc)
759 * @property {Vector} shift - move noise in 2D, 3D or 4D space
760 *
761 * @property {number} octaves - number of layers for fbm noise
762 * @property {number} gain - how much to multiply amplitude per layer
763 * @property {number} lacunarity - how much to multiply scale per layer
764 * @property {array} amps - array of amplitudes for each layer
765 * @property {number} erosion - how much previous layers influence amplitude of later layers
766 * @property {number} sharpness - billowed or rigded noise (0 = normal, 1 = billowed, -1 = ridged)
767 * @property {number} steps - will turn noise into steps (integer, number of steps)
768 *
769 * @property {number} warp - how much to warp the noise
770 * @property {number} warpNoise - noise to warp the noise with
771 * @property {number} warp2 - second warp, can only be used if warp is used too
772 * @property {number} warpNoise2 - second warp noise
773 *
774 * @property {boolean} invert - invert the noise
775 * @property {boolean} abs - absolute value of the noise
776 * @property {boolean} clamp - clamp the noise between min and max
777 * @property {boolean} tileX - tile the noise in x direction
778 * @property {boolean} tileY - tile the noise in y direction
779 * @property {boolean} tile - tile the noise in all directions (will override tileX and tileY)
780 *
781 * @constructor
782 */
783 constructor(opts) {
784 opts = opts || {};
785
786 this.pos = new Vector(0, 0, 0);
787
788 this._seed = Noise.firstDefined(opts.seed, opts.s, Math.random() * 1000000);
789 this.prng = new Srand(this._seed);
790
791 // fbm stuff
792 // how many layers
793 this.octaves = Noise.firstDefined(opts.octaves, opts.oct, 0);
794 // how much to multiply amplitude per layer
795 this.gain = Noise.firstDefined(opts.gain, opts.persistence, opts.per, 0.5);
796 // how much to multiply scale per layer
797 this.lacunarity = Noise.firstDefined(opts.lacunarity, opts.lac, 2);
798
799 this.layers = undefined;
800 this.noise2D = undefined;
801 this.noise3D = undefined;
802 this.noise4D = undefined;
803
804 let octaves = this.octaves;
805 if (this._octaves.isNoise) {
806 octaves = Math.floor(this._octaves.max);
807 }
808 if (this.octaves > 0 || opts.layers != undefined) {
809 this.layers = [];
810 for (
811 let i = 0;
812 i < this.octaves || (opts.layers && i < opts.layers.length);
813 i++
814 ) {
815 let settings =
816 opts.layers != undefined && opts.layers.length > i
817 ? opts.layers[i]
818 : {};
819 settings.seed = this.prng.inRange(0, 1000000000);
820
821 if (opts.all) {
822 for (let k of Object.keys(opts.all)) {
823 settings[k] = opts.all[k];
824 }
825 }
826 if (settings.isNoise != true) {
827 this.layers.push(new Noise(settings));
828 } else {
829 this.layers.push(settings);
830 }
831 }
832 } else {
833 let random = this.prng.random.bind(this.prng);
834 this.noise2D = Noise.Simplex.createNoise2D(random);
835 this.noise3D = Noise.Simplex.createNoise3D(random);
836 this.noise4D = Noise.Simplex.createNoise4D(random);
837 }
838
839 this.scale = Noise.firstDefined(opts.scale, opts.scl, 1);
840 this.power = Noise.firstDefined(opts.power, opts.pow, 1);
841
842 this.shift = Noise.firstDefined(
843 opts.shift,
844 new Vector(opts.x || 0.357, opts.y || 0.579, opts.z || 0.248, opts.w || 0)
845 );
846
847 // how much previous layers influence amplitude of later layers
848 this.erosion = Noise.firstDefined(opts.erosion, opts.ero, 0);
849 // how much to move x, y, z to calculate derivative
850 // (x2 - x1) / delta, (y2 - y1) / delta, (z2 - z1) / delta
851 this.delta = Noise.firstDefined(opts.delta, opts.del, 0.0001 * this.scale);
852
853 // amp is also only used for fbm
854 this.amp = Noise.firstDefined(opts.amplitude, opts.amp);
855
856 this.sharpness = Noise.firstDefined(opts.sharpness, opts.sharp, 0);
857
858 this.steps = opts.steps;
859
860 this.min = Noise.firstDefined(opts.min, -1);
861 this.max = Noise.firstDefined(opts.max, 1);
862
863 this.combine = undefined;
864
865 this.mod = opts.mod;
866
867 this.warp = undefined;
868 this.warp2 = undefined;
869 this.warpNoise = undefined;
870 this.warpNoise2 = undefined;
871
872 if (opts.warp != undefined) {
873 this.warp = opts.warp;
874
875 if (opts.warpNoise) {
876 this.warpNoise = opts.warpNoise;
877 this.warpNoise.seed = this.prng.inRange(0, 1000000000);
878 if (this.warpNoise.isNoise != true) {
879 this.warpNoise = new Noise(opts.warpNoise);
880 }
881 }
882 }
883 if (opts.warp2 != undefined) {
884 this.warp2 = opts.warp2;
885
886 if (opts.warpNoise2) {
887 this.warpNoise2 = opts.warpNoise2;
888 if (this.warpNoise2.isNoise != true)
889 this.warpNoise2 = new Noise(opts.warpNoise2);
890 }
891 }
892
893 this.defaultUp = opts.defaultUp;
894
895 if (opts.amps) {
896 this.multiplyAmps(opts.amps);
897 }
898
899 // wether to use central position when calculating derivative
900 this.central = opts.central;
901
902 this.tileX = opts.tileX;
903 this.tileY = opts.tileY;
904
905 if (opts.tile) {
906 this.tileX = true;
907 this.tileY = true;
908 }
909
910 this.isNoise = true;
911
912 // vector to store derivative, will be reused
913 this.derivative = undefined;
914 }
915
916 get scale() {
917 return this.getPropertyAtPosition("_scale", this.pos);
918 }
919 set scale(scale) {
920 this._scale = scale;
921 this.checkProperty("_scale");
922 }
923
924 get power() {
925 return this.getPropertyAtPosition("_power", this.pos);
926 }
927 set power(power) {
928 this._power = power;
929 this.checkProperty("_power");
930 }
931
932 get octaves() {
933 return this.getPropertyAtPosition("_octaves", this.pos);
934 }
935 set octaves(octaves) {
936 this._octaves = octaves;
937 this.checkProperty("_octaves");
938 }
939
940 get gain() {
941 return this.getPropertyAtPosition("_gain", this.pos);
942 }
943 set gain(gain) {
944 this._gain = gain;
945 this.checkProperty("_gain");
946 }
947
948 get lacunarity() {
949 return this.getPropertyAtPosition("_lacunarity", this.pos);
950 }
951 set lacunarity(lacunarity) {
952 this._lacunarity = lacunarity;
953 this.checkProperty("_lacunarity");
954 }
955
956 get erosion() {
957 return this.getPropertyAtPosition("_erosion", this.pos);
958 }
959 set erosion(erosion) {
960 this._erosion = erosion;
961 this.checkProperty("_erosion");
962 }
963
964 get amp() {
965 return this.getPropertyAtPosition("_amp", this.pos);
966 }
967 set amp(amp) {
968 this._amp = amp;
969 this.checkProperty("_amp");
970 }
971
972 get combine() {
973 return this.getPropertyAtPosition("_combine", this.pos);
974 }
975 set combine(combine) {
976 this._combine = combine;
977 this.checkProperty("_combine");
978 }
979
980 get sharpness() {
981 return this.getPropertyAtPosition("_sharpness", this.pos);
982 }
983 set sharpness(sharpness) {
984 this._sharpness = sharpness;
985 this.checkProperty("_sharpness");
986 }
987
988 get warp() {
989 return this.getPropertyAtPosition("_warp", this.pos);
990 }
991 set warp(warp) {
992 this._warp = warp;
993 this.checkProperty("_warp");
994 }
995
996 get warp2() {
997 return this.getPropertyAtPosition("_warp2", this.pos);
998 }
999 set warp2(warp2) {
1000 this._warp2 = warp2;
1001 this.checkProperty("_warp2");
1002 }
1003
1004 get steps() {
1005 return this.getPropertyAtPosition("_steps", this.pos);
1006 }
1007 set steps(steps) {
1008 this._steps = steps;
1009 this.checkProperty("_steps");
1010 }
1011
1012 get min() {
1013 return this.getPropertyAtPosition("_min", this.pos);
1014 }
1015 set min(min) {
1016 this._min = min;
1017 this.checkProperty("_min");
1018 }
1019
1020 get max() {
1021 return this.getPropertyAtPosition("_max", this.pos);
1022 }
1023 set max(max) {
1024 this._max = max;
1025 this.checkProperty("_max");
1026 }
1027
1028 get seed() {
1029 return this._seed;
1030 }
1031 set seed(seed) {
1032 this.setSeed(seed);
1033 }
1034
1035 /**
1036 * set seed for noise object, will create new simplex noise objects
1037 * if no param given will generate random seed
1038 * @param {number} seed
1039 * @returns {number}
1040 */
1041 setSeed(seed) {
1042 this._seed = seed != undefined ? seed : Math.random() * 1000000000;
1043
1044 if (this.prng) this.prng = new Srand(this._seed);
1045 let random = this.prng.random.bind(this.prng);
1046 if (this.noise2D) this.noise2D = new Noise.Simplex.createNoise2D(random);
1047 if (this.noise3D) this.noise3D = new Noise.Simplex.createNoise3D(random);
1048 if (this.noise4D) this.noise4D = new Noise.Simplex.createNoise4D(random);
1049
1050 if (this.layers) {
1051 for (let i = 0; i < this.layers.length; i++) {
1052 this.layers[i].seed = this.prng.inRange(0, 1000000000);
1053 }
1054 }
1055
1056 for (let k of Object.keys(this)) {
1057 if (this[k] != undefined && this[k].isNoise) {
1058 this[k].seed = this.prng.inRange(0, 1000000000);
1059 }
1060 }
1061
1062 return seed;
1063 }
1064
1065 /**
1066 * check if a property is a number or am object, if its an object
1067 * but not a noise object, convert it to a noise object
1068 * @param {string} key
1069 */
1070 checkProperty(key) {
1071 let v = this[key];
1072 if (v != undefined && typeof v != "number" && !v.isNoise) {
1073 if (v.seed == undefined) v.seed = this.prng.random() * 1000000;
1074
1075 this[key] = new Noise(v);
1076 }
1077 }
1078
1079 /**
1080 * get a property by key, if its a number return number
1081 * if its a noise object, return the value at position
1082 *
1083 * @param {string} key
1084 * @param {Vector} position
1085 * @returns {number}
1086 */
1087 getPropertyAtPosition(key, position) {
1088 let v = this[key];
1089 if (v == undefined) return;
1090 if (typeof v == "number") return v;
1091 if (v.isNoise)
1092 return position != undefined
1093 ? v.get(position.x, position.y, position.z, position.w)
1094 : v;
1095 }
1096
1097 /**
1098 * shift noise field
1099 *
1100 * @param {number} dX
1101 * @param {number} dY
1102 * @param {number} dZ
1103 * @param {number} dW
1104 */
1105 shiftBy(dX, dY, dZ, dW) {
1106 this.shift.x += dX || 0;
1107 this.shift.y += dY || 0;
1108 this.shift.z += dZ || 0;
1109 this.shift.w += dW || 0;
1110 }
1111
1112 /**
1113 * multiply amplitude of all layers by array of values
1114 * only works if noise object has layers
1115 *
1116 * @param {array} arr
1117 */
1118 multiplyAmps(arr) {
1119 if (this.layers == undefined) return;
1120
1121 for (let i = 0; i < this.layers.length && i < arr.length; i++) {
1122 this.layers[i].amp *= arr[i];
1123 }
1124 }
1125
1126 lerp(a, b, t) {
1127 return (b - a) * t + a;
1128 }
1129
1130 tilePosition() {
1131 let x = this.pos.x;
1132 let y = this.pos.y;
1133 let newX = 0,
1134 newY = 0,
1135 newZ = 0,
1136 newW = 0;
1137 if (this.tileX) {
1138 newX = Math.sin(x * Math.PI * 2);
1139 newY = Math.cos(x * Math.PI * 2);
1140 }
1141 if (this.tileY) {
1142 newZ = Math.sin(y * Math.PI * 2);
1143 newW = Math.cos(y * Math.PI * 2);
1144 }
1145 if (this.tileX && !this.tileY) {
1146 this.pos.set(newX, newY + y);
1147 } else if (this.tileY && !this.tileX) {
1148 this.pos.set(newZ + x, newW);
1149 } else if (this.tileX && this.tileY) {
1150 this.pos.set(newX, newY, newZ, newW);
1151 }
1152 }
1153
1154 warpPosition() {
1155 let warp = this.warp;
1156 if (warp == undefined || warp == 0) return;
1157 let x = this.pos.x,
1158 y = this.pos.y,
1159 z = this.pos.z,
1160 w = this.pos.w;
1161
1162 if (this.warpNoise) this.warpNoise.pos.copy(this.pos);
1163
1164 let noise = this.warpNoise || this;
1165 let scl = noise.scale;
1166 x +=
1167 noise.getFBM(
1168 x - 74.98 * scl,
1169 y + 41.33 * scl,
1170 z != undefined ? z + 76.56 * scl : undefined,
1171 undefined,
1172 true
1173 ) * warp;
1174 y +=
1175 noise.getFBM(
1176 x + 1.23 * scl,
1177 y + 5.79 * scl,
1178 z != undefined ? z + 12.85 * scl : undefined,
1179 undefined,
1180 true
1181 ) * warp;
1182 if (z != undefined) {
1183 z +=
1184 noise.getFBM(
1185 x + 11.47 * scl,
1186 y + 17.98 * scl,
1187 z + 23.56 * scl,
1188 undefined,
1189 true
1190 ) * warp;
1191 }
1192 if (w != undefined) {
1193 w +=
1194 noise.getFBM(
1195 x + 54.47 * scl,
1196 y + 34.98 * scl,
1197 z + 76.56 * scl,
1198 w + 45.98 * scl,
1199 true
1200 ) * warp;
1201 }
1202
1203 let warp2 = this.warp2;
1204 if (warp2 == undefined || warp2 == 0) {
1205 this.pos.set(x, y, z, w);
1206 return;
1207 }
1208
1209 if (this.warpNoise2) this.warpNoise2.pos.copy(this.pos);
1210
1211 noise = this.warpNoise2 || this;
1212 scl = noise.scale;
1213 x +=
1214 noise.getFBM(
1215 x + 11.47 * scl,
1216 y + 17.98 * scl,
1217 undefined,
1218 undefined,
1219 true
1220 ) * warp2;
1221 y +=
1222 noise.getFBM(
1223 x - 73.98 * scl,
1224 y + 44.33 * scl,
1225 undefined,
1226 undefined,
1227 true
1228 ) * warp2;
1229 if (w != undefined) {
1230 z +=
1231 noise.getFBM(
1232 x + 11.23 * scl,
1233 y + 53.79 * scl,
1234 z + 96.31 * scl,
1235 undefined,
1236 true
1237 ) * warp2;
1238 }
1239 if (w != undefined) {
1240 w +=
1241 noise.getFBM(
1242 x + 11.23 * scl,
1243 y + 53.79 * scl,
1244 z + 96.31 * scl,
1245 w + 23.56 * scl,
1246 true
1247 ) * warp2;
1248 }
1249
1250 this.pos.set(x, y, z, w);
1251 }
1252
1253 getFBM(x, y, z, w, noErosion) {
1254 let scale = this.scale;
1255
1256 // if no layers exit early
1257 if (this.layers == undefined) {
1258 // if object has simplex noise return result of that
1259 if (this.noise4D != undefined && w != undefined) {
1260 this.lastNoiseCall = "noise4D";
1261 return this.noise4D(x * scale, y * scale, z * scale, w * scale);
1262 }
1263 if (this.noise3D != undefined && z != undefined) {
1264 this.lastNoiseCall = "noise3D";
1265 return this.noise3D(x * scale, y * scale, z * scale);
1266 }
1267 if (this.noise2D != undefined) {
1268 this.lastNoiseCall = "noise2D";
1269 return this.noise2D(x * scale, y * scale);
1270 }
1271 // no data
1272 return 0;
1273 }
1274 // for calculating angle between derivative and tangent
1275 // when erosion > 0
1276 let up =
1277 this.defaultUp != undefined ? this.defaultUp(x, y, z) : Noise.defaultUp;
1278
1279 let maxAmp = 1;
1280 let amp = 1,
1281 freq = scale;
1282
1283 let lac = this.lacunarity;
1284 let gain = this.gain;
1285
1286 // reuse vector
1287 this.sum = this.sum || new Vector();
1288 this.sum.set(0, 0, 0);
1289
1290 let n = 0;
1291 let erosion = noErosion ? 0 : this.erosion;
1292 let octaves = this.octaves;
1293 for (let i = 0; i <= octaves && i < this.layers.length; i++) {
1294 let l = this.layers[i];
1295 let layerAmp = l.amp || 1;
1296 let val =
1297 l.get(
1298 x * freq,
1299 y * freq,
1300 z != undefined ? z * freq : undefined,
1301 w != undefined ? w * freq : undefined
1302 ) *
1303 amp *
1304 layerAmp;
1305 if (erosion > 0) {
1306 let d = l.getDerivative(x * freq, y * freq, z * freq);
1307 d.setLength(amp * layerAmp);
1308
1309 this.sum.add(d);
1310 // calculate normalized angle between sum of derivatives and tangent, should be between 0 and 1
1311 let mult = Math.abs(1 - up.angleTo(this.sum) / Math.PI);
1312
1313 n += val * (mult * erosion + 1 - erosion);
1314 } else {
1315 n += val;
1316 }
1317 amp *= gain;
1318 freq *= lac;
1319 maxAmp += amp * layerAmp;
1320 }
1321 return n / maxAmp;
1322 }
1323
1324 /**
1325 *
1326 *
1327 * @param {number} x
1328 * @param {number} y
1329 * @param {number} z
1330 * @param {number} w
1331 * @returns {number}
1332 */
1333 getNoise(x, y, z, w) {
1334 x = x || 0;
1335 y = y || 0;
1336 this.pos.set(
1337 x + this.shift.x,
1338 y + this.shift.y,
1339 z != undefined ? z + this.shift.z : undefined,
1340 w != undefined ? w + this.shift.w : undefined
1341 );
1342
1343 if (this.tileX || this.tileY) this.tilePosition();
1344 if (this.warp || this.warp2) this.warpPosition();
1345
1346 let norm = this.getFBM(this.pos.x, this.pos.y, this.pos.z, this.pos.w);
1347
1348 let power = this.power;
1349 if (power && power != 1) {
1350 // convert to [0 - 1], apply power and back to [-1, 1]
1351 norm = (Math.pow((norm + 1) * 0.5, power) - 0.5) * 2;
1352 //norm = Math.pow(norm, power);
1353 }
1354
1355 if (this.sharpness != undefined && this.sharpness != 0) {
1356 let sharp = this.sharpness;
1357
1358 let billow = (Math.abs(norm) - 0.5) * 2;
1359 let ridged = (0.5 - Math.abs(norm)) * 2;
1360
1361 norm = this.lerp(norm, billow, Math.max(0, sharp));
1362 norm = this.lerp(norm, ridged, Math.abs(Math.min(0, sharp)));
1363 }
1364
1365 if (this.clamp) {
1366 norm = Math.min(norm, 1);
1367 norm = Math.max(norm, -1);
1368 }
1369
1370 // modify with function
1371 if (this.mod) {
1372 norm = this.mod(norm, this.pos, this, up);
1373 }
1374
1375 //combine with other noise:
1376 if (this.combine) {
1377 norm *= this.combine;
1378 }
1379
1380 // turn into steps
1381 // (e.g. 2 steps => only 0 or 1, 3 steps => 0, 0.5 and 1)
1382 let steps = this.steps;
1383 if (steps != undefined && steps >= 2) {
1384 steps = Math.round(steps);
1385 let s = (Math.floor((norm + 1) * steps * 0.5) / (steps - 1) - 0.5) * 2;
1386 return s;
1387 }
1388
1389 return norm;
1390 }
1391
1392 getDerivative(x, y, z, n) {
1393 // left side or central difference
1394 // very expensive (four/six noise calls), should be changed to analytical derivatives
1395 // see https://iquilezles.org/www/articles/morenoise/morenoise.htm
1396
1397 n = n || this.get(x, y, z);
1398 let mov = this.delta;
1399
1400 let dx =
1401 (this.central ? this.get(x - mov, y, z) : n) - this.get(x + mov, y, z);
1402 let dy =
1403 (this.central ? this.get(x, y - mov, z) : n) - this.get(x, y + mov, z);
1404 let dz =
1405 (this.central ? this.get(x, y, z - mov) : n) - this.get(x, y, z + mov);
1406
1407 if (this.derivative == undefined) this.derivative = new Vector();
1408 this.derivative.set(dx, dy, dz);
1409 this.derivative.normalize();
1410 return this.derivative;
1411 }
1412
1413 /**
1414 * converts from -1, 1 to min, max
1415 *
1416 * @param {number} norm
1417 * @returns {number}
1418 */
1419 mapNormalizedToMinMax(norm) {
1420 return (norm + 1) * 0.5 * (this.max - this.min) + this.min;
1421 }
1422 /**
1423 * converts from min, max to -1, 1
1424 * @param {number} minMax
1425 * @returns {number}
1426 */
1427 mapMinMaxToNormalized(minMax) {
1428 return ((minMax - this.min) / (this.max - this.min) - 0.5) * 2;
1429 }
1430
1431 /**
1432 * function to get normalized noise value (between -1 and 1)
1433 * can be called either with x, y, z or with a vector
1434 *
1435 * @param {number} x
1436 * @param {number} y
1437 * @param {number} z
1438 * @param {number} w
1439 * @returns {number}
1440 */
1441 getNormalized(x, y, z, w) {
1442 if (typeof x == "number") {
1443 return this.getNoise(x, y, z, w);
1444 }
1445 return this.getNoise(x.x, x.y, x.z, x.w);
1446 }
1447
1448 /**
1449 * same as getNormalized
1450 *
1451 * @param {number} x
1452 * @param {number} y
1453 * @param {number} z
1454 * @param {number} w
1455 * @returns {number}
1456 */
1457 getNorm(x, y, z, w) {
1458 return this.getNormalized(x, y, z, w);
1459 }
1460
1461 /**
1462 * main function to get noise value
1463 * will return value between min and max
1464 * call either with x, y, z or with a vector
1465 *
1466 * @param {number} x
1467 * @param {number} y
1468 * @param {number} z
1469 * @param {number} w
1470 * @returns {number}
1471 */
1472 get(x, y, z, w) {
1473 return this.mapNormalizedToMinMax(this.getNormalized(x, y, z, w));
1474 }
1475}
1476
1477export default Noise;