597 lines
6.4 KiB
TypeScript
597 lines
6.4 KiB
TypeScript
|
// This is free and unencumbered software released into the public domain
|
||
|
|
||
|
import shuffleSeed from "./shuffle_seed";
|
||
|
|
||
|
const NORM_3D = 1.0 / 103.0;
|
||
|
const SQUISH_3D = (Math.sqrt(3 + 1) - 1) / 3;
|
||
|
const STRETCH_3D = (1 / Math.sqrt(3 + 1) - 1) / 3;
|
||
|
|
||
|
export type Noise3D = (x: number, y: number, z: number) => number;
|
||
|
|
||
|
interface Contribution3D {
|
||
|
dx: number;
|
||
|
dy: number;
|
||
|
dz: number;
|
||
|
next?: Contribution3D;
|
||
|
xsb: number;
|
||
|
ysb: number;
|
||
|
zsb: number;
|
||
|
}
|
||
|
|
||
|
function contribution3D(
|
||
|
multiplier: number,
|
||
|
xsb: number,
|
||
|
ysb: number,
|
||
|
zsb: number,
|
||
|
): Contribution3D {
|
||
|
return {
|
||
|
dx: -xsb - multiplier * SQUISH_3D,
|
||
|
dy: -ysb - multiplier * SQUISH_3D,
|
||
|
dz: -zsb - multiplier * SQUISH_3D,
|
||
|
xsb,
|
||
|
ysb,
|
||
|
zsb,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
export function makeNoise3D(clientSeed: number): Noise3D {
|
||
|
const contributions: Contribution3D[] = [];
|
||
|
for (let i = 0; i < p3D.length; i += 9) {
|
||
|
const baseSet = base3D[p3D[i]];
|
||
|
let previous: Contribution3D | null = null;
|
||
|
let current: Contribution3D | null = null;
|
||
|
for (let k = 0; k < baseSet.length; k += 4) {
|
||
|
current = contribution3D(
|
||
|
baseSet[k],
|
||
|
baseSet[k + 1],
|
||
|
baseSet[k + 2],
|
||
|
baseSet[k + 3],
|
||
|
);
|
||
|
if (previous === null) contributions[i / 9] = current;
|
||
|
else previous.next = current;
|
||
|
previous = current;
|
||
|
}
|
||
|
current!.next = contribution3D(
|
||
|
p3D[i + 1],
|
||
|
p3D[i + 2],
|
||
|
p3D[i + 3],
|
||
|
p3D[i + 4],
|
||
|
);
|
||
|
current!.next.next = contribution3D(
|
||
|
p3D[i + 5],
|
||
|
p3D[i + 6],
|
||
|
p3D[i + 7],
|
||
|
p3D[i + 8],
|
||
|
);
|
||
|
}
|
||
|
const lookup: Contribution3D[] = [];
|
||
|
for (let i = 0; i < lookupPairs3D.length; i += 2) {
|
||
|
lookup[lookupPairs3D[i]] = contributions[lookupPairs3D[i + 1]];
|
||
|
}
|
||
|
|
||
|
const perm = new Uint8Array(256);
|
||
|
const perm3D = new Uint8Array(256);
|
||
|
const source = new Uint8Array(256);
|
||
|
for (let i = 0; i < 256; i++) source[i] = i;
|
||
|
let seed = new Uint32Array(1);
|
||
|
seed[0] = clientSeed;
|
||
|
seed = shuffleSeed(shuffleSeed(shuffleSeed(seed)));
|
||
|
for (let i = 255; i >= 0; i--) {
|
||
|
seed = shuffleSeed(seed);
|
||
|
const r = new Uint32Array(1);
|
||
|
r[0] = (seed[0] + 31) % (i + 1);
|
||
|
if (r[0] < 0) r[0] += i + 1;
|
||
|
perm[i] = source[r[0]];
|
||
|
perm3D[i] = (perm[i] % 24) * 3;
|
||
|
source[r[0]] = source[i];
|
||
|
}
|
||
|
|
||
|
return (x: number, y: number, z: number): number => {
|
||
|
const stretchOffset = (x + y + z) * STRETCH_3D;
|
||
|
|
||
|
const xs = x + stretchOffset;
|
||
|
const ys = y + stretchOffset;
|
||
|
const zs = z + stretchOffset;
|
||
|
|
||
|
const xsb = Math.floor(xs);
|
||
|
const ysb = Math.floor(ys);
|
||
|
const zsb = Math.floor(zs);
|
||
|
|
||
|
const squishOffset = (xsb + ysb + zsb) * SQUISH_3D;
|
||
|
|
||
|
const dx0 = x - (xsb + squishOffset);
|
||
|
const dy0 = y - (ysb + squishOffset);
|
||
|
const dz0 = z - (zsb + squishOffset);
|
||
|
|
||
|
const xins = xs - xsb;
|
||
|
const yins = ys - ysb;
|
||
|
const zins = zs - zsb;
|
||
|
|
||
|
const inSum = xins + yins + zins;
|
||
|
const hash = (yins - zins + 1) |
|
||
|
((xins - yins + 1) << 1) |
|
||
|
((xins - zins + 1) << 2) |
|
||
|
(inSum << 3) |
|
||
|
((inSum + zins) << 5) |
|
||
|
((inSum + yins) << 7) |
|
||
|
((inSum + xins) << 9);
|
||
|
|
||
|
let value = 0;
|
||
|
|
||
|
for (
|
||
|
let c: Contribution3D | undefined = lookup[hash];
|
||
|
c !== undefined;
|
||
|
c = c.next
|
||
|
) {
|
||
|
const dx = dx0 + c.dx;
|
||
|
const dy = dy0 + c.dy;
|
||
|
const dz = dz0 + c.dz;
|
||
|
|
||
|
const attn = 2 - dx * dx - dy * dy - dz * dz;
|
||
|
if (attn > 0) {
|
||
|
const px = xsb + c.xsb;
|
||
|
const py = ysb + c.ysb;
|
||
|
const pz = zsb + c.zsb;
|
||
|
|
||
|
const indexPartA = perm[px & 0xff];
|
||
|
const indexPartB = perm[(indexPartA + py) & 0xff];
|
||
|
const index = perm3D[(indexPartB + pz) & 0xff];
|
||
|
|
||
|
const valuePart = gradients3D[index] * dx +
|
||
|
gradients3D[index + 1] * dy +
|
||
|
gradients3D[index + 2] * dz;
|
||
|
|
||
|
value += attn * attn * attn * attn * valuePart;
|
||
|
}
|
||
|
}
|
||
|
return value * NORM_3D;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
const base3D = [
|
||
|
[0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1],
|
||
|
[2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1, 3, 1, 1, 1],
|
||
|
[1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1],
|
||
|
];
|
||
|
|
||
|
const gradients3D = [
|
||
|
-11,
|
||
|
4,
|
||
|
4,
|
||
|
-4,
|
||
|
11,
|
||
|
4,
|
||
|
-4,
|
||
|
4,
|
||
|
11,
|
||
|
11,
|
||
|
4,
|
||
|
4,
|
||
|
4,
|
||
|
11,
|
||
|
4,
|
||
|
4,
|
||
|
4,
|
||
|
11,
|
||
|
-11,
|
||
|
-4,
|
||
|
4,
|
||
|
-4,
|
||
|
-11,
|
||
|
4,
|
||
|
-4,
|
||
|
-4,
|
||
|
11,
|
||
|
11,
|
||
|
-4,
|
||
|
4,
|
||
|
4,
|
||
|
-11,
|
||
|
4,
|
||
|
4,
|
||
|
-4,
|
||
|
11,
|
||
|
-11,
|
||
|
4,
|
||
|
-4,
|
||
|
-4,
|
||
|
11,
|
||
|
-4,
|
||
|
-4,
|
||
|
4,
|
||
|
-11,
|
||
|
11,
|
||
|
4,
|
||
|
-4,
|
||
|
4,
|
||
|
11,
|
||
|
-4,
|
||
|
4,
|
||
|
4,
|
||
|
-11,
|
||
|
-11,
|
||
|
-4,
|
||
|
-4,
|
||
|
-4,
|
||
|
-11,
|
||
|
-4,
|
||
|
-4,
|
||
|
-4,
|
||
|
-11,
|
||
|
11,
|
||
|
-4,
|
||
|
-4,
|
||
|
4,
|
||
|
-11,
|
||
|
-4,
|
||
|
4,
|
||
|
-4,
|
||
|
-11,
|
||
|
];
|
||
|
|
||
|
const lookupPairs3D = [
|
||
|
0,
|
||
|
2,
|
||
|
1,
|
||
|
1,
|
||
|
2,
|
||
|
2,
|
||
|
5,
|
||
|
1,
|
||
|
6,
|
||
|
0,
|
||
|
7,
|
||
|
0,
|
||
|
32,
|
||
|
2,
|
||
|
34,
|
||
|
2,
|
||
|
129,
|
||
|
1,
|
||
|
133,
|
||
|
1,
|
||
|
160,
|
||
|
5,
|
||
|
161,
|
||
|
5,
|
||
|
518,
|
||
|
0,
|
||
|
519,
|
||
|
0,
|
||
|
546,
|
||
|
4,
|
||
|
550,
|
||
|
4,
|
||
|
645,
|
||
|
3,
|
||
|
647,
|
||
|
3,
|
||
|
672,
|
||
|
5,
|
||
|
673,
|
||
|
5,
|
||
|
674,
|
||
|
4,
|
||
|
677,
|
||
|
3,
|
||
|
678,
|
||
|
4,
|
||
|
679,
|
||
|
3,
|
||
|
680,
|
||
|
13,
|
||
|
681,
|
||
|
13,
|
||
|
682,
|
||
|
12,
|
||
|
685,
|
||
|
14,
|
||
|
686,
|
||
|
12,
|
||
|
687,
|
||
|
14,
|
||
|
712,
|
||
|
20,
|
||
|
714,
|
||
|
18,
|
||
|
809,
|
||
|
21,
|
||
|
813,
|
||
|
23,
|
||
|
840,
|
||
|
20,
|
||
|
841,
|
||
|
21,
|
||
|
1198,
|
||
|
19,
|
||
|
1199,
|
||
|
22,
|
||
|
1226,
|
||
|
18,
|
||
|
1230,
|
||
|
19,
|
||
|
1325,
|
||
|
23,
|
||
|
1327,
|
||
|
22,
|
||
|
1352,
|
||
|
15,
|
||
|
1353,
|
||
|
17,
|
||
|
1354,
|
||
|
15,
|
||
|
1357,
|
||
|
17,
|
||
|
1358,
|
||
|
16,
|
||
|
1359,
|
||
|
16,
|
||
|
1360,
|
||
|
11,
|
||
|
1361,
|
||
|
10,
|
||
|
1362,
|
||
|
11,
|
||
|
1365,
|
||
|
10,
|
||
|
1366,
|
||
|
9,
|
||
|
1367,
|
||
|
9,
|
||
|
1392,
|
||
|
11,
|
||
|
1394,
|
||
|
11,
|
||
|
1489,
|
||
|
10,
|
||
|
1493,
|
||
|
10,
|
||
|
1520,
|
||
|
8,
|
||
|
1521,
|
||
|
8,
|
||
|
1878,
|
||
|
9,
|
||
|
1879,
|
||
|
9,
|
||
|
1906,
|
||
|
7,
|
||
|
1910,
|
||
|
7,
|
||
|
2005,
|
||
|
6,
|
||
|
2007,
|
||
|
6,
|
||
|
2032,
|
||
|
8,
|
||
|
2033,
|
||
|
8,
|
||
|
2034,
|
||
|
7,
|
||
|
2037,
|
||
|
6,
|
||
|
2038,
|
||
|
7,
|
||
|
2039,
|
||
|
6,
|
||
|
];
|
||
|
|
||
|
const p3D = [
|
||
|
0,
|
||
|
0,
|
||
|
1,
|
||
|
-1,
|
||
|
0,
|
||
|
0,
|
||
|
1,
|
||
|
0,
|
||
|
-1,
|
||
|
0,
|
||
|
0,
|
||
|
-1,
|
||
|
1,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
1,
|
||
|
-1,
|
||
|
0,
|
||
|
0,
|
||
|
-1,
|
||
|
0,
|
||
|
1,
|
||
|
0,
|
||
|
0,
|
||
|
-1,
|
||
|
1,
|
||
|
0,
|
||
|
2,
|
||
|
1,
|
||
|
1,
|
||
|
0,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
-1,
|
||
|
0,
|
||
|
2,
|
||
|
1,
|
||
|
0,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
-1,
|
||
|
1,
|
||
|
0,
|
||
|
2,
|
||
|
0,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
-1,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
3,
|
||
|
2,
|
||
|
1,
|
||
|
0,
|
||
|
3,
|
||
|
1,
|
||
|
2,
|
||
|
0,
|
||
|
1,
|
||
|
3,
|
||
|
2,
|
||
|
0,
|
||
|
1,
|
||
|
3,
|
||
|
1,
|
||
|
0,
|
||
|
2,
|
||
|
1,
|
||
|
3,
|
||
|
0,
|
||
|
2,
|
||
|
1,
|
||
|
3,
|
||
|
0,
|
||
|
1,
|
||
|
2,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
0,
|
||
|
0,
|
||
|
2,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
1,
|
||
|
1,
|
||
|
0,
|
||
|
1,
|
||
|
0,
|
||
|
2,
|
||
|
0,
|
||
|
2,
|
||
|
0,
|
||
|
1,
|
||
|
1,
|
||
|
0,
|
||
|
0,
|
||
|
1,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
2,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
1,
|
||
|
1,
|
||
|
-1,
|
||
|
1,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
1,
|
||
|
-1,
|
||
|
1,
|
||
|
1,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
-1,
|
||
|
2,
|
||
|
3,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
2,
|
||
|
2,
|
||
|
3,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
2,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
2,
|
||
|
3,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
2,
|
||
|
0,
|
||
|
2,
|
||
|
0,
|
||
|
2,
|
||
|
1,
|
||
|
1,
|
||
|
-1,
|
||
|
1,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
2,
|
||
|
2,
|
||
|
1,
|
||
|
1,
|
||
|
-1,
|
||
|
1,
|
||
|
2,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
2,
|
||
|
1,
|
||
|
-1,
|
||
|
1,
|
||
|
1,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
2,
|
||
|
2,
|
||
|
1,
|
||
|
-1,
|
||
|
1,
|
||
|
1,
|
||
|
2,
|
||
|
0,
|
||
|
2,
|
||
|
0,
|
||
|
2,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
-1,
|
||
|
2,
|
||
|
2,
|
||
|
0,
|
||
|
0,
|
||
|
2,
|
||
|
1,
|
||
|
1,
|
||
|
1,
|
||
|
-1,
|
||
|
2,
|
||
|
0,
|
||
|
2,
|
||
|
0,
|
||
|
];
|