[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
0

Configure Feed

Select the types of activity you want to include in your feed.

every-noise / noise.js
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;