function poissonDisk() {
let firstSphere = Sphere.random(r, radius);
let candidates = [firstSphere];
let allSpheres = [firstSphere];
let octs = octree();
let simplex = new SimplexNoise(randomSeed);
let inSphere = (x, y, z, cx, cy, cz, radius) => {
return sqr(x - cx) + sqr(y - cy) + sqr(z - cz) < sqr(radius);
};
let cubeSphereIntersect = (rx, ry, rz, rwidth, rheight, rdepth, cx, cy, cz, radius) => {
let dx = cx - Math.max(rx, Math.min(cx, rx + rwidth));
let dy = cy - Math.max(ry, Math.min(cy, ry + rheight));
let dz = cz - Math.max(rz, Math.min(cz, rz + rdepth));
return (sqr(dx) + sqr(dy) + sqr(dz)) < sqr(radius);
};
let search = (octtree, cx, cy, cz, radius) => {
let results = [];
octs.visit(function(node, x1, y1, z1, x2, y2, z2) {
if (!node.length) {
do {
var d = node.data;
if (inSphere(d[0], d[1], d[2], cx, cy, cz, radius)) {
results.push({
x: d[0],
y: d[1],
z: d[2],
});
}
} while (node = node.next);
}
return !cubeSphereIntersect(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1, cx, cy, cz, radius);
});
return results;
};
let nearbySpheres = (sphere, radius = searchRadius) => {
return search(octs, sphere.x, sphere.y, sphere.z, radius);
};
let tooClose = (candidate, radius) => {
for (let sphere of nearbySpheres(candidate, radius)) {
if (candidate.tooClose(sphere, radius)) return true;
}
return false;
};
let generateCandidate = (active) => {
let radius = searchRadius * ((simplex.noise4D(active.x * spacing, active.y * spacing, active.z * spacing, time) / 2 + 0.5) * radiusMultiplier + radiusShift);
for (var i = 0; i < searchAttempts; i++) {
let candidate = active.candidate(radius);
if (candidate.inBounds() && !tooClose(candidate, radius)) return candidate;
}
active.radius = radius;
return null;
}
let addSphere = (sphere) => {
candidates.push(sphere);
allSpheres.push(sphere);
octs.add([sphere.x, sphere.y, sphere.z]);
};
while (candidates.length > 0) {
let active = candidates[candidates.length - 1];
let candidate = generateCandidate(active);
if (candidate == null) {
candidates.pop();
} else {
addSphere(candidate);
}
}
return allSpheres;
}