playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
95 lines (94 loc) • 3.28 kB
JavaScript
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
};