UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

103 lines (80 loc) 2.99 kB
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); } const SCRATCH_DIMENSIONS = 4; const _scratch_center = new Float64Array(SCRATCH_DIMENSIONS); const _scratch_sphere = new Float64Array(SCRATCH_DIMENSIONS + 1); /** * 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 sphere_component_count = dimensions + 1; let center; let sphere; if (dimensions <= SCRATCH_DIMENSIONS) { // avoid allocation center = _scratch_center; sphere = _scratch_sphere; center.fill(0); } else { center = new Float64Array(dimensions); sphere = new Float64Array(sphere_component_count); } for (let i = 0; i < count; i++) { const sphere_offset = offset + i * sphere_component_count; //read sphere for (let j = 0; j < sphere_component_count; 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*sphere_component_count; //read sphere for (let j = 0; j < sphere_component_count; 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; }