UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

95 lines (94 loc) 3.28 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { Debug } from "../debug.js"; import { Vec3 } from "../math/vec3.js"; const tmpVecA = new Vec3(); const tmpVecB = new Vec3(); class BoundingSphere { /** * Creates a new BoundingSphere instance. * * @param {Vec3} [center] - The world space coordinate marking the center of the sphere. The * constructor takes a reference of this parameter. * @param {number} [radius] - The radius of the bounding sphere. Defaults to 0.5. * @example * // Create a new bounding sphere centered on the origin with a radius of 0.5 * const sphere = new pc.BoundingSphere(); */ constructor(center = new Vec3(), radius = 0.5) { /** * Center of sphere. * * @type {Vec3} * @readonly */ __publicField(this, "center"); /** * The radius of the bounding sphere. * * @type {number} */ __publicField(this, "radius"); Debug.assert(!Object.isFrozen(center), "The constructor of 'BoundingSphere' does not accept a constant (frozen) object as a 'center' parameter"); this.center = center; this.radius = radius; } /** * Test if a point is inside the sphere. * * @param {Vec3} point - Point to test. * @returns {boolean} True if the point is inside the sphere and false otherwise. * @example * const sphere = new pc.BoundingSphere(new pc.Vec3(0, 0, 0), 1); * const point = new pc.Vec3(0.5, 0, 0); * const isInside = sphere.containsPoint(point); // true */ containsPoint(point) { const lenSq = tmpVecA.sub2(point, this.center).lengthSq(); const r = this.radius; return lenSq < r * r; } /** * Test if a ray intersects with the sphere. * * @param {Ray} ray - Ray to test against (direction must be normalized). * @param {Vec3} [point] - If there is an intersection, the intersection point will be copied * into here. * @returns {boolean} True if there is an intersection. */ intersectsRay(ray, point) { const m = tmpVecA.copy(ray.origin).sub(this.center); const b = m.dot(tmpVecB.copy(ray.direction).normalize()); const c = m.dot(m) - this.radius * this.radius; if (c > 0 && b > 0) { return false; } const discr = b * b - c; if (discr < 0) { return false; } const t = Math.abs(-b - Math.sqrt(discr)); if (point) { point.copy(ray.direction).mulScalar(t).add(ray.origin); } return true; } /** * Test if a Bounding Sphere is overlapping, enveloping, or inside this Bounding Sphere. * * @param {BoundingSphere} sphere - Bounding Sphere to test. * @returns {boolean} True if the Bounding Sphere is overlapping, enveloping, or inside this Bounding Sphere and false otherwise. */ intersectsBoundingSphere(sphere) { tmpVecA.sub2(sphere.center, this.center); const totalRadius = sphere.radius + this.radius; if (tmpVecA.lengthSq() <= totalRadius * totalRadius) { return true; } return false; } } export { BoundingSphere };