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.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 (inputX, inputY, inputZ, distanceType, outputFunc) {
let lastRandom,
numberFeaturePoints,
cubeX, cubeY, cubeZ,
randomX, randomY, randomZ,
featureX, featureY, featureZ,
distance;
const distanceArray = [9999999, 9999999, 9999999];
const baseX = _floor(inputX),
baseY = _floor(inputY),
baseZ = _floor(inputZ);
for (let i = -1; i < 2; ++i) {
for (let j = -1; j < 2; ++j) {
for (let k = -1; k < 2; ++k) {
cubeX = baseX + i;
cubeY = baseY + j;
cubeZ = baseZ + 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);
randomX = lastRandom / 0x100000000;
lastRandom = this.wXorshift(lastRandom);
randomY = lastRandom / 0x100000000;
lastRandom = this.wXorshift(lastRandom);
randomZ = lastRandom / 0x100000000;
featureX = randomX + cubeX;
featureY = randomY + cubeY;
featureZ = randomZ + cubeZ;
if (distanceType === EUCLIDEAN_DISTANCE) {
const dx = inputX - featureX,
dy = inputY - featureY,
dz = inputZ - featureZ;
distance = (dx * dx) + (dy * dy) + (dz * dz);
}
else if (distanceType === CHEBYSHEV_DISTANCE) {
distance = _max(
_abs(inputX - featureX),
_max(_abs(inputY - featureY), _abs(inputZ - featureZ))
);
}
else {
distance = _abs(inputX - featureX) + _abs(inputY - featureY) + _abs(inputZ - featureZ);
}
this.wInsert(distanceArray, distance);
}
}
}
}
distanceArray[0] = distanceArray[0] < 0 ? 0 : distanceArray[0] > 1 ? 1 : distanceArray[0];
distanceArray[1] = distanceArray[1] < 0 ? 0 : distanceArray[1] > 1 ? 1 : distanceArray[1];
distanceArray[2] = distanceArray[2] < 0 ? 0 : distanceArray[2] > 1 ? 1 : distanceArray[2];
return outputFunc(distanceArray);
};