@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
71 lines (55 loc) • 1.99 kB
JavaScript
import Vector3 from "../../../../core/geom/Vector3.js";
import Vector4 from "../../../../core/geom/Vector4.js";
import { max2 } from "../../../../core/math/max2.js";
import { isMesh } from "./isMesh.js";
import { rootObject3DFastMatrixUpdate } from "../../../graphics/ecs/mesh/rootObject3DFastMatrixUpdate.js";
/**
*
* @param {Object3D} o
* @returns {Vector4} center is x,y,z while radius is w
*/
export function computeObjectBoundingSphere(o) {
/*
TODO: There are better ways of doing this:
https://github.com/CGAL/cgal/blob/c68cf8fc4c850f8cd84c6900faa781286a7117ed/Bounding_volumes/include/CGAL/Min_sphere_of_spheres_d/Min_sphere_of_spheres_d_impl.h
*/
/**
* Individual geometry-bounding spheres comprising the object
* @type {Sphere[]}
*/
const balls = [];
rootObject3DFastMatrixUpdate(o);
o.traverse(m => {
if (isMesh(m)) {
const geometry = m.geometry;
const sphere = geometry.boundingSphere.clone();
if (m !== o) {
sphere.applyMatrix4(m.matrixWorld);
}
balls.push(sphere);
}
});
// compute overall center
const center = new Vector3();
const numBalls = balls.length;
for (let i = 0; i < numBalls; i++) {
const sphere = balls[i];
center.add(sphere.center);
}
if (numBalls > 0) {
center.multiplyScalar(1 / numBalls);
}
// compute radius of the main sphere by computing the largest distance from the overall center to the edge of each individual sphere
let radius = 0;
for (let i = 0; i < numBalls; i++) {
const sphere = balls[i];
const distance_to_ball_edge = center.distanceTo(sphere.center) + sphere.radius;
radius = max2(radius, distance_to_ball_edge);
}
return new Vector4(
center.x,
center.y,
center.z,
radius
);
}