P.wXorshift = function (value) {
let x = value ^ (value >> 12);
x = x ^ (x << 25);
x = x ^ (x >> 27);
return x * 2;
};
P.wHash = function (i, j, k) {
return (((((2166136261 ^ i) * 16777619) ^ j) * 16777619) ^ k) * 16777619 & 0xffffffff;
};
P.worleyDistanceFunctions = {
[EUCLIDEAN_DISTANCE]: function (p1, p2) {
const d = function (p1, p2) {
return [p1.x - p2.x, p1.y - p2.y, p1.z - p2.z];
};
return d(p1, p2).reduce((sum, x) => sum + (x * x), 0);
},
[MANHATTAN_DISTANCE]: function (p1, p2) {
const d = function (p1, p2) {
return [p1.x - p2.x, p1.y - p2.y, p1.z - p2.z];
};
return d(p1, p2).reduce((sum, x) => sum + _abs(x), 0);
},
};
P.wProbLookup = function (value) {
value = value & 0xffffffff;
if (value < 393325350) return 1;
if (value < 1022645910) return 2;
if (value < 1861739990) return 3;
if (value < 2700834071) return 4;
if (value < 3372109335) return 5;
if (value < 3819626178) return 6;
if (value < 4075350088) return 7;
if (value < 4203212043) return 8;
return 9;
};
P.wInsert = function (arr, value) {
let temp;
for (let i = arr.length - 1; i >= 0; i--) {
if (value > arr[i]) break;
temp = arr[i];
arr[i] = value;
if (i + 1 < arr.length) arr[i + 1] = temp;
}
};
P.worleyOutputFunctions = {
X: function (arr) {
return arr[0];
},
Y: function (arr) {
return arr[1];
},
Z: function (arr) {
return arr[2];
},
XminusY: function (arr) {
return arr[0] - arr[1];
},
XminusZ: function (arr) {
return arr[0] - arr[2];
},
YminusX: function (arr) {
return arr[1] - arr[0];
},
YminusZ: function (arr) {
return arr[1] - arr[2];
},
ZminusX: function (arr) {
return arr[2] - arr[0];
},
ZminusY: function (arr) {
return arr[2] - arr[1];
},
XaddY: function (arr) {
return arr[0] + arr[1];
},
XaddZ: function (arr) {
return arr[0] + arr[2];
},
YaddZ: function (arr) {
return arr[1] + arr[2];
},
XaddYminusZ: function (arr) {
return arr[0] + arr[1] - arr[2];
},
XaddZminusY: function (arr) {
return arr[0] + arr[2] - arr[1];
},
YaddZminusX: function (arr) {
return arr[1] + arr[2] - arr[0];
},
XmultiplyY: function (arr) {
return arr[0] * arr[1];
},
XmultiplyZ: function (arr) {
return arr[0] * arr[2];
},
YmultiplyZ: function (arr) {
return arr[1] * arr[2];
},
XmultiplyYaddZ: function (arr) {
return (arr[0] * arr[1]) + arr[2];
},
XmultiplyZaddY: function (arr) {
return (arr[0] * arr[2]) + arr[1];
},
YmultiplyZaddX: function (arr) {
return (arr[1] * arr[2]) + arr[0];
},
XmultiplyYminusZ: function (arr) {
return (arr[0] * arr[1]) - arr[2];
},
XmultiplyZminusY: function (arr) {
return (arr[0] * arr[2]) - arr[1];
},
YmultiplyZminusX: function (arr) {
return (arr[1] * arr[2]) - arr[0];
},
sum: function (arr) {
return arr[0] + arr[1] + arr[2];
},
}
P.worleyNoise = function (input, distanceFunc, outputFunc) {
let lastRandom,
numberFeaturePoints,
featurePoint = { x: 0, y: 0, z: 0 };
const randomDiff = { x: 0, y: 0, z: 0 };
let cubeX, cubeY, cubeZ;
const distanceArray = [9999999, 9999999, 9999999];
let {x:inputX, y:inputY, z:inputZ} = input;
inputX = _floor(inputX);
inputY = _floor(inputY);
inputZ = _floor(inputZ);
for (let i = -1; i < 2; ++i) {
for (let j = -1; j < 2; ++j) {
for (let k = -1; k < 2; ++k) {
cubeX = inputX + i;
cubeY = inputY + j;
cubeZ = inputZ + k;
lastRandom = this.wXorshift(
this.wHash(
(cubeX + this.worleySeed) & 0xffffffff,
(cubeY) & 0xffffffff,
(cubeZ) & 0xffffffff
)
);
numberFeaturePoints = this.wProbLookup(lastRandom);
for (let l = 0; l < numberFeaturePoints; ++l) {
lastRandom = this.wXorshift(lastRandom);
randomDiff.X = lastRandom / 0x100000000;
lastRandom = this.wXorshift(lastRandom);
randomDiff.Y = lastRandom / 0x100000000;
lastRandom = this.wXorshift(lastRandom);
randomDiff.Z = lastRandom / 0x100000000;
featurePoint = {
x: randomDiff.X + cubeX,
y: randomDiff.Y + cubeY,
z: randomDiff.Z + cubeZ
};
this.wInsert(distanceArray, distanceFunc(input, featurePoint));
}
}
}
}
const preFinal = distanceArray.map(x => x < 0 ? 0 : x > 1 ? 1 : x );
const final = outputFunc(preFinal);
return final;
};