var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// dist/index.js
var dist_exports = {};
__export(dist_exports, {
AxisAlignedBoundingBox: () => AxisAlignedBoundingBox,
BoundingSphere: () => BoundingSphere,
CullingVolume: () => CullingVolume,
INTERSECTION: () => INTERSECTION,
OrientedBoundingBox: () => OrientedBoundingBox,
Plane: () => Plane,
_PerspectiveFrustum: () => PerspectiveFrustum,
_PerspectiveOffCenterFrustum: () => PerspectiveOffCenterFrustum,
computeEigenDecomposition: () => computeEigenDecomposition,
makeAxisAlignedBoundingBoxFromPoints: () => makeAxisAlignedBoundingBoxFromPoints,
makeBoundingSphereFromPoints: () => makeBoundingSphereFromPoints,
makeOrientedBoundingBoxFromPoints: () => makeOrientedBoundingBoxFromPoints
});
module.exports = __toCommonJS(dist_exports);
// dist/constants.js
var INTERSECTION = {
OUTSIDE: -1,
// Represents that an object is not contained within the frustum.
INTERSECTING: 0,
// Represents that an object intersects one of the frustum's planes.
INSIDE: 1
// Represents that an object is fully within the frustum.
};
// dist/lib/bounding-volumes/axis-aligned-bounding-box.js
var import_core = require("@math.gl/core");
var scratchVector = new import_core.Vector3();
var scratchNormal = new import_core.Vector3();
var AxisAlignedBoundingBox = class {
/**
* Creates an instance of an AxisAlignedBoundingBox from the minimum and maximum points along the x, y, and z axes.
* @param minimum=[0, 0, 0] The minimum point along the x, y, and z axes.
* @param maximum=[0, 0, 0] The maximum point along the x, y, and z axes.
* @param center The center of the box; automatically computed if not supplied.
*/
constructor(minimum = [0, 0, 0], maximum = [0, 0, 0], center) {
center = center || scratchVector.copy(minimum).add(maximum).scale(0.5);
this.center = new import_core.Vector3(center);
this.halfDiagonal = new import_core.Vector3(maximum).subtract(this.center);
this.minimum = new import_core.Vector3(minimum);
this.maximum = new import_core.Vector3(maximum);
}
/**
* Duplicates a AxisAlignedBoundingBox instance.
*
* @returns {AxisAlignedBoundingBox} A new AxisAlignedBoundingBox instance.
*/
clone() {
return new AxisAlignedBoundingBox(this.minimum, this.maximum, this.center);
}
/**
* Compares the provided AxisAlignedBoundingBox componentwise and returns
* true
if they are equal, false
otherwise.
*
* @param {AxisAlignedBoundingBox} [right] The second AxisAlignedBoundingBox to compare with.
* @returns {Boolean} true
if left and right are equal, false
otherwise.
*/
equals(right) {
return this === right || Boolean(right) && this.minimum.equals(right.minimum) && this.maximum.equals(right.maximum);
}
/**
* Applies a 4x4 affine transformation matrix to a bounding sphere.
* @param transform The transformation matrix to apply to the bounding sphere.
* @returns itself, i.e. the modified BoundingVolume.
*/
transform(transform) {
this.center.transformAsPoint(transform);
this.halfDiagonal.transform(transform);
this.minimum.transform(transform);
this.maximum.transform(transform);
return this;
}
/**
* Determines which side of a plane a box is located.
*/
intersectPlane(plane) {
const { halfDiagonal } = this;
const normal = scratchNormal.from(plane.normal);
const e = halfDiagonal.x * Math.abs(normal.x) + halfDiagonal.y * Math.abs(normal.y) + halfDiagonal.z * Math.abs(normal.z);
const s = this.center.dot(normal) + plane.distance;
if (s - e > 0) {
return INTERSECTION.INSIDE;
}
if (s + e < 0) {
return INTERSECTION.OUTSIDE;
}
return INTERSECTION.INTERSECTING;
}
/** Computes the estimated distance from the closest point on a bounding box to a point. */
distanceTo(point) {
return Math.sqrt(this.distanceSquaredTo(point));
}
/** Computes the estimated distance squared from the closest point on a bounding box to a point. */
distanceSquaredTo(point) {
const offset = scratchVector.from(point).subtract(this.center);
const { halfDiagonal } = this;
let distanceSquared = 0;
let d;
d = Math.abs(offset.x) - halfDiagonal.x;
if (d > 0) {
distanceSquared += d * d;
}
d = Math.abs(offset.y) - halfDiagonal.y;
if (d > 0) {
distanceSquared += d * d;
}
d = Math.abs(offset.z) - halfDiagonal.z;
if (d > 0) {
distanceSquared += d * d;
}
return distanceSquared;
}
};
// dist/lib/bounding-volumes/bounding-sphere.js
var import_core2 = require("@math.gl/core");
var scratchVector2 = new import_core2.Vector3();
var scratchVector22 = new import_core2.Vector3();
var BoundingSphere = class {
/** Creates a bounding sphere */
constructor(center = [0, 0, 0], radius = 0) {
this.radius = -0;
this.center = new import_core2.Vector3();
this.fromCenterRadius(center, radius);
}
/** Sets the bounding sphere from `center` and `radius`. */
fromCenterRadius(center, radius) {
this.center.from(center);
this.radius = radius;
return this;
}
/**
* Computes a bounding sphere from the corner points of an axis-aligned bounding box. The sphere
* tightly and fully encompasses the box.
*/
fromCornerPoints(corner, oppositeCorner) {
oppositeCorner = scratchVector2.from(oppositeCorner);
this.center = new import_core2.Vector3().from(corner).add(oppositeCorner).scale(0.5);
this.radius = this.center.distance(oppositeCorner);
return this;
}
/** Compares the provided BoundingSphere component wise */
equals(right) {
return this === right || Boolean(right) && this.center.equals(right.center) && this.radius === right.radius;
}
/** Duplicates a BoundingSphere instance. */
clone() {
return new BoundingSphere(this.center, this.radius);
}
/** Computes a bounding sphere that contains both the left and right bounding spheres. */
union(boundingSphere) {
const leftCenter = this.center;
const leftRadius = this.radius;
const rightCenter = boundingSphere.center;
const rightRadius = boundingSphere.radius;
const toRightCenter = scratchVector2.copy(rightCenter).subtract(leftCenter);
const centerSeparation = toRightCenter.magnitude();
if (leftRadius >= centerSeparation + rightRadius) {
return this.clone();
}
if (rightRadius >= centerSeparation + leftRadius) {
return boundingSphere.clone();
}
const halfDistanceBetweenTangentPoints = (leftRadius + centerSeparation + rightRadius) * 0.5;
scratchVector22.copy(toRightCenter).scale((-leftRadius + halfDistanceBetweenTangentPoints) / centerSeparation).add(leftCenter);
this.center.copy(scratchVector22);
this.radius = halfDistanceBetweenTangentPoints;
return this;
}
/** Computes a bounding sphere by enlarging the provided sphere to contain the provided point. */
expand(point) {
const scratchPoint = scratchVector2.from(point);
const radius = scratchPoint.subtract(this.center).magnitude();
if (radius > this.radius) {
this.radius = radius;
}
return this;
}
// BoundingVolume interface
/**
* Applies a 4x4 affine transformation matrix to a bounding sphere.
* @param sphere The bounding sphere to apply the transformation to.
* @param transform The transformation matrix to apply to the bounding sphere.
* @returns self.
*/
transform(transform) {
this.center.transform(transform);
const scale = import_core2.mat4.getScaling(scratchVector2, transform);
this.radius = Math.max(scale[0], Math.max(scale[1], scale[2])) * this.radius;
return this;
}
/** Computes the estimated distance squared from the closest point on a bounding sphere to a point. */
distanceSquaredTo(point) {
const d = this.distanceTo(point);
return d * d;
}
/** Computes the estimated distance from the closest point on a bounding sphere to a point. */
distanceTo(point) {
const scratchPoint = scratchVector2.from(point);
const delta = scratchPoint.subtract(this.center);
return Math.max(0, delta.len() - this.radius);
}
/** Determines which side of a plane a sphere is located. */
intersectPlane(plane) {
const center = this.center;
const radius = this.radius;
const normal = plane.normal;
const distanceToPlane = normal.dot(center) + plane.distance;
if (distanceToPlane < -radius) {
return INTERSECTION.OUTSIDE;
}
if (distanceToPlane < radius) {
return INTERSECTION.INTERSECTING;
}
return INTERSECTION.INSIDE;
}
};
// dist/lib/bounding-volumes/oriented-bounding-box.js
var import_core3 = require("@math.gl/core");
var scratchVector3 = new import_core3.Vector3();
var scratchOffset = new import_core3.Vector3();
var scratchVectorU = new import_core3.Vector3();
var scratchVectorV = new import_core3.Vector3();
var scratchVectorW = new import_core3.Vector3();
var scratchCorner = new import_core3.Vector3();
var scratchToCenter = new import_core3.Vector3();
var MATRIX3 = {
COLUMN0ROW0: 0,
COLUMN0ROW1: 1,
COLUMN0ROW2: 2,
COLUMN1ROW0: 3,
COLUMN1ROW1: 4,
COLUMN1ROW2: 5,
COLUMN2ROW0: 6,
COLUMN2ROW1: 7,
COLUMN2ROW2: 8
};
var OrientedBoundingBox = class {
constructor(center = [0, 0, 0], halfAxes = [0, 0, 0, 0, 0, 0, 0, 0, 0]) {
this.center = new import_core3.Vector3().from(center);
this.halfAxes = new import_core3.Matrix3(halfAxes);
}
/** Returns an array with three halfSizes for the bounding box */
get halfSize() {
const xAxis = this.halfAxes.getColumn(0);
const yAxis = this.halfAxes.getColumn(1);
const zAxis = this.halfAxes.getColumn(2);
return [new import_core3.Vector3(xAxis).len(), new import_core3.Vector3(yAxis).len(), new import_core3.Vector3(zAxis).len()];
}
/** Returns a quaternion describing the orientation of the bounding box */
get quaternion() {
const xAxis = this.halfAxes.getColumn(0);
const yAxis = this.halfAxes.getColumn(1);
const zAxis = this.halfAxes.getColumn(2);
const normXAxis = new import_core3.Vector3(xAxis).normalize();
const normYAxis = new import_core3.Vector3(yAxis).normalize();
const normZAxis = new import_core3.Vector3(zAxis).normalize();
return new import_core3.Quaternion().fromMatrix3(new import_core3.Matrix3([...normXAxis, ...normYAxis, ...normZAxis]));
}
/**
* Create OrientedBoundingBox from quaternion based OBB,
*/
fromCenterHalfSizeQuaternion(center, halfSize, quaternion) {
const quaternionObject = new import_core3.Quaternion(quaternion);
const directionsMatrix = new import_core3.Matrix3().fromQuaternion(quaternionObject);
directionsMatrix[0] = directionsMatrix[0] * halfSize[0];
directionsMatrix[1] = directionsMatrix[1] * halfSize[0];
directionsMatrix[2] = directionsMatrix[2] * halfSize[0];
directionsMatrix[3] = directionsMatrix[3] * halfSize[1];
directionsMatrix[4] = directionsMatrix[4] * halfSize[1];
directionsMatrix[5] = directionsMatrix[5] * halfSize[1];
directionsMatrix[6] = directionsMatrix[6] * halfSize[2];
directionsMatrix[7] = directionsMatrix[7] * halfSize[2];
directionsMatrix[8] = directionsMatrix[8] * halfSize[2];
this.center = new import_core3.Vector3().from(center);
this.halfAxes = directionsMatrix;
return this;
}
/** Duplicates a OrientedBoundingBox instance. */
clone() {
return new OrientedBoundingBox(this.center, this.halfAxes);
}
/** Compares the provided OrientedBoundingBox component wise and returns */
equals(right) {
return this === right || Boolean(right) && this.center.equals(right.center) && this.halfAxes.equals(right.halfAxes);
}
/** Computes a tight-fitting bounding sphere enclosing the provided oriented bounding box. */
getBoundingSphere(result = new BoundingSphere()) {
const halfAxes = this.halfAxes;
const u = halfAxes.getColumn(0, scratchVectorU);
const v = halfAxes.getColumn(1, scratchVectorV);
const w = halfAxes.getColumn(2, scratchVectorW);
const cornerVector = scratchVector3.copy(u).add(v).add(w);
result.center.copy(this.center);
result.radius = cornerVector.magnitude();
return result;
}
/** Determines which side of a plane the oriented bounding box is located. */
intersectPlane(plane) {
const center = this.center;
const normal = plane.normal;
const halfAxes = this.halfAxes;
const normalX = normal.x;
const normalY = normal.y;
const normalZ = normal.z;
const radEffective = Math.abs(normalX * halfAxes[MATRIX3.COLUMN0ROW0] + normalY * halfAxes[MATRIX3.COLUMN0ROW1] + normalZ * halfAxes[MATRIX3.COLUMN0ROW2]) + Math.abs(normalX * halfAxes[MATRIX3.COLUMN1ROW0] + normalY * halfAxes[MATRIX3.COLUMN1ROW1] + normalZ * halfAxes[MATRIX3.COLUMN1ROW2]) + Math.abs(normalX * halfAxes[MATRIX3.COLUMN2ROW0] + normalY * halfAxes[MATRIX3.COLUMN2ROW1] + normalZ * halfAxes[MATRIX3.COLUMN2ROW2]);
const distanceToPlane = normal.dot(center) + plane.distance;
if (distanceToPlane <= -radEffective) {
return INTERSECTION.OUTSIDE;
} else if (distanceToPlane >= radEffective) {
return INTERSECTION.INSIDE;
}
return INTERSECTION.INTERSECTING;
}
/** Computes the estimated distance from the closest point on a bounding box to a point. */
distanceTo(point) {
return Math.sqrt(this.distanceSquaredTo(point));
}
/**
* Computes the estimated distance squared from the closest point
* on a bounding box to a point.
* See Geometric Tools for Computer Graphics 10.4.2
*/
distanceSquaredTo(point) {
const offset = scratchOffset.from(point).subtract(this.center);
const halfAxes = this.halfAxes;
const u = halfAxes.getColumn(0, scratchVectorU);
const v = halfAxes.getColumn(1, scratchVectorV);
const w = halfAxes.getColumn(2, scratchVectorW);
const uHalf = u.magnitude();
const vHalf = v.magnitude();
const wHalf = w.magnitude();
u.normalize();
v.normalize();
w.normalize();
let distanceSquared = 0;
let d;
d = Math.abs(offset.dot(u)) - uHalf;
if (d > 0) {
distanceSquared += d * d;
}
d = Math.abs(offset.dot(v)) - vHalf;
if (d > 0) {
distanceSquared += d * d;
}
d = Math.abs(offset.dot(w)) - wHalf;
if (d > 0) {
distanceSquared += d * d;
}
return distanceSquared;
}
/**
* The distances calculated by the vector from the center of the bounding box
* to position projected onto direction.
*
* - If you imagine the infinite number of planes with normal direction,
* this computes the smallest distance to the closest and farthest planes
* from `position` that intersect the bounding box.
*
* @param position The position to calculate the distance from.
* @param direction The direction from position.
* @param result An Interval (array of length 2) to store the nearest and farthest distances.
* @returns Interval (array of length 2) with nearest and farthest distances
* on the bounding box from position in direction.
*/
// eslint-disable-next-line max-statements
computePlaneDistances(position, direction, result = [-0, -0]) {
let minDist = Number.POSITIVE_INFINITY;
let maxDist = Number.NEGATIVE_INFINITY;
const center = this.center;
const halfAxes = this.halfAxes;
const u = halfAxes.getColumn(0, scratchVectorU);
const v = halfAxes.getColumn(1, scratchVectorV);
const w = halfAxes.getColumn(2, scratchVectorW);
const corner = scratchCorner.copy(u).add(v).add(w).add(center);
const toCenter = scratchToCenter.copy(corner).subtract(position);
let mag = direction.dot(toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
corner.copy(center).add(u).add(v).subtract(w);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
corner.copy(center).add(u).subtract(v).add(w);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
corner.copy(center).add(u).subtract(v).subtract(w);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
center.copy(corner).subtract(u).add(v).add(w);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
center.copy(corner).subtract(u).add(v).subtract(w);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
center.copy(corner).subtract(u).subtract(v).add(w);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
center.copy(corner).subtract(u).subtract(v).subtract(w);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
result[0] = minDist;
result[1] = maxDist;
return result;
}
/**
* Applies a 4x4 affine transformation matrix to a bounding sphere.
* @param transform The transformation matrix to apply to the bounding sphere.
* @returns itself, i.e. the modified BoundingVolume.
*/
transform(transformation) {
this.center.transformAsPoint(transformation);
const xAxis = this.halfAxes.getColumn(0, scratchVectorU);
xAxis.transformAsPoint(transformation);
const yAxis = this.halfAxes.getColumn(1, scratchVectorV);
yAxis.transformAsPoint(transformation);
const zAxis = this.halfAxes.getColumn(2, scratchVectorW);
zAxis.transformAsPoint(transformation);
this.halfAxes = new import_core3.Matrix3([...xAxis, ...yAxis, ...zAxis]);
return this;
}
getTransform() {
throw new Error("not implemented");
}
};
// dist/lib/culling-volume.js
var import_core5 = require("@math.gl/core");
// dist/lib/plane.js
var import_core4 = require("@math.gl/core");
var scratchPosition = new import_core4.Vector3();
var scratchNormal2 = new import_core4.Vector3();
var Plane = class {
constructor(normal = [0, 0, 1], distance = 0) {
this.normal = new import_core4.Vector3();
this.distance = -0;
this.fromNormalDistance(normal, distance);
}
/** Creates a plane from a normal and a distance from the origin. */
fromNormalDistance(normal, distance) {
(0, import_core4.assert)(Number.isFinite(distance));
this.normal.from(normal).normalize();
this.distance = distance;
return this;
}
/** Creates a plane from a normal and a point on the plane. */
fromPointNormal(point, normal) {
point = scratchPosition.from(point);
this.normal.from(normal).normalize();
const distance = -this.normal.dot(point);
this.distance = distance;
return this;
}
/** Creates a plane from the general equation */
fromCoefficients(a, b, c, d) {
this.normal.set(a, b, c);
(0, import_core4.assert)((0, import_core4.equals)(this.normal.len(), 1));
this.distance = d;
return this;
}
/** Duplicates a Plane instance. */
clone() {
return new Plane(this.normal, this.distance);
}
/** Compares the provided Planes by normal and distance */
equals(right) {
return (0, import_core4.equals)(this.distance, right.distance) && (0, import_core4.equals)(this.normal, right.normal);
}
/** Computes the signed shortest distance of a point to a plane.
* The sign of the distance determines which side of the plane the point is on.
*/
getPointDistance(point) {
return this.normal.dot(point) + this.distance;
}
/** Transforms the plane by the given transformation matrix. */
transform(matrix4) {
const normal = scratchNormal2.copy(this.normal).transformAsVector(matrix4).normalize();
const point = this.normal.scale(-this.distance).transform(matrix4);
return this.fromPointNormal(point, normal);
}
projectPointOntoPlane(point, result = [0, 0, 0]) {
const scratchPoint = scratchPosition.from(point);
const pointDistance = this.getPointDistance(scratchPoint);
const scaledNormal = scratchNormal2.copy(this.normal).scale(pointDistance);
return scratchPoint.subtract(scaledNormal).to(result);
}
};
// dist/lib/culling-volume.js
var faces = [new import_core5.Vector3([1, 0, 0]), new import_core5.Vector3([0, 1, 0]), new import_core5.Vector3([0, 0, 1])];
var scratchPlaneCenter = new import_core5.Vector3();
var scratchPlaneNormal = new import_core5.Vector3();
var CullingVolume = class {
/**
* Create a new `CullingVolume` bounded by an array of clipping planed
* @param planes Array of clipping planes.
* */
constructor(planes = []) {
this.planes = planes;
}
/**
* Constructs a culling volume from a bounding sphere. Creates six planes that create a box containing the sphere.
* The planes are aligned to the x, y, and z axes in world coordinates.
*/
fromBoundingSphere(boundingSphere) {
this.planes.length = 2 * faces.length;
const center = boundingSphere.center;
const radius = boundingSphere.radius;
let planeIndex = 0;
for (const faceNormal of faces) {
let plane0 = this.planes[planeIndex];
let plane1 = this.planes[planeIndex + 1];
if (!plane0) {
plane0 = this.planes[planeIndex] = new Plane();
}
if (!plane1) {
plane1 = this.planes[planeIndex + 1] = new Plane();
}
const plane0Center = scratchPlaneCenter.copy(faceNormal).scale(-radius).add(center);
plane0.fromPointNormal(plane0Center, faceNormal);
const plane1Center = scratchPlaneCenter.copy(faceNormal).scale(radius).add(center);
const negatedFaceNormal = scratchPlaneNormal.copy(faceNormal).negate();
plane1.fromPointNormal(plane1Center, negatedFaceNormal);
planeIndex += 2;
}
return this;
}
/** Determines whether a bounding volume intersects the culling volume. */
computeVisibility(boundingVolume) {
let intersect = INTERSECTION.INSIDE;
for (const plane of this.planes) {
const result = boundingVolume.intersectPlane(plane);
switch (result) {
case INTERSECTION.OUTSIDE:
return INTERSECTION.OUTSIDE;
case INTERSECTION.INTERSECTING:
intersect = INTERSECTION.INTERSECTING;
break;
default:
}
}
return intersect;
}
/**
* Determines whether a bounding volume intersects the culling volume.
*
* @param parentPlaneMask A bit mask from the boundingVolume's parent's check against the same culling
* volume, such that if (planeMask & (1 << planeIndex) === 0), for k < 31, then
* the parent (and therefore this) volume is completely inside plane[planeIndex]
* and that plane check can be skipped.
*/
computeVisibilityWithPlaneMask(boundingVolume, parentPlaneMask) {
(0, import_core5.assert)(Number.isFinite(parentPlaneMask), "parentPlaneMask is required.");
if (parentPlaneMask === CullingVolume.MASK_OUTSIDE || parentPlaneMask === CullingVolume.MASK_INSIDE) {
return parentPlaneMask;
}
let mask = CullingVolume.MASK_INSIDE;
const planes = this.planes;
for (let k = 0; k < this.planes.length; ++k) {
const flag = k < 31 ? 1 << k : 0;
if (k < 31 && (parentPlaneMask & flag) === 0) {
continue;
}
const plane = planes[k];
const result = boundingVolume.intersectPlane(plane);
if (result === INTERSECTION.OUTSIDE) {
return CullingVolume.MASK_OUTSIDE;
} else if (result === INTERSECTION.INTERSECTING) {
mask |= flag;
}
}
return mask;
}
};
CullingVolume.MASK_OUTSIDE = 4294967295;
CullingVolume.MASK_INSIDE = 0;
CullingVolume.MASK_INDETERMINATE = 2147483647;
// dist/lib/perspective-off-center-frustum.js
var import_core6 = require("@math.gl/core");
var scratchPlaneUpVector = new import_core6.Vector3();
var scratchPlaneRightVector = new import_core6.Vector3();
var scratchPlaneNearCenter = new import_core6.Vector3();
var scratchPlaneFarCenter = new import_core6.Vector3();
var scratchPlaneNormal2 = new import_core6.Vector3();
var PerspectiveOffCenterFrustum = class {
/**
* The viewing frustum is defined by 6 planes.
* Each plane is represented by a {@link Vector4} object, where the x, y, and z components
* define the unit vector normal to the plane, and the w component is the distance of the
* plane from the origin/camera position.
*
* @alias PerspectiveOffCenterFrustum
*
* @example
* const frustum = new PerspectiveOffCenterFrustum({
* left : -1.0,
* right : 1.0,
* top : 1.0,
* bottom : -1.0,
* near : 1.0,
* far : 100.0
* });
*
* @see PerspectiveFrustum
*/
constructor(options = {}) {
this._cullingVolume = new CullingVolume([
new Plane(),
new Plane(),
new Plane(),
new Plane(),
new Plane(),
new Plane()
]);
this._perspectiveMatrix = new import_core6.Matrix4();
this._infinitePerspective = new import_core6.Matrix4();
const { near = 1, far = 5e8 } = options;
this.left = options.left;
this._left = void 0;
this.right = options.right;
this._right = void 0;
this.top = options.top;
this._top = void 0;
this.bottom = options.bottom;
this._bottom = void 0;
this.near = near;
this._near = near;
this.far = far;
this._far = far;
}
/**
* Returns a duplicate of a PerspectiveOffCenterFrustum instance.
* @returns {PerspectiveOffCenterFrustum} A new PerspectiveFrustum instance.
* */
clone() {
return new PerspectiveOffCenterFrustum({
right: this.right,
left: this.left,
top: this.top,
bottom: this.bottom,
near: this.near,
far: this.far
});
}
/**
* Compares the provided PerspectiveOffCenterFrustum componentwise and returns
* true
if they are equal, false
otherwise.
*
* @returns {Boolean} true
if they are equal, false
otherwise.
*/
equals(other) {
return other && other instanceof PerspectiveOffCenterFrustum && this.right === other.right && this.left === other.left && this.top === other.top && this.bottom === other.bottom && this.near === other.near && this.far === other.far;
}
/**
* Gets the perspective projection matrix computed from the view frustum.
* @memberof PerspectiveOffCenterFrustum.prototype
* @type {Matrix4}
*
* @see PerspectiveOffCenterFrustum#infiniteProjectionMatrix
*/
get projectionMatrix() {
this._update();
return this._perspectiveMatrix;
}
/**
* Gets the perspective projection matrix computed from the view frustum with an infinite far plane.
* @memberof PerspectiveOffCenterFrustum.prototype
* @type {Matrix4}
*
* @see PerspectiveOffCenterFrustum#projectionMatrix
*/
get infiniteProjectionMatrix() {
this._update();
return this._infinitePerspective;
}
/**
* Creates a culling volume for this frustum.
* @returns {CullingVolume} A culling volume at the given position and orientation.
*
* @example
* // Check if a bounding volume intersects the frustum.
* const cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);
* const intersect = cullingVolume.computeVisibility(boundingVolume);
*/
// eslint-disable-next-line complexity, max-statements
computeCullingVolume(position, direction, up) {
(0, import_core6.assert)(position, "position is required.");
(0, import_core6.assert)(direction, "direction is required.");
(0, import_core6.assert)(up, "up is required.");
const planes = this._cullingVolume.planes;
up = scratchPlaneUpVector.copy(up).normalize();
const right = scratchPlaneRightVector.copy(direction).cross(up).normalize();
const nearCenter = scratchPlaneNearCenter.copy(direction).multiplyByScalar(this.near).add(position);
const farCenter = scratchPlaneFarCenter.copy(direction).multiplyByScalar(this.far).add(position);
let normal = scratchPlaneNormal2;
normal.copy(right).multiplyByScalar(this.left).add(nearCenter).subtract(position).cross(up);
planes[0].fromPointNormal(position, normal);
normal.copy(right).multiplyByScalar(this.right).add(nearCenter).subtract(position).cross(up).negate();
planes[1].fromPointNormal(position, normal);
normal.copy(up).multiplyByScalar(this.bottom).add(nearCenter).subtract(position).cross(right).negate();
planes[2].fromPointNormal(position, normal);
normal.copy(up).multiplyByScalar(this.top).add(nearCenter).subtract(position).cross(right);
planes[3].fromPointNormal(position, normal);
normal = new import_core6.Vector3().copy(direction);
planes[4].fromPointNormal(nearCenter, normal);
normal.negate();
planes[5].fromPointNormal(farCenter, normal);
return this._cullingVolume;
}
/**
* Returns the pixel's width and height in meters.
*
* @returns {Vector2} The modified result parameter or a new instance of {@link Vector2} with the pixel's width and height in the x and y properties, respectively.
*
* @exception {DeveloperError} drawingBufferWidth must be greater than zero.
* @exception {DeveloperError} drawingBufferHeight must be greater than zero.
*
* @example
* // Example 1
* // Get the width and height of a pixel.
* const pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 1.0, new Vector2());
*
* @example
* // Example 2
* // Get the width and height of a pixel if the near plane was set to 'distance'.
* // For example, get the size of a pixel of an image on a billboard.
* const position = camera.position;
* const direction = camera.direction;
* const toCenter = Vector3.subtract(primitive.boundingVolume.center, position, new Vector3()); // vector from camera to a primitive
* const toCenterProj = Vector3.multiplyByScalar(direction, Vector3.dot(direction, toCenter), new Vector3()); // project vector onto camera direction vector
* const distance = Vector3.magnitude(toCenterProj);
* const pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, distance, new Vector2());
*/
getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result) {
this._update();
(0, import_core6.assert)(Number.isFinite(drawingBufferWidth) && Number.isFinite(drawingBufferHeight));
(0, import_core6.assert)(drawingBufferWidth > 0);
(0, import_core6.assert)(drawingBufferHeight > 0);
(0, import_core6.assert)(distance > 0);
(0, import_core6.assert)(result);
const inverseNear = 1 / this.near;
let tanTheta = this.top * inverseNear;
const pixelHeight = 2 * distance * tanTheta / drawingBufferHeight;
tanTheta = this.right * inverseNear;
const pixelWidth = 2 * distance * tanTheta / drawingBufferWidth;
result.x = pixelWidth;
result.y = pixelHeight;
return result;
}
// eslint-disable-next-line complexity, max-statements
_update() {
(0, import_core6.assert)(Number.isFinite(this.right) && Number.isFinite(this.left) && Number.isFinite(this.top) && Number.isFinite(this.bottom) && Number.isFinite(this.near) && Number.isFinite(this.far));
const { top, bottom, right, left, near, far } = this;
if (top !== this._top || bottom !== this._bottom || left !== this._left || right !== this._right || near !== this._near || far !== this._far) {
(0, import_core6.assert)(this.near > 0 && this.near < this.far, "near must be greater than zero and less than far.");
this._left = left;
this._right = right;
this._top = top;
this._bottom = bottom;
this._near = near;
this._far = far;
this._perspectiveMatrix = new import_core6.Matrix4().frustum({
left,
right,
bottom,
top,
near,
far
});
this._infinitePerspective = new import_core6.Matrix4().frustum({
left,
right,
bottom,
top,
near,
far: Infinity
});
}
}
};
// dist/lib/perspective-frustum.js
var import_core7 = require("@math.gl/core");
var defined = (val) => val !== null && typeof val !== "undefined";
var PerspectiveFrustum = class {
constructor(options = {}) {
this._offCenterFrustum = new PerspectiveOffCenterFrustum();
const { fov, aspectRatio, near = 1, far = 5e8, xOffset = 0, yOffset = 0 } = options;
this.fov = fov;
this.aspectRatio = aspectRatio;
this.near = near;
this.far = far;
this.xOffset = xOffset;
this.yOffset = yOffset;
}
/**
* Returns a duplicate of a PerspectiveFrustum instance.
*/
clone() {
return new PerspectiveFrustum({
aspectRatio: this.aspectRatio,
fov: this.fov,
near: this.near,
far: this.far
});
}
/**
* Compares the provided PerspectiveFrustum componentwise and returns
* true
if they are equal, false
otherwise.
*/
equals(other) {
if (!defined(other) || !(other instanceof PerspectiveFrustum)) {
return false;
}
this._update();
other._update();
return this.fov === other.fov && this.aspectRatio === other.aspectRatio && this.near === other.near && this.far === other.far && this._offCenterFrustum.equals(other._offCenterFrustum);
}
/**
* Gets the perspective projection matrix computed from the view this.
*/
get projectionMatrix() {
this._update();
return this._offCenterFrustum.projectionMatrix;
}
/**
* The perspective projection matrix computed from the view frustum with an infinite far plane.
*/
get infiniteProjectionMatrix() {
this._update();
return this._offCenterFrustum.infiniteProjectionMatrix;
}
/**
* Gets the angle of the vertical field of view, in radians.
*/
get fovy() {
this._update();
return this._fovy;
}
/**
* @private
*/
get sseDenominator() {
this._update();
return this._sseDenominator;
}
/**
* Creates a culling volume for this this.ion.
* @returns {CullingVolume} A culling volume at the given position and orientation.
*
* @example
* // Check if a bounding volume intersects the this.
* var cullingVolume = this.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);
* var intersect = cullingVolume.computeVisibility(boundingVolume);
*/
computeCullingVolume(position, direction, up) {
this._update();
return this._offCenterFrustum.computeCullingVolume(position, direction, up);
}
/**
* Returns the pixel's width and height in meters.
* @returns {Vector2} The modified result parameter or a new instance of {@link Vector2} with the pixel's width and height in the x and y properties, respectively.
*
* @exception {DeveloperError} drawingBufferWidth must be greater than zero.
* @exception {DeveloperError} drawingBufferHeight must be greater than zero.
*
* @example
* // Example 1
* // Get the width and height of a pixel.
* var pixelSize = camera.this.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 1.0, new Vector2());
*
* @example
* // Example 2
* // Get the width and height of a pixel if the near plane was set to 'distance'.
* // For example, get the size of a pixel of an image on a billboard.
* var position = camera.position;
* var direction = camera.direction;
* var toCenter = Vector3.subtract(primitive.boundingVolume.center, position, new Vector3()); // vector from camera to a primitive
* var toCenterProj = Vector3.multiplyByScalar(direction, Vector3.dot(direction, toCenter), new Vector3()); // project vector onto camera direction vector
* var distance = Vector3.magnitude(toCenterProj);
* var pixelSize = camera.this.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, distance, new Vector2());
*/
getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result) {
this._update();
return this._offCenterFrustum.getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result || new import_core7.Vector2());
}
// eslint-disable-next-line complexity, max-statements
_update() {
(0, import_core7.assert)(Number.isFinite(this.fov) && Number.isFinite(this.aspectRatio) && Number.isFinite(this.near) && Number.isFinite(this.far));
const f = this._offCenterFrustum;
if (this.fov !== this._fov || this.aspectRatio !== this._aspectRatio || this.near !== this._near || this.far !== this._far || this.xOffset !== this._xOffset || this.yOffset !== this._yOffset) {
(0, import_core7.assert)(this.fov >= 0 && this.fov < Math.PI);
(0, import_core7.assert)(this.aspectRatio > 0);
(0, import_core7.assert)(this.near >= 0 && this.near < this.far);
this._aspectRatio = this.aspectRatio;
this._fov = this.fov;
this._fovy = this.aspectRatio <= 1 ? this.fov : Math.atan(Math.tan(this.fov * 0.5) / this.aspectRatio) * 2;
this._near = this.near;
this._far = this.far;
this._sseDenominator = 2 * Math.tan(0.5 * this._fovy);
this._xOffset = this.xOffset;
this._yOffset = this.yOffset;
f.top = this.near * Math.tan(0.5 * this._fovy);
f.bottom = -f.top;
f.right = this.aspectRatio * f.top;
f.left = -f.right;
f.near = this.near;
f.far = this.far;
f.right += this.xOffset;
f.left += this.xOffset;
f.top += this.yOffset;
f.bottom += this.yOffset;
}
}
};
// dist/lib/algorithms/bounding-sphere-from-points.js
var import_core8 = require("@math.gl/core");
var fromPointsXMin = new import_core8.Vector3();
var fromPointsYMin = new import_core8.Vector3();
var fromPointsZMin = new import_core8.Vector3();
var fromPointsXMax = new import_core8.Vector3();
var fromPointsYMax = new import_core8.Vector3();
var fromPointsZMax = new import_core8.Vector3();
var fromPointsCurrentPos = new import_core8.Vector3();
var fromPointsScratch = new import_core8.Vector3();
var fromPointsRitterCenter = new import_core8.Vector3();
var fromPointsMinBoxPt = new import_core8.Vector3();
var fromPointsMaxBoxPt = new import_core8.Vector3();
var fromPointsNaiveCenterScratch = new import_core8.Vector3();
function makeBoundingSphereFromPoints(positions, result = new BoundingSphere()) {
if (!positions || positions.length === 0) {
return result.fromCenterRadius([0, 0, 0], 0);
}
const currentPos = fromPointsCurrentPos.copy(positions[0]);
const xMin = fromPointsXMin.copy(currentPos);
const yMin = fromPointsYMin.copy(currentPos);
const zMin = fromPointsZMin.copy(currentPos);
const xMax = fromPointsXMax.copy(currentPos);
const yMax = fromPointsYMax.copy(currentPos);
const zMax = fromPointsZMax.copy(currentPos);
for (const position of positions) {
currentPos.copy(position);
const x = currentPos.x;
const y = currentPos.y;
const z = currentPos.z;
if (x < xMin.x) {
xMin.copy(currentPos);
}
if (x > xMax.x) {
xMax.copy(currentPos);
}
if (y < yMin.y) {
yMin.copy(currentPos);
}
if (y > yMax.y) {
yMax.copy(currentPos);
}
if (z < zMin.z) {
zMin.copy(currentPos);
}
if (z > zMax.z) {
zMax.copy(currentPos);
}
}
const xSpan = fromPointsScratch.copy(xMax).subtract(xMin).magnitudeSquared();
const ySpan = fromPointsScratch.copy(yMax).subtract(yMin).magnitudeSquared();
const zSpan = fromPointsScratch.copy(zMax).subtract(zMin).magnitudeSquared();
let diameter1 = xMin;
let diameter2 = xMax;
let maxSpan = xSpan;
if (ySpan > maxSpan) {
maxSpan = ySpan;
diameter1 = yMin;
diameter2 = yMax;
}
if (zSpan > maxSpan) {
maxSpan = zSpan;
diameter1 = zMin;
diameter2 = zMax;
}
const ritterCenter = fromPointsRitterCenter;
ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;
ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;
ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;
let radiusSquared = fromPointsScratch.copy(diameter2).subtract(ritterCenter).magnitudeSquared();
let ritterRadius = Math.sqrt(radiusSquared);
const minBoxPt = fromPointsMinBoxPt;
minBoxPt.x = xMin.x;
minBoxPt.y = yMin.y;
minBoxPt.z = zMin.z;
const maxBoxPt = fromPointsMaxBoxPt;
maxBoxPt.x = xMax.x;
maxBoxPt.y = yMax.y;
maxBoxPt.z = zMax.z;
const naiveCenter = fromPointsNaiveCenterScratch.copy(minBoxPt).add(maxBoxPt).multiplyByScalar(0.5);
let naiveRadius = 0;
for (const position of positions) {
currentPos.copy(position);
const r = fromPointsScratch.copy(currentPos).subtract(naiveCenter).magnitude();
if (r > naiveRadius) {
naiveRadius = r;
}
const oldCenterToPointSquared = fromPointsScratch.copy(currentPos).subtract(ritterCenter).magnitudeSquared();
if (oldCenterToPointSquared > radiusSquared) {
const oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);
ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;
radiusSquared = ritterRadius * ritterRadius;
const oldToNew = oldCenterToPoint - ritterRadius;
ritterCenter.x = (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) / oldCenterToPoint;
ritterCenter.y = (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) / oldCenterToPoint;
ritterCenter.z = (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) / oldCenterToPoint;
}
}
if (ritterRadius < naiveRadius) {
ritterCenter.to(result.center);
result.radius = ritterRadius;
} else {
naiveCenter.to(result.center);
result.radius = naiveRadius;
}
return result;
}
// dist/lib/algorithms/bounding-box-from-points.js
var import_core10 = require("@math.gl/core");
// dist/lib/algorithms/compute-eigen-decomposition.js
var import_core9 = require("@math.gl/core");
var scratchMatrix = new import_core9.Matrix3();
var scratchUnitary = new import_core9.Matrix3();
var scratchDiagonal = new import_core9.Matrix3();
var jMatrix = new import_core9.Matrix3();
var jMatrixTranspose = new import_core9.Matrix3();
function computeEigenDecomposition(matrix, result = {}) {
const EIGEN_TOLERANCE = import_core9._MathUtils.EPSILON20;
const EIGEN_MAX_SWEEPS = 10;
let count = 0;
let sweep = 0;
const unitaryMatrix = scratchUnitary;
const diagonalMatrix = scratchDiagonal;
unitaryMatrix.identity();
diagonalMatrix.copy(matrix);
const epsilon = EIGEN_TOLERANCE * computeFrobeniusNorm(diagonalMatrix);
while (sweep < EIGEN_MAX_SWEEPS && offDiagonalFrobeniusNorm(diagonalMatrix) > epsilon) {
shurDecomposition(diagonalMatrix, jMatrix);
jMatrixTranspose.copy(jMatrix).transpose();
diagonalMatrix.multiplyRight(jMatrix);
diagonalMatrix.multiplyLeft(jMatrixTranspose);
unitaryMatrix.multiplyRight(jMatrix);
if (++count > 2) {
++sweep;
count = 0;
}
}
result.unitary = unitaryMatrix.toTarget(result.unitary);
result.diagonal = diagonalMatrix.toTarget(result.diagonal);
return result;
}
function computeFrobeniusNorm(matrix) {
let norm = 0;
for (let i = 0; i < 9; ++i) {
const temp = matrix[i];
norm += temp * temp;
}
return Math.sqrt(norm);
}
var rowVal = [1, 0, 0];
var colVal = [2, 2, 1];
function offDiagonalFrobeniusNorm(matrix) {
let norm = 0;
for (let i = 0; i < 3; ++i) {
const temp = matrix[scratchMatrix.getElementIndex(colVal[i], rowVal[i])];
norm += 2 * temp * temp;
}
return Math.sqrt(norm);
}
function shurDecomposition(matrix, result) {
const tolerance = import_core9._MathUtils.EPSILON15;
let maxDiagonal = 0;
let rotAxis = 1;
for (let i = 0; i < 3; ++i) {
const temp = Math.abs(matrix[scratchMatrix.getElementIndex(colVal[i], rowVal[i])]);
if (temp > maxDiagonal) {
rotAxis = i;
maxDiagonal = temp;
}
}
const p = rowVal[rotAxis];
const q = colVal[rotAxis];
let c = 1;
let s = 0;
if (Math.abs(matrix[scratchMatrix.getElementIndex(q, p)]) > tolerance) {
const qq = matrix[scratchMatrix.getElementIndex(q, q)];
const pp = matrix[scratchMatrix.getElementIndex(p, p)];
const qp = matrix[scratchMatrix.getElementIndex(q, p)];
const tau = (qq - pp) / 2 / qp;
let t;
if (tau < 0) {
t = -1 / (-tau + Math.sqrt(1 + tau * tau));
} else {
t = 1 / (tau + Math.sqrt(1 + tau * tau));
}
c = 1 / Math.sqrt(1 + t * t);
s = t * c;
}
import_core9.Matrix3.IDENTITY.to(result);
result[scratchMatrix.getElementIndex(p, p)] = result[scratchMatrix.getElementIndex(q, q)] = c;
result[scratchMatrix.getElementIndex(q, p)] = s;
result[scratchMatrix.getElementIndex(p, q)] = -s;
return result;
}
// dist/lib/algorithms/bounding-box-from-points.js
var scratchVector23 = new import_core10.Vector3();
var scratchVector32 = new import_core10.Vector3();
var scratchVector4 = new import_core10.Vector3();
var scratchVector5 = new import_core10.Vector3();
var scratchVector6 = new import_core10.Vector3();
var scratchCovarianceResult = new import_core10.Matrix3();
var scratchEigenResult = {
diagonal: new import_core10.Matrix3(),
unitary: new import_core10.Matrix3()
};
function makeOrientedBoundingBoxFromPoints(positions, result = new OrientedBoundingBox()) {
if (!positions || positions.length === 0) {
result.halfAxes = new import_core10.Matrix3([0, 0, 0, 0, 0, 0, 0, 0, 0]);
result.center = new import_core10.Vector3();
return result;
}
const length = positions.length;
const meanPoint = new import_core10.Vector3(0, 0, 0);
for (const position of positions) {
meanPoint.add(position);
}
const invLength = 1 / length;
meanPoint.multiplyByScalar(invLength);
let exx = 0;
let exy = 0;
let exz = 0;
let eyy = 0;
let eyz = 0;
let ezz = 0;
for (const position of positions) {
const p = scratchVector23.copy(position).subtract(meanPoint);
exx += p.x * p.x;
exy += p.x * p.y;
exz += p.x * p.z;
eyy += p.y * p.y;
eyz += p.y * p.z;
ezz += p.z * p.z;
}
exx *= invLength;
exy *= invLength;
exz *= invLength;
eyy *= invLength;
eyz *= invLength;
ezz *= invLength;
const covarianceMatrix = scratchCovarianceResult;
covarianceMatrix[0] = exx;
covarianceMatrix[1] = exy;
covarianceMatrix[2] = exz;
covarianceMatrix[3] = exy;
covarianceMatrix[4] = eyy;
covarianceMatrix[5] = eyz;
covarianceMatrix[6] = exz;
covarianceMatrix[7] = eyz;
covarianceMatrix[8] = ezz;
const { unitary } = computeEigenDecomposition(covarianceMatrix, scratchEigenResult);
const rotation = result.halfAxes.copy(unitary);
let v1 = rotation.getColumn(0, scratchVector4);
let v2 = rotation.getColumn(1, scratchVector5);
let v3 = rotation.getColumn(2, scratchVector6);
let u1 = -Number.MAX_VALUE;
let u2 = -Number.MAX_VALUE;
let u3 = -Number.MAX_VALUE;
let l1 = Number.MAX_VALUE;
let l2 = Number.MAX_VALUE;
let l3 = Number.MAX_VALUE;
for (const position of positions) {
scratchVector23.copy(position);
u1 = Math.max(scratchVector23.dot(v1), u1);
u2 = Math.max(scratchVector23.dot(v2), u2);
u3 = Math.max(scratchVector23.dot(v3), u3);
l1 = Math.min(scratchVector23.dot(v1), l1);
l2 = Math.min(scratchVector23.dot(v2), l2);
l3 = Math.min(scratchVector23.dot(v3), l3);
}
v1 = v1.multiplyByScalar(0.5 * (l1 + u1));
v2 = v2.multiplyByScalar(0.5 * (l2 + u2));
v3 = v3.multiplyByScalar(0.5 * (l3 + u3));
result.center.copy(v1).add(v2).add(v3);
const scale = scratchVector32.set(u1 - l1, u2 - l2, u3 - l3).multiplyByScalar(0.5);
const scaleMatrix = new import_core10.Matrix3([scale[0], 0, 0, 0, scale[1], 0, 0, 0, scale[2]]);
result.halfAxes.multiplyRight(scaleMatrix);
return result;
}
function makeAxisAlignedBoundingBoxFromPoints(positions, result = new AxisAlignedBoundingBox()) {
if (!positions || positions.length === 0) {
result.minimum.set(0, 0, 0);
result.maximum.set(0, 0, 0);
result.center.set(0, 0, 0);
result.halfDiagonal.set(0, 0, 0);
return result;
}
let minimumX = positions[0][0];
let minimumY = positions[0][1];
let minimumZ = positions[0][2];
let maximumX = positions[0][0];
let maximumY = positions[0][1];
let maximumZ = positions[0][2];
for (const p of positions) {
const x = p[0];
const y = p[1];
const z = p[2];
minimumX = Math.min(x, minimumX);
maximumX = Math.max(x, maximumX);
minimumY = Math.min(y, minimumY);
maximumY = Math.max(y, maximumY);
minimumZ = Math.min(z, minimumZ);
maximumZ = Math.max(z, maximumZ);
}
result.minimum.set(minimumX, minimumY, minimumZ);
result.maximum.set(maximumX, maximumY, maximumZ);
result.center.copy(result.minimum).add(result.maximum).scale(0.5);
result.halfDiagonal.copy(result.maximum).subtract(result.center);
return result;
}
//# sourceMappingURL=index.cjs.map