@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
86 lines (67 loc) • 2.5 kB
JavaScript
import { assert } from "../../assert.js";
/**
*
* @param {number[]|Float32Array|Float64Array} a
* @param {number[]|Float32Array|Float64Array} b
* @param {number} d number of dimensions
* @returns {number}
*/
function compute_point_distance(a, b, d) {
let result = 0;
for (let i = 0; i < d; i++) {
const x = a[i] - b[i];
result += x * x;
}
return Math.sqrt(result);
}
/**
* Computes bounding sphere of a number of spheres
* NOTE: implementation does not produce a very tight sphere, here is a good resource for a better implementation:
* https://github.com/CGAL/cgal/blob/master/Bounding_volumes/include/CGAL/Min_sphere_of_spheres_d/Min_sphere_of_spheres_d_support_set.h
* @param {number[]|Float32Array|Float64Array} result
* @param {number[]|Float32Array|Float64Array} data
* @param {number} offset
* @param {number} count
* @param {number} dimensions
*/
export function computeBoundingSphereOfSpheres(result, data, offset, count, dimensions) {
assert.isArrayLike(result, 'result');
const center = new Float64Array(dimensions);
const sphere = new Float64Array(dimensions + 1);
for (let i = 0; i < count; i++) {
const sphere_offset = offset + i * dimensions;
//read sphere
for (let j = 0; j < dimensions + 1; j++) {
sphere[j] = data[sphere_offset + j];
}
// add position of the sphere to center accumulator
for (let j = 0; j < dimensions; j++) {
center[j] += sphere[j];
}
}
// compute average
for (let i = 0; i < dimensions; i++) {
center[i] /= count;
}
let max_radius = 0;
for (let i = 0; i < count; i++) {
// compute squared distance from center to each sphere
const sphere_offset = offset + i * dimensions;
//read sphere
for (let j = 0; j < dimensions + 1; j++) {
sphere[j] = data[sphere_offset + j];
}
const sqr_distance_to_center = compute_point_distance(center, sphere, dimensions);
const sphere_radius = sphere[dimensions];
const distance = sqr_distance_to_center + sphere_radius;
if (distance > max_radius) {
max_radius = distance;
}
}
for (let i = 0; i < dimensions; i++) {
// write center
result[i] = center[i];
}
// write radius
result[dimensions] = max_radius;
}