123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- import { ArrayTools } from "../Misc/arrayTools.js";
- import { Matrix, Vector3 } from "../Maths/math.vector.js";
- import { Epsilon } from "../Maths/math.constants.js";
- /**
- * Class used to store bounding box information
- */
- export class BoundingBox {
- /**
- * Creates a new bounding box
- * @param min defines the minimum vector (in local space)
- * @param max defines the maximum vector (in local space)
- * @param worldMatrix defines the new world matrix
- */
- constructor(min, max, worldMatrix) {
- /**
- * Gets the 8 vectors representing the bounding box in local space
- */
- this.vectors = ArrayTools.BuildArray(8, Vector3.Zero);
- /**
- * Gets the center of the bounding box in local space
- */
- this.center = Vector3.Zero();
- /**
- * Gets the center of the bounding box in world space
- */
- this.centerWorld = Vector3.Zero();
- /**
- * Gets the extend size in local space
- */
- this.extendSize = Vector3.Zero();
- /**
- * Gets the extend size in world space
- */
- this.extendSizeWorld = Vector3.Zero();
- /**
- * Gets the OBB (object bounding box) directions
- */
- this.directions = ArrayTools.BuildArray(3, Vector3.Zero);
- /**
- * Gets the 8 vectors representing the bounding box in world space
- */
- this.vectorsWorld = ArrayTools.BuildArray(8, Vector3.Zero);
- /**
- * Gets the minimum vector in world space
- */
- this.minimumWorld = Vector3.Zero();
- /**
- * Gets the maximum vector in world space
- */
- this.maximumWorld = Vector3.Zero();
- /**
- * Gets the minimum vector in local space
- */
- this.minimum = Vector3.Zero();
- /**
- * Gets the maximum vector in local space
- */
- this.maximum = Vector3.Zero();
- /** @internal */
- this._drawWrapperFront = null;
- /** @internal */
- this._drawWrapperBack = null;
- this.reConstruct(min, max, worldMatrix);
- }
- // Methods
- /**
- * Recreates the entire bounding box from scratch as if we call the constructor in place
- * @param min defines the new minimum vector (in local space)
- * @param max defines the new maximum vector (in local space)
- * @param worldMatrix defines the new world matrix
- */
- reConstruct(min, max, worldMatrix) {
- const minX = min.x, minY = min.y, minZ = min.z, maxX = max.x, maxY = max.y, maxZ = max.z;
- const vectors = this.vectors;
- this.minimum.copyFromFloats(minX, minY, minZ);
- this.maximum.copyFromFloats(maxX, maxY, maxZ);
- vectors[0].copyFromFloats(minX, minY, minZ);
- vectors[1].copyFromFloats(maxX, maxY, maxZ);
- vectors[2].copyFromFloats(maxX, minY, minZ);
- vectors[3].copyFromFloats(minX, maxY, minZ);
- vectors[4].copyFromFloats(minX, minY, maxZ);
- vectors[5].copyFromFloats(maxX, maxY, minZ);
- vectors[6].copyFromFloats(minX, maxY, maxZ);
- vectors[7].copyFromFloats(maxX, minY, maxZ);
- // OBB
- max.addToRef(min, this.center).scaleInPlace(0.5);
- max.subtractToRef(min, this.extendSize).scaleInPlace(0.5);
- this._worldMatrix = worldMatrix || Matrix.IdentityReadOnly;
- this._update(this._worldMatrix);
- }
- /**
- * Scale the current bounding box by applying a scale factor
- * @param factor defines the scale factor to apply
- * @returns the current bounding box
- */
- scale(factor) {
- const tmpVectors = BoundingBox._TmpVector3;
- const diff = this.maximum.subtractToRef(this.minimum, tmpVectors[0]);
- const len = diff.length();
- diff.normalizeFromLength(len);
- const distance = len * factor;
- const newRadius = diff.scaleInPlace(distance * 0.5);
- const min = this.center.subtractToRef(newRadius, tmpVectors[1]);
- const max = this.center.addToRef(newRadius, tmpVectors[2]);
- this.reConstruct(min, max, this._worldMatrix);
- return this;
- }
- /**
- * Gets the world matrix of the bounding box
- * @returns a matrix
- */
- getWorldMatrix() {
- return this._worldMatrix;
- }
- /**
- * @internal
- */
- _update(world) {
- const minWorld = this.minimumWorld;
- const maxWorld = this.maximumWorld;
- const directions = this.directions;
- const vectorsWorld = this.vectorsWorld;
- const vectors = this.vectors;
- if (!world.isIdentity()) {
- minWorld.setAll(Number.MAX_VALUE);
- maxWorld.setAll(-Number.MAX_VALUE);
- for (let index = 0; index < 8; ++index) {
- const v = vectorsWorld[index];
- Vector3.TransformCoordinatesToRef(vectors[index], world, v);
- minWorld.minimizeInPlace(v);
- maxWorld.maximizeInPlace(v);
- }
- // Extend
- maxWorld.subtractToRef(minWorld, this.extendSizeWorld).scaleInPlace(0.5);
- maxWorld.addToRef(minWorld, this.centerWorld).scaleInPlace(0.5);
- }
- else {
- minWorld.copyFrom(this.minimum);
- maxWorld.copyFrom(this.maximum);
- for (let index = 0; index < 8; ++index) {
- vectorsWorld[index].copyFrom(vectors[index]);
- }
- // Extend
- this.extendSizeWorld.copyFrom(this.extendSize);
- this.centerWorld.copyFrom(this.center);
- }
- Vector3.FromArrayToRef(world.m, 0, directions[0]);
- Vector3.FromArrayToRef(world.m, 4, directions[1]);
- Vector3.FromArrayToRef(world.m, 8, directions[2]);
- this._worldMatrix = world;
- }
- /**
- * Tests if the bounding box is intersecting the frustum planes
- * @param frustumPlanes defines the frustum planes to test
- * @returns true if there is an intersection
- */
- isInFrustum(frustumPlanes) {
- return BoundingBox.IsInFrustum(this.vectorsWorld, frustumPlanes);
- }
- /**
- * Tests if the bounding box is entirely inside the frustum planes
- * @param frustumPlanes defines the frustum planes to test
- * @returns true if there is an inclusion
- */
- isCompletelyInFrustum(frustumPlanes) {
- return BoundingBox.IsCompletelyInFrustum(this.vectorsWorld, frustumPlanes);
- }
- /**
- * Tests if a point is inside the bounding box
- * @param point defines the point to test
- * @returns true if the point is inside the bounding box
- */
- intersectsPoint(point) {
- const min = this.minimumWorld;
- const max = this.maximumWorld;
- const minX = min.x, minY = min.y, minZ = min.z, maxX = max.x, maxY = max.y, maxZ = max.z;
- const pointX = point.x, pointY = point.y, pointZ = point.z;
- const delta = -Epsilon;
- if (maxX - pointX < delta || delta > pointX - minX) {
- return false;
- }
- if (maxY - pointY < delta || delta > pointY - minY) {
- return false;
- }
- if (maxZ - pointZ < delta || delta > pointZ - minZ) {
- return false;
- }
- return true;
- }
- /**
- * Tests if the bounding box intersects with a bounding sphere
- * @param sphere defines the sphere to test
- * @returns true if there is an intersection
- */
- intersectsSphere(sphere) {
- return BoundingBox.IntersectsSphere(this.minimumWorld, this.maximumWorld, sphere.centerWorld, sphere.radiusWorld);
- }
- /**
- * Tests if the bounding box intersects with a box defined by a min and max vectors
- * @param min defines the min vector to use
- * @param max defines the max vector to use
- * @returns true if there is an intersection
- */
- intersectsMinMax(min, max) {
- const myMin = this.minimumWorld;
- const myMax = this.maximumWorld;
- const myMinX = myMin.x, myMinY = myMin.y, myMinZ = myMin.z, myMaxX = myMax.x, myMaxY = myMax.y, myMaxZ = myMax.z;
- const minX = min.x, minY = min.y, minZ = min.z, maxX = max.x, maxY = max.y, maxZ = max.z;
- if (myMaxX < minX || myMinX > maxX) {
- return false;
- }
- if (myMaxY < minY || myMinY > maxY) {
- return false;
- }
- if (myMaxZ < minZ || myMinZ > maxZ) {
- return false;
- }
- return true;
- }
- /**
- * Disposes the resources of the class
- */
- dispose() {
- this._drawWrapperFront?.dispose();
- this._drawWrapperBack?.dispose();
- }
- // Statics
- /**
- * Tests if two bounding boxes are intersections
- * @param box0 defines the first box to test
- * @param box1 defines the second box to test
- * @returns true if there is an intersection
- */
- static Intersects(box0, box1) {
- return box0.intersectsMinMax(box1.minimumWorld, box1.maximumWorld);
- }
- /**
- * Tests if a bounding box defines by a min/max vectors intersects a sphere
- * @param minPoint defines the minimum vector of the bounding box
- * @param maxPoint defines the maximum vector of the bounding box
- * @param sphereCenter defines the sphere center
- * @param sphereRadius defines the sphere radius
- * @returns true if there is an intersection
- */
- static IntersectsSphere(minPoint, maxPoint, sphereCenter, sphereRadius) {
- const vector = BoundingBox._TmpVector3[0];
- Vector3.ClampToRef(sphereCenter, minPoint, maxPoint, vector);
- const num = Vector3.DistanceSquared(sphereCenter, vector);
- return num <= sphereRadius * sphereRadius;
- }
- /**
- * Tests if a bounding box defined with 8 vectors is entirely inside frustum planes
- * @param boundingVectors defines an array of 8 vectors representing a bounding box
- * @param frustumPlanes defines the frustum planes to test
- * @returns true if there is an inclusion
- */
- static IsCompletelyInFrustum(boundingVectors, frustumPlanes) {
- for (let p = 0; p < 6; ++p) {
- const frustumPlane = frustumPlanes[p];
- for (let i = 0; i < 8; ++i) {
- if (frustumPlane.dotCoordinate(boundingVectors[i]) < 0) {
- return false;
- }
- }
- }
- return true;
- }
- /**
- * Tests if a bounding box defined with 8 vectors intersects frustum planes
- * @param boundingVectors defines an array of 8 vectors representing a bounding box
- * @param frustumPlanes defines the frustum planes to test
- * @returns true if there is an intersection
- */
- static IsInFrustum(boundingVectors, frustumPlanes) {
- for (let p = 0; p < 6; ++p) {
- let canReturnFalse = true;
- const frustumPlane = frustumPlanes[p];
- for (let i = 0; i < 8; ++i) {
- if (frustumPlane.dotCoordinate(boundingVectors[i]) >= 0) {
- canReturnFalse = false;
- break;
- }
- }
- if (canReturnFalse) {
- return false;
- }
- }
- return true;
- }
- }
- BoundingBox._TmpVector3 = ArrayTools.BuildArray(3, Vector3.Zero);
- //# sourceMappingURL=boundingBox.js.map
|