UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

86 lines (67 loc) 2.5 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); } /** * 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; }