[READ-ONLY] Mirror of https://github.com/flo-bit/uber-noise. advanced noise generation for the browser and node.js flo-bit.dev/uber-noise/
browser nodejs noise noise-generator npm typescript
0

Configure Feed

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

better documentation, more tests

+334 -514
+41 -7
Readme.md
··· 2 2 3 3 advanced noise generation for the browser and node.js 4 4 5 + - written in typescript 6 + - seeded noise 7 + - based on simplex noise (2D, 3D and 4D) 8 + - fractal brownian motion (fbm) 9 + - custom gain, lacunarity, scale, shift, power 10 + - billowed, ridged, warped, stepped noise 11 + - seamless tiling noise (1D and 2D) 12 + - most options can be set to own noise instance 13 + 5 14 ## Install 6 15 7 16 ```bash ··· 21 30 ```javascript 22 31 const noise = new UberNoise(); 23 32 24 - // get noise value at x,y 25 - const value = noise.get(x, y); 26 - 27 - // get noise value at x,y,z 33 + // get noise value at x, y, z 28 34 const value = noise.get(x, y, z); 29 - 30 - // get noise value at x,y,z,w 31 - const value = noise.get(x, y, z, w); 35 + // OR 36 + const value = noise.get({x, y, z}); 32 37 ``` 33 38 34 39 ### Set noise options ··· 51 56 scale: { min: 0.01, max: 0.1, scale: 0.01 }, 52 57 }); 53 58 ``` 59 + 60 + ### All options 61 + 62 + | Option | Type | Default Value | Description | 63 + |---------------|----------------------------------|-------------------|----------------------------------------------------| 64 + | `seed` | `string \| number` | `Math.random()` | Seed for the noise, defaults to a random value. | 65 + | `min` | `number \| UberNoise \| NoiseOptions` | `-1` | Minimum value of noise. | 66 + | `max` | `number \| UberNoise \| NoiseOptions` | `1` | Maximum value of noise. | 67 + | `scale` | `number \| UberNoise \| NoiseOptions` | `1` | Scale of the noise ("zoom" level). | 68 + | `power` | `number \| UberNoise \| NoiseOptions` | `1` | Power of the noise (1 = linear, 2 = quadratic). | 69 + | `shift` | `number[]` | `[0, 0, 0, 0]` | Move noise in 2D, 3D, or 4D space. | 70 + | `octaves` | `number` | `0` | Number of layers for fbm noise. | 71 + | `gain` | `number \| UberNoise \| NoiseOptions` | `0.5` | Amplitude multiplier per fbm layer. | 72 + | `lacunarity` | `number \| UberNoise \| NoiseOptions` | `2` | Scale multiplier per fbm layer. | 73 + | `amps` | `number[]` | `[]` | Array of custom amplitudes for each fbm layer. | 74 + | `layers` | `NoiseOptions[]` | `[]` | Custom noise options for each fbm layer. | 75 + | `sharpness` | `number \| UberNoise \| NoiseOptions` | `0` | Sharpness of noise (0 = normal, 1 = billowed, -1 = ridged). | 76 + | `steps` | `number \| UberNoise \| NoiseOptions` | `0` | Discretizes the noise into steps. | 77 + | `warp` | `number \| UberNoise \| NoiseOptions` | `0` | Amount to warp the noise. | 78 + | `warpNoise` | `UberNoise` | `undefined` | Custom noise used to warp the noise. | 79 + | `warp2` | `number \| UberNoise \| NoiseOptions` | `0` | Second level of warping, only used if `warp` is used too. | 80 + | `warpNoise2` | `UberNoise` | `undefined` | Second custom noise for additional warping. | 81 + | `invert` | `boolean` | `false` | Invert the noise output. | 82 + | `abs` | `boolean` | `false` | Take the absolute value of the noise. | 83 + | `clamp` | `boolean` | `false` | Clamp the noise between min and max values (otherwise noise might overflow slightly). | 84 + | `tileX` | `boolean` | `false` | Tile the noise in the x direction. | 85 + | `tileY` | `boolean` | `false` | Tile the noise in the y direction. | 86 + | `tile` | `boolean` | `false` | Tile the noise in x and y directions (overwrites `tileX` and `tileY`) | 87 +
+1 -432
dist/uber-noise.js
··· 1 - import { createNoise2D, createNoise3D, createNoise4D, } from 'simplex-noise'; 2 - import alea from 'alea'; 3 - /** 4 - * 5 - * @property {number} seed - seed for the noise, if not provided, Math.random() will be used, 6 - * currently same results can only be guaranteed for newly created noise objects with same seed 7 - * (as opposed to an old noise object where you changed the seed) 8 - * 9 - * @property {number} min - minimun value of noise 10 - * @property {number} max - maximum value of noise 11 - * 12 - * @property {number} scale - scale of the noise 13 - * @property {number} power - power of the noise (1 = linear, 2 = quadratic, etc) 14 - * @property {Vector} shift - move noise in 2D, 3D or 4D space 15 - * 16 - * @property {number} octaves - number of layers for fbm noise 17 - * @property {number} gain - how much to multiply amplitude per layer 18 - * @property {number} lacunarity - how much to multiply scale per layer 19 - * @property {array} amps - array of amplitudes for each layer 20 - * @property {number} erosion - how much previous layers influence amplitude of later layers 21 - * @property {number} sharpness - billowed or rigded noise (0 = normal, 1 = billowed, -1 = ridged) 22 - * @property {number} steps - will turn noise into steps (integer, number of steps) 23 - * 24 - * @property {number} warp - how much to warp the noise 25 - * @property {number} warpNoise - noise to warp the noise with 26 - * @property {number} warp2 - second warp, can only be used if warp is used too 27 - * @property {number} warpNoise2 - second warp noise 28 - * 29 - * @property {boolean} invert - invert the noise 30 - * @property {boolean} abs - absolute value of the noise 31 - * @property {boolean} clamp - clamp the noise between min and max 32 - * @property {boolean} tileX - tile the noise in x direction 33 - * @property {boolean} tileY - tile the noise in y direction 34 - * @property {boolean} tile - tile the noise in all directions (will override tileX and tileY) 35 - * 36 - * @constructor 37 - */ 38 - function lerp(a, b, t) { 39 - return (b - a) * t + a; 40 - } 41 - export default class UberNoise { 42 - noise2D; 43 - noise3D; 44 - noise4D; 45 - seed; 46 - _min = -1; 47 - _max = 1; 48 - _scale = 1; 49 - _power = 1; 50 - shift = { 51 - x: 0, 52 - y: 0, 53 - }; 54 - octaves = 0; 55 - _gain = 0.5; 56 - _lacunarity = 2; 57 - amps = []; 58 - _erosion = 0; 59 - _sharpness = 0; 60 - _steps = 0; 61 - _warp = 0; 62 - _warpNoise; 63 - _warp2 = 0; 64 - _warpNoise2; 65 - tileX = false; 66 - tileY = false; 67 - position = { 68 - x: 0, 69 - y: 0, 70 - }; 71 - pngr; 72 - layers = []; 73 - constructor(options = {}) { 74 - this.seed = options.seed ?? Math.random(); 75 - this.pngr = alea(this.seed); 76 - this.min = options.min ?? -1; 77 - this.max = options.max ?? 1; 78 - this.scale = options.scale ?? 1; 79 - this.power = options.power ?? 1; 80 - this.octaves = options.octaves ?? options.layers?.length ?? 0; 81 - this.gain = options.gain ?? 0.5; 82 - this.lacunarity = options.lacunarity ?? 2; 83 - this.sharpness = options.sharpness ?? 0; 84 - this.steps = options.steps ?? 0; 85 - this.warp = options.warp ?? 0; 86 - this.warpNoise = options.warpNoise; 87 - this.warp2 = options.warp2 ?? 0; 88 - this.warpNoise2 = options.warpNoise2; 89 - this.amps = options.amps ?? []; 90 - this.tileX = options.tileX ?? options.tile ?? false; 91 - this.tileY = options.tileY ?? options.tile ?? false; 92 - this.createLayers(options); 93 - } 94 - createLayers(options) { 95 - // process layers 96 - for (let i = 0; i < this.octaves; i++) { 97 - const layerOptions = options.layers?.[i] ?? {}; 98 - if (layerOptions instanceof UberNoise) { 99 - this.layers[i] = layerOptions; 100 - continue; 101 - } 102 - if (layerOptions.seed === undefined) 103 - layerOptions.seed = this.pngr(); 104 - this.layers[i] = new UberNoise(layerOptions); 105 - } 106 - if (this.layers.length == 0) { 107 - this.noise2D = createNoise2D(this.pngr); 108 - this.noise3D = createNoise3D(this.pngr); 109 - this.noise4D = createNoise4D(this.pngr); 110 - } 111 - } 112 - warpPosition(warp, warpNoise) { 113 - if (warp == undefined || warp == 0) 114 - return; 115 - if (warpNoise != undefined) 116 - warpNoise.position = this.position; 117 - let x = this.position.x, y = this.position.y, z = this.position.z, w = this.position.w; 118 - const noise = warpNoise ?? this; 119 - const scl = this.scale; 120 - // move some amount so that we don't sample the same point as the original noise 121 - this.position.x = x + 54.47 * scl; 122 - this.position.y = y - 34.98 * scl; 123 - if (z != undefined) 124 - this.position.z = z + 21.63 * scl; 125 - if (w != undefined) 126 - this.position.w = w - 67.1 * scl; 127 - x += noise.getFBM() * warp; 128 - y += noise.getFBM() * warp; 129 - if (z != undefined) 130 - z += noise.getFBM() * warp; 131 - if (w != undefined) 132 - w += noise.getFBM() * warp; 133 - this.position.x = x; 134 - this.position.y = y; 135 - this.position.z = z; 136 - this.position.w = w; 137 - } 138 - tilePosition() { 139 - if (!this.tileX && !this.tileY) 140 - return; 141 - const x = this.position.x; 142 - const y = this.position.y; 143 - let newX = 0, newY = 0, newZ = 0, newW = 0; 144 - if (this.tileX) { 145 - newX = Math.sin(x * Math.PI * 2); 146 - newY = Math.cos(x * Math.PI * 2); 147 - } 148 - if (this.tileY) { 149 - newZ = Math.sin(y * Math.PI * 2); 150 - newW = Math.cos(y * Math.PI * 2); 151 - } 152 - if (this.tileX && !this.tileY) { 153 - this.position.x = newX; 154 - this.position.y = newY + y; 155 - } 156 - else if (this.tileY && !this.tileX) { 157 - this.position.x = newZ + x; 158 - this.position.y = newW; 159 - } 160 - else if (this.tileX && this.tileY) { 161 - this.position.x = newX; 162 - this.position.y = newY; 163 - this.position.z = newZ; 164 - this.position.w = newW; 165 - } 166 - } 167 - getFBM() { 168 - const x = this.position.x, y = this.position.y, z = this.position.z, w = this.position.w; 169 - const scale = this.scale; 170 - if (this.layers.length == 0) { 171 - if (z != undefined && w != undefined && this.noise4D != undefined) { 172 - return this.noise4D(x * scale, y * scale, z * scale, w * scale); 173 - } 174 - if (z != undefined && this.noise3D != undefined) { 175 - return this.noise3D(x * scale, y * scale, z * scale); 176 - } 177 - if (this.noise2D != undefined) { 178 - return this.noise2D(x * scale, y * scale); 179 - } 180 - return 0; 181 - } 182 - let maxAmp = 1; 183 - let amp = 1, freq = scale; 184 - const lacunarity = this.lacunarity; 185 - const gain = this.gain; 186 - let n = 0; 187 - for (let i = 0; i < this.octaves; i++) { 188 - const layer = this.layers[i]; 189 - const layerAmp = this.amps[i] ?? 1; 190 - const value = layer.get(x * freq, y * freq, z != undefined ? z * freq : undefined, w != undefined ? w * freq : undefined) * 191 - amp * 192 - layerAmp; 193 - n += value; 194 - amp *= gain; 195 - freq *= lacunarity; 196 - maxAmp += amp * layerAmp; 197 - } 198 - return n / maxAmp; 199 - } 200 - applyShift() { 201 - const shift = this.shift; 202 - if (shift !== undefined) { 203 - this.position.x += shift.x; 204 - this.position.y += shift.y; 205 - if (this.position.z) 206 - this.position.z += shift.z ?? 0; 207 - if (this.position.w) 208 - this.position.w += shift.w ?? 0; 209 - } 210 - } 211 - applyPower(norm) { 212 - const power = this.power; 213 - if (power != 1) { 214 - // convert to [0 - 1], apply power and back to [-1, 1] 215 - norm = (Math.pow((norm + 1) * 0.5, power) - 0.5) * 2; 216 - } 217 - return norm; 218 - } 219 - applySharpness(norm) { 220 - const sharpness = this.sharpness; 221 - if (sharpness != 0) { 222 - const billow = (Math.abs(norm) - 0.5) * 2; 223 - const ridged = (0.5 - Math.abs(norm)) * 2; 224 - norm = lerp(norm, billow, Math.max(0, sharpness)); 225 - norm = lerp(norm, ridged, Math.max(0, -sharpness)); 226 - } 227 - return norm; 228 - } 229 - applySteps(norm) { 230 - const steps = this.steps; 231 - if (steps != 0) { 232 - // convert from -1 to 1 to 0 to 1 233 - norm = (norm + 1) * 0.5; 234 - // apply steps 235 - norm = Math.floor(norm * steps) / steps; 236 - // convert back to -1 to 1 237 - norm = norm * 2 - 1; 238 - } 239 - return norm; 240 - } 241 - getNoise(x, y, z = undefined, w = undefined) { 242 - // set position 243 - this.position.x = x; 244 - this.position.y = y; 245 - this.position.z = z; 246 - this.position.w = w; 247 - // apply shift 248 - this.applyShift(); 249 - // apply tiling 250 - this.tilePosition(); 251 - // apply warp 252 - this.warpPosition(this.warp, this.warpNoise); 253 - this.warpPosition(this.warp2, this.warpNoise2); 254 - let norm = this.getFBM(); 255 - // apply power 256 - norm = this.applyPower(norm); 257 - // apply sharpness 258 - norm = this.applySharpness(norm); 259 - // apply steps 260 - norm = this.applySteps(norm); 261 - return norm; 262 - } 263 - // same as normalized but returns between min and max 264 - get(x, y = undefined, z = undefined, w = undefined) { 265 - const norm = this.normalized(x, y, z, w); 266 - return this.normalizedToMinMax(norm); 267 - } 268 - // same as get but returns between -1 and 1 269 - normalized(x, y = undefined, z = undefined, w = undefined) { 270 - // if x is an array, treat it as a vector 271 - if (Array.isArray(x)) { 272 - w = x[3]; 273 - z = x[2]; 274 - y = x[1]; 275 - x = x[0]; 276 - } 277 - else if (typeof x === 'object') { 278 - w = x.w; 279 - z = x.z; 280 - y = x.y; 281 - x = x.x; 282 - } 283 - // if y is undefined, treat it as 2D noise with y = 0 284 - y = y ?? 0; 285 - return this.getNoise(x, y, z, w); 286 - } 287 - /** 288 - * convert value between min and max to normalized value between -1 and 1 289 - * 290 - * @param value {number} 291 - * @returns {number} 292 - */ 293 - minMaxToNormalized(value) { 294 - return ((value - this.min) / (this.max - this.min)) * 2 - 1; 295 - } 296 - /** 297 - * convert normlized value to value between min and max 298 - * 299 - * @param value {number} 300 - * @returns {number} 301 - */ 302 - normalizedToMinMax(value) { 303 - return (value + 1) * 0.5 * (this.max - this.min) + this.min; 304 - } 305 - move(x, y, z = undefined, w = undefined) { 306 - if (!this.shift) { 307 - this.shift = { x, y, z, w }; 308 - return; 309 - } 310 - this.shift.x += x; 311 - this.shift.y += y; 312 - if (z != undefined) { 313 - this.shift.z = (this.shift.z ?? 0) + z; 314 - } 315 - if (w != undefined) { 316 - this.shift.w = (this.shift.w ?? 0) + w; 317 - } 318 - } 319 - checkParameterInput(value) { 320 - if (typeof value === 'object' && !(value instanceof UberNoise)) { 321 - if (value.seed === undefined) { 322 - value.seed = this.pngr(); 323 - } 324 - value = new UberNoise(value); 325 - } 326 - return value; 327 - } 328 - getParameter(value) { 329 - if (typeof value === 'number') { 330 - return value; 331 - } 332 - return value.get(this.position); 333 - } 334 - // getter and setter for min and max 335 - get min() { 336 - return this.getParameter(this._min); 337 - } 338 - set min(value) { 339 - this._min = this.checkParameterInput(value); 340 - } 341 - get max() { 342 - return this.getParameter(this._max); 343 - } 344 - set max(value) { 345 - this._max = this.checkParameterInput(value); 346 - } 347 - // getter and setter for scale and power 348 - get scale() { 349 - return this.getParameter(this._scale); 350 - } 351 - set scale(value) { 352 - this._scale = this.checkParameterInput(value); 353 - } 354 - get power() { 355 - return this.getParameter(this._power); 356 - } 357 - set power(value) { 358 - this._power = this.checkParameterInput(value); 359 - } 360 - // getter and setter for gain and lacunarity 361 - get gain() { 362 - return this.getParameter(this._gain); 363 - } 364 - set gain(value) { 365 - this._gain = this.checkParameterInput(value); 366 - } 367 - get lacunarity() { 368 - return this.getParameter(this._lacunarity); 369 - } 370 - set lacunarity(value) { 371 - this._lacunarity = this.checkParameterInput(value); 372 - } 373 - // getter and setter for erosion, sharpness and steps 374 - get erosion() { 375 - return this.getParameter(this._erosion); 376 - } 377 - set erosion(value) { 378 - this._erosion = this.checkParameterInput(value); 379 - } 380 - get sharpness() { 381 - return this.getParameter(this._sharpness); 382 - } 383 - set sharpness(value) { 384 - this._sharpness = this.checkParameterInput(value); 385 - } 386 - get steps() { 387 - return Math.round(this.getParameter(this._steps)); 388 - } 389 - set steps(value) { 390 - this._steps = this.checkParameterInput(value); 391 - } 392 - // getter and setter for warp, warpNoise, warp2 and warpNoise2 393 - get warp() { 394 - return this.getParameter(this._warp); 395 - } 396 - set warp(value) { 397 - this._warp = this.checkParameterInput(value); 398 - } 399 - get warpNoise() { 400 - return this._warpNoise; 401 - } 402 - set warpNoise(value) { 403 - if (value == undefined) { 404 - this._warpNoise = undefined; 405 - return; 406 - } 407 - const processed = this.checkParameterInput(value); 408 - if (processed instanceof UberNoise) { 409 - this._warpNoise = processed; 410 - } 411 - } 412 - get warp2() { 413 - return this.getParameter(this._warp2); 414 - } 415 - set warp2(value) { 416 - this._warp2 = this.checkParameterInput(value); 417 - } 418 - get warpNoise2() { 419 - return this._warpNoise2; 420 - } 421 - set warpNoise2(value) { 422 - if (value == undefined) { 423 - this._warpNoise2 = undefined; 424 - return; 425 - } 426 - const processed = this.checkParameterInput(value); 427 - if (processed instanceof UberNoise) { 428 - this._warpNoise2 = processed; 429 - } 430 - } 431 - } 432 - export { UberNoise, }; 1 + var v0=Object.create;var{defineProperty:f0,getPrototypeOf:d0,getOwnPropertyNames:z0}=Object;var w0=Object.prototype.hasOwnProperty;var l0=(C,E,L)=>{L=C!=null?v0(d0(C)):{};const D=E||!C||!C.__esModule?f0(L,"default",{value:C,enumerable:!0}):L;for(let I of z0(C))if(!w0.call(D,I))f0(D,I,{get:()=>C[I],enumerable:!0});return D};var t0=(C,E)=>()=>(E||C((E={exports:{}}).exports,E),E.exports);var j0=t0((F0,g0)=>{(function(C,E){if(typeof F0==="object")g0.exports=E();else if(typeof define==="function"&&define.amd)define(E);else C.Alea=E()})(F0,function(){return C.importState=function(L){var D=new C;return D.importState(L),D},C;function C(){return function(L){var D=0,I=0,_=0,B=1;if(L.length==0)L=[+new Date];var H=E();D=H(" "),I=H(" "),_=H(" ");for(var S=0;S<L.length;S++){if(D-=H(L[S]),D<0)D+=1;if(I-=H(L[S]),I<0)I+=1;if(_-=H(L[S]),_<0)_+=1}H=null;var K=function(){var T=2091639*D+B*0.00000000023283064365386964;return D=I,I=_,_=T-(B=T|0)};return K.next=K,K.uint32=function(){return K()*4294967296},K.fract53=function(){return K()+(K()*2097152|0)*0.00000000000000011102230246251566},K.version="Alea 0.9",K.args=L,K.exportState=function(){return[D,I,_,B]},K.importState=function(T){D=+T[0]||0,I=+T[1]||0,_=+T[2]||0,B=+T[3]||0},K}(Array.prototype.slice.call(arguments))}function E(){var L=4022871197,D=function(I){I=I.toString();for(var _=0;_<I.length;_++){L+=I.charCodeAt(_);var B=0.02519603282416938*L;L=B>>>0,B-=L,B*=L,L=B>>>0,B-=L,L+=B*4294967296}return(L>>>0)*0.00000000023283064365386964};return D.version="Mash 0.9",D}})});function c0(C=Math.random){const E=A0(C),L=new Float64Array(E).map((I)=>h0[I%12*2]),D=new Float64Array(E).map((I)=>h0[I%12*2+1]);return function I(_,B){let H=0,S=0,K=0;const T=(_+B)*y0,W=v(_+T),b=v(B+T),U=(W+b)*B0,c=W-U,G=b-U,Y=_-c,F=B-G;let N,u;if(Y>F)N=1,u=0;else N=0,u=1;const k=Y-N+B0,Q=F-u+B0,A=Y-1+2*B0,q=F-1+2*B0,f=W&255,h=b&255;let V=0.5-Y*Y-F*F;if(V>=0){const J=f+E[h],X=L[J],Z=D[J];V*=V,H=V*V*(X*Y+Z*F)}let $=0.5-k*k-Q*Q;if($>=0){const J=f+N+E[h+u],X=L[J],Z=D[J];$*=$,S=$*$*(X*k+Z*Q)}let M=0.5-A*A-q*q;if(M>=0){const J=f+1+E[h+1],X=L[J],Z=D[J];M*=M,K=M*M*(X*A+Z*q)}return 70*(H+S+K)}}function N0(C=Math.random){const E=A0(C),L=new Float64Array(E).map((_)=>Y0[_%12*3]),D=new Float64Array(E).map((_)=>Y0[_%12*3+1]),I=new Float64Array(E).map((_)=>Y0[_%12*3+2]);return function _(B,H,S){let K,T,W,b;const U=(B+H+S)*0.3333333333333333,c=v(B+U),G=v(H+U),Y=v(S+U),F=(c+G+Y)*0.16666666666666666,N=c-F,u=G-F,k=Y-F,Q=B-N,A=H-u,q=S-k;let f,h,V,$,M,J;if(Q>=A)if(A>=q)f=1,h=0,V=0,$=1,M=1,J=0;else if(Q>=q)f=1,h=0,V=0,$=1,M=0,J=1;else f=0,h=0,V=1,$=1,M=0,J=1;else if(A<q)f=0,h=0,V=1,$=0,M=1,J=1;else if(Q<q)f=0,h=1,V=0,$=0,M=1,J=1;else f=0,h=1,V=0,$=1,M=1,J=0;const X=Q-f+0.16666666666666666,Z=A-h+0.16666666666666666,g=q-V+0.16666666666666666,j=Q-$+0.3333333333333333,s=A-M+0.3333333333333333,p=q-J+0.3333333333333333,n=Q-1+0.5,e=A-1+0.5,i=q-1+0.5,y=c&255,x=G&255,m=Y&255;let d=0.6-Q*Q-A*A-q*q;if(d<0)K=0;else{const O=y+E[x+E[m]];d*=d,K=d*d*(L[O]*Q+D[O]*A+I[O]*q)}let z=0.6-X*X-Z*Z-g*g;if(z<0)T=0;else{const O=y+f+E[x+h+E[m+V]];z*=z,T=z*z*(L[O]*X+D[O]*Z+I[O]*g)}let w=0.6-j*j-s*s-p*p;if(w<0)W=0;else{const O=y+$+E[x+M+E[m+J]];w*=w,W=w*w*(L[O]*j+D[O]*s+I[O]*p)}let l=0.6-n*n-e*e-i*i;if(l<0)b=0;else{const O=y+1+E[x+1+E[m+1]];l*=l,b=l*l*(L[O]*n+D[O]*e+I[O]*i)}return 32*(K+T+W+b)}}function u0(C=Math.random){const E=A0(C),L=new Float64Array(E).map((B)=>H0[B%32*4]),D=new Float64Array(E).map((B)=>H0[B%32*4+1]),I=new Float64Array(E).map((B)=>H0[B%32*4+2]),_=new Float64Array(E).map((B)=>H0[B%32*4+3]);return function B(H,S,K,T){let W,b,U,c,G;const Y=(H+S+K+T)*x0,F=v(H+Y),N=v(S+Y),u=v(K+Y),k=v(T+Y),Q=(F+N+u+k)*R,A=F-Q,q=N-Q,f=u-Q,h=k-Q,V=H-A,$=S-q,M=K-f,J=T-h;let X=0,Z=0,g=0,j=0;if(V>$)X++;else Z++;if(V>M)X++;else g++;if(V>J)X++;else j++;if($>M)Z++;else g++;if($>J)Z++;else j++;if(M>J)g++;else j++;const s=X>=3?1:0,p=Z>=3?1:0,n=g>=3?1:0,e=j>=3?1:0,i=X>=2?1:0,y=Z>=2?1:0,x=g>=2?1:0,m=j>=2?1:0,d=X>=1?1:0,z=Z>=1?1:0,w=g>=1?1:0,l=j>=1?1:0,O=V-s+R,J0=$-p+R,K0=M-n+R,V0=J-e+R,$0=V-i+2*R,M0=$-y+2*R,P0=M-x+2*R,T0=J-m+2*R,O0=V-d+3*R,S0=$-z+3*R,Q0=M-w+3*R,R0=J-l+3*R,W0=V-1+4*R,q0=$-1+4*R,X0=M-1+4*R,Z0=J-1+4*R,o=F&255,a=N&255,r=u&255,C0=k&255;let E0=0.6-V*V-$*$-M*M-J*J;if(E0<0)W=0;else{const P=o+E[a+E[r+E[C0]]];E0*=E0,W=E0*E0*(L[P]*V+D[P]*$+I[P]*M+_[P]*J)}let L0=0.6-O*O-J0*J0-K0*K0-V0*V0;if(L0<0)b=0;else{const P=o+s+E[a+p+E[r+n+E[C0+e]]];L0*=L0,b=L0*L0*(L[P]*O+D[P]*J0+I[P]*K0+_[P]*V0)}let D0=0.6-$0*$0-M0*M0-P0*P0-T0*T0;if(D0<0)U=0;else{const P=o+i+E[a+y+E[r+x+E[C0+m]]];D0*=D0,U=D0*D0*(L[P]*$0+D[P]*M0+I[P]*P0+_[P]*T0)}let I0=0.6-O0*O0-S0*S0-Q0*Q0-R0*R0;if(I0<0)c=0;else{const P=o+d+E[a+z+E[r+w+E[C0+l]]];I0*=I0,c=I0*I0*(L[P]*O0+D[P]*S0+I[P]*Q0+_[P]*R0)}let _0=0.6-W0*W0-q0*q0-X0*X0-Z0*Z0;if(_0<0)G=0;else{const P=o+1+E[a+1+E[r+1+E[C0+1]]];_0*=_0,G=_0*_0*(L[P]*W0+D[P]*q0+I[P]*X0+_[P]*Z0)}return 27*(W+b+U+c+G)}}function A0(C){const L=new Uint8Array(512);for(let D=0;D<256;D++)L[D]=D;for(let D=0;D<255;D++){const I=D+~~(C()*(256-D)),_=L[D];L[D]=L[I],L[I]=_}for(let D=256;D<512;D++)L[D]=L[D-256];return L}var b0=Math.sqrt(3),U0=Math.sqrt(5),y0=0.5*(b0-1),B0=(3-b0)/6;var x0=(U0-1)/4,R=(5-U0)/20,v=(C)=>Math.floor(C)|0,h0=new Float64Array([1,1,-1,1,1,-1,-1,-1,1,0,-1,0,1,0,-1,0,0,1,0,-1,0,1,0,-1]),Y0=new Float64Array([1,1,0,-1,1,0,1,-1,0,-1,-1,0,1,0,1,-1,0,1,1,0,-1,-1,0,-1,0,1,1,0,-1,1,0,1,-1,0,-1,-1]),H0=new Float64Array([0,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,1,0,1,1,1,0,1,-1,1,0,-1,1,1,0,-1,-1,-1,0,1,1,-1,0,1,-1,-1,0,-1,1,-1,0,-1,-1,1,1,0,1,1,1,0,-1,1,-1,0,1,1,-1,0,-1,-1,1,0,1,-1,1,0,-1,-1,-1,0,1,-1,-1,0,-1,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,0]);var k0=l0(j0(),1),G0=function(C,E,L){return(E-C)*L+C};class t{noise2D;noise3D;noise4D;seed;_min=-1;_max=1;_scale=1;_power=1;shift={x:0,y:0};octaves=0;_gain=0.5;_lacunarity=2;amps=[];_sharpness=0;_steps=0;_warp=0;_warpNoise;_warp2=0;_warpNoise2;tileX=!1;tileY=!1;position={x:0,y:0};pngr;layers=[];constructor(C={}){this.seed=C.seed??Math.random(),this.pngr=k0.default(this.seed),this.min=C.min??-1,this.max=C.max??1,this.scale=C.scale??1,this.power=C.power??1,this.octaves=C.octaves??C.layers?.length??0,this.gain=C.gain??0.5,this.lacunarity=C.lacunarity??2,this.sharpness=C.sharpness??0,this.steps=C.steps??0,this.warp=C.warp??0,this.warpNoise=C.warpNoise,this.warp2=C.warp2??0,this.warpNoise2=C.warpNoise2,this.amps=C.amps??[],this.tileX=C.tileX??C.tile??!1,this.tileY=C.tileY??C.tile??!1,this.createLayers(C)}createLayers(C){for(let E=0;E<this.octaves;E++){const L=C.layers?.[E]??{};if(L instanceof t){this.layers[E]=L;continue}if(L.seed===void 0)L.seed=this.pngr();this.layers[E]=new t(L)}if(this.layers.length==0)this.noise2D=c0(this.pngr),this.noise3D=N0(this.pngr),this.noise4D=u0(this.pngr)}warpPosition(C,E){if(C==null||C==0)return;if(E!=null)E.position=this.position;let L=this.position.x,D=this.position.y,I=this.position.z,_=this.position.w;const B=E??this,H=this.scale;if(this.position.x=L+54.47*H,this.position.y=D-34.98*H,I!=null)this.position.z=I+21.63*H;if(_!=null)this.position.w=_-67.1*H;if(L+=B.getFBM()*C,D+=B.getFBM()*C,I!=null)I+=B.getFBM()*C;if(_!=null)_+=B.getFBM()*C;this.position.x=L,this.position.y=D,this.position.z=I,this.position.w=_}tilePosition(){if(!this.tileX&&!this.tileY)return;const C=this.position.x,E=this.position.y;let L=0,D=0,I=0,_=0;if(this.tileX)L=Math.sin(C*Math.PI*2),D=Math.cos(C*Math.PI*2);if(this.tileY)I=Math.sin(E*Math.PI*2),_=Math.cos(E*Math.PI*2);if(this.tileX&&!this.tileY)this.position.x=L,this.position.y=D+E;else if(this.tileY&&!this.tileX)this.position.x=I+C,this.position.y=_;else if(this.tileX&&this.tileY)this.position.x=L,this.position.y=D,this.position.z=I,this.position.w=_}getFBM(){const C=this.position.x,E=this.position.y,L=this.position.z,D=this.position.w,I=this.scale;if(this.layers.length==0){if(L!=null&&D!=null&&this.noise4D!=null)return this.noise4D(C*I,E*I,L*I,D*I);if(L!=null&&this.noise3D!=null)return this.noise3D(C*I,E*I,L*I);if(this.noise2D!=null)return this.noise2D(C*I,E*I);return 0}let _=1,B=1,H=I;const S=this.lacunarity,K=this.gain;let T=0;for(let W=0;W<this.octaves;W++){const b=this.layers[W],U=this.amps[W]??1,c=b.get(C*H,E*H,L!=null?L*H:void 0,D!=null?D*H:void 0)*B*U;T+=c,B*=K,H*=S,_+=B*U}return T/_}applyShift(){const C=this.shift;if(C!==void 0){if(this.position.x+=C.x,this.position.y+=C.y,this.position.z)this.position.z+=C.z??0;if(this.position.w)this.position.w+=C.w??0}}applyPower(C){const E=this.power;if(E!=1)C=(Math.pow((C+1)*0.5,E)-0.5)*2;return C}applySharpness(C){const E=this.sharpness;if(E!=0){const L=(Math.abs(C)-0.5)*2,D=(0.5-Math.abs(C))*2;C=G0(C,L,Math.max(0,E)),C=G0(C,D,Math.max(0,-E))}return C}applySteps(C){const E=this.steps;if(E!=0)C=(C+1)*0.5,C=Math.floor(C*E)/E,C=C*2-1;return C}getNoise(C,E,L=void 0,D=void 0){this.position.x=C,this.position.y=E,this.position.z=L,this.position.w=D,this.applyShift(),this.tilePosition(),this.warpPosition(this.warp,this.warpNoise),this.warpPosition(this.warp2,this.warpNoise2);let I=this.getFBM();return I=this.applyPower(I),I=this.applySharpness(I),I=this.applySteps(I),I}get(C,E=void 0,L=void 0,D=void 0){const I=this.normalized(C,E,L,D);return this.normalizedToMinMax(I)}normalized(C,E=void 0,L=void 0,D=void 0){if(Array.isArray(C))D=C[3],L=C[2],E=C[1],C=C[0];else if(typeof C==="object")D=C.w,L=C.z,E=C.y,C=C.x;return E=E??0,this.getNoise(C,E,L,D)}minMaxToNormalized(C){return(C-this.min)/(this.max-this.min)*2-1}normalizedToMinMax(C){return(C+1)*0.5*(this.max-this.min)+this.min}move(C,E,L=void 0,D=void 0){if(!this.shift){this.shift={x:C,y:E,z:L,w:D};return}if(this.shift.x+=C,this.shift.y+=E,L!=null)this.shift.z=(this.shift.z??0)+L;if(D!=null)this.shift.w=(this.shift.w??0)+D;return this}checkParameterInput(C){if(typeof C==="object"&&!(C instanceof t)){if(C.seed===void 0)C.seed=this.pngr();C=new t(C)}return C}getParameter(C){if(typeof C==="number")return C;return C.get(this.position)}get min(){return this.getParameter(this._min)}set min(C){this._min=this.checkParameterInput(C)}get max(){return this.getParameter(this._max)}set max(C){this._max=this.checkParameterInput(C)}get scale(){return this.getParameter(this._scale)}set scale(C){this._scale=this.checkParameterInput(C)}get power(){return this.getParameter(this._power)}set power(C){this._power=this.checkParameterInput(C)}get gain(){return this.getParameter(this._gain)}set gain(C){this._gain=this.checkParameterInput(C)}get lacunarity(){return this.getParameter(this._lacunarity)}set lacunarity(C){this._lacunarity=this.checkParameterInput(C)}get sharpness(){return this.getParameter(this._sharpness)}set sharpness(C){this._sharpness=this.checkParameterInput(C)}get steps(){return Math.round(this.getParameter(this._steps))}set steps(C){this._steps=this.checkParameterInput(C)}get warp(){return this.getParameter(this._warp)}set warp(C){this._warp=this.checkParameterInput(C)}get warpNoise(){return this._warpNoise}set warpNoise(C){if(C==null){this._warpNoise=void 0;return}const E=this.checkParameterInput(C);if(E instanceof t)this._warpNoise=E}get warp2(){return this.getParameter(this._warp2)}set warp2(C){this._warp2=this.checkParameterInput(C)}get warpNoise2(){return this._warpNoise2}set warpNoise2(C){if(C==null){this._warpNoise2=void 0;return}const E=this.checkParameterInput(C);if(E instanceof t)this._warpNoise2=E}}export{t as default,t as UberNoise};
+17 -2
package.json
··· 4 4 "version": "0.2.1", 5 5 "description": "uber-noise is a advanced noise library for 2D, 3D and 4D noise generation. based on simplex-noise", 6 6 "scripts": { 7 - "build": "tsc", 7 + "build": "tsc --noEmit && bun build ./src/uber-noise.ts --outdir ./dist --target browser --format esm --minify", 8 8 "dev": "tsc -w", 9 - "test": "bun test", 9 + "test": "bun test --coverage", 10 10 "measure": "bun run uber-noise.benchmark.ts" 11 11 }, 12 12 "main": "./dist/uber-noise.js", ··· 17 17 "default": "./dist/uber-noise.js" 18 18 } 19 19 }, 20 + "repository": { 21 + "type": "git", 22 + "url": "https://github.com/flo-bit/uber-noise.git" 23 + }, 24 + "bugs": { 25 + "url": "https://github.com/flo-bit/uber-noise/issues" 26 + }, 27 + "homepage": "https://github.com/flo-bit/uber-noise#readme", 28 + "engines": { 29 + "node": ">=14" 30 + }, 20 31 "keywords": [ 21 32 "noise", 22 33 "simplex" 34 + ], 35 + "files": [ 36 + "dist", 37 + "src" 23 38 ], 24 39 "author": "flo-bit", 25 40 "license": "MIT",
+134 -72
src/uber-noise.ts
··· 9 9 10 10 import alea from 'alea'; 11 11 12 - /** 13 - * 14 - * @property {number} seed - seed for the noise, if not provided, Math.random() will be used, 15 - * currently same results can only be guaranteed for newly created noise objects with same seed 16 - * (as opposed to an old noise object where you changed the seed) 17 - * 18 - * @property {number} min - minimun value of noise 19 - * @property {number} max - maximum value of noise 20 - * 21 - * @property {number} scale - scale of the noise 22 - * @property {number} power - power of the noise (1 = linear, 2 = quadratic, etc) 23 - * @property {Vector} shift - move noise in 2D, 3D or 4D space 24 - * 25 - * @property {number} octaves - number of layers for fbm noise 26 - * @property {number} gain - how much to multiply amplitude per layer 27 - * @property {number} lacunarity - how much to multiply scale per layer 28 - * @property {array} amps - array of amplitudes for each layer 29 - * @property {number} erosion - how much previous layers influence amplitude of later layers 30 - * @property {number} sharpness - billowed or rigded noise (0 = normal, 1 = billowed, -1 = ridged) 31 - * @property {number} steps - will turn noise into steps (integer, number of steps) 32 - * 33 - * @property {number} warp - how much to warp the noise 34 - * @property {number} warpNoise - noise to warp the noise with 35 - * @property {number} warp2 - second warp, can only be used if warp is used too 36 - * @property {number} warpNoise2 - second warp noise 37 - * 38 - * @property {boolean} invert - invert the noise 39 - * @property {boolean} abs - absolute value of the noise 40 - * @property {boolean} clamp - clamp the noise between min and max 41 - * @property {boolean} tileX - tile the noise in x direction 42 - * @property {boolean} tileY - tile the noise in y direction 43 - * @property {boolean} tile - tile the noise in all directions (will override tileX and tileY) 44 - * 45 - * @constructor 46 - */ 47 - 48 12 function lerp(a: number, b: number, t: number): number { 49 13 return (b - a) * t + a; 50 14 } ··· 56 20 w?: number; 57 21 }; 58 22 59 - type NoiseParameterInput = number | UberNoise | NoiseOptions; 60 23 type NoiseParameter = number | UberNoise; 61 24 62 25 type NoiseOptions = { 63 26 /** 64 27 * seed for the noise, if not provided, Math.random() will be used, 28 + * 29 + * @default Math.random() 65 30 */ 66 31 seed?: string | number; 67 32 68 33 /** 69 34 * minimun value of noise 35 + * 36 + * @default -1 70 37 */ 71 - min?: NoiseParameterInput; 38 + min?: number | UberNoise | NoiseOptions; 72 39 73 40 /** 74 41 * maximum value of noise 42 + * 43 + * @default 1 75 44 */ 76 - max?: NoiseParameterInput; 45 + max?: number | UberNoise | NoiseOptions; 77 46 78 47 /** 79 48 * scale of the noise ("zoom" in or out) 49 + * 50 + * @default 1 80 51 */ 81 - scale?: NoiseParameterInput; 52 + scale?: number | UberNoise | NoiseOptions; 82 53 83 54 /** 84 55 * power of the noise (1 = linear, 2 = quadratic, etc) 56 + * 57 + * @default 1 85 58 */ 86 - power?: NoiseParameterInput; 59 + power?: number | UberNoise | NoiseOptions; 87 60 88 61 /** 89 62 * move noise in 2D, 3D or 4D space 63 + * 64 + * @default [0, 0, 0, 0] 90 65 */ 91 66 shift?: number[]; 92 67 93 68 /** 94 69 * number of layers for fbm noise 70 + * 71 + * @default 0 95 72 */ 96 73 octaves?: number; 74 + 97 75 /** 98 76 * how much to multiply amplitude per fbm layer 77 + * 78 + * @default 0.5 99 79 */ 100 - gain?: NoiseParameterInput; 80 + gain?: number | UberNoise | NoiseOptions; 81 + 101 82 /** 102 83 * how much to multiply scale per fbm layer 84 + * 85 + * @default 2 103 86 */ 104 - lacunarity?: NoiseParameterInput; 87 + lacunarity?: number | UberNoise | NoiseOptions; 105 88 106 89 /** 107 90 * array of amplitudes for each fbm layer 91 + * 92 + * @default [] 108 93 */ 109 94 amps?: number[]; 110 95 111 96 /** 112 97 * custom noise options for each fbm layer 98 + * 99 + * @default [] 113 100 */ 114 101 layers?: NoiseOptions[]; 115 102 116 103 /** 117 104 * billowed or rigded noise (0 = normal, 1 = billowed, -1 = ridged) 105 + * 106 + * @default 0 118 107 */ 119 - sharpness?: NoiseParameterInput; 108 + sharpness?: number | UberNoise | NoiseOptions; 109 + 120 110 /** 121 111 * will turn noise into discrete steps (integer, number of steps) 112 + * 113 + * @default 0 122 114 */ 123 - steps?: NoiseParameterInput; 115 + steps?: number | UberNoise | NoiseOptions; 124 116 125 117 /** 126 118 * how much to warp the noise 119 + * 120 + * @default 0 127 121 */ 128 - warp?: NoiseParameterInput; 122 + warp?: number | UberNoise | NoiseOptions; 123 + 129 124 /** 130 125 * custom noise to warp the noise with 126 + * 127 + * @default undefined 131 128 */ 132 129 warpNoise?: UberNoise; 130 + 133 131 /** 134 - * second warp, can only be used if warp is used 135 - * too 132 + * second warp, can only be used if warp is used too 133 + * 134 + * @default 0 136 135 */ 137 - warp2?: NoiseParameterInput; 136 + warp2?: number | UberNoise | NoiseOptions; 138 137 /** 139 138 * second warp noise 139 + * 140 + * @default undefined 140 141 */ 141 142 warpNoise2?: UberNoise; 142 143 143 144 /** 144 145 * should the noise be inverted 146 + * 147 + * @default false 145 148 */ 146 149 invert?: boolean; 150 + 147 151 /** 148 152 * should we take the absolute value of the noise 153 + * 154 + * @default false 149 155 */ 150 156 abs?: boolean; 157 + 151 158 /** 152 159 * should we clamp the noise between min and max 160 + * 161 + * @default false 153 162 */ 154 163 clamp?: boolean; 155 164 156 165 /** 157 166 * tile the noise in x direction 167 + * 168 + * @default false 158 169 */ 159 170 tileX?: boolean; 160 171 /** 161 172 * tile the noise in y direction 173 + * 174 + * @default false 162 175 */ 163 176 tileY?: boolean; 164 177 /** 165 178 * tile the noise in all directions (will override tileX and tileY) 179 + * 180 + * @default false 166 181 */ 167 182 tile?: boolean; 168 183 }; ··· 190 205 191 206 private amps: number[] = []; 192 207 193 - private _erosion: NoiseParameter = 0; 194 208 private _sharpness: NoiseParameter = 0; 195 209 private _steps: NoiseParameter = 0; 196 210 ··· 453 467 return norm; 454 468 } 455 469 456 - // same as normalized but returns between min and max 470 + /** 471 + * get noise value at position x, y, z, w 472 + * 473 + * all transformations will be applied to the noise (shift, warp, power, sharpness, steps, min, max, fmb, etc) 474 + * 475 + * either pass in 476 + * - x, y, z, w as separate arguments 477 + * - as first argument an object {x, y, z, w} 478 + * - as first argument an array [x, y, z, w] 479 + * 480 + * if y is not provided, it will be set to 0 481 + * if z is not provided, will use 2D noise 482 + * if w is not provided, will use 3D noise 483 + * 484 + * @param x {number | VectorLikeObject | Array<number>} 485 + * @param y {number | undefined} 486 + * @param z {number | undefined} 487 + * @param w {number | undefined} 488 + * @returns {number} 489 + */ 457 490 get( 458 491 x: number | VectorLikeObject | Array<number>, 459 492 y: number | undefined = undefined, ··· 464 497 return this.normalizedToMinMax(norm); 465 498 } 466 499 467 - // same as get but returns between -1 and 1 500 + /** 501 + * get normalized noise value at position x, y, z, w 502 + * 503 + * all transformations will be applied to the noise (shift, warp, power, sharpness, steps, fmb, etc) 504 + * EXCEPT min and max, noise will be returned as a value between -1 and 1 505 + * 506 + * either pass in 507 + * - x, y, z, w as separate arguments 508 + * - as first argument an object {x, y, z, w} 509 + * - as first argument an array [x, y, z, w] 510 + * 511 + * if y is not provided, it will be set to 0 512 + * if z is not provided, will use 2D noise 513 + * if w is not provided, will use 3D noise 514 + * 515 + * @param x {number | VectorLikeObject | Array<number>} 516 + * @param y {number | undefined} 517 + * @param z {number | undefined} 518 + * @param w {number | undefined} 519 + * @returns {number} 520 + */ 468 521 normalized( 469 522 x: number | VectorLikeObject | Array<number>, 470 523 y: number | undefined = undefined, ··· 509 562 return (value + 1) * 0.5 * (this.max - this.min) + this.min; 510 563 } 511 564 565 + /** 566 + * 567 + * shift the noise in 2D, 3D or 4D space, will be added to the position 568 + * 569 + * if called multiple times, the shifts will be added 570 + * 571 + * returns the UberNoise object for chaining 572 + * 573 + * @param x {number} 574 + * @param y {number} 575 + * @param z {number | undefined} 576 + * @param w {number | undefined} 577 + * @returns {UberNoise} 578 + */ 512 579 move( 513 580 x: number, 514 581 y: number, ··· 528 595 if (w != undefined) { 529 596 this.shift.w = (this.shift.w ?? 0) + w; 530 597 } 598 + 599 + return this; 531 600 } 532 601 533 - private checkParameterInput(value: NoiseParameterInput): UberNoise | number { 602 + private checkParameterInput( 603 + value: number | UberNoise | NoiseOptions, 604 + ): UberNoise | number { 534 605 if (typeof value === 'object' && !(value instanceof UberNoise)) { 535 606 if (value.seed === undefined) { 536 607 value.seed = this.pngr(); ··· 551 622 get min(): number { 552 623 return this.getParameter(this._min); 553 624 } 554 - set min(value: NoiseParameterInput) { 625 + set min(value: number | UberNoise | NoiseOptions) { 555 626 this._min = this.checkParameterInput(value); 556 627 } 557 628 get max(): number { 558 629 return this.getParameter(this._max); 559 630 } 560 - set max(value: NoiseParameterInput) { 631 + set max(value: number | UberNoise | NoiseOptions) { 561 632 this._max = this.checkParameterInput(value); 562 633 } 563 634 ··· 565 636 get scale(): number { 566 637 return this.getParameter(this._scale); 567 638 } 568 - set scale(value: NoiseParameterInput) { 639 + set scale(value: number | UberNoise | NoiseOptions) { 569 640 this._scale = this.checkParameterInput(value); 570 641 } 571 642 get power(): number { 572 643 return this.getParameter(this._power); 573 644 } 574 - set power(value: NoiseParameterInput) { 645 + set power(value: number | UberNoise | NoiseOptions) { 575 646 this._power = this.checkParameterInput(value); 576 647 } 577 648 ··· 579 650 get gain(): number { 580 651 return this.getParameter(this._gain); 581 652 } 582 - set gain(value: NoiseParameterInput) { 653 + set gain(value: number | UberNoise | NoiseOptions) { 583 654 this._gain = this.checkParameterInput(value); 584 655 } 585 656 get lacunarity(): number { 586 657 return this.getParameter(this._lacunarity); 587 658 } 588 - set lacunarity(value: NoiseParameterInput) { 659 + set lacunarity(value: number | UberNoise | NoiseOptions) { 589 660 this._lacunarity = this.checkParameterInput(value); 590 661 } 591 662 592 - // getter and setter for erosion, sharpness and steps 593 - get erosion(): number { 594 - return this.getParameter(this._erosion); 595 - } 596 - set erosion(value: NoiseParameterInput) { 597 - this._erosion = this.checkParameterInput(value); 598 - } 599 663 get sharpness(): number { 600 664 return this.getParameter(this._sharpness); 601 665 } 602 - set sharpness(value: NoiseParameterInput) { 666 + set sharpness(value: number | UberNoise | NoiseOptions) { 603 667 this._sharpness = this.checkParameterInput(value); 604 668 } 605 669 get steps(): number { 606 670 return Math.round(this.getParameter(this._steps)); 607 671 } 608 - set steps(value: NoiseParameterInput) { 672 + set steps(value: number | UberNoise | NoiseOptions) { 609 673 this._steps = this.checkParameterInput(value); 610 674 } 611 675 612 - // getter and setter for warp, warpNoise, warp2 and warpNoise2 613 676 get warp(): number { 614 677 return this.getParameter(this._warp); 615 678 } 616 - set warp(value: NoiseParameterInput) { 679 + set warp(value: number | UberNoise | NoiseOptions) { 617 680 this._warp = this.checkParameterInput(value); 618 681 } 619 682 get warpNoise(): UberNoise | undefined { ··· 633 696 get warp2(): number { 634 697 return this.getParameter(this._warp2); 635 698 } 636 - set warp2(value: NoiseParameterInput) { 699 + set warp2(value: number | UberNoise | NoiseOptions) { 637 700 this._warp2 = this.checkParameterInput(value); 638 701 } 639 702 get warpNoise2(): UberNoise | undefined { ··· 656 719 UberNoise, 657 720 type NoiseOptions, 658 721 type NoiseParameter, 659 - type NoiseParameterInput, 660 722 type VectorLikeObject as VectorObject, 661 723 };
+141 -1
uber-noise.test.ts
··· 38 38 const value3 = noise.get(0, size); 39 39 const value4 = noise.get(size, size); 40 40 41 + const value5 = noise.get(size * 2, 0); 42 + const value6 = noise.get(0, size * 2); 43 + const value7 = noise.get(size * 2, size * 2); 44 + 41 45 expect(value1).toBeCloseTo(value2, 5); 42 46 expect(value1).toBeCloseTo(value3, 5); 43 47 expect(value1).toBeCloseTo(value4, 5); 48 + 49 + expect(value1).toBeCloseTo(value5, 5); 50 + expect(value1).toBeCloseTo(value6, 5); 51 + expect(value1).toBeCloseTo(value7, 5); 44 52 }); 45 53 46 54 test('Sharpness affects the noise output', () => { ··· 80 88 }); 81 89 82 90 test('shifting the noise works', () => { 83 - const noise = new UberNoise({ seed: 12345, octaves: 1 }); 91 + const noise = new UberNoise({ 92 + seed: 12345, 93 + octaves: 1, 94 + }); 84 95 85 96 const value = noise.get(0.5, 0.5); 86 97 noise.move(1, 1); ··· 88 99 89 100 expect(value).toBeCloseTo(secondValue); 90 101 }); 102 + 103 + test('min max to normalized', () => { 104 + const noise = new UberNoise({ seed: 12345, min: 0.2, max: 10.8 }); 105 + 106 + const value = noise.get(0.5, 0.5); 107 + const normalized = noise.normalized(0.5, 0.5); 108 + 109 + const expected = noise.minMaxToNormalized(value); 110 + 111 + expect(normalized).toBeCloseTo(expected); 112 + }); 113 + 114 + test('test values', () => { 115 + const noise = new UberNoise({ 116 + seed: 12345, 117 + min: -0.2, 118 + max: 0.8, 119 + octaves: 5, 120 + lacunarity: 2.5, 121 + sharpness: 0.5, 122 + power: 2, 123 + shift: [1, 2, 3], 124 + scale: 2, 125 + steps: 200, 126 + warp: 2, 127 + invert: true, 128 + abs: true, 129 + clamp: true, 130 + }); 131 + 132 + const expected = [ 133 + [ 134 + 0.145, 0.28, 0.18, 0.175, 0.125, 0.155, 0.23, 0.245, 0.095, 0.135, 0.16, 135 + 0.21, 0.225, 0.13, 0.26, 0.175, 0.235, 0.22, 0.145, 0.245, 136 + ], 137 + [ 138 + 0.165, 0.16, 0.25, 0.17, 0.24, 0.22, 0.185, 0.145, 0.255, 0.26, 0.19, 139 + 0.225, 0.115, 0.16, 0.19, 0.155, 0.2, 0.19, 0.14, 0.12, 140 + ], 141 + [ 142 + 0.235, 0.2, 0.14, 0.18, 0.185, 0.14, 0.125, 0.145, 0.22, 0.17, 0.185, 143 + 0.225, 0.2, 0.22, 0.175, 0.15, 0.135, 0.205, 0.17, 0.25, 144 + ], 145 + [ 146 + 0.05, 0.065, 0.235, 0.17, 0.225, 0.06, 0.16, 0.16, 0.13, 0.145, 0.205, 147 + 0.16, 0.08, 0.11, 0.22, 0.085, 0.11, 0.22, 0.23, 0.18, 148 + ], 149 + [ 150 + 0.225, 0.14, 0.195, 0.075, 0.26, 0.25, 0.245, 0.145, 0.165, 0.09, 0.125, 151 + 0.18, 0.165, 0.125, 0.075, 0.075, 0.235, 0.23, 0.21, 0.235, 152 + ], 153 + [ 154 + 0.145, 0.26, 0.225, 0.215, 0.23, 0.19, 0.175, 0.125, 0.245, 0.235, 0.11, 155 + 0.245, 0.265, 0.28, 0.185, 0.245, 0.175, 0.09, 0.175, 0.11, 156 + ], 157 + [ 158 + 0.065, 0.115, 0.165, 0.055, 0.07, 0.08, 0.105, 0.24, 0.125, 0.11, 0.18, 159 + 0.18, 0.185, 0.05, 0.135, 0.06, 0.23, 0.12, 0.22, 0.255, 160 + ], 161 + [ 162 + 0.215, 0.225, 0.24, 0.11, 0.15, 0.19, 0.2, 0.23, 0.185, 0.18, 0.155, 163 + 0.175, 0.24, 0.085, 0.145, 0.165, 0.26, 0.115, 0.06, 0.18, 164 + ], 165 + [ 166 + 0.28, 0.225, 0.075, 0.25, 0.255, 0.1, 0.185, 0.24, 0.13, 0.16, 0.24, 0.24, 167 + 0.225, 0.23, 0.15, 0.15, 0.225, 0.2, 0.125, 0.185, 168 + ], 169 + [ 170 + 0.23, 0.19, 0.21, 0.23, 0.19, 0.16, 0.21, 0.195, 0.19, 0.185, 0.225, 0.23, 171 + 0.185, 0.2, 0.115, 0.08, 0.18, 0.165, 0.165, 0.215, 172 + ], 173 + [ 174 + 0.175, 0.23, 0.15, 0.18, 0.22, 0.14, 0.18, 0.145, 0.23, 0.145, 0.115, 175 + 0.12, 0.225, 0.27, 0.155, 0.17, 0.075, 0.17, 0.12, 0.165, 176 + ], 177 + [ 178 + 0.235, 0.175, 0.205, 0.195, 0.155, 0.1, 0.16, 0.225, 0.25, 0.135, 0.175, 179 + 0.2, 0.145, 0.13, 0.11, 0.1, 0.065, 0.165, 0.19, 0.245, 180 + ], 181 + [ 182 + 0.265, 0.275, 0.05, 0.235, 0.11, 0.14, 0.225, 0.185, 0.075, 0.1, 0.225, 183 + 0.11, 0.19, 0.05, 0.21, 0.185, 0.285, 0.085, 0.245, 0.18, 184 + ], 185 + [ 186 + 0.125, 0.13, 0.06, 0.215, 0.23, 0.26, 0.23, 0.225, 0.14, 0.2, 0.155, 0.16, 187 + 0.235, 0.16, 0.17, 0.11, 0.095, 0.165, 0.125, 0.175, 188 + ], 189 + [ 190 + 0.225, 0.25, 0.165, 0.105, 0.245, 0.23, 0.14, 0.235, 0.135, 0.205, 0.165, 191 + 0.07, 0.115, 0.18, 0.24, 0.24, 0.155, 0.14, 0.18, 0.225, 192 + ], 193 + [ 194 + 0.195, 0.18, 0.16, 0.115, 0.09, 0.22, 0.12, 0.185, 0.16, 0.07, 0.18, 195 + 0.205, 0.275, 0.135, 0.235, 0.095, 0.245, 0.21, 0.18, 0.05, 196 + ], 197 + [ 198 + 0.23, 0.165, 0.235, 0.14, 0.2, 0.25, 0.16, 0.06, 0.14, 0.145, 0.165, 0.07, 199 + 0.085, 0.08, 0.255, 0.16, 0.2, 0.125, 0.15, 0.235, 200 + ], 201 + [ 202 + 0.21, 0.255, 0.105, 0.155, 0.175, 0.165, 0.235, 0.205, 0.085, 0.19, 0.055, 203 + 0.12, 0.125, 0.12, 0.21, 0.19, 0.225, 0.095, 0.155, 0.21, 204 + ], 205 + [ 206 + 0.17, 0.22, 0.19, 0.19, 0.21, 0.24, 0.135, 0.2, 0.125, 0.19, 0.21, 0.165, 207 + 0.235, 0.165, 0.125, 0.05, 0.085, 0.215, 0.225, 0.17, 208 + ], 209 + [ 210 + 0.21, 0.11, 0.11, 0.21, 0.15, 0.23, 0.245, 0.22, 0.17, 0.175, 0.19, 0.205, 211 + 0.15, 0.225, 0.095, 0.115, 0.185, 0.17, 0.18, 0.095, 212 + ], 213 + ]; 214 + 215 + let log = '[['; 216 + 217 + for (let i = 0; i < 20; i++) { 218 + for (let j = 0; j < 20; j++) { 219 + const value = noise.get(i, j); 220 + 221 + log += `${value.toFixed(5)},`; 222 + 223 + expect(value).toBeCloseTo(expected[i][j], 5); 224 + } 225 + 226 + log += '],['; 227 + } 228 + 229 + // console.log(log); 230 + });