UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

71 lines (55 loc) 1.99 kB
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 ); }