randiny
Version:
<h1 style="margin-bottom: 0">Randiny</h1> <h2 style="font-size: 14px; margin-top: 0">A pseudo random number generator, capable of generating random numbers, and noise maps.</h2>
292 lines • 11.1 kB
JavaScript
"use strict";
/*
I couldn't figure out simplex noise. So I used a package.
I would've put it as a dependency, but I need to modify it, to use my RandomNoiseClass.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createNoise2D = createNoise2D;
exports.createNoise3D = createNoise3D;
exports.buildPermutationTable = buildPermutationTable;
const RandomNumber_1 = __importDefault(require("./RandomNumber"));
const SQRT3 = /*#__PURE__*/ Math.sqrt(3.0);
const SQRT5 = /*#__PURE__*/ Math.sqrt(5.0);
const F2 = 0.5 * (SQRT3 - 1.0);
const G2 = (3.0 - SQRT3) / 6.0;
const F3 = 1.0 / 3.0;
const G3 = 1.0 / 6.0;
const F4 = (SQRT5 - 1.0) / 4.0;
const G4 = (5.0 - SQRT5) / 20.0;
// I'm really not sure why this | 0 (basically a coercion to int)
// is making this faster but I get ~5 million ops/sec more on the
// benchmarks across the board or a ~10% speedup.
const fastFloor = (x) => Math.floor(x) | 0;
const grad2 = /*#__PURE__*/ 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]);
// double seems to be faster than single or int's
// probably because most operations are in double precision
const grad3 = /*#__PURE__*/ 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]);
// double is a bit quicker here as well
const grad4 = /*#__PURE__*/ 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]);
function createNoise2D(rng) {
const perm = buildPermutationTable(rng);
// precalculating this yields a little ~3% performance improvement.
const permGrad2x = new Float64Array(perm).map(v => grad2[(v % 12) * 2]);
const permGrad2y = new Float64Array(perm).map(v => grad2[(v % 12) * 2 + 1]);
return function noise2D(x, y) {
// if(!isFinite(x) || !isFinite(y)) return 0;
let n0 = 0; // Noise contributions from the three corners
let n1 = 0;
let n2 = 0;
// Skew the input space to determine which simplex cell we're in
const s = (x + y) * F2; // Hairy factor for 2D
const i = fastFloor(x + s);
const j = fastFloor(y + s);
const t = (i + j) * G2;
const X0 = i - t; // Unskew the cell origin back to (x,y) space
const Y0 = j - t;
const x0 = x - X0; // The x,y distances from the cell origin
const y0 = y - Y0;
// For the 2D case, the simplex shape is an equilateral triangle.
// Determine which simplex we are in.
let i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
if (x0 > y0) {
i1 = 1;
j1 = 0;
} // lower triangle, XY order: (0,0)->(1,0)->(1,1)
else {
i1 = 0;
j1 = 1;
} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
// A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
// a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
// c = (3-sqrt(3))/6
const x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
const y1 = y0 - j1 + G2;
const x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
const y2 = y0 - 1.0 + 2.0 * G2;
// Work out the hashed gradient indices of the three simplex corners
const ii = i & 255;
const jj = j & 255;
// Calculate the contribution from the three corners
let t0 = 0.5 - x0 * x0 - y0 * y0;
if (t0 >= 0) {
const gi0 = ii + perm[jj];
const g0x = permGrad2x[gi0];
const g0y = permGrad2y[gi0];
t0 *= t0;
// n0 = t0 * t0 * (grad2[gi0] * x0 + grad2[gi0 + 1] * y0); // (x,y) of grad3 used for 2D gradient
n0 = t0 * t0 * (g0x * x0 + g0y * y0);
}
let t1 = 0.5 - x1 * x1 - y1 * y1;
if (t1 >= 0) {
const gi1 = ii + i1 + perm[jj + j1];
const g1x = permGrad2x[gi1];
const g1y = permGrad2y[gi1];
t1 *= t1;
// n1 = t1 * t1 * (grad2[gi1] * x1 + grad2[gi1 + 1] * y1);
n1 = t1 * t1 * (g1x * x1 + g1y * y1);
}
let t2 = 0.5 - x2 * x2 - y2 * y2;
if (t2 >= 0) {
const gi2 = ii + 1 + perm[jj + 1];
const g2x = permGrad2x[gi2];
const g2y = permGrad2y[gi2];
t2 *= t2;
// n2 = t2 * t2 * (grad2[gi2] * x2 + grad2[gi2 + 1] * y2);
n2 = t2 * t2 * (g2x * x2 + g2y * y2);
}
// Add contributions from each corner to get the final noise value.
// The result is scaled to return values in the interval [-1,1].
return new RandomNumber_1.default(rng, 70.0 * (n0 + n1 + n2));
};
}
/**
* Creates a 3D noise function
* @returns {NoiseFunction3D}
*/
function createNoise3D(rng) {
const perm = buildPermutationTable(rng);
// precalculating these seems to yield a speedup of over 15%
const permGrad3x = new Float64Array(perm).map(v => grad3[(v % 12) * 3]);
const permGrad3y = new Float64Array(perm).map(v => grad3[(v % 12) * 3 + 1]);
const permGrad3z = new Float64Array(perm).map(v => grad3[(v % 12) * 3 + 2]);
return function noise3D(x, y, z) {
let n0, n1, n2, n3; // Noise contributions from the four corners
// Skew the input space to determine which simplex cell we're in
const s = (x + y + z) * F3; // Very nice and simple skew factor for 3D
const i = fastFloor(x + s);
const j = fastFloor(y + s);
const k = fastFloor(z + s);
const t = (i + j + k) * G3;
const X0 = i - t; // Unskew the cell origin back to (x,y,z) space
const Y0 = j - t;
const Z0 = k - t;
const x0 = x - X0; // The x,y,z distances from the cell origin
const y0 = y - Y0;
const z0 = z - Z0;
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
// Determine which simplex we are in.
let i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
let i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
if (x0 >= y0) {
if (y0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
} // X Y Z order
else if (x0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 0;
k2 = 1;
} // X Z Y order
else {
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 0;
k2 = 1;
} // Z X Y order
}
else { // x0<y0
if (y0 < z0) {
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 0;
j2 = 1;
k2 = 1;
} // Z Y X order
else if (x0 < z0) {
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 0;
j2 = 1;
k2 = 1;
} // Y Z X order
else {
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
} // Y X Z order
}
// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
// c = 1/6.
const x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
const y1 = y0 - j1 + G3;
const z1 = z0 - k1 + G3;
const x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
const y2 = y0 - j2 + 2.0 * G3;
const z2 = z0 - k2 + 2.0 * G3;
const x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
const y3 = y0 - 1.0 + 3.0 * G3;
const z3 = z0 - 1.0 + 3.0 * G3;
// Work out the hashed gradient indices of the four simplex corners
const ii = i & 255;
const jj = j & 255;
const kk = k & 255;
// Calculate the contribution from the four corners
let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
if (t0 < 0)
n0 = 0.0;
else {
const gi0 = ii + perm[jj + perm[kk]];
t0 *= t0;
n0 = t0 * t0 * (permGrad3x[gi0] * x0 + permGrad3y[gi0] * y0 + permGrad3z[gi0] * z0);
}
let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
if (t1 < 0)
n1 = 0.0;
else {
const gi1 = ii + i1 + perm[jj + j1 + perm[kk + k1]];
t1 *= t1;
n1 = t1 * t1 * (permGrad3x[gi1] * x1 + permGrad3y[gi1] * y1 + permGrad3z[gi1] * z1);
}
let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
if (t2 < 0)
n2 = 0.0;
else {
const gi2 = ii + i2 + perm[jj + j2 + perm[kk + k2]];
t2 *= t2;
n2 = t2 * t2 * (permGrad3x[gi2] * x2 + permGrad3y[gi2] * y2 + permGrad3z[gi2] * z2);
}
let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
if (t3 < 0)
n3 = 0.0;
else {
const gi3 = ii + 1 + perm[jj + 1 + perm[kk + 1]];
t3 *= t3;
n3 = t3 * t3 * (permGrad3x[gi3] * x3 + permGrad3y[gi3] * y3 + permGrad3z[gi3] * z3);
}
// Add contributions from each corner to get the final noise value.
// The result is scaled to stay just inside [-1,1]
return new RandomNumber_1.default(rng, 32.0 * (n0 + n1 + n2 + n3));
};
}
/**
* Builds a random permutation table.
* This is exported only for (internal) testing purposes.
* Do not rely on this export.
* @private
*/
function buildPermutationTable(rng) {
const tableSize = 512;
const p = new Uint8Array(tableSize);
for (let i = 0; i < tableSize / 2; i++) {
p[i] = i;
}
for (let i = 0; i < tableSize / 2 - 1; i++) {
const r = i + ~~(rng.nextValue().get() * (256 - i));
const aux = p[i];
p[i] = p[r];
p[r] = aux;
}
for (let i = 256; i < tableSize; i++) {
p[i] = p[i - 256];
}
return p;
}
//# sourceMappingURL=SimplexNoise.js.map