@math.gl/culling 4.1.0-alpha.9 → 4.2.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -25,6 +25,7 @@ __export(dist_exports, {
25
25
  INTERSECTION: () => INTERSECTION,
26
26
  OrientedBoundingBox: () => OrientedBoundingBox,
27
27
  Plane: () => Plane,
28
+ Ray: () => Ray,
28
29
  _PerspectiveFrustum: () => PerspectiveFrustum,
29
30
  _PerspectiveOffCenterFrustum: () => PerspectiveOffCenterFrustum,
30
31
  computeEigenDecomposition: () => computeEigenDecomposition,
@@ -37,8 +38,11 @@ module.exports = __toCommonJS(dist_exports);
37
38
  // dist/constants.js
38
39
  var INTERSECTION = {
39
40
  OUTSIDE: -1,
41
+ // Represents that an object is not contained within the frustum.
40
42
  INTERSECTING: 0,
43
+ // Represents that an object intersects one of the frustum's planes.
41
44
  INSIDE: 1
45
+ // Represents that an object is fully within the frustum.
42
46
  };
43
47
 
44
48
  // dist/lib/bounding-volumes/axis-aligned-bounding-box.js
@@ -46,6 +50,12 @@ var import_core = require("@math.gl/core");
46
50
  var scratchVector = new import_core.Vector3();
47
51
  var scratchNormal = new import_core.Vector3();
48
52
  var AxisAlignedBoundingBox = class {
53
+ /**
54
+ * Creates an instance of an AxisAlignedBoundingBox from the minimum and maximum points along the x, y, and z axes.
55
+ * @param minimum=[0, 0, 0] The minimum point along the x, y, and z axes.
56
+ * @param maximum=[0, 0, 0] The maximum point along the x, y, and z axes.
57
+ * @param center The center of the box; automatically computed if not supplied.
58
+ */
49
59
  constructor(minimum = [0, 0, 0], maximum = [0, 0, 0], center) {
50
60
  center = center || scratchVector.copy(minimum).add(maximum).scale(0.5);
51
61
  this.center = new import_core.Vector3(center);
@@ -53,12 +63,29 @@ var AxisAlignedBoundingBox = class {
53
63
  this.minimum = new import_core.Vector3(minimum);
54
64
  this.maximum = new import_core.Vector3(maximum);
55
65
  }
66
+ /**
67
+ * Duplicates a AxisAlignedBoundingBox instance.
68
+ *
69
+ * @returns {AxisAlignedBoundingBox} A new AxisAlignedBoundingBox instance.
70
+ */
56
71
  clone() {
57
72
  return new AxisAlignedBoundingBox(this.minimum, this.maximum, this.center);
58
73
  }
74
+ /**
75
+ * Compares the provided AxisAlignedBoundingBox componentwise and returns
76
+ * <code>true</code> if they are equal, <code>false</code> otherwise.
77
+ *
78
+ * @param {AxisAlignedBoundingBox} [right] The second AxisAlignedBoundingBox to compare with.
79
+ * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
80
+ */
59
81
  equals(right) {
60
82
  return this === right || Boolean(right) && this.minimum.equals(right.minimum) && this.maximum.equals(right.maximum);
61
83
  }
84
+ /**
85
+ * Applies a 4x4 affine transformation matrix to a bounding sphere.
86
+ * @param transform The transformation matrix to apply to the bounding sphere.
87
+ * @returns itself, i.e. the modified BoundingVolume.
88
+ */
62
89
  transform(transform) {
63
90
  this.center.transformAsPoint(transform);
64
91
  this.halfDiagonal.transform(transform);
@@ -66,6 +93,9 @@ var AxisAlignedBoundingBox = class {
66
93
  this.maximum.transform(transform);
67
94
  return this;
68
95
  }
96
+ /**
97
+ * Determines which side of a plane a box is located.
98
+ */
69
99
  intersectPlane(plane) {
70
100
  const { halfDiagonal } = this;
71
101
  const normal = scratchNormal.from(plane.normal);
@@ -79,9 +109,11 @@ var AxisAlignedBoundingBox = class {
79
109
  }
80
110
  return INTERSECTION.INTERSECTING;
81
111
  }
112
+ /** Computes the estimated distance from the closest point on a bounding box to a point. */
82
113
  distanceTo(point) {
83
114
  return Math.sqrt(this.distanceSquaredTo(point));
84
115
  }
116
+ /** Computes the estimated distance squared from the closest point on a bounding box to a point. */
85
117
  distanceSquaredTo(point) {
86
118
  const offset = scratchVector.from(point).subtract(this.center);
87
119
  const { halfDiagonal } = this;
@@ -108,28 +140,37 @@ var import_core2 = require("@math.gl/core");
108
140
  var scratchVector2 = new import_core2.Vector3();
109
141
  var scratchVector22 = new import_core2.Vector3();
110
142
  var BoundingSphere = class {
143
+ /** Creates a bounding sphere */
111
144
  constructor(center = [0, 0, 0], radius = 0) {
112
145
  this.radius = -0;
113
146
  this.center = new import_core2.Vector3();
114
147
  this.fromCenterRadius(center, radius);
115
148
  }
149
+ /** Sets the bounding sphere from `center` and `radius`. */
116
150
  fromCenterRadius(center, radius) {
117
151
  this.center.from(center);
118
152
  this.radius = radius;
119
153
  return this;
120
154
  }
155
+ /**
156
+ * Computes a bounding sphere from the corner points of an axis-aligned bounding box. The sphere
157
+ * tightly and fully encompasses the box.
158
+ */
121
159
  fromCornerPoints(corner, oppositeCorner) {
122
160
  oppositeCorner = scratchVector2.from(oppositeCorner);
123
161
  this.center = new import_core2.Vector3().from(corner).add(oppositeCorner).scale(0.5);
124
162
  this.radius = this.center.distance(oppositeCorner);
125
163
  return this;
126
164
  }
165
+ /** Compares the provided BoundingSphere component wise */
127
166
  equals(right) {
128
167
  return this === right || Boolean(right) && this.center.equals(right.center) && this.radius === right.radius;
129
168
  }
169
+ /** Duplicates a BoundingSphere instance. */
130
170
  clone() {
131
171
  return new BoundingSphere(this.center, this.radius);
132
172
  }
173
+ /** Computes a bounding sphere that contains both the left and right bounding spheres. */
133
174
  union(boundingSphere) {
134
175
  const leftCenter = this.center;
135
176
  const leftRadius = this.radius;
@@ -149,6 +190,7 @@ var BoundingSphere = class {
149
190
  this.radius = halfDistanceBetweenTangentPoints;
150
191
  return this;
151
192
  }
193
+ /** Computes a bounding sphere by enlarging the provided sphere to contain the provided point. */
152
194
  expand(point) {
153
195
  const scratchPoint = scratchVector2.from(point);
154
196
  const radius = scratchPoint.subtract(this.center).magnitude();
@@ -157,21 +199,31 @@ var BoundingSphere = class {
157
199
  }
158
200
  return this;
159
201
  }
202
+ // BoundingVolume interface
203
+ /**
204
+ * Applies a 4x4 affine transformation matrix to a bounding sphere.
205
+ * @param sphere The bounding sphere to apply the transformation to.
206
+ * @param transform The transformation matrix to apply to the bounding sphere.
207
+ * @returns self.
208
+ */
160
209
  transform(transform) {
161
210
  this.center.transform(transform);
162
211
  const scale = import_core2.mat4.getScaling(scratchVector2, transform);
163
212
  this.radius = Math.max(scale[0], Math.max(scale[1], scale[2])) * this.radius;
164
213
  return this;
165
214
  }
215
+ /** Computes the estimated distance squared from the closest point on a bounding sphere to a point. */
166
216
  distanceSquaredTo(point) {
167
217
  const d = this.distanceTo(point);
168
218
  return d * d;
169
219
  }
220
+ /** Computes the estimated distance from the closest point on a bounding sphere to a point. */
170
221
  distanceTo(point) {
171
222
  const scratchPoint = scratchVector2.from(point);
172
223
  const delta = scratchPoint.subtract(this.center);
173
224
  return Math.max(0, delta.len() - this.radius);
174
225
  }
226
+ /** Determines which side of a plane a sphere is located. */
175
227
  intersectPlane(plane) {
176
228
  const center = this.center;
177
229
  const radius = this.radius;
@@ -212,12 +264,14 @@ var OrientedBoundingBox = class {
212
264
  this.center = new import_core3.Vector3().from(center);
213
265
  this.halfAxes = new import_core3.Matrix3(halfAxes);
214
266
  }
267
+ /** Returns an array with three halfSizes for the bounding box */
215
268
  get halfSize() {
216
269
  const xAxis = this.halfAxes.getColumn(0);
217
270
  const yAxis = this.halfAxes.getColumn(1);
218
271
  const zAxis = this.halfAxes.getColumn(2);
219
272
  return [new import_core3.Vector3(xAxis).len(), new import_core3.Vector3(yAxis).len(), new import_core3.Vector3(zAxis).len()];
220
273
  }
274
+ /** Returns a quaternion describing the orientation of the bounding box */
221
275
  get quaternion() {
222
276
  const xAxis = this.halfAxes.getColumn(0);
223
277
  const yAxis = this.halfAxes.getColumn(1);
@@ -227,6 +281,9 @@ var OrientedBoundingBox = class {
227
281
  const normZAxis = new import_core3.Vector3(zAxis).normalize();
228
282
  return new import_core3.Quaternion().fromMatrix3(new import_core3.Matrix3([...normXAxis, ...normYAxis, ...normZAxis]));
229
283
  }
284
+ /**
285
+ * Create OrientedBoundingBox from quaternion based OBB,
286
+ */
230
287
  fromCenterHalfSizeQuaternion(center, halfSize, quaternion) {
231
288
  const quaternionObject = new import_core3.Quaternion(quaternion);
232
289
  const directionsMatrix = new import_core3.Matrix3().fromQuaternion(quaternionObject);
@@ -243,12 +300,15 @@ var OrientedBoundingBox = class {
243
300
  this.halfAxes = directionsMatrix;
244
301
  return this;
245
302
  }
303
+ /** Duplicates a OrientedBoundingBox instance. */
246
304
  clone() {
247
305
  return new OrientedBoundingBox(this.center, this.halfAxes);
248
306
  }
307
+ /** Compares the provided OrientedBoundingBox component wise and returns */
249
308
  equals(right) {
250
309
  return this === right || Boolean(right) && this.center.equals(right.center) && this.halfAxes.equals(right.halfAxes);
251
310
  }
311
+ /** Computes a tight-fitting bounding sphere enclosing the provided oriented bounding box. */
252
312
  getBoundingSphere(result = new BoundingSphere()) {
253
313
  const halfAxes = this.halfAxes;
254
314
  const u = halfAxes.getColumn(0, scratchVectorU);
@@ -259,6 +319,7 @@ var OrientedBoundingBox = class {
259
319
  result.radius = cornerVector.magnitude();
260
320
  return result;
261
321
  }
322
+ /** Determines which side of a plane the oriented bounding box is located. */
262
323
  intersectPlane(plane) {
263
324
  const center = this.center;
264
325
  const normal = plane.normal;
@@ -275,9 +336,15 @@ var OrientedBoundingBox = class {
275
336
  }
276
337
  return INTERSECTION.INTERSECTING;
277
338
  }
339
+ /** Computes the estimated distance from the closest point on a bounding box to a point. */
278
340
  distanceTo(point) {
279
341
  return Math.sqrt(this.distanceSquaredTo(point));
280
342
  }
343
+ /**
344
+ * Computes the estimated distance squared from the closest point
345
+ * on a bounding box to a point.
346
+ * See Geometric Tools for Computer Graphics 10.4.2
347
+ */
281
348
  distanceSquaredTo(point) {
282
349
  const offset = scratchOffset.from(point).subtract(this.center);
283
350
  const halfAxes = this.halfAxes;
@@ -306,6 +373,21 @@ var OrientedBoundingBox = class {
306
373
  }
307
374
  return distanceSquared;
308
375
  }
376
+ /**
377
+ * The distances calculated by the vector from the center of the bounding box
378
+ * to position projected onto direction.
379
+ *
380
+ * - If you imagine the infinite number of planes with normal direction,
381
+ * this computes the smallest distance to the closest and farthest planes
382
+ * from `position` that intersect the bounding box.
383
+ *
384
+ * @param position The position to calculate the distance from.
385
+ * @param direction The direction from position.
386
+ * @param result An Interval (array of length 2) to store the nearest and farthest distances.
387
+ * @returns Interval (array of length 2) with nearest and farthest distances
388
+ * on the bounding box from position in direction.
389
+ */
390
+ // eslint-disable-next-line max-statements
309
391
  computePlaneDistances(position, direction, result = [-0, -0]) {
310
392
  let minDist = Number.POSITIVE_INFINITY;
311
393
  let maxDist = Number.NEGATIVE_INFINITY;
@@ -358,6 +440,11 @@ var OrientedBoundingBox = class {
358
440
  result[1] = maxDist;
359
441
  return result;
360
442
  }
443
+ /**
444
+ * Applies a 4x4 affine transformation matrix to a bounding sphere.
445
+ * @param transform The transformation matrix to apply to the bounding sphere.
446
+ * @returns itself, i.e. the modified BoundingVolume.
447
+ */
361
448
  transform(transformation) {
362
449
  this.center.transformAsPoint(transformation);
363
450
  const xAxis = this.halfAxes.getColumn(0, scratchVectorU);
@@ -387,12 +474,14 @@ var Plane = class {
387
474
  this.distance = -0;
388
475
  this.fromNormalDistance(normal, distance);
389
476
  }
477
+ /** Creates a plane from a normal and a distance from the origin. */
390
478
  fromNormalDistance(normal, distance) {
391
479
  (0, import_core4.assert)(Number.isFinite(distance));
392
480
  this.normal.from(normal).normalize();
393
481
  this.distance = distance;
394
482
  return this;
395
483
  }
484
+ /** Creates a plane from a normal and a point on the plane. */
396
485
  fromPointNormal(point, normal) {
397
486
  point = scratchPosition.from(point);
398
487
  this.normal.from(normal).normalize();
@@ -400,21 +489,28 @@ var Plane = class {
400
489
  this.distance = distance;
401
490
  return this;
402
491
  }
492
+ /** Creates a plane from the general equation */
403
493
  fromCoefficients(a, b, c, d) {
404
494
  this.normal.set(a, b, c);
405
495
  (0, import_core4.assert)((0, import_core4.equals)(this.normal.len(), 1));
406
496
  this.distance = d;
407
497
  return this;
408
498
  }
499
+ /** Duplicates a Plane instance. */
409
500
  clone() {
410
501
  return new Plane(this.normal, this.distance);
411
502
  }
503
+ /** Compares the provided Planes by normal and distance */
412
504
  equals(right) {
413
505
  return (0, import_core4.equals)(this.distance, right.distance) && (0, import_core4.equals)(this.normal, right.normal);
414
506
  }
507
+ /** Computes the signed shortest distance of a point to a plane.
508
+ * The sign of the distance determines which side of the plane the point is on.
509
+ */
415
510
  getPointDistance(point) {
416
511
  return this.normal.dot(point) + this.distance;
417
512
  }
513
+ /** Transforms the plane by the given transformation matrix. */
418
514
  transform(matrix4) {
419
515
  const normal = scratchNormal2.copy(this.normal).transformAsVector(matrix4).normalize();
420
516
  const point = this.normal.scale(-this.distance).transform(matrix4);
@@ -426,6 +522,30 @@ var Plane = class {
426
522
  const scaledNormal = scratchNormal2.copy(this.normal).scale(pointDistance);
427
523
  return scratchPoint.subtract(scaledNormal).to(result);
428
524
  }
525
+ /**
526
+ * Computes the intersection of a ray and this plane.
527
+ *
528
+ * @param {Ray} ray The ray.
529
+ * @param {Vector3} [result] The object onto which to store the result.
530
+ * @returns {Vector3} The intersection point or undefined if there is no intersections.
531
+ */
532
+ intersectWithRay(ray, result) {
533
+ if (!result)
534
+ result = new import_core4.Vector3();
535
+ const origin = ray.origin;
536
+ const direction = ray.direction;
537
+ const normal = this.normal;
538
+ const denominator = normal.dot(direction);
539
+ if (Math.abs(denominator) < import_core4._MathUtils.EPSILON15) {
540
+ return void 0;
541
+ }
542
+ const t = (-this.distance - normal.dot(origin)) / denominator;
543
+ if (t < 0) {
544
+ return void 0;
545
+ }
546
+ result = result.copy(direction).multiplyByScalar(t);
547
+ return origin.add(result);
548
+ }
429
549
  };
430
550
 
431
551
  // dist/lib/culling-volume.js
@@ -433,9 +553,17 @@ var faces = [new import_core5.Vector3([1, 0, 0]), new import_core5.Vector3([0, 1
433
553
  var scratchPlaneCenter = new import_core5.Vector3();
434
554
  var scratchPlaneNormal = new import_core5.Vector3();
435
555
  var CullingVolume = class {
556
+ /**
557
+ * Create a new `CullingVolume` bounded by an array of clipping planed
558
+ * @param planes Array of clipping planes.
559
+ * */
436
560
  constructor(planes = []) {
437
561
  this.planes = planes;
438
562
  }
563
+ /**
564
+ * Constructs a culling volume from a bounding sphere. Creates six planes that create a box containing the sphere.
565
+ * The planes are aligned to the x, y, and z axes in world coordinates.
566
+ */
439
567
  fromBoundingSphere(boundingSphere) {
440
568
  this.planes.length = 2 * faces.length;
441
569
  const center = boundingSphere.center;
@@ -459,6 +587,7 @@ var CullingVolume = class {
459
587
  }
460
588
  return this;
461
589
  }
590
+ /** Determines whether a bounding volume intersects the culling volume. */
462
591
  computeVisibility(boundingVolume) {
463
592
  let intersect = INTERSECTION.INSIDE;
464
593
  for (const plane of this.planes) {
@@ -474,6 +603,14 @@ var CullingVolume = class {
474
603
  }
475
604
  return intersect;
476
605
  }
606
+ /**
607
+ * Determines whether a bounding volume intersects the culling volume.
608
+ *
609
+ * @param parentPlaneMask A bit mask from the boundingVolume's parent's check against the same culling
610
+ * volume, such that if (planeMask & (1 << planeIndex) === 0), for k < 31, then
611
+ * the parent (and therefore this) volume is completely inside plane[planeIndex]
612
+ * and that plane check can be skipped.
613
+ */
477
614
  computeVisibilityWithPlaneMask(boundingVolume, parentPlaneMask) {
478
615
  (0, import_core5.assert)(Number.isFinite(parentPlaneMask), "parentPlaneMask is required.");
479
616
  if (parentPlaneMask === CullingVolume.MASK_OUTSIDE || parentPlaneMask === CullingVolume.MASK_INSIDE) {
@@ -501,14 +638,57 @@ CullingVolume.MASK_OUTSIDE = 4294967295;
501
638
  CullingVolume.MASK_INSIDE = 0;
502
639
  CullingVolume.MASK_INDETERMINATE = 2147483647;
503
640
 
504
- // dist/lib/perspective-off-center-frustum.js
641
+ // dist/lib/ray.js
505
642
  var import_core6 = require("@math.gl/core");
506
- var scratchPlaneUpVector = new import_core6.Vector3();
507
- var scratchPlaneRightVector = new import_core6.Vector3();
508
- var scratchPlaneNearCenter = new import_core6.Vector3();
509
- var scratchPlaneFarCenter = new import_core6.Vector3();
510
- var scratchPlaneNormal2 = new import_core6.Vector3();
643
+ var Ray = class {
644
+ /**
645
+ * Creates a new ray that extends infinitely from the provided origin in the provided direction.
646
+ *
647
+ * @param [origin=Vector3] The origin of the ray.
648
+ * @param [direction=Vector3] The direction of the ray.
649
+ */
650
+ constructor(origin, direction) {
651
+ if (origin)
652
+ origin = origin.clone();
653
+ else
654
+ origin = new import_core6.Vector3();
655
+ if (direction)
656
+ direction = direction.clone().normalize();
657
+ else
658
+ direction = new import_core6.Vector3();
659
+ this.origin = origin;
660
+ this.direction = direction;
661
+ }
662
+ };
663
+
664
+ // dist/lib/perspective-off-center-frustum.js
665
+ var import_core7 = require("@math.gl/core");
666
+ var scratchPlaneUpVector = new import_core7.Vector3();
667
+ var scratchPlaneRightVector = new import_core7.Vector3();
668
+ var scratchPlaneNearCenter = new import_core7.Vector3();
669
+ var scratchPlaneFarCenter = new import_core7.Vector3();
670
+ var scratchPlaneNormal2 = new import_core7.Vector3();
511
671
  var PerspectiveOffCenterFrustum = class {
672
+ /**
673
+ * The viewing frustum is defined by 6 planes.
674
+ * Each plane is represented by a {@link Vector4} object, where the x, y, and z components
675
+ * define the unit vector normal to the plane, and the w component is the distance of the
676
+ * plane from the origin/camera position.
677
+ *
678
+ * @alias PerspectiveOffCenterFrustum
679
+ *
680
+ * @example
681
+ * const frustum = new PerspectiveOffCenterFrustum({
682
+ * left : -1.0,
683
+ * right : 1.0,
684
+ * top : 1.0,
685
+ * bottom : -1.0,
686
+ * near : 1.0,
687
+ * far : 100.0
688
+ * });
689
+ *
690
+ * @see PerspectiveFrustum
691
+ */
512
692
  constructor(options = {}) {
513
693
  this._cullingVolume = new CullingVolume([
514
694
  new Plane(),
@@ -518,8 +698,8 @@ var PerspectiveOffCenterFrustum = class {
518
698
  new Plane(),
519
699
  new Plane()
520
700
  ]);
521
- this._perspectiveMatrix = new import_core6.Matrix4();
522
- this._infinitePerspective = new import_core6.Matrix4();
701
+ this._perspectiveMatrix = new import_core7.Matrix4();
702
+ this._infinitePerspective = new import_core7.Matrix4();
523
703
  const { near = 1, far = 5e8 } = options;
524
704
  this.left = options.left;
525
705
  this._left = void 0;
@@ -534,6 +714,10 @@ var PerspectiveOffCenterFrustum = class {
534
714
  this.far = far;
535
715
  this._far = far;
536
716
  }
717
+ /**
718
+ * Returns a duplicate of a PerspectiveOffCenterFrustum instance.
719
+ * @returns {PerspectiveOffCenterFrustum} A new PerspectiveFrustum instance.
720
+ * */
537
721
  clone() {
538
722
  return new PerspectiveOffCenterFrustum({
539
723
  right: this.right,
@@ -544,21 +728,51 @@ var PerspectiveOffCenterFrustum = class {
544
728
  far: this.far
545
729
  });
546
730
  }
731
+ /**
732
+ * Compares the provided PerspectiveOffCenterFrustum componentwise and returns
733
+ * <code>true</code> if they are equal, <code>false</code> otherwise.
734
+ *
735
+ * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
736
+ */
547
737
  equals(other) {
548
738
  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;
549
739
  }
740
+ /**
741
+ * Gets the perspective projection matrix computed from the view frustum.
742
+ * @memberof PerspectiveOffCenterFrustum.prototype
743
+ * @type {Matrix4}
744
+ *
745
+ * @see PerspectiveOffCenterFrustum#infiniteProjectionMatrix
746
+ */
550
747
  get projectionMatrix() {
551
748
  this._update();
552
749
  return this._perspectiveMatrix;
553
750
  }
751
+ /**
752
+ * Gets the perspective projection matrix computed from the view frustum with an infinite far plane.
753
+ * @memberof PerspectiveOffCenterFrustum.prototype
754
+ * @type {Matrix4}
755
+ *
756
+ * @see PerspectiveOffCenterFrustum#projectionMatrix
757
+ */
554
758
  get infiniteProjectionMatrix() {
555
759
  this._update();
556
760
  return this._infinitePerspective;
557
761
  }
762
+ /**
763
+ * Creates a culling volume for this frustum.
764
+ * @returns {CullingVolume} A culling volume at the given position and orientation.
765
+ *
766
+ * @example
767
+ * // Check if a bounding volume intersects the frustum.
768
+ * const cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);
769
+ * const intersect = cullingVolume.computeVisibility(boundingVolume);
770
+ */
771
+ // eslint-disable-next-line complexity, max-statements
558
772
  computeCullingVolume(position, direction, up) {
559
- (0, import_core6.assert)(position, "position is required.");
560
- (0, import_core6.assert)(direction, "direction is required.");
561
- (0, import_core6.assert)(up, "up is required.");
773
+ (0, import_core7.assert)(position, "position is required.");
774
+ (0, import_core7.assert)(direction, "direction is required.");
775
+ (0, import_core7.assert)(up, "up is required.");
562
776
  const planes = this._cullingVolume.planes;
563
777
  up = scratchPlaneUpVector.copy(up).normalize();
564
778
  const right = scratchPlaneRightVector.copy(direction).cross(up).normalize();
@@ -573,19 +787,43 @@ var PerspectiveOffCenterFrustum = class {
573
787
  planes[2].fromPointNormal(position, normal);
574
788
  normal.copy(up).multiplyByScalar(this.top).add(nearCenter).subtract(position).cross(right);
575
789
  planes[3].fromPointNormal(position, normal);
576
- normal = new import_core6.Vector3().copy(direction);
790
+ normal = new import_core7.Vector3().copy(direction);
577
791
  planes[4].fromPointNormal(nearCenter, normal);
578
792
  normal.negate();
579
793
  planes[5].fromPointNormal(farCenter, normal);
580
794
  return this._cullingVolume;
581
795
  }
796
+ /**
797
+ * Returns the pixel's width and height in meters.
798
+ *
799
+ * @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.
800
+ *
801
+ * @exception {DeveloperError} drawingBufferWidth must be greater than zero.
802
+ * @exception {DeveloperError} drawingBufferHeight must be greater than zero.
803
+ *
804
+ * @example
805
+ * // Example 1
806
+ * // Get the width and height of a pixel.
807
+ * const pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 1.0, new Vector2());
808
+ *
809
+ * @example
810
+ * // Example 2
811
+ * // Get the width and height of a pixel if the near plane was set to 'distance'.
812
+ * // For example, get the size of a pixel of an image on a billboard.
813
+ * const position = camera.position;
814
+ * const direction = camera.direction;
815
+ * const toCenter = Vector3.subtract(primitive.boundingVolume.center, position, new Vector3()); // vector from camera to a primitive
816
+ * const toCenterProj = Vector3.multiplyByScalar(direction, Vector3.dot(direction, toCenter), new Vector3()); // project vector onto camera direction vector
817
+ * const distance = Vector3.magnitude(toCenterProj);
818
+ * const pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, distance, new Vector2());
819
+ */
582
820
  getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result) {
583
821
  this._update();
584
- (0, import_core6.assert)(Number.isFinite(drawingBufferWidth) && Number.isFinite(drawingBufferHeight));
585
- (0, import_core6.assert)(drawingBufferWidth > 0);
586
- (0, import_core6.assert)(drawingBufferHeight > 0);
587
- (0, import_core6.assert)(distance > 0);
588
- (0, import_core6.assert)(result);
822
+ (0, import_core7.assert)(Number.isFinite(drawingBufferWidth) && Number.isFinite(drawingBufferHeight));
823
+ (0, import_core7.assert)(drawingBufferWidth > 0);
824
+ (0, import_core7.assert)(drawingBufferHeight > 0);
825
+ (0, import_core7.assert)(distance > 0);
826
+ (0, import_core7.assert)(result);
589
827
  const inverseNear = 1 / this.near;
590
828
  let tanTheta = this.top * inverseNear;
591
829
  const pixelHeight = 2 * distance * tanTheta / drawingBufferHeight;
@@ -595,18 +833,19 @@ var PerspectiveOffCenterFrustum = class {
595
833
  result.y = pixelHeight;
596
834
  return result;
597
835
  }
836
+ // eslint-disable-next-line complexity, max-statements
598
837
  _update() {
599
- (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));
838
+ (0, import_core7.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));
600
839
  const { top, bottom, right, left, near, far } = this;
601
840
  if (top !== this._top || bottom !== this._bottom || left !== this._left || right !== this._right || near !== this._near || far !== this._far) {
602
- (0, import_core6.assert)(this.near > 0 && this.near < this.far, "near must be greater than zero and less than far.");
841
+ (0, import_core7.assert)(this.near > 0 && this.near < this.far, "near must be greater than zero and less than far.");
603
842
  this._left = left;
604
843
  this._right = right;
605
844
  this._top = top;
606
845
  this._bottom = bottom;
607
846
  this._near = near;
608
847
  this._far = far;
609
- this._perspectiveMatrix = new import_core6.Matrix4().frustum({
848
+ this._perspectiveMatrix = new import_core7.Matrix4().frustum({
610
849
  left,
611
850
  right,
612
851
  bottom,
@@ -614,7 +853,7 @@ var PerspectiveOffCenterFrustum = class {
614
853
  near,
615
854
  far
616
855
  });
617
- this._infinitePerspective = new import_core6.Matrix4().frustum({
856
+ this._infinitePerspective = new import_core7.Matrix4().frustum({
618
857
  left,
619
858
  right,
620
859
  bottom,
@@ -627,7 +866,7 @@ var PerspectiveOffCenterFrustum = class {
627
866
  };
628
867
 
629
868
  // dist/lib/perspective-frustum.js
630
- var import_core7 = require("@math.gl/core");
869
+ var import_core8 = require("@math.gl/core");
631
870
  var defined = (val) => val !== null && typeof val !== "undefined";
632
871
  var PerspectiveFrustum = class {
633
872
  constructor(options = {}) {
@@ -640,6 +879,9 @@ var PerspectiveFrustum = class {
640
879
  this.xOffset = xOffset;
641
880
  this.yOffset = yOffset;
642
881
  }
882
+ /**
883
+ * Returns a duplicate of a PerspectiveFrustum instance.
884
+ */
643
885
  clone() {
644
886
  return new PerspectiveFrustum({
645
887
  aspectRatio: this.aspectRatio,
@@ -648,6 +890,10 @@ var PerspectiveFrustum = class {
648
890
  far: this.far
649
891
  });
650
892
  }
893
+ /**
894
+ * Compares the provided PerspectiveFrustum componentwise and returns
895
+ * <code>true</code> if they are equal, <code>false</code> otherwise.
896
+ */
651
897
  equals(other) {
652
898
  if (!defined(other) || !(other instanceof PerspectiveFrustum)) {
653
899
  return false;
@@ -656,37 +902,82 @@ var PerspectiveFrustum = class {
656
902
  other._update();
657
903
  return this.fov === other.fov && this.aspectRatio === other.aspectRatio && this.near === other.near && this.far === other.far && this._offCenterFrustum.equals(other._offCenterFrustum);
658
904
  }
905
+ /**
906
+ * Gets the perspective projection matrix computed from the view this.
907
+ */
659
908
  get projectionMatrix() {
660
909
  this._update();
661
910
  return this._offCenterFrustum.projectionMatrix;
662
911
  }
912
+ /**
913
+ * The perspective projection matrix computed from the view frustum with an infinite far plane.
914
+ */
663
915
  get infiniteProjectionMatrix() {
664
916
  this._update();
665
917
  return this._offCenterFrustum.infiniteProjectionMatrix;
666
918
  }
919
+ /**
920
+ * Gets the angle of the vertical field of view, in radians.
921
+ */
667
922
  get fovy() {
668
923
  this._update();
669
924
  return this._fovy;
670
925
  }
926
+ /**
927
+ * @private
928
+ */
671
929
  get sseDenominator() {
672
930
  this._update();
673
931
  return this._sseDenominator;
674
932
  }
933
+ /**
934
+ * Creates a culling volume for this this.ion.
935
+ * @returns {CullingVolume} A culling volume at the given position and orientation.
936
+ *
937
+ * @example
938
+ * // Check if a bounding volume intersects the this.
939
+ * var cullingVolume = this.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);
940
+ * var intersect = cullingVolume.computeVisibility(boundingVolume);
941
+ */
675
942
  computeCullingVolume(position, direction, up) {
676
943
  this._update();
677
944
  return this._offCenterFrustum.computeCullingVolume(position, direction, up);
678
945
  }
946
+ /**
947
+ * Returns the pixel's width and height in meters.
948
+ * @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.
949
+ *
950
+ * @exception {DeveloperError} drawingBufferWidth must be greater than zero.
951
+ * @exception {DeveloperError} drawingBufferHeight must be greater than zero.
952
+ *
953
+ * @example
954
+ * // Example 1
955
+ * // Get the width and height of a pixel.
956
+ * var pixelSize = camera.this.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 1.0, new Vector2());
957
+ *
958
+ * @example
959
+ * // Example 2
960
+ * // Get the width and height of a pixel if the near plane was set to 'distance'.
961
+ * // For example, get the size of a pixel of an image on a billboard.
962
+ * var position = camera.position;
963
+ * var direction = camera.direction;
964
+ * var toCenter = Vector3.subtract(primitive.boundingVolume.center, position, new Vector3()); // vector from camera to a primitive
965
+ * var toCenterProj = Vector3.multiplyByScalar(direction, Vector3.dot(direction, toCenter), new Vector3()); // project vector onto camera direction vector
966
+ * var distance = Vector3.magnitude(toCenterProj);
967
+ * var pixelSize = camera.this.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, distance, new Vector2());
968
+ */
679
969
  getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result) {
680
970
  this._update();
681
- return this._offCenterFrustum.getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result || new import_core7.Vector2());
971
+ return this._offCenterFrustum.getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, result || new import_core8.Vector2());
682
972
  }
973
+ // eslint-disable-next-line complexity, max-statements
683
974
  _update() {
684
- (0, import_core7.assert)(Number.isFinite(this.fov) && Number.isFinite(this.aspectRatio) && Number.isFinite(this.near) && Number.isFinite(this.far));
975
+ (0, import_core8.assert)(Number.isFinite(this.fov) && Number.isFinite(this.aspectRatio) && Number.isFinite(this.near) && Number.isFinite(this.far));
685
976
  const f = this._offCenterFrustum;
686
977
  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) {
687
- (0, import_core7.assert)(this.fov >= 0 && this.fov < Math.PI);
688
- (0, import_core7.assert)(this.aspectRatio > 0);
689
- (0, import_core7.assert)(this.near >= 0 && this.near < this.far);
978
+ (0, import_core8.assert)(this.fov >= 0 && this.fov < Math.PI);
979
+ (0, import_core8.assert)(this.aspectRatio > 0);
980
+ (0, import_core8.assert)(this.near >= 0 && this.near < this.far);
690
981
  this._aspectRatio = this.aspectRatio;
691
982
  this._fov = this.fov;
692
983
  this._fovy = this.aspectRatio <= 1 ? this.fov : Math.atan(Math.tan(this.fov * 0.5) / this.aspectRatio) * 2;
@@ -710,19 +1001,19 @@ var PerspectiveFrustum = class {
710
1001
  };
711
1002
 
712
1003
  // dist/lib/algorithms/bounding-sphere-from-points.js
713
- var import_core8 = require("@math.gl/core");
714
- var fromPointsXMin = new import_core8.Vector3();
715
- var fromPointsYMin = new import_core8.Vector3();
716
- var fromPointsZMin = new import_core8.Vector3();
717
- var fromPointsXMax = new import_core8.Vector3();
718
- var fromPointsYMax = new import_core8.Vector3();
719
- var fromPointsZMax = new import_core8.Vector3();
720
- var fromPointsCurrentPos = new import_core8.Vector3();
721
- var fromPointsScratch = new import_core8.Vector3();
722
- var fromPointsRitterCenter = new import_core8.Vector3();
723
- var fromPointsMinBoxPt = new import_core8.Vector3();
724
- var fromPointsMaxBoxPt = new import_core8.Vector3();
725
- var fromPointsNaiveCenterScratch = new import_core8.Vector3();
1004
+ var import_core9 = require("@math.gl/core");
1005
+ var fromPointsXMin = new import_core9.Vector3();
1006
+ var fromPointsYMin = new import_core9.Vector3();
1007
+ var fromPointsZMin = new import_core9.Vector3();
1008
+ var fromPointsXMax = new import_core9.Vector3();
1009
+ var fromPointsYMax = new import_core9.Vector3();
1010
+ var fromPointsZMax = new import_core9.Vector3();
1011
+ var fromPointsCurrentPos = new import_core9.Vector3();
1012
+ var fromPointsScratch = new import_core9.Vector3();
1013
+ var fromPointsRitterCenter = new import_core9.Vector3();
1014
+ var fromPointsMinBoxPt = new import_core9.Vector3();
1015
+ var fromPointsMaxBoxPt = new import_core9.Vector3();
1016
+ var fromPointsNaiveCenterScratch = new import_core9.Vector3();
726
1017
  function makeBoundingSphereFromPoints(positions, result = new BoundingSphere()) {
727
1018
  if (!positions || positions.length === 0) {
728
1019
  return result.fromCenterRadius([0, 0, 0], 0);
@@ -818,17 +1109,17 @@ function makeBoundingSphereFromPoints(positions, result = new BoundingSphere())
818
1109
  }
819
1110
 
820
1111
  // dist/lib/algorithms/bounding-box-from-points.js
821
- var import_core10 = require("@math.gl/core");
1112
+ var import_core11 = require("@math.gl/core");
822
1113
 
823
1114
  // dist/lib/algorithms/compute-eigen-decomposition.js
824
- var import_core9 = require("@math.gl/core");
825
- var scratchMatrix = new import_core9.Matrix3();
826
- var scratchUnitary = new import_core9.Matrix3();
827
- var scratchDiagonal = new import_core9.Matrix3();
828
- var jMatrix = new import_core9.Matrix3();
829
- var jMatrixTranspose = new import_core9.Matrix3();
1115
+ var import_core10 = require("@math.gl/core");
1116
+ var scratchMatrix = new import_core10.Matrix3();
1117
+ var scratchUnitary = new import_core10.Matrix3();
1118
+ var scratchDiagonal = new import_core10.Matrix3();
1119
+ var jMatrix = new import_core10.Matrix3();
1120
+ var jMatrixTranspose = new import_core10.Matrix3();
830
1121
  function computeEigenDecomposition(matrix, result = {}) {
831
- const EIGEN_TOLERANCE = import_core9._MathUtils.EPSILON20;
1122
+ const EIGEN_TOLERANCE = import_core10._MathUtils.EPSILON20;
832
1123
  const EIGEN_MAX_SWEEPS = 10;
833
1124
  let count = 0;
834
1125
  let sweep = 0;
@@ -871,7 +1162,7 @@ function offDiagonalFrobeniusNorm(matrix) {
871
1162
  return Math.sqrt(norm);
872
1163
  }
873
1164
  function shurDecomposition(matrix, result) {
874
- const tolerance = import_core9._MathUtils.EPSILON15;
1165
+ const tolerance = import_core10._MathUtils.EPSILON15;
875
1166
  let maxDiagonal = 0;
876
1167
  let rotAxis = 1;
877
1168
  for (let i = 0; i < 3; ++i) {
@@ -899,7 +1190,7 @@ function shurDecomposition(matrix, result) {
899
1190
  c = 1 / Math.sqrt(1 + t * t);
900
1191
  s = t * c;
901
1192
  }
902
- import_core9.Matrix3.IDENTITY.to(result);
1193
+ import_core10.Matrix3.IDENTITY.to(result);
903
1194
  result[scratchMatrix.getElementIndex(p, p)] = result[scratchMatrix.getElementIndex(q, q)] = c;
904
1195
  result[scratchMatrix.getElementIndex(q, p)] = s;
905
1196
  result[scratchMatrix.getElementIndex(p, q)] = -s;
@@ -907,24 +1198,24 @@ function shurDecomposition(matrix, result) {
907
1198
  }
908
1199
 
909
1200
  // dist/lib/algorithms/bounding-box-from-points.js
910
- var scratchVector23 = new import_core10.Vector3();
911
- var scratchVector32 = new import_core10.Vector3();
912
- var scratchVector4 = new import_core10.Vector3();
913
- var scratchVector5 = new import_core10.Vector3();
914
- var scratchVector6 = new import_core10.Vector3();
915
- var scratchCovarianceResult = new import_core10.Matrix3();
1201
+ var scratchVector23 = new import_core11.Vector3();
1202
+ var scratchVector32 = new import_core11.Vector3();
1203
+ var scratchVector4 = new import_core11.Vector3();
1204
+ var scratchVector5 = new import_core11.Vector3();
1205
+ var scratchVector6 = new import_core11.Vector3();
1206
+ var scratchCovarianceResult = new import_core11.Matrix3();
916
1207
  var scratchEigenResult = {
917
- diagonal: new import_core10.Matrix3(),
918
- unitary: new import_core10.Matrix3()
1208
+ diagonal: new import_core11.Matrix3(),
1209
+ unitary: new import_core11.Matrix3()
919
1210
  };
920
1211
  function makeOrientedBoundingBoxFromPoints(positions, result = new OrientedBoundingBox()) {
921
1212
  if (!positions || positions.length === 0) {
922
- result.halfAxes = new import_core10.Matrix3([0, 0, 0, 0, 0, 0, 0, 0, 0]);
923
- result.center = new import_core10.Vector3();
1213
+ result.halfAxes = new import_core11.Matrix3([0, 0, 0, 0, 0, 0, 0, 0, 0]);
1214
+ result.center = new import_core11.Vector3();
924
1215
  return result;
925
1216
  }
926
1217
  const length = positions.length;
927
- const meanPoint = new import_core10.Vector3(0, 0, 0);
1218
+ const meanPoint = new import_core11.Vector3(0, 0, 0);
928
1219
  for (const position of positions) {
929
1220
  meanPoint.add(position);
930
1221
  }
@@ -986,7 +1277,7 @@ function makeOrientedBoundingBoxFromPoints(positions, result = new OrientedBound
986
1277
  v3 = v3.multiplyByScalar(0.5 * (l3 + u3));
987
1278
  result.center.copy(v1).add(v2).add(v3);
988
1279
  const scale = scratchVector32.set(u1 - l1, u2 - l2, u3 - l3).multiplyByScalar(0.5);
989
- const scaleMatrix = new import_core10.Matrix3([scale[0], 0, 0, 0, scale[1], 0, 0, 0, scale[2]]);
1280
+ const scaleMatrix = new import_core11.Matrix3([scale[0], 0, 0, 0, scale[1], 0, 0, 0, scale[2]]);
990
1281
  result.halfAxes.multiplyRight(scaleMatrix);
991
1282
  return result;
992
1283
  }