RosettaCodeData/Task/Perlin-noise/JavaScript/perlin-noise.js

81 lines
2.8 KiB
JavaScript

let p = Array(512).fill(0);
function fade(t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
function lerp(t, a, b) {
return a + t * (b - a);
}
function grad(hash, x, y, z) {
const h = hash & 15; // CONVERT LOW 4 BITS OF HASH CODE
const u = h < 8 ? x : y; // INTO 12 GRADIENT DIRECTIONS.
const v = h < 4 ? y : (h == 12 || h == 14) ? x : z;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
function perlinNoise(x, y, z) {
const X = Math.floor(x) & 0xff; // FIND UNIT CUBE THAT
const Y = Math.floor(y) & 0xff; // CONTAINS POINT.
const Z = Math.floor(z) & 0xff;
x -= Math.floor(x); // FIND RELATIVE X,Y,Z
y -= Math.floor(y); // OF POINT IN CUBE.
z -= Math.floor(z);
const u = fade(x); // COMPUTE FADE CURVES
const v = fade(y); // FOR EACH OF X,Y,Z.
const w = fade(z);
const A = p[X] + Y;
const AA = p[A] + Z;
const AB = p[A + 1] + Z; // HASH COORDINATES OF
const B = p[X + 1] + Y;
const BA = p[B] + Z;
const BB = p[B + 1] + Z; // THE 8 CUBE CORNERS,
return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD
grad(p[BA ], x - 1, y , z )), // BLENDED
lerp(u, grad(p[AB ], x , y - 1, z ), // RESULTS
grad(p[BB ], x - 1, y - 1, z ))), // FROM 8
lerp(v, lerp(u, grad(p[AA + 1], x , y , z - 1), // CORNERS
grad(p[BA + 1], x - 1, y , z - 1)), // OF CUBE
lerp(u, grad(p[AB + 1], x , y - 1, z - 1),
grad(p[BB + 1], x - 1, y - 1, z - 1))));
}
async function readFile(fileName) {
try {
const response = await fetch('../' + fileName);
if (!response.ok) {
throw new Error('Cannot open file');
}
const text = await response.text();
const lines = text.split('\n');
let index = 0;
for (const line of lines) {
const numbers = line.split(',');
for (const word of numbers) {
if (word.trim()) {
const number = parseInt(word);
p[index] = number;
p[256 + index] = number;
index++;
}
}
}
} catch (error) {
console.error(error.message);
}
}
async function main() {
await readFile('permutation.txt');
console.log('Perlin noise applied to (3.14, 42.0, 7.0) gives ' +
perlinNoise(3.14, 42.0, 7.0).toFixed(16));
}
main();