@xeokit/xeokit-sdk 2.6.28 → 2.6.29

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.
Files changed (40) hide show
  1. package/README.md +1 -0
  2. package/dist/xeokit-sdk.cjs.js +915 -220
  3. package/dist/xeokit-sdk.es.js +910 -221
  4. package/dist/xeokit-sdk.es5.js +576 -486
  5. package/dist/xeokit-sdk.min.cjs.js +5 -5
  6. package/dist/xeokit-sdk.min.es.js +5 -5
  7. package/dist/xeokit-sdk.min.es5.js +4 -4
  8. package/package.json +1 -1
  9. package/src/extras/PointerCircle/PointerCircle.js +1 -1
  10. package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.js +22 -41
  11. package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +3 -18
  12. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsMouseControl.js +20 -41
  13. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +4 -20
  14. package/src/plugins/DistanceMeasurementsPlugin/index.js +1 -1
  15. package/src/plugins/StoreyViewsPlugin/StoreyViewsPlugin.js +31 -1
  16. package/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js +20 -8
  17. package/src/plugins/ZonesPlugin/ZonesPlugin.js +1939 -0
  18. package/src/plugins/ZonesPlugin/index.js +1 -1875
  19. package/src/viewer/Viewer.js +2 -2
  20. package/src/viewer/scene/math/MeshSurfaceArea.js +90 -0
  21. package/src/viewer/scene/math/MeshVolume.js +102 -0
  22. package/src/viewer/scene/math/index.js +3 -0
  23. package/src/viewer/scene/math/isTriangleMeshSolid.js +162 -0
  24. package/src/viewer/scene/math/math.js +8 -0
  25. package/src/viewer/scene/model/SceneModel.js +64 -34
  26. package/src/viewer/scene/model/SceneModelEntity.js +46 -1
  27. package/src/viewer/scene/model/SceneModelMesh.js +74 -1
  28. package/src/viewer/scene/model/dtx/lines/DTXLinesLayer.js +7 -1
  29. package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +77 -1
  30. package/src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js +6 -1
  31. package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js +6 -1
  32. package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +33 -12
  33. package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +6 -1
  34. package/src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js +6 -1
  35. package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +31 -10
  36. package/src/viewer/scene/scene/Scene.js +16 -5
  37. package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +0 -1
  38. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.d.ts +7 -0
  39. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsPlugin.d.ts +26 -1
  40. package/types/plugins/DistanceMeasurementsPlugin/index.d.ts +3 -1
@@ -5280,6 +5280,14 @@ const math = {
5280
5280
  return aabb[0] > p[0] || aabb[3] < p[0] || aabb[1] > p[1] || aabb[4] < p[1] || aabb[2] > p[2] || aabb[5] < p[2];
5281
5281
  },
5282
5282
 
5283
+ point3AABB3AbsoluteIntersect(aabb, p) {
5284
+ return (
5285
+ aabb[0] <= p[0] && aabb[3] >= p[0] &&
5286
+ aabb[1] <= p[1] && aabb[4] >= p[1] &&
5287
+ aabb[2] <= p[2] && aabb[5] >= p[2]
5288
+ );
5289
+ },
5290
+
5283
5291
  /**
5284
5292
  *
5285
5293
  * @param dir
@@ -9285,7 +9293,7 @@ class PointerCircle {
9285
9293
  destroy() {
9286
9294
  if (!this._destroyed) {
9287
9295
  this.stop();
9288
- document.body.removeChild(this._circleDiv);
9296
+ this._circleDiv.parentElement.removeChild(this._circleDiv);
9289
9297
  this._destroyed = true;
9290
9298
  }
9291
9299
  }
@@ -10541,7 +10549,7 @@ class SceneModelEntity {
10541
10549
  for (let i = 0, len = this.meshes.length; i < len; i++) {
10542
10550
  this.meshes[i]._setOffset(this._offset);
10543
10551
  }
10544
- this._aabbDirty = true;
10552
+ this._aabbDirty = true;
10545
10553
  this.model._aabbDirty = true;
10546
10554
  this.scene._aabbDirty = true;
10547
10555
  this.scene._objectOffsetUpdated(this, offset);
@@ -10558,6 +10566,51 @@ class SceneModelEntity {
10558
10566
  }
10559
10567
  }
10560
10568
 
10569
+ getEachIndex(callback) {
10570
+ for (let i = 0, len = this.meshes.length; i < len; i++) {
10571
+ this.meshes[i].getEachIndex(callback);
10572
+ }
10573
+ }
10574
+
10575
+ /**
10576
+ * Returns the volume of this SceneModelEntity.
10577
+ *
10578
+ * Only works when {@link Scene.readableGeometryEnabled | Scene.readableGeometryEnabled} is `true` and the
10579
+ * SceneModelEntity contains solid triangle meshes; returns `0` otherwise.
10580
+ *
10581
+ * @returns {number}
10582
+ */
10583
+ get volume() {
10584
+ let volume = 0;
10585
+ for (let i = 0, len = this.meshes.length; i < len; i++) {
10586
+ const meshVolume = this.meshes[i].volume;
10587
+ if (meshVolume < 0) {
10588
+ return -1;
10589
+ }
10590
+ volume += meshVolume;
10591
+ }
10592
+ return volume;
10593
+ }
10594
+
10595
+ /**
10596
+ * Returns the surface area of this SceneModelEntity.
10597
+ *
10598
+ * Only works when {@link Scene.readableGeometryEnabled | Scene.readableGeometryEnabled} is `true` and the
10599
+ * SceneModelEntity contains triangle meshes; returns `0` otherwise.
10600
+ *
10601
+ * @returns {number}
10602
+ */
10603
+ get surfaceArea() {
10604
+ let surfaceArea = 0;
10605
+ for (let i = 0, len = this.meshes.length; i < len; i++) {
10606
+ const meshSurfaceArea = this.meshes[i].surfaceArea;
10607
+ if (meshSurfaceArea >= 0) {
10608
+ surfaceArea += meshSurfaceArea;
10609
+ }
10610
+ }
10611
+ return surfaceArea > 0 ? surfaceArea : -1;
10612
+ }
10613
+
10561
10614
  _getFlag(flag) {
10562
10615
  return !!(this._flags & flag);
10563
10616
  }
@@ -10622,7 +10675,7 @@ class SceneModelEntity {
10622
10675
  }
10623
10676
  }
10624
10677
 
10625
- const tempVec4a$9 = math.vec4();
10678
+ const tempVec4a$a = math.vec4();
10626
10679
  const tempVec4b$6 = math.vec4();
10627
10680
 
10628
10681
 
@@ -10782,9 +10835,9 @@ class Marker extends Component {
10782
10835
  this.fire("viewPos", this._viewPos);
10783
10836
  }
10784
10837
  if (this._canvasPosDirty) {
10785
- tempVec4a$9.set(this._viewPos);
10786
- tempVec4a$9[3] = 1.0;
10787
- math.transformPoint4(this.scene.camera.projMatrix, tempVec4a$9, tempVec4b$6);
10838
+ tempVec4a$a.set(this._viewPos);
10839
+ tempVec4a$a[3] = 1.0;
10840
+ math.transformPoint4(this.scene.camera.projMatrix, tempVec4a$a, tempVec4b$6);
10788
10841
  const aabb = this.scene.canvas.boundary;
10789
10842
  this._canvasPos[0] = Math.floor((1 + tempVec4b$6[0] / tempVec4b$6[3]) * aabb[2] / 2);
10790
10843
  this._canvasPos[1] = Math.floor((1 - tempVec4b$6[1] / tempVec4b$6[3]) * aabb[3] / 2);
@@ -12614,22 +12667,13 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12614
12667
  this.pointerLens = cfg.pointerLens;
12615
12668
 
12616
12669
  this._active = false;
12617
- this._mouseState = MOUSE_FINDING_ORIGIN;
12618
12670
 
12619
12671
  this._currentAngleMeasurement = null;
12620
12672
 
12621
- // init markerDiv element (think about making its style configurable)
12622
12673
  this._initMarkerDiv();
12623
12674
 
12624
- this._onMouseHoverSurface = null;
12625
- this._onHoverNothing = null;
12626
- this._onPickedNothing = null;
12627
- this._onPickedSurface = null;
12628
-
12629
- this._onInputMouseDown = null;
12630
- this._onInputMouseUp = null;
12631
-
12632
12675
  this._snapping = cfg.snapping !== false;
12676
+ this._mouseState = MOUSE_FINDING_ORIGIN;
12633
12677
 
12634
12678
  this._attachPlugin(angleMeasurementsPlugin, cfg);
12635
12679
  }
@@ -12694,20 +12738,10 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12694
12738
  *
12695
12739
  * This is `true` by default.
12696
12740
  *
12697
- * Internally, this deactivates then activates the AngleMeasurementsMouseControl when changed, which means that
12698
- * it will destroy any AngleMeasurements currently under construction, and incurs some overhead, since it unbinds
12699
- * and rebinds various input handlers.
12700
- *
12701
12741
  * @param {boolean} snapping Whether to enable snap-to-vertex and snap-edge for this AngleMeasurementsMouseControl.
12702
12742
  */
12703
12743
  set snapping(snapping) {
12704
- if (snapping !== this._snapping) {
12705
- this._snapping = snapping;
12706
- this.deactivate();
12707
- this.activate();
12708
- } else {
12709
- this._snapping = snapping;
12710
- }
12744
+ this._snapping = snapping;
12711
12745
  }
12712
12746
 
12713
12747
  /**
@@ -12751,11 +12785,7 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12751
12785
 
12752
12786
  const pagePos = math.vec2();
12753
12787
 
12754
- this._onMouseHoverSurface = cameraControl.on(
12755
- this._snapping
12756
- ? "hoverSnapOrSurface"
12757
- : "hoverSurface",
12758
- event => {
12788
+ const hoverOn = event => {
12759
12789
  if (event.snappedToVertex || event.snappedToEdge) {
12760
12790
  if (pointerLens) {
12761
12791
  pointerLens.visible = true;
@@ -12817,7 +12847,10 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12817
12847
  canvas.style.cursor = "pointer";
12818
12848
  break;
12819
12849
  }
12820
- });
12850
+ };
12851
+ this._onHoverSnapOrSurface = cameraControl.on("hoverSnapOrSurface", e => { if (this._snapping) hoverOn(e); });
12852
+ this._onHoverSurface = cameraControl.on("hoverSurface", e => { if (! this._snapping) hoverOn(e); });
12853
+
12821
12854
  canvas.addEventListener('mousedown', this._onMouseDown = (e) => {
12822
12855
  if (e.which !== 1) {
12823
12856
  return;
@@ -12905,11 +12938,8 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12905
12938
  break;
12906
12939
  }
12907
12940
  });
12908
- this._onMouseHoverOff = cameraControl.on(
12909
- this._snapping
12910
- ? "hoverSnapOrSurfaceOff"
12911
- : "hoverOff",
12912
- event => {
12941
+
12942
+ const hoverOff = event => {
12913
12943
  mouseHovering = false;
12914
12944
  if (pointerLens) {
12915
12945
  pointerLens.visible = true;
@@ -12939,7 +12969,10 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12939
12969
  }
12940
12970
  canvas.style.cursor = "default";
12941
12971
  }
12942
- });
12972
+ };
12973
+ this._onHoverSnapOrSurfaceOff = cameraControl.on("hoverSnapOrSurfaceOff", e => { if (this._snapping) hoverOff(e); });
12974
+ this._onHoverOff = cameraControl.on("hoverOff", e => { if (! this._snapping) hoverOff(e); });
12975
+
12943
12976
  this._active = true;
12944
12977
  }
12945
12978
 
@@ -12952,22 +12985,22 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12952
12985
  if (!this._active) {
12953
12986
  return;
12954
12987
  }
12988
+
12955
12989
  if (this.pointerLens) {
12956
12990
  this.pointerLens.visible = false;
12957
12991
  }
12958
- if (this.markerDiv) {
12959
- this._destroyMarkerDiv();
12960
- }
12992
+
12961
12993
  this.reset();
12994
+
12962
12995
  const canvas = this.scene.canvas.canvas;
12963
12996
  canvas.removeEventListener("mousedown", this._onMouseDown);
12964
12997
  canvas.removeEventListener("mouseup", this._onMouseUp);
12965
12998
  const cameraControl = this.angleMeasurementsPlugin.viewer.cameraControl;
12966
- cameraControl.off(this._onMouseHoverSurface);
12967
- cameraControl.off(this._onPickedSurface);
12968
- cameraControl.off(this._onHoverNothing);
12969
- cameraControl.off(this._onPickedNothing);
12970
- this._currentAngleMeasurement = null;
12999
+ cameraControl.off(this._onHoverSnapOrSurface);
13000
+ cameraControl.off(this._onHoverSurface);
13001
+ cameraControl.off(this._onHoverSnapOrSurfaceOff);
13002
+ cameraControl.off(this._onHoverOff);
13003
+
12971
13004
  this._active = false;
12972
13005
  }
12973
13006
 
@@ -12990,6 +13023,7 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12990
13023
  this._currentAngleMeasurement.destroy();
12991
13024
  this._currentAngleMeasurement = null;
12992
13025
  }
13026
+
12993
13027
  this._mouseState = MOUSE_FINDING_ORIGIN;
12994
13028
  }
12995
13029
 
@@ -13505,8 +13539,6 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13505
13539
 
13506
13540
  this._currentAngleMeasurement = null;
13507
13541
 
13508
- this._onCanvasTouchStart = null;
13509
- this._onCanvasTouchEnd = null;
13510
13542
  this._longTouchTimeoutMs = 300;
13511
13543
  this._snapping = cfg.snapping !== false;
13512
13544
  this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
@@ -13542,20 +13574,10 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13542
13574
  *
13543
13575
  * This is `true` by default.
13544
13576
  *
13545
- * Internally, this deactivates then activates the AngleMeasurementsMouseControl when changed, which means that
13546
- * it will destroy any AngleMeasurements currently under construction, and incurs some overhead, since it unbinds
13547
- * and rebinds various input handlers.
13548
- *
13549
13577
  * @param {boolean} snapping Whether to enable snap-to-vertex and snap-edge for this AngleMeasurementsMouseControl.
13550
13578
  */
13551
13579
  set snapping(snapping) {
13552
- if (snapping !== this._snapping) {
13553
- this._snapping = snapping;
13554
- this.deactivate();
13555
- this.activate();
13556
- } else {
13557
- this._snapping = snapping;
13558
- }
13580
+ this._snapping = snapping;
13559
13581
  }
13560
13582
 
13561
13583
  /**
@@ -14325,14 +14347,11 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14325
14347
  this.plugin.pointerLens.visible = false;
14326
14348
  }
14327
14349
  this.reset();
14350
+
14328
14351
  const canvas = this.plugin.viewer.scene.canvas.canvas;
14329
14352
  canvas.removeEventListener("touchstart", this._onCanvasTouchStart);
14330
14353
  canvas.removeEventListener("touchend", this._onCanvasTouchEnd);
14331
- if (this._currentAngleMeasurement) {
14332
- this.angleMeasurementsPlugin.fire("measurementCancel", this._currentAngleMeasurement);
14333
- this._currentAngleMeasurement.destroy();
14334
- this._currentAngleMeasurement = null;
14335
- }
14354
+
14336
14355
  this._active = false;
14337
14356
  this.plugin.viewer.cameraControl.active = true;
14338
14357
  }
@@ -23515,7 +23534,7 @@ const tempVec3c$u = math.vec3();
23515
23534
  const tempVec3d$d = math.vec3();
23516
23535
  const tempVec3e$2 = math.vec3();
23517
23536
  const tempVec3f$2 = math.vec3();
23518
- const tempVec4a$8 = math.vec4();
23537
+ const tempVec4a$9 = math.vec4();
23519
23538
  const tempVec4b$5 = math.vec4();
23520
23539
  const tempVec4c$2 = math.vec4();
23521
23540
  const tempMat = math.mat4();
@@ -24381,7 +24400,7 @@ class Camera extends Component {
24381
24400
  * @returns {[number, number]} the canvas position
24382
24401
  */
24383
24402
  projectWorldPos(worldPos) {
24384
- const _worldPos = tempVec4a$8;
24403
+ const _worldPos = tempVec4a$9;
24385
24404
  const viewPos = tempVec4b$5;
24386
24405
  const screenPos = tempVec4c$2;
24387
24406
  _worldPos[0] = worldPos[0];
@@ -30136,6 +30155,8 @@ class Scene extends Component {
30136
30155
 
30137
30156
  this._aabbDirty = true;
30138
30157
 
30158
+ this._readableGeometry = !!cfg.readableGeometryEnabled;
30159
+
30139
30160
  /**
30140
30161
  * The {@link Viewer} this Scene belongs to.
30141
30162
  * @type {Viewer}
@@ -31015,18 +31036,27 @@ class Scene extends Component {
31015
31036
  }
31016
31037
 
31017
31038
  /**
31018
- * Whether precision surface picking is enabled.
31039
+ * Whether geometry is readable.
31019
31040
  *
31020
31041
  * This is set via the {@link Viewer} constructor and is ````false```` by default.
31021
31042
  *
31022
- * The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.
31043
+ * The ````readableGeometryEnabled```` option for ````Scene#pick```` only works if this is set ````true````.
31023
31044
  *
31024
31045
  * Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer.
31025
31046
  *
31026
- * @returns {Boolean} True if precision picking is enabled.
31047
+ * @returns {Boolean} True if geometry is readable.
31048
+ */
31049
+ get readableGeometryEnabled() {
31050
+ return this._readableGeometry;
31051
+ }
31052
+
31053
+ /**
31054
+ * Whether precision surface picking is enabled.
31055
+ * @deprecated
31056
+ * @returns {*|boolean}
31027
31057
  */
31028
31058
  get pickSurfacePrecisionEnabled() {
31029
- return false; // Removed
31059
+ return this._readableGeometry;
31030
31060
  }
31031
31061
 
31032
31062
  /**
@@ -32004,7 +32034,7 @@ class Scene extends Component {
32004
32034
  *
32005
32035
  * @param {*} params Picking parameters.
32006
32036
  * @param {Boolean} [params.pickSurface=false] Whether to find the picked position on the surface of the Entity.
32007
- * @param {Boolean} [params.pickSurfacePrecision=false] When picking an Entity surface position, indicates whether or not we want full-precision {@link PickResult#worldPos}. Only works when {@link Scene#pickSurfacePrecisionEnabled} is ````true````. If pick succeeds, the returned {@link PickResult} will have {@link PickResult#precision} set ````true````, to indicate that it contains full-precision surface pick results.
32037
+ * @param {Boolean} [params.pickSurfacePrecision=false] When picking an Entity surface position, indicates whether or not we want full-precision {@link PickResult#worldPos}. Only works when {@link Scene#readableGeometryEnabled} is ````true````. If pick succeeds, the returned {@link PickResult} will have {@link PickResult#precision} set ````true````, to indicate that it contains full-precision surface pick results.
32008
32038
  * @param {Boolean} [params.pickSurfaceNormal=false] Whether to find the picked normal on the surface of the Entity. Only works if ````pickSurface```` is given.
32009
32039
  * @param {Number[]} [params.canvasPos] Canvas-space coordinates. When ray-picking, this will override the **origin** and ** direction** parameters and will cause the ray to be fired through the canvas at this position, directly along the negative View-space Z-axis.
32010
32040
  * @param {Number[]} [params.origin] World-space ray origin when ray-picking. Ignored when canvasPos given.
@@ -50604,10 +50634,360 @@ class Bitmap extends Component {
50604
50634
  }
50605
50635
  }
50606
50636
 
50637
+ /**
50638
+ * Uses edge adjacency counts to identify if the given triangle mesh can be rendered with backface culling enabled.
50639
+ *
50640
+ * If all edges are connected to exactly two triangles, then the mesh will likely be a closed solid, and we can safely
50641
+ * render it with backface culling enabled.
50642
+ *
50643
+ * Otherwise, the mesh is a surface, and we must render it with backface culling disabled.
50644
+ *
50645
+ * @private
50646
+ */
50647
+ const isTriangleMeshSolid = (indices, positions) => {
50648
+
50649
+ const vertexIndexMapping = [];
50650
+ let edges = [];
50651
+
50652
+ function compareIndexPositions(a, b) {
50653
+ let posA, posB;
50654
+
50655
+ for (let i = 0; i < 3; i++) {
50656
+ posA = positions [a * 3 + i];
50657
+ posB = positions [b * 3 + i];
50658
+
50659
+ if (posA !== posB) {
50660
+ return posB - posA;
50661
+ }
50662
+ }
50663
+
50664
+ return 0;
50665
+ }
50666
+ // Group together indices corresponding to same position coordinates
50667
+ let newIndices = indices.slice().sort(compareIndexPositions);
50668
+
50669
+ // Calculate the mapping:
50670
+ // - from original index in indices array
50671
+ // - to indices-for-unique-positions
50672
+ let uniqueVertexIndex = null;
50673
+
50674
+ for (let i = 0, len = newIndices.length; i < len; i++) {
50675
+ if (i === 0 || 0 !== compareIndexPositions(
50676
+ newIndices[i],
50677
+ newIndices[i - 1],
50678
+ )) {
50679
+ // different position
50680
+ uniqueVertexIndex = newIndices [i];
50681
+ }
50682
+
50683
+ vertexIndexMapping [
50684
+ newIndices[i]
50685
+ ] = uniqueVertexIndex;
50686
+ }
50687
+
50688
+ // Generate the list of edges
50689
+ for (let i = 0, len = indices.length; i < len; i += 3) {
50690
+
50691
+ const a = vertexIndexMapping[indices[i]];
50692
+ const b = vertexIndexMapping[indices[i + 1]];
50693
+ const c = vertexIndexMapping[indices[i + 2]];
50694
+
50695
+ let a2 = a;
50696
+ let b2 = b;
50697
+ let c2 = c;
50698
+
50699
+ if (a > b && a > c) {
50700
+ if (b > c) {
50701
+ a2 = a;
50702
+ b2 = b;
50703
+ c2 = c;
50704
+ } else {
50705
+ a2 = a;
50706
+ b2 = c;
50707
+ c2 = b;
50708
+ }
50709
+ } else if (b > a && b > c) {
50710
+ if (a > c) {
50711
+ a2 = b;
50712
+ b2 = a;
50713
+ c2 = c;
50714
+ } else {
50715
+ a2 = b;
50716
+ b2 = c;
50717
+ c2 = a;
50718
+ }
50719
+ } else if (c > a && c > b) {
50720
+ if (a > b) {
50721
+ a2 = c;
50722
+ b2 = a;
50723
+ c2 = b;
50724
+ } else {
50725
+ a2 = c;
50726
+ b2 = b;
50727
+ c2 = a;
50728
+ }
50729
+ }
50730
+
50731
+ edges[i + 0] = [
50732
+ a2, b2
50733
+ ];
50734
+ edges[i + 1] = [
50735
+ b2, c2
50736
+ ];
50737
+
50738
+ if (a2 > c2) {
50739
+ const temp = c2;
50740
+ c2 = a2;
50741
+ a2 = temp;
50742
+ }
50743
+
50744
+ edges[i + 2] = [
50745
+ c2, a2
50746
+ ];
50747
+ }
50748
+
50749
+ // Group semantically equivalent edgdes together
50750
+ function compareEdges(e1, e2) {
50751
+ let a, b;
50752
+
50753
+ for (let i = 0; i < 2; i++) {
50754
+ a = e1[i];
50755
+ b = e2[i];
50756
+
50757
+ if (b !== a) {
50758
+ return b - a;
50759
+ }
50760
+ }
50761
+
50762
+ return 0;
50763
+ }
50764
+
50765
+ edges = edges.slice(0, indices.length);
50766
+
50767
+ edges.sort(compareEdges);
50768
+
50769
+ // Make sure each edge is used exactly twice
50770
+ let sameEdgeCount = 0;
50771
+
50772
+ for (let i = 0; i < edges.length; i++) {
50773
+ if (i === 0 || 0 !== compareEdges(
50774
+ edges[i], edges[i - 1]
50775
+ )) {
50776
+ // different edge
50777
+ if (0 !== i && sameEdgeCount !== 2) {
50778
+ return false;
50779
+ }
50780
+
50781
+ sameEdgeCount = 1;
50782
+ } else {
50783
+ // same edge
50784
+ sameEdgeCount++;
50785
+ }
50786
+ }
50787
+
50788
+ if (edges.length > 0 && sameEdgeCount !== 2) {
50789
+ return false;
50790
+ }
50791
+
50792
+ // Each edge is used exactly twice, this is a
50793
+ // watertight surface and hence a solid geometry.
50794
+ return true;
50795
+ };
50796
+
50797
+ const v1$1 = math.vec3();
50798
+ const v2$1 = math.vec3();
50799
+ const v3$1 = math.vec3();
50800
+
50801
+ /**
50802
+ * Calculates the volume of triangle meshes.
50803
+ */
50804
+ class MeshVolume {
50805
+ constructor() {
50806
+ this.vertices = [];
50807
+ this.indices = [];
50808
+ this.reset();
50809
+ }
50810
+
50811
+ /**
50812
+ * Resets, ready to add vertices and indices for a new mesh.
50813
+ */
50814
+ reset() {
50815
+ this.lenVertices = 0;
50816
+ this.lenIndices = 0;
50817
+ this.primitive = null;
50818
+ }
50819
+
50820
+ setPrimitive(primitive) {
50821
+ this.primitive = primitive;
50822
+ }
50823
+
50824
+ /**
50825
+ * Adds a vertex.
50826
+ * @param vertex
50827
+ */
50828
+ addVertex(vertex) {
50829
+ this.vertices[this.lenVertices++] = vertex[0];
50830
+ this.vertices[this.lenVertices++] = vertex[1];
50831
+ this.vertices[this.lenVertices++] = vertex[2];
50832
+ }
50833
+
50834
+ /**
50835
+ * Adds an index.
50836
+ * @param index
50837
+ */
50838
+ addIndex(index) {
50839
+ this.indices[this.lenIndices++] = index;
50840
+ }
50841
+
50842
+ /**
50843
+ * Gets the volume of the mesh.
50844
+ *
50845
+ * The mesh must be a closed solid.
50846
+ *
50847
+ * @returns {number} The volume of the mesh, or -1 if the mesh is not solid, in which case volume cannot be determined.
50848
+ */
50849
+ get volume() {
50850
+
50851
+ const vertices = this.vertices;
50852
+ const indices = this.indices;
50853
+
50854
+ if (this.primitive !== "solid" && this.primitive !== "surface" && this.primitive !== "triangles") {
50855
+ return -1;
50856
+ }
50857
+
50858
+ if (this.primitive !== "solid" && !isTriangleMeshSolid(indices, vertices)) {
50859
+ return -1;
50860
+ }
50861
+
50862
+ let volume = 0;
50863
+
50864
+ for (let i = 0; i < this.lenIndices; i += 3) {
50865
+
50866
+ const index1 = indices[i] * 3;
50867
+ const index2 = indices[i + 1] * 3;
50868
+ const index3 = indices[i + 2] * 3;
50869
+
50870
+ v1$1[0] = vertices[index1];
50871
+ v1$1[1] = vertices[index1 + 1];
50872
+ v1$1[2] = vertices[index1 + 2];
50873
+
50874
+ v2$1[0] = vertices[index2];
50875
+ v2$1[1] = vertices[index2 + 1];
50876
+ v2$1[2] = vertices[index2 + 2];
50877
+
50878
+ v3$1[0] = vertices[index3];
50879
+ v3$1[1] = vertices[index3 + 1];
50880
+ v3$1[2] = vertices[index3 + 2];
50881
+
50882
+ math.cross3Vec3(v1$1, v2$1, v1$1);
50883
+
50884
+ volume += math.dotVec3(v1$1, v3$1);
50885
+ }
50886
+
50887
+ return volume;
50888
+ }
50889
+ }
50890
+
50891
+ /**
50892
+ * Singleton instance of {@link MeshVolume}.
50893
+ * @type {MeshVolume}
50894
+ */
50895
+ const meshVolume = new MeshVolume();
50896
+
50897
+ const v1 = math.vec3();
50898
+ const v2 = math.vec3();
50899
+ const v3 = math.vec3();
50900
+ const v4 = math.vec3();
50901
+ const v5 = math.vec3();
50902
+ const v6 = math.vec3();
50903
+
50904
+ /**
50905
+ * Calculates the surface area of triangle meshes.
50906
+ */
50907
+ class MeshSurfaceArea {
50908
+ constructor() {
50909
+ this.vertices = [];
50910
+ this.indices = [];
50911
+ this.reset();
50912
+ }
50913
+
50914
+ /**
50915
+ * Resets, ready to add vertices and indices for a new mesh.
50916
+ */
50917
+ reset() {
50918
+ this.lenVertices = 0;
50919
+ this.lenIndices = 0;
50920
+ }
50921
+
50922
+ /**
50923
+ * Adds a vertex.
50924
+ * @param vertex
50925
+ */
50926
+ addVertex(vertex) {
50927
+ this.vertices[this.lenVertices++] = vertex[0];
50928
+ this.vertices[this.lenVertices++] = vertex[1];
50929
+ this.vertices[this.lenVertices++] = vertex[2];
50930
+ }
50931
+
50932
+ /**
50933
+ * Adds an index.
50934
+ * @param index
50935
+ */
50936
+ addIndex(index) {
50937
+ this.indices[this.lenIndices++] = index;
50938
+ }
50939
+
50940
+ /**
50941
+ * Gets the surface area of the mesh.
50942
+ *
50943
+ * @returns {number}
50944
+ */
50945
+ get surfaceArea() {
50946
+
50947
+ const vertices = this.vertices;
50948
+ const indices = this.indices;
50949
+
50950
+ let surfaceArea = 0;
50951
+
50952
+ for (let i = 0; i < this.lenIndices; i += 3) {
50953
+
50954
+ const index1 = indices[i] * 3;
50955
+ const index2 = indices[i + 1] * 3;
50956
+ const index3 = indices[i + 2] * 3;
50957
+
50958
+ v1[0] = vertices[index1];
50959
+ v1[1] = vertices[index1 + 1];
50960
+ v1[2] = vertices[index1 + 2];
50961
+
50962
+ v2[0] = vertices[index2];
50963
+ v2[1] = vertices[index2 + 1];
50964
+ v2[2] = vertices[index2 + 2];
50965
+
50966
+ v3[0] = vertices[index3];
50967
+ v3[1] = vertices[index3 + 1];
50968
+ v3[2] = vertices[index3 + 2];
50969
+
50970
+ math.subVec3(v1, v2, v4);
50971
+ math.subVec3(v3, v2, v5);
50972
+
50973
+ surfaceArea += math.lenVec3(math.cross3Vec3(v4, v5, v6)) * 0.5;
50974
+ }
50975
+
50976
+ return surfaceArea;
50977
+ }
50978
+ }
50979
+
50980
+ /**
50981
+ * Singleton instance of {@link MeshSurfaceArea}.
50982
+ * @type {MeshSurfaceArea}
50983
+ */
50984
+ const meshSurfaceArea = new MeshSurfaceArea();
50985
+
50607
50986
  const tempOBB3$1 = math.OBB3();
50608
50987
  const tempOBB3b = math.OBB3();
50609
50988
  const tempOBB3c = math.OBB3();
50610
50989
 
50990
+
50611
50991
  /**
50612
50992
  * A mesh within a {@link SceneModel}.
50613
50993
  *
@@ -50720,6 +51100,9 @@ class SceneModelMesh {
50720
51100
  if (transform) {
50721
51101
  transform._addMesh(this);
50722
51102
  }
51103
+
51104
+ this._volume = null;
51105
+ this._surfaceArea = null;
50723
51106
  }
50724
51107
 
50725
51108
  _sceneModelDirty() {
@@ -50898,7 +51281,75 @@ class SceneModelMesh {
50898
51281
  * @private
50899
51282
  */
50900
51283
  getEachVertex(callback) {
50901
- this.layer.getEachVertex(this.portionId, callback);
51284
+ if (this.layer.getEachVertex) {
51285
+ this.layer.getEachVertex(this.portionId, callback);
51286
+ }
51287
+ }
51288
+
51289
+ /**
51290
+ * @private
51291
+ */
51292
+ getEachIndex(callback) {
51293
+ if (this.layer.getEachIndex ) {
51294
+ this.layer.getEachIndex(this.portionId, callback);
51295
+ }
51296
+ }
51297
+
51298
+ /**
51299
+ * Returns the volume of this SceneModelMesh.
51300
+ * @returns {number}
51301
+ */
51302
+ get volume() {
51303
+ if (this._volume !== null) {
51304
+ return this._volume;
51305
+ }
51306
+ switch (this.layer.primitive) {
51307
+ case "solid":
51308
+ case "surface":
51309
+ case "triangles":
51310
+ meshVolume.reset();
51311
+ meshVolume.setPrimitive(this.layer.primitive);
51312
+ this.getEachVertex((vertex) =>{
51313
+ meshVolume.addVertex(vertex);
51314
+ });
51315
+ this.getEachIndex((index)=>{
51316
+ meshVolume.addIndex(index);
51317
+ });
51318
+ this._volume = meshVolume.volume;
51319
+ break;
51320
+ default:
51321
+ this._volume = 0;
51322
+ break;
51323
+ }
51324
+ return this._volume;
51325
+ }
51326
+
51327
+ /**
51328
+ * Returns the surface area of this SceneModelMesh.
51329
+ * @returns {number}
51330
+ */
51331
+ get surfaceArea() {
51332
+ if (this._surfaceArea !== null) {
51333
+ return this._surfaceArea;
51334
+ }
51335
+ switch (this.layer.primitive) {
51336
+ case "solid":
51337
+ case "surface":
51338
+ case "triangles":
51339
+ meshSurfaceArea.reset();
51340
+ this.getEachVertex((vertex) =>{
51341
+ meshSurfaceArea.addVertex(vertex);
51342
+ });
51343
+ this.getEachIndex((index)=>{
51344
+ meshSurfaceArea.addIndex(index);
51345
+ });
51346
+ this._surfaceArea = meshSurfaceArea.surfaceArea;
51347
+ break;
51348
+ default:
51349
+ this._surfaceArea = 0;
51350
+ break;
51351
+ }
51352
+ return this._surfaceArea;
50902
51353
  }
50903
51354
 
50904
51355
  /**
@@ -55702,7 +56153,7 @@ function octDecodeVec2(oct) { // Decode an oct-encoded normal
55702
56153
 
55703
56154
  const tempMat4$1 = math.mat4();
55704
56155
  const tempMat4b = math.mat4();
55705
- const tempVec4a$7 = math.vec4([0, 0, 0, 1]);
56156
+ const tempVec4a$8 = math.vec4([0, 0, 0, 1]);
55706
56157
 
55707
56158
  const tempVec3a$z = math.vec3();
55708
56159
  const tempVec3b$v = math.vec3();
@@ -55732,7 +56183,7 @@ class VBOBatchingTrianglesLayer {
55732
56183
  */
55733
56184
  constructor(cfg) {
55734
56185
 
55735
- console.info("Creating VBOBatchingTrianglesLayer");
56186
+ // console.info("Creating VBOBatchingTrianglesLayer");
55736
56187
 
55737
56188
  /**
55738
56189
  * Owner model
@@ -55822,6 +56273,11 @@ class VBOBatchingTrianglesLayer {
55822
56273
  * @type {boolean}
55823
56274
  */
55824
56275
  this.solid = !!cfg.solid;
56276
+
56277
+ /**
56278
+ * The type of primitives in this layer.
56279
+ */
56280
+ this.primitive = cfg.primitive;
55825
56281
  }
55826
56282
 
55827
56283
  get aabb() {
@@ -56018,7 +56474,7 @@ class VBOBatchingTrianglesLayer {
56018
56474
  numIndices: indices.length,
56019
56475
  };
56020
56476
 
56021
- if (scene.pickSurfacePrecisionEnabled) {
56477
+ if (scene.readableGeometryEnabled) {
56022
56478
  // Quantized in-memory positions are initialized in finalize()
56023
56479
 
56024
56480
  portion.indices = indices;
@@ -56055,7 +56511,7 @@ class VBOBatchingTrianglesLayer {
56055
56511
  ? new Uint16Array(buffer.positions)
56056
56512
  : quantizePositions(buffer.positions, this._modelAABB, this._state.positionsDecodeMatrix = math.mat4()); // BOTTLENECK
56057
56513
  state.positionsBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, quantizedPositions, quantizedPositions.length, 3, gl.STATIC_DRAW);
56058
- if (this.model.scene.pickSurfacePrecisionEnabled) {
56514
+ if (this.model.scene.readableGeometryEnabled) {
56059
56515
  for (let i = 0, numPortions = this._portions.length; i < numPortions; i++) {
56060
56516
  const portion = this._portions[i];
56061
56517
  const start = portion.vertsBaseIndex * 3;
@@ -56484,7 +56940,7 @@ class VBOBatchingTrianglesLayer {
56484
56940
  if (this._state.offsetsBuf) {
56485
56941
  this._state.offsetsBuf.setData(tempArray, firstOffset, lenOffsets);
56486
56942
  }
56487
- if (this.model.scene.pickSurfacePrecisionEnabled) {
56943
+ if (this.model.scene.readableGeometryEnabled) {
56488
56944
  portion.offset[0] = offset[0];
56489
56945
  portion.offset[1] = offset[1];
56490
56946
  portion.offset[2] = offset[2];
@@ -56492,7 +56948,7 @@ class VBOBatchingTrianglesLayer {
56492
56948
  }
56493
56949
 
56494
56950
  getEachVertex(portionId, callback) {
56495
- if (!this.model.scene.pickSurfacePrecisionEnabled) {
56951
+ if (!this.model.scene.readableGeometryEnabled) {
56496
56952
  return;
56497
56953
  }
56498
56954
  const state = this._state;
@@ -56503,18 +56959,19 @@ class VBOBatchingTrianglesLayer {
56503
56959
  }
56504
56960
  const positions = portion.quantizedPositions;
56505
56961
  const origin = state.origin;
56506
- const offset = portion.offset;
56507
- const offsetX = origin[0] + offset[0];
56508
- const offsetY = origin[1] + offset[1];
56509
- const offsetZ = origin[2] + offset[2];
56510
- const worldPos = tempVec4a$7;
56962
+ const offsetX = origin[0] ;
56963
+ const offsetY = origin[1] ;
56964
+ const offsetZ = origin[2] ;
56965
+ const worldPos = tempVec4a$8;
56966
+ const sceneModelMatrix = this.model.matrix;
56967
+ const positionsDecodeMatrix = state.positionsDecodeMatrix;
56511
56968
  for (let i = 0, len = positions.length; i < len; i += 3) {
56512
56969
  worldPos[0] = positions[i];
56513
56970
  worldPos[1] = positions[i + 1];
56514
56971
  worldPos[2] = positions[i + 2];
56515
56972
  worldPos[3] = 1.0;
56516
- math.decompressPosition(worldPos, state.positionsDecodeMatrix);
56517
- math.transformPoint4(this.model.worldMatrix, worldPos);
56973
+ math.decompressPosition(worldPos, positionsDecodeMatrix);
56974
+ math.transformPoint4(sceneModelMatrix, worldPos);
56518
56975
  worldPos[0] += offsetX;
56519
56976
  worldPos[1] += offsetY;
56520
56977
  worldPos[2] += offsetZ;
@@ -56522,6 +56979,21 @@ class VBOBatchingTrianglesLayer {
56522
56979
  }
56523
56980
  }
56524
56981
 
56982
+ getEachIndex(portionId, callback) {
56983
+ if (!this.model.scene.readableGeometryEnabled) {
56984
+ return;
56985
+ }
56986
+ const portion = this._portions[portionId];
56987
+ if (!portion) {
56988
+ this.model.error("portion not found: " + portionId);
56989
+ return;
56990
+ }
56991
+ const indices = portion.indices;
56992
+ for (let i = 0, len = indices.length; i < len; i++) {
56993
+ callback(indices[i]);
56994
+ }
56995
+ }
56996
+
56525
56997
  getElementsCountAndOffset(portionId) {
56526
56998
  let count = null;
56527
56999
  let offset = null;
@@ -56809,7 +57281,7 @@ class VBOBatchingTrianglesLayer {
56809
57281
 
56810
57282
  precisionRayPickSurface(portionId, worldRayOrigin, worldRayDir, worldSurfacePos, worldNormal) {
56811
57283
 
56812
- if (!this.model.scene.pickSurfacePrecisionEnabled) {
57284
+ if (!this.model.scene.readableGeometryEnabled) {
56813
57285
  return false;
56814
57286
  }
56815
57287
 
@@ -60789,7 +61261,7 @@ function getRenderers$6(scene) {
60789
61261
 
60790
61262
  const tempUint8Vec4$2 = new Uint8Array(4);
60791
61263
  const tempFloat32$2 = new Float32Array(1);
60792
- const tempVec4a$6 = math.vec4([0, 0, 0, 1]);
61264
+ const tempVec4a$7 = math.vec4([0, 0, 0, 1]);
60793
61265
  const tempVec3fa$2 = new Float32Array(3);
60794
61266
 
60795
61267
  const tempVec3a$w = math.vec3();
@@ -60817,7 +61289,7 @@ class VBOInstancingTrianglesLayer {
60817
61289
  */
60818
61290
  constructor(cfg) {
60819
61291
 
60820
- console.info("Creating VBOInstancingTrianglesLayer");
61292
+ // console.info("Creating VBOInstancingTrianglesLayer");
60821
61293
 
60822
61294
  /**
60823
61295
  * Owner model
@@ -60920,6 +61392,11 @@ class VBOInstancingTrianglesLayer {
60920
61392
  * @type {number|*}
60921
61393
  */
60922
61394
  this.numIndices = cfg.geometry.numIndices;
61395
+
61396
+ /**
61397
+ * The type of primitives in this layer.
61398
+ */
61399
+ this.primitive = cfg.geometry.primitive;
60923
61400
  }
60924
61401
 
60925
61402
  get aabb() {
@@ -61033,7 +61510,7 @@ class VBOInstancingTrianglesLayer {
61033
61510
 
61034
61511
  const portion = {};
61035
61512
 
61036
- if (this.model.scene.pickSurfacePrecisionEnabled) {
61513
+ if (this.model.scene.readableGeometryEnabled) {
61037
61514
  portion.matrix = meshMatrix.slice();
61038
61515
  portion.inverseMatrix = null; // Lazy-computed in precisionRayPickSurface
61039
61516
  portion.normalMatrix = null; // Lazy-computed in precisionRayPickSurface
@@ -61471,7 +61948,7 @@ class VBOInstancingTrianglesLayer {
61471
61948
  }
61472
61949
 
61473
61950
  getEachVertex(portionId, callback) {
61474
- if (!this.model.scene.pickSurfacePrecisionEnabled) {
61951
+ if (!this.model.scene.readableGeometryEnabled) {
61475
61952
  return false;
61476
61953
  }
61477
61954
  const state = this._state;
@@ -61483,13 +61960,12 @@ class VBOInstancingTrianglesLayer {
61483
61960
  }
61484
61961
  const positions = geometry.quantizedPositions;
61485
61962
  const origin = state.origin;
61486
- const offset = portion.offset;
61487
- const offsetX = origin[0] + offset[0];
61488
- const offsetY = origin[1] + offset[1];
61489
- const offsetZ = origin[2] + offset[2];
61490
- const worldPos = tempVec4a$6;
61963
+ const offsetX = origin[0] ;
61964
+ const offsetY = origin[1] ;
61965
+ const offsetZ = origin[2] ;
61966
+ const worldPos = tempVec4a$7;
61491
61967
  const portionMatrix = portion.matrix;
61492
- const sceneModelPatrix = this.model.sceneModelMatrix;
61968
+ const sceneModelMatrix = this.model.matrix;
61493
61969
  const positionsDecodeMatrix = state.positionsDecodeMatrix;
61494
61970
  for (let i = 0, len = positions.length; i < len; i += 3) {
61495
61971
  worldPos[0] = positions[i];
@@ -61497,7 +61973,7 @@ class VBOInstancingTrianglesLayer {
61497
61973
  worldPos[2] = positions[i + 2];
61498
61974
  math.decompressPosition(worldPos, positionsDecodeMatrix);
61499
61975
  math.transformPoint3(portionMatrix, worldPos);
61500
- math.transformPoint3(sceneModelPatrix, worldPos);
61976
+ math.transformPoint3(sceneModelMatrix, worldPos);
61501
61977
  worldPos[0] += offsetX;
61502
61978
  worldPos[1] += offsetY;
61503
61979
  worldPos[2] += offsetZ;
@@ -61505,6 +61981,23 @@ class VBOInstancingTrianglesLayer {
61505
61981
  }
61506
61982
  }
61507
61983
 
61984
+ getEachIndex(portionId, callback) {
61985
+ if (!this.model.scene.readableGeometryEnabled) {
61986
+ return false;
61987
+ }
61988
+ const state = this._state;
61989
+ const geometry = state.geometry;
61990
+ const portion = this._portions[portionId];
61991
+ if (!portion) {
61992
+ this.model.error("portion not found: " + portionId);
61993
+ return;
61994
+ }
61995
+ const indices = geometry.indices;
61996
+ for (let i = 0, len = indices.length; i < len; i++) {
61997
+ callback(indices[i]);
61998
+ }
61999
+ }
62000
+
61508
62001
  setMatrix(portionId, matrix) {
61509
62002
  if (!this._finalized) {
61510
62003
  throw "Not finalized";
@@ -61811,7 +62304,7 @@ class VBOInstancingTrianglesLayer {
61811
62304
 
61812
62305
  precisionRayPickSurface(portionId, worldRayOrigin, worldRayDir, worldSurfacePos, worldNormal) {
61813
62306
 
61814
- if (!this.model.scene.pickSurfacePrecisionEnabled) {
62307
+ if (!this.model.scene.readableGeometryEnabled) {
61815
62308
  return false;
61816
62309
  }
61817
62310
 
@@ -62968,7 +63461,7 @@ class VBOBatchingLinesLayer {
62968
63461
  */
62969
63462
  constructor(cfg) {
62970
63463
 
62971
- console.info("Creating VBOBatchingLinesLayer");
63464
+ // console.info("Creating VBOBatchingLinesLayer");
62972
63465
 
62973
63466
  /**
62974
63467
  * Index of this LinesBatchingLayer in {@link VBOSceneModel#_layerList}.
@@ -63023,6 +63516,11 @@ class VBOBatchingLinesLayer {
63023
63516
  if (cfg.origin) {
63024
63517
  this._state.origin = math.vec3(cfg.origin);
63025
63518
  }
63519
+
63520
+ /**
63521
+ * The type of primitives in this layer.
63522
+ */
63523
+ this.primitive = cfg.primitive;
63026
63524
  }
63027
63525
 
63028
63526
  get aabb() {
@@ -64731,7 +65229,7 @@ class VBOInstancingLinesLayer {
64731
65229
  */
64732
65230
  constructor(cfg) {
64733
65231
 
64734
- console.info("VBOInstancingLinesLayer");
65232
+ // console.info("VBOInstancingLinesLayer");
64735
65233
 
64736
65234
  /**
64737
65235
  * Owner model
@@ -64811,6 +65309,11 @@ class VBOInstancingLinesLayer {
64811
65309
  }
64812
65310
 
64813
65311
  this._finalized = false;
65312
+
65313
+ /**
65314
+ * The type of primitives in this layer.
65315
+ */
65316
+ this.primitive = cfg.primitive;
64814
65317
  }
64815
65318
 
64816
65319
  get aabb() {
@@ -66944,7 +67447,7 @@ class VBOBatchingPointsLayer {
66944
67447
  */
66945
67448
  constructor(cfg) {
66946
67449
 
66947
- console.info("Creating VBOBatchingPointsLayer");
67450
+ // console.info("Creating VBOBatchingPointsLayer");
66948
67451
 
66949
67452
  /**
66950
67453
  * Owner model
@@ -69541,7 +70044,7 @@ class VBOInstancingPointsLayer {
69541
70044
  */
69542
70045
  constructor(cfg) {
69543
70046
 
69544
- console.info("VBOInstancingPointsLayer");
70047
+ // console.info("VBOInstancingPointsLayer");
69545
70048
 
69546
70049
  /**
69547
70050
  * Owner model
@@ -69615,6 +70118,11 @@ class VBOInstancingPointsLayer {
69615
70118
  this.aabbDirty = true;
69616
70119
 
69617
70120
  this._finalized = false;
70121
+
70122
+ /**
70123
+ * The type of primitives in this layer.
70124
+ */
70125
+ this.primitive = cfg.geometry.primitive;
69618
70126
  }
69619
70127
 
69620
70128
  get aabb() {
@@ -71276,7 +71784,7 @@ class DTXLinesLayer {
71276
71784
 
71277
71785
  constructor(model, cfg) {
71278
71786
 
71279
- console.info("Creating DTXLinesLayer");
71787
+ // console.info("Creating DTXLinesLayer");
71280
71788
 
71281
71789
  dataTextureRamStats$1.numberOfLayers++;
71282
71790
 
@@ -71315,6 +71823,12 @@ class DTXLinesLayer {
71315
71823
  this._aabb = math.collapseAABB3();
71316
71824
  this.aabbDirty = true;
71317
71825
  this._numUpdatesInFrame = 0;
71826
+
71827
+ /**
71828
+ * The type of primitives in this layer.
71829
+ */
71830
+ this.primitive = cfg.primitive;
71831
+
71318
71832
  this._finalized = false;
71319
71833
  }
71320
71834
 
@@ -72140,7 +72654,7 @@ const tempVec3b$i = math.vec3();
72140
72654
  const tempVec3c$e = math.vec3();
72141
72655
  math.vec3();
72142
72656
 
72143
- const tempVec4a$5 = math.vec4();
72657
+ const tempVec4a$6 = math.vec4();
72144
72658
 
72145
72659
  const tempMat4a$c = math.mat4();
72146
72660
 
@@ -72419,11 +72933,11 @@ class DTXTrianglesColorRenderer {
72419
72933
  if (saoEnabled) {
72420
72934
  const viewportWidth = gl.drawingBufferWidth;
72421
72935
  const viewportHeight = gl.drawingBufferHeight;
72422
- tempVec4a$5[0] = viewportWidth;
72423
- tempVec4a$5[1] = viewportHeight;
72424
- tempVec4a$5[2] = sao.blendCutoff;
72425
- tempVec4a$5[3] = sao.blendFactor;
72426
- gl.uniform4fv(this._uSAOParams, tempVec4a$5);
72936
+ tempVec4a$6[0] = viewportWidth;
72937
+ tempVec4a$6[1] = viewportHeight;
72938
+ tempVec4a$6[2] = sao.blendCutoff;
72939
+ tempVec4a$6[3] = sao.blendFactor;
72940
+ gl.uniform4fv(this._uSAOParams, tempVec4a$6);
72427
72941
  this._program.bindTexture(this._uOcclusionTexture, frameCtx.occlusionTexture, 10);
72428
72942
  }
72429
72943
  }
@@ -78650,6 +79164,7 @@ const INDICES_EDGE_INDICES_ALIGNEMENT_SIZE = 8;
78650
79164
  */
78651
79165
  const MAX_OBJECT_UPDATES_IN_FRAME_WITHOUT_BATCHED_UPDATE = 10;
78652
79166
 
79167
+ const tempVec4a$5 = math.vec4();
78653
79168
  const tempMat4a = new Float32Array(16);
78654
79169
  const tempUint8Array4 = new Uint8Array(4);
78655
79170
  const tempFloat32Array3 = new Float32Array(3);
@@ -78665,7 +79180,7 @@ class DTXTrianglesLayer {
78665
79180
 
78666
79181
  constructor(model, cfg) {
78667
79182
 
78668
- console.info("Creating DTXTrianglesLayer");
79183
+ //console.info("Creating DTXTrianglesLayer");
78669
79184
 
78670
79185
  dataTextureRamStats.numberOfLayers++;
78671
79186
 
@@ -78705,6 +79220,10 @@ class DTXTrianglesLayer {
78705
79220
 
78706
79221
  this._subPortions = [];
78707
79222
 
79223
+ if (this.model.scene.readableGeometryEnabled) {
79224
+ this._subPortionReadableGeometries = {};
79225
+ }
79226
+
78708
79227
  /**
78709
79228
  * Due to `index rebucketting` process in ```prepareMeshGeometry``` function, it's possible that a single
78710
79229
  * portion is expanded to more than 1 real sub-portion.
@@ -78734,6 +79253,11 @@ class DTXTrianglesLayer {
78734
79253
  */
78735
79254
  this._numUpdatesInFrame = 0;
78736
79255
 
79256
+ /**
79257
+ * The type of primitives in this layer.
79258
+ */
79259
+ this.primitive = cfg.primitive;
79260
+
78737
79261
  this._finalized = false;
78738
79262
  }
78739
79263
 
@@ -79038,6 +79562,15 @@ class DTXTrianglesLayer {
79038
79562
  numVertices: bucketGeometry.numTriangles
79039
79563
  });
79040
79564
 
79565
+ if (this.model.scene.readableGeometryEnabled) {
79566
+ this._subPortionReadableGeometries[subPortionId] = {
79567
+ indices: bucket.indices,
79568
+ positionsCompressed: bucket.positionsCompressed,
79569
+ positionsDecodeMatrix: portionCfg.positionsDecodeMatrix,
79570
+ meshMatrix: portionCfg.meshMatrix
79571
+ };
79572
+ }
79573
+
79041
79574
  this._numPortions++;
79042
79575
 
79043
79576
  dataTextureRamStats.numberOfPortions++;
@@ -79688,6 +80221,63 @@ class DTXTrianglesLayer {
79688
80221
  // gl.bindTexture (gl.TEXTURE_2D, null);
79689
80222
  }
79690
80223
 
80224
+ getEachVertex(portionId, callback) {
80225
+ if (!this.model.scene.readableGeometryEnabled) {
80226
+ return;
80227
+ }
80228
+ const state = this._state;
80229
+ const subPortionIds = this._portionToSubPortionsMap[portionId];
80230
+ if (!subPortionIds) {
80231
+ this.model.error("portion not found: " + portionId);
80232
+ return;
80233
+ }
80234
+ for (let i = 0, len = subPortionIds.length; i < len; i++) {
80235
+ const subPortionId = subPortionIds[i];
80236
+ const subPortionReadableGeometry = this._subPortionReadableGeometries[subPortionId];
80237
+ const positions = subPortionReadableGeometry.positionsCompressed;
80238
+ const positionsDecodeMatrix = subPortionReadableGeometry.positionsDecodeMatrix;
80239
+ subPortionReadableGeometry.meshMatrix;
80240
+ const origin = state.origin;
80241
+ const offsetX = origin[0] ;
80242
+ const offsetY = origin[1] ;
80243
+ const offsetZ = origin[2] ;
80244
+ const worldPos = tempVec4a$5;
80245
+ for (let i = 0, len = positions.length; i < len; i += 3) {
80246
+ worldPos[0] = positions[i];
80247
+ worldPos[1] = positions[i + 1];
80248
+ worldPos[2] = positions[i + 2];
80249
+ worldPos[3] = 1.0;
80250
+ math.decompressPosition(worldPos, positionsDecodeMatrix);
80251
+ math.transformPoint4(this.model.worldMatrix, worldPos);
80252
+ math.transformPoint4(this.model.worldMatrix, worldPos);
80253
+ worldPos[0] += offsetX;
80254
+ worldPos[1] += offsetY;
80255
+ worldPos[2] += offsetZ;
80256
+ callback(worldPos);
80257
+ }
80258
+ }
80259
+ }
80260
+
80261
+ getEachIndex(portionId, callback) {
80262
+ if (!this.model.scene.readableGeometryEnabled) {
80263
+ return;
80264
+ }
80265
+ const subPortionIds = this._portionToSubPortionsMap[portionId];
80266
+ if (!subPortionIds) {
80267
+ this.model.error("portion not found: " + portionId);
80268
+ return;
80269
+ }
80270
+ for (let i = 0, len = subPortionIds.length; i < len; i++) {
80271
+ const subPortionId = subPortionIds[i];
80272
+ const subPortionReadableGeometry = this._subPortionReadableGeometries[subPortionId];
80273
+ const indices = subPortionReadableGeometry.indices;
80274
+ for (let i = 0, len = indices.length; i < len; i++) {
80275
+ callback(indices[i]);
80276
+ }
80277
+ }
80278
+ }
80279
+
80280
+
79691
80281
  // ---------------------- COLOR RENDERING -----------------------------------
79692
80282
 
79693
80283
  drawColorOpaque(renderFlags, frameCtx) {
@@ -83030,7 +83620,10 @@ class SceneModel extends Component {
83030
83620
  this._meshList = [];
83031
83621
 
83032
83622
  this.layerList = []; // For GL state efficiency when drawing, InstancingLayers are in first part, BatchingLayers are in second
83623
+ this._layersToFinalize = [];
83624
+
83033
83625
  this._entityList = [];
83626
+ this._entitiesToFinalize = [];
83034
83627
 
83035
83628
  this._geometries = {};
83036
83629
  this._dtxBuckets = {}; // Geometries with optimizations used for data texture representation
@@ -83106,6 +83699,7 @@ class SceneModel extends Component {
83106
83699
  this._numTriangles = 0;
83107
83700
  this._numLines = 0;
83108
83701
  this._numPoints = 0;
83702
+ this._layersFinalized = false;
83109
83703
 
83110
83704
  this._edgeThreshold = cfg.edgeThreshold || 10;
83111
83705
 
@@ -85047,7 +85641,7 @@ class SceneModel extends Component {
85047
85641
  let dtxLayer = this._dtxLayers[layerId];
85048
85642
  if (dtxLayer) {
85049
85643
  if (!dtxLayer.canCreatePortion(cfg)) {
85050
- dtxLayer.finalize();
85644
+ // dtxLayer.finalize();
85051
85645
  delete this._dtxLayers[layerId];
85052
85646
  dtxLayer = null;
85053
85647
  } else {
@@ -85058,16 +85652,17 @@ class SceneModel extends Component {
85058
85652
  case "triangles":
85059
85653
  case "solid":
85060
85654
  case "surface":
85061
- dtxLayer = new DTXTrianglesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()
85655
+ dtxLayer = new DTXTrianglesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
85062
85656
  break;
85063
85657
  case "lines":
85064
- dtxLayer = new DTXLinesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()
85658
+ dtxLayer = new DTXLinesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
85065
85659
  break;
85066
85660
  default:
85067
85661
  return;
85068
85662
  }
85069
85663
  this._dtxLayers[layerId] = dtxLayer;
85070
85664
  this.layerList.push(dtxLayer);
85665
+ this._layersToFinalize.push(dtxLayer);
85071
85666
  return dtxLayer;
85072
85667
  }
85073
85668
 
@@ -85099,7 +85694,8 @@ class SceneModel extends Component {
85099
85694
  origin,
85100
85695
  maxGeometryBatchSize: this._maxGeometryBatchSize,
85101
85696
  solid: (cfg.primitive === "solid"),
85102
- autoNormals: true
85697
+ autoNormals: true,
85698
+ primitive: cfg.primitive
85103
85699
  });
85104
85700
  break;
85105
85701
  case "solid":
@@ -85114,7 +85710,8 @@ class SceneModel extends Component {
85114
85710
  origin,
85115
85711
  maxGeometryBatchSize: this._maxGeometryBatchSize,
85116
85712
  solid: (cfg.primitive === "solid"),
85117
- autoNormals: true
85713
+ autoNormals: true,
85714
+ primitive: cfg.primitive
85118
85715
  });
85119
85716
  break;
85120
85717
  case "surface":
@@ -85129,7 +85726,8 @@ class SceneModel extends Component {
85129
85726
  origin,
85130
85727
  maxGeometryBatchSize: this._maxGeometryBatchSize,
85131
85728
  solid: (cfg.primitive === "solid"),
85132
- autoNormals: true
85729
+ autoNormals: true,
85730
+ primitive: cfg.primitive
85133
85731
  });
85134
85732
  break;
85135
85733
  case "lines":
@@ -85141,7 +85739,8 @@ class SceneModel extends Component {
85141
85739
  positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
85142
85740
  uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
85143
85741
  origin,
85144
- maxGeometryBatchSize: this._maxGeometryBatchSize
85742
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
85743
+ primitive: cfg.primitive
85145
85744
  });
85146
85745
  break;
85147
85746
  case "points":
@@ -85153,7 +85752,8 @@ class SceneModel extends Component {
85153
85752
  positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
85154
85753
  uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
85155
85754
  origin,
85156
- maxGeometryBatchSize: this._maxGeometryBatchSize
85755
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
85756
+ primitive: cfg.primitive
85157
85757
  });
85158
85758
  break;
85159
85759
  }
@@ -85169,6 +85769,7 @@ class SceneModel extends Component {
85169
85769
  }
85170
85770
  this._vboBatchingLayers[layerId] = vboBatchingLayer;
85171
85771
  this.layerList.push(vboBatchingLayer);
85772
+ this._layersToFinalize.push(vboBatchingLayer);
85172
85773
  return vboBatchingLayer;
85173
85774
  }
85174
85775
 
@@ -85261,6 +85862,7 @@ class SceneModel extends Component {
85261
85862
  }
85262
85863
  this._vboInstancingLayers[layerId] = vboInstancingLayer;
85263
85864
  this.layerList.push(vboInstancingLayer);
85865
+ this._layersToFinalize.push(vboInstancingLayer);
85264
85866
  return vboInstancingLayer;
85265
85867
  }
85266
85868
 
@@ -85361,38 +85963,47 @@ class SceneModel extends Component {
85361
85963
  lodCullable); // Internally sets SceneModelEntity#parent to this SceneModel
85362
85964
  this._entityList.push(entity);
85363
85965
  this._entities[cfg.id] = entity;
85966
+ this._entitiesToFinalize.push(entity);
85364
85967
  this.numEntities++;
85365
85968
  }
85366
85969
 
85367
85970
  /**
85368
- * Finalizes this SceneModel.
85369
- *
85370
- * Once finalized, you can't add anything more to this SceneModel.
85971
+ * Pre-renders all meshes that have been added, even if the SceneModel has not bee finalized yet.
85972
+ * This is use for progressively showing the SceneModel while it is being loaded or constructed.
85973
+ * @returns {boolean}
85371
85974
  */
85372
- finalize() {
85975
+ preFinalize() {
85373
85976
  if (this.destroyed) {
85374
- return;
85977
+ return false;
85978
+ }
85979
+ if (this._layersToFinalize.length === 0) {
85980
+ return false;
85375
85981
  }
85376
85982
  this._createDummyEntityForUnusedMeshes();
85377
- for (let i = 0, len = this.layerList.length; i < len; i++) {
85378
- const layer = this.layerList[i];
85983
+ for (let i = 0, len = this._layersToFinalize.length; i < len; i++) {
85984
+ const layer = this._layersToFinalize[i];
85379
85985
  layer.finalize();
85380
85986
  }
85381
- this._geometries = {};
85382
- this._dtxBuckets = {};
85383
- this._textures = {};
85384
- this._textureSets = {};
85385
- this._dtxLayers = {};
85386
- this._vboInstancingLayers = {};
85387
85987
  this._vboBatchingLayers = {};
85388
- for (let i = 0, len = this._entityList.length; i < len; i++) {
85389
- const entity = this._entityList[i];
85988
+ this._vboInstancingLayers = {};
85989
+ this._dtxLayers = {};
85990
+ this._layersToFinalize = [];
85991
+ for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
85992
+ const entity = this._entitiesToFinalize[i];
85390
85993
  entity._finalize();
85391
85994
  }
85392
- for (let i = 0, len = this._entityList.length; i < len; i++) {
85393
- const entity = this._entityList[i];
85995
+ for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
85996
+ const entity = this._entitiesToFinalize[i];
85394
85997
  entity._finalize2();
85395
85998
  }
85999
+ this._entitiesToFinalize = [];
86000
+ this.scene._aabbDirty = true;
86001
+ this._viewMatrixDirty = true;
86002
+ this._matrixDirty = true;
86003
+ this._aabbDirty = true;
86004
+ this._setWorldMatrixDirty();
86005
+ this._sceneModelDirty();
86006
+ this.position = this._position;
85396
86007
  // Sort layers to reduce WebGL shader switching when rendering them
85397
86008
  this.layerList.sort((a, b) => {
85398
86009
  if (a.sortId < b.sortId) {
@@ -85408,15 +86019,23 @@ class SceneModel extends Component {
85408
86019
  layer.layerIndex = i;
85409
86020
  }
85410
86021
  this.glRedraw();
85411
- this.scene._aabbDirty = true;
85412
- this._viewMatrixDirty = true;
85413
- this._matrixDirty = true;
85414
- this._aabbDirty = true;
85415
-
85416
- this._setWorldMatrixDirty();
85417
- this._sceneModelDirty();
86022
+ this._layersFinalized = true;
86023
+ }
85418
86024
 
85419
- this.position = this._position;
86025
+ /**
86026
+ * Finalizes this SceneModel.
86027
+ *
86028
+ * Once finalized, you can't add anything more to this SceneModel.
86029
+ */
86030
+ finalize() {
86031
+ if (this.destroyed) {
86032
+ return;
86033
+ }
86034
+ this.preFinalize();
86035
+ this._geometries = {};
86036
+ this._dtxBuckets = {};
86037
+ this._textures = {};
86038
+ this._textureSets = {};
85420
86039
  }
85421
86040
 
85422
86041
  /** @private */
@@ -85454,7 +86073,7 @@ class SceneModel extends Component {
85454
86073
  _createDummyEntityForUnusedMeshes() {
85455
86074
  const unusedMeshIds = Object.keys(this._unusedMeshes);
85456
86075
  if (unusedMeshIds.length > 0) {
85457
- const entityId = `${this.id}-dummyEntityForUnusedMeshes`;
86076
+ const entityId = `${this.id}-${math.createUUID()}`;
85458
86077
  this.warn(`Creating dummy SceneModelEntity "${entityId}" for unused SceneMeshes: [${unusedMeshIds.join(",")}]`);
85459
86078
  this.createEntity({
85460
86079
  id: entityId,
@@ -85826,6 +86445,7 @@ class SceneModel extends Component {
85826
86445
  for (let i = 0, len = this._entityList.length; i < len; i++) {
85827
86446
  this._entityList[i]._destroy();
85828
86447
  }
86448
+ this._layersToFinalize = {};
85829
86449
  // Object.entries(this._geometries).forEach(([id, geometry]) => {
85830
86450
  // geometry.destroy();
85831
86451
  // });
@@ -88323,12 +88943,6 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88323
88943
 
88324
88944
  this._initMarkerDiv();
88325
88945
 
88326
- this._onCameraControlHoverSnapOrSurface = null;
88327
- this._onCameraControlHoverSnapOrSurfaceOff = null;
88328
- this._onMouseDown = null;
88329
- this._onMouseUp = null;
88330
- this._onCanvasTouchStart = null;
88331
- this._onCanvasTouchEnd = null;
88332
88946
  this._snapping = cfg.snapping !== false;
88333
88947
  this._mouseState = MOUSE_FIRST_CLICK_EXPECTED;
88334
88948
 
@@ -88392,20 +89006,10 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88392
89006
  *
88393
89007
  * This is `true` by default.
88394
89008
  *
88395
- * Internally, this deactivates then activates the DistanceMeasurementsMouseControl when changed, which means that
88396
- * it will destroy any DistanceMeasurements currently under construction, and incurs some overhead, since it unbinds
88397
- * and rebinds various input handlers.
88398
- *
88399
89009
  * @param snapping
88400
89010
  */
88401
89011
  set snapping(snapping) {
88402
- if (snapping !== this._snapping) {
88403
- this._snapping = snapping;
88404
- this.deactivate();
88405
- this.activate();
88406
- } else {
88407
- this._snapping = snapping;
88408
- }
89012
+ this._snapping = snapping;
88409
89013
  }
88410
89014
 
88411
89015
  /**
@@ -88417,7 +89021,7 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88417
89021
  get snapping() {
88418
89022
  return this._snapping;
88419
89023
  }
88420
-
89024
+
88421
89025
  /**
88422
89026
  * Activates this DistanceMeasurementsMouseControl, ready to respond to input.
88423
89027
  */
@@ -88452,11 +89056,8 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88452
89056
  const getLeft = el => el.offsetLeft + (el.offsetParent && (el.offsetParent !== canvas.parentNode) && getLeft(el.offsetParent));
88453
89057
 
88454
89058
  const pagePos = math.vec2();
88455
-
88456
- this._onCameraControlHoverSnapOrSurface = cameraControl.on(
88457
- this._snapping
88458
- ? "hoverSnapOrSurface"
88459
- : "hoverSurface", event => {
89059
+
89060
+ const hoverOn = event => {
88460
89061
  const canvasPos = event.snappedCanvasPos || event.canvasPos;
88461
89062
  mouseHovering = true;
88462
89063
  pointerWorldPos.set(event.worldPos);
@@ -88509,7 +89110,9 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88509
89110
  this._markerDiv.style.left = `-10000px`;
88510
89111
  this._markerDiv.style.top = `-10000px`;
88511
89112
  }
88512
- });
89113
+ };
89114
+ this._onHoverSnapOrSurface = cameraControl.on("hoverSnapOrSurface", e => { if (this._snapping) hoverOn(e); });
89115
+ this._onHoverSurface = cameraControl.on("hoverSurface", e => { if (! this._snapping) hoverOn(e); });
88513
89116
 
88514
89117
  canvas.addEventListener('mousedown', this._onMouseDown = (e) => {
88515
89118
  if (e.which !== 1) {
@@ -88570,10 +89173,7 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88570
89173
  }
88571
89174
  });
88572
89175
 
88573
- this._onCameraControlHoverSnapOrSurfaceOff = cameraControl.on(
88574
- this._snapping
88575
- ? "hoverSnapOrSurfaceOff"
88576
- : "hoverOff", event => {
89176
+ const hoverOff = event => {
88577
89177
  if (this.pointerLens) {
88578
89178
  this.pointerLens.visible = true;
88579
89179
  this.pointerLens.canvasPos = event.canvasPos;
@@ -88588,7 +89188,9 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88588
89188
  this._currentDistanceMeasurement.axisVisible = false;
88589
89189
  }
88590
89190
  canvas.style.cursor = "default";
88591
- });
89191
+ };
89192
+ this._onHoverSnapOrSurfaceOff = cameraControl.on("hoverSnapOrSurfaceOff", e => { if (this._snapping) hoverOff(e); });
89193
+ this._onHoverOff = cameraControl.on("hoverOff", e => { if (! this._snapping) hoverOff(e); });
88592
89194
 
88593
89195
  this._active = true;
88594
89196
  }
@@ -88602,27 +89204,24 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88602
89204
  if (!this._active) {
88603
89205
  return;
88604
89206
  }
88605
-
89207
+
88606
89208
  this.fire("activated", false);
88607
89209
 
88608
89210
  if (this.pointerLens) {
88609
89211
  this.pointerLens.visible = false;
88610
89212
  }
88611
- // if (this._markerDiv) {
88612
- // this._destroyMarkerDiv()
88613
- // }
88614
- // this.reset();
89213
+
89214
+ this.reset();
89215
+
88615
89216
  const canvas = this.scene.canvas.canvas;
88616
89217
  canvas.removeEventListener("mousedown", this._onMouseDown);
88617
89218
  canvas.removeEventListener("mouseup", this._onMouseUp);
88618
89219
  const cameraControl = this.distanceMeasurementsPlugin.viewer.cameraControl;
88619
- cameraControl.off(this._onCameraControlHoverSnapOrSurface);
88620
- cameraControl.off(this._onCameraControlHoverSnapOrSurfaceOff);
88621
- // if (this._currentDistanceMeasurement) {
88622
- // this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
88623
- // this._currentDistanceMeasurement.destroy();
88624
- // this._currentDistanceMeasurement = null;
88625
- // }
89220
+ cameraControl.off(this._onHoverSnapOrSurface);
89221
+ cameraControl.off(this._onHoverSurface);
89222
+ cameraControl.off(this._onHoverSnapOrSurfaceOff);
89223
+ cameraControl.off(this._onHoverOff);
89224
+
88626
89225
  this._active = false;
88627
89226
  }
88628
89227
 
@@ -89306,11 +89905,8 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
89306
89905
  targetVisible: null,
89307
89906
  };
89308
89907
 
89309
- this._onCanvasTouchStart = null;
89310
- this._onCanvasTouchEnd = null;
89311
89908
  this._longTouchTimeoutMs = 300;
89312
89909
  this._snapping = cfg.snapping !== false;
89313
- this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
89314
89910
 
89315
89911
  this._attachPlugin(distanceMeasurementsPlugin, cfg);
89316
89912
  }
@@ -89343,20 +89939,10 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
89343
89939
  *
89344
89940
  * This is `true` by default.
89345
89941
  *
89346
- * Internally, this deactivates then activates the DistanceMeasurementsTouchControl when changed, which means that
89347
- * it will destroy any DistanceMeasurements currently under construction, and incurs some overhead, since it unbinds
89348
- * and rebinds various input handlers.
89349
- *
89350
89942
  * @param {boolean} snapping Whether to enable snap-to-vertex and snap-edge for this DistanceMeasurementsTouchControl.
89351
89943
  */
89352
89944
  set snapping(snapping) {
89353
- if (snapping !== this._snapping) {
89354
- this._snapping = snapping;
89355
- this.deactivate();
89356
- this.activate();
89357
- } else {
89358
- this._snapping = snapping;
89359
- }
89945
+ this._snapping = snapping;
89360
89946
  }
89361
89947
 
89362
89948
  /**
@@ -89968,14 +90554,11 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
89968
90554
  this.plugin.pointerLens.visible = false;
89969
90555
  }
89970
90556
  this.reset();
90557
+
89971
90558
  const canvas = this.plugin.viewer.scene.canvas.canvas;
89972
90559
  canvas.removeEventListener("touchstart", this._onCanvasTouchStart);
89973
90560
  canvas.removeEventListener("touchend", this._onCanvasTouchEnd);
89974
- if (this._currentDistanceMeasurement) {
89975
- this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
89976
- this._currentDistanceMeasurement.destroy();
89977
- this._currentDistanceMeasurement = null;
89978
- }
90561
+
89979
90562
  this._active = false;
89980
90563
  this.plugin.viewer.cameraControl.active = true;
89981
90564
  }
@@ -89991,12 +90574,12 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
89991
90574
  if (!this._active) {
89992
90575
  return;
89993
90576
  }
90577
+
89994
90578
  if (this._currentDistanceMeasurement) {
89995
90579
  this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
89996
90580
  this._currentDistanceMeasurement.destroy();
89997
90581
  this._currentDistanceMeasurement = null;
89998
90582
  }
89999
- this._mouseState = WAITING_FOR_ORIGIN_TOUCH_START;
90000
90583
  }
90001
90584
 
90002
90585
  /**
@@ -109082,7 +109665,7 @@ class Viewer {
109082
109665
  * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.
109083
109666
  * @param {Boolean} [cfg.alphaDepthMask=true] Whether writing into the depth buffer is enabled or disabled when rendering transparent objects.
109084
109667
  * @param {Boolean} [cfg.entityOffsetsEnabled=false] Whether to enable {@link Entity#offset}. For best performance, only set this ````true```` when you need to use {@link Entity#offset}.
109085
- * @param {Boolean} [cfg.pickSurfacePrecisionEnabled=false] Whether to enable full-precision accuracy when surface picking with {@link Scene#pick}. Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer. The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.
109668
+ * @param {Boolean} [cfg.readableGeometryEnabled=false] Whether to enable full-precision accuracy when surface picking with {@link Scene#pick}. Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer. The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.
109086
109669
  * @param {Boolean} [cfg.logarithmicDepthBufferEnabled=false] Whether to enable logarithmic depth buffer. When this is true,
109087
109670
  * you can set huge values for {@link Perspective#far} and {@link Ortho#far}, to push the far clipping plane back so
109088
109671
  * that it does not clip huge models.
@@ -109152,7 +109735,7 @@ class Viewer {
109152
109735
  saoEnabled: cfg.saoEnabled,
109153
109736
  alphaDepthMask: (cfg.alphaDepthMask !== false),
109154
109737
  entityOffsetsEnabled: (!!cfg.entityOffsetsEnabled),
109155
- pickSurfacePrecisionEnabled: (!!cfg.pickSurfacePrecisionEnabled),
109738
+ readableGeometryEnabled: (!!cfg.readableGeometryEnabled),
109156
109739
  logarithmicDepthBufferEnabled: (!!cfg.logarithmicDepthBufferEnabled),
109157
109740
  pbrEnabled: (!!cfg.pbrEnabled),
109158
109741
  colorTextureEnabled: (cfg.colorTextureEnabled !== false),
@@ -122938,13 +123521,43 @@ class StoreyViewsPlugin extends Plugin {
122938
123521
  getStoreyContainingWorldPos(worldPos) {
122939
123522
  for (var storeyId in this.storeys) {
122940
123523
  const storey = this.storeys[storeyId];
122941
- if (math.point3AABB3Intersect(storey.storeyAABB, worldPos)) {
123524
+ if (math.point3AABB3AbsoluteIntersect(storey.storeyAABB, worldPos)) {
122942
123525
  return storeyId;
122943
123526
  }
122944
123527
  }
122945
123528
  return null;
122946
123529
  }
122947
123530
 
123531
+ /**
123532
+ * Gets the ID of the storey which's bounding box contains the y point of the world position
123533
+ *
123534
+ * @param {Number[]} worldPos 3D World-space position.
123535
+ * @returns {String} ID of the storey containing the position, or null if the position falls outside all the storeys.
123536
+ */
123537
+ getStoreyInVerticalRange(worldPos) {
123538
+ for(let storeyId in this.storeys) {
123539
+ const storey = this.storeys[storeyId];
123540
+ const aabb = [0,0,0,0,0,0], pos = [0,0,0];
123541
+ aabb[1] = storey.storeyAABB[1];
123542
+ aabb[4] = storey.storeyAABB[4];
123543
+ pos[1] = worldPos[1];
123544
+ if (math.point3AABB3AbsoluteIntersect(aabb, pos)) {
123545
+ return storeyId;
123546
+ }
123547
+ }
123548
+ return null;
123549
+ }
123550
+
123551
+ isPositionAboveOrBelowBuilding(worldPos){
123552
+ const keys = Object.keys(this.storeys);
123553
+ const ids = [keys[0], keys[keys.length-1]];
123554
+ if(worldPos[1] < this.storeys[ids[0]].storeyAABB[1])
123555
+ return ids[0];
123556
+ else if (worldPos[1] > this.storeys[ids[1]].storeyAABB[4])
123557
+ return ids[1];
123558
+ return null;
123559
+ }
123560
+
122948
123561
  /**
122949
123562
  * Converts a 3D World-space position to a 2D position within a StoreyMap image.
122950
123563
  *
@@ -131832,6 +132445,9 @@ class XKTLoaderPlugin extends Plugin {
131832
132445
  this.viewer.scene.canvas.spinner.processes++;
131833
132446
 
131834
132447
  const finish = () => {
132448
+ if (sceneModel.destroyed) {
132449
+ return;
132450
+ }
131835
132451
  // this._createDefaultMetaModelIfNeeded(sceneModel, params, options);
131836
132452
  sceneModel.finalize();
131837
132453
  metaModel.finalize();
@@ -131913,7 +132529,9 @@ class XKTLoaderPlugin extends Plugin {
131913
132529
  const loadJSONs = (metaDataFiles, done, error) => {
131914
132530
  let i = 0;
131915
132531
  const loadNext = () => {
131916
- if (i >= metaDataFiles.length) {
132532
+ if (sceneModel.destroyed) {
132533
+ done();
132534
+ } else if (i >= metaDataFiles.length) {
131917
132535
  done();
131918
132536
  } else {
131919
132537
  this._dataSource.getMetaModel(`${baseDir}${metaDataFiles[i]}`, (metaModelData) => {
@@ -131923,7 +132541,7 @@ class XKTLoaderPlugin extends Plugin {
131923
132541
  globalizeObjectIds: options.globalizeObjectIds
131924
132542
  });
131925
132543
  i++;
131926
- this.scheduleTask(loadNext, 100);
132544
+ this.scheduleTask(loadNext, 200);
131927
132545
  }, error);
131928
132546
  }
131929
132547
  };
@@ -131932,13 +132550,16 @@ class XKTLoaderPlugin extends Plugin {
131932
132550
  const loadXKTs_excludeTheirMetaModels = (xktFiles, done, error) => { // Load XKTs, ignore metamodels in the XKT
131933
132551
  let i = 0;
131934
132552
  const loadNext = () => {
131935
- if (i >= xktFiles.length) {
132553
+ if (sceneModel.destroyed) {
132554
+ done();
132555
+ } else if (i >= xktFiles.length) {
131936
132556
  done();
131937
132557
  } else {
131938
132558
  this._dataSource.getXKT(`${baseDir}${xktFiles[i]}`, (arrayBuffer) => {
131939
132559
  this._parseModel(arrayBuffer, params, options, sceneModel, null /* Ignore metamodel in XKT */, manifestCtx);
132560
+ sceneModel.preFinalize();
131940
132561
  i++;
131941
- this.scheduleTask(loadNext, 100);
132562
+ this.scheduleTask(loadNext, 200);
131942
132563
  }, error);
131943
132564
  }
131944
132565
  };
@@ -131947,13 +132568,16 @@ class XKTLoaderPlugin extends Plugin {
131947
132568
  const loadXKTs_includeTheirMetaModels = (xktFiles, done, error) => { // Load XKTs, parse metamodels from the XKT
131948
132569
  let i = 0;
131949
132570
  const loadNext = () => {
131950
- if (i >= xktFiles.length) {
132571
+ if (sceneModel.destroyed) {
132572
+ done();
132573
+ } else if (i >= xktFiles.length) {
131951
132574
  done();
131952
132575
  } else {
131953
132576
  this._dataSource.getXKT(`${baseDir}${xktFiles[i]}`, (arrayBuffer) => {
131954
132577
  this._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);
132578
+ sceneModel.preFinalize();
131955
132579
  i++;
131956
- this.scheduleTask(loadNext, 100);
132580
+ this.scheduleTask(loadNext, 200);
131957
132581
  }, error);
131958
132582
  }
131959
132583
  };
@@ -132003,11 +132627,12 @@ class XKTLoaderPlugin extends Plugin {
132003
132627
  _loadModel(src, params, options, sceneModel, metaModel, manifestCtx, done, error) {
132004
132628
  this._dataSource.getXKT(params.src, (arrayBuffer) => {
132005
132629
  this._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);
132630
+ sceneModel.preFinalize();
132006
132631
  done();
132007
132632
  }, error);
132008
132633
  }
132009
132634
 
132010
- _parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {
132635
+ async _parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {
132011
132636
  if (sceneModel.destroyed) {
132012
132637
  return;
132013
132638
  }
@@ -132019,7 +132644,7 @@ class XKTLoaderPlugin extends Plugin {
132019
132644
  this.error("Unsupported .XKT file version: " + xktVersion + " - this XKTLoaderPlugin supports versions " + Object.keys(parsers));
132020
132645
  return;
132021
132646
  }
132022
- this.log("Loading .xkt V" + xktVersion);
132647
+ // this.log("Loading .xkt V" + xktVersion);
132023
132648
  const numElements = dataView.getUint32(4, true);
132024
132649
  const elements = [];
132025
132650
  let byteOffset = (numElements + 2) * 4;
@@ -138781,7 +139406,7 @@ const triangulateEarClipping = function(planeCoords) {
138781
139406
  next.prev = ear.prev;
138782
139407
  }
138783
139408
 
138784
- return [ planeCoords, baseTriangles ];
139409
+ return [ planeCoords, baseTriangles, isCCW ];
138785
139410
  };
138786
139411
 
138787
139412
  const marker3D = function(scene, color) {
@@ -139303,7 +139928,7 @@ class Zone extends Component {
139303
139928
  const altitude = this._geometry.altitude + (downward ? this._geometry.height : 0);
139304
139929
  const height = this._geometry.height * (downward ? -1 : 1);
139305
139930
 
139306
- const [ baseVertices, baseTriangles ] = triangulateEarClipping(planeCoords); // TODO: prevent crossing edges
139931
+ const [ baseVertices, baseTriangles, isCCW ] = triangulateEarClipping(planeCoords); // TODO: prevent crossing edges
139307
139932
 
139308
139933
  const pos = [ ];
139309
139934
  const ind = [ ];
@@ -139327,7 +139952,7 @@ class Zone extends Component {
139327
139952
  // sides
139328
139953
  for (let i = 0; i < baseVertices.length; ++i) {
139329
139954
  const a = baseVertices[i];
139330
- const b = baseVertices[(i+1) % baseVertices.length];
139955
+ const b = baseVertices[(baseVertices.length + i + (isCCW ? 1 : -1)) % baseVertices.length];
139331
139956
  const f = altitude;
139332
139957
  const c = altitude + height;
139333
139958
 
@@ -139370,6 +139995,28 @@ class Zone extends Component {
139370
139995
 
139371
139996
  this._zoneMesh.zone = this;
139372
139997
 
139998
+ {
139999
+ const u = math.vec2();
140000
+ const v = math.vec2();
140001
+
140002
+ let baseArea = 0;
140003
+
140004
+ for (let t of baseTriangles) {
140005
+ const p0 = baseVertices[t[0]];
140006
+ const p1 = baseVertices[t[1]];
140007
+ const p2 = baseVertices[t[2]];
140008
+
140009
+ math.subVec2(p1, p0, u);
140010
+ math.subVec2(p2, p0, v);
140011
+
140012
+ baseArea += Math.abs(u[0] * v[1] - u[1] * v[0]);
140013
+ }
140014
+
140015
+ this._baseArea = baseArea / 2;
140016
+ }
140017
+
140018
+ this._metrics = null;
140019
+
139373
140020
 
139374
140021
  const min = idx => Math.min(...pos.map(p => p[idx]));
139375
140022
  const max = idx => Math.max(...pos.map(p => p[idx]));
@@ -139384,6 +140031,48 @@ class Zone extends Component {
139384
140031
  this._center = math.vec3([ (xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2 ]);
139385
140032
  }
139386
140033
 
140034
+ get baseArea() {
140035
+ return this._baseArea;
140036
+ }
140037
+
140038
+ get area() {
140039
+ return this._getMetrics().area;
140040
+ }
140041
+
140042
+ get volume() {
140043
+ return this._getMetrics().volume;
140044
+ }
140045
+
140046
+ _getMetrics() {
140047
+ if (this._metrics === null) {
140048
+ // Sum the volume of tetrahedrons formed by the origin and face triangles
140049
+ let volume = 0;
140050
+ let area = 0;
140051
+ const geo = this._zoneMesh.geometry;
140052
+ const pts = [ math.vec3(), math.vec3(), math.vec3() ];
140053
+ const tmpVec3 = math.vec3();
140054
+ for (let i = 0; i < geo.indices.length; i += 3) {
140055
+ for (let off = 0; off < 3; ++off) {
140056
+ const p = pts[off];
140057
+ const pIdx = 3 * geo.indices[i + off];
140058
+ for (let c = 0; c < 3; ++c) {
140059
+ p[c] = geo.positions[pIdx + c];
140060
+ }
140061
+ }
140062
+ volume += math.dotVec3(pts[0], math.cross3Vec3(pts[1], pts[2], tmpVec3));
140063
+ math.subVec3(pts[1], pts[0], pts[1]);
140064
+ math.subVec3(pts[2], pts[0], pts[2]);
140065
+ area += math.lenVec3(math.cross3Vec3(pts[1], pts[2], tmpVec3));
140066
+ }
140067
+
140068
+ this._metrics = {
140069
+ area: area / 2,
140070
+ volume: volume / 6
140071
+ };
140072
+ }
140073
+ return this._metrics;
140074
+ }
140075
+
139387
140076
  sectionedAverage(sectionPlanes) {
139388
140077
  const planeCoords = this._geometry.planeCoordinates.slice();
139389
140078
 
@@ -140512,4 +141201,4 @@ class ZoneTranslateTouchControl extends ZoneTranslateControl {
140512
141201
  }
140513
141202
  }
140514
141203
 
140515
- export { AlphaFormat, AmbientLight, AngleMeasurementEditMouseControl, AngleMeasurementEditTouchControl, AngleMeasurementsControl, AngleMeasurementsMouseControl, AngleMeasurementsPlugin, AngleMeasurementsTouchControl, AnnotationsPlugin, AxisGizmoPlugin, BCFViewpointsPlugin, Bitmap, ByteType, CameraMemento, CameraPath, CameraPathAnimation, CityJSONLoaderPlugin, ClampToEdgeWrapping, Component, CompressedMediaType, Configs, ContextMenu, CubicBezierCurve, Curve, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DirLight, DistanceMeasurementEditMouseControl, DistanceMeasurementEditTouchControl, DistanceMeasurementsControl, DistanceMeasurementsMouseControl, DistanceMeasurementsPlugin, DistanceMeasurementsTouchControl, DotBIMDefaultDataSource, DotBIMLoaderPlugin, EdgeMaterial, EmphasisMaterial, FaceAlignedSectionPlanesPlugin, FastNavPlugin, FloatType, Fresnel, Frustum$1 as Frustum, FrustumPlane, GIFMediaType, GLTFDefaultDataSource, GLTFLoaderPlugin, HalfFloatType, ImagePlane, IntType, JPEGMediaType, KTX2TextureTranscoder, LASLoaderPlugin, LambertMaterial, LightMap, LineSet, LinearEncoding, LinearFilter, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, Loader, LoadingManager, LocaleService, LuminanceAlphaFormat, LuminanceFormat, Map$1 as Map, Marker, MarqueePicker, MarqueePickerMouseControl, Mesh, MetallicMaterial, MirroredRepeatWrapping, ModelMemento, NavCubePlugin, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, Node$2 as Node, OBJLoaderPlugin, ObjectsKdTree3, ObjectsMemento, PNGMediaType, Path, PerformanceModel, PhongMaterial, PickResult, Plugin, PointLight, PointerCircle, PointerLens, QuadraticBezierCurve, Queue, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, ReadableGeometry, RedFormat, RedIntegerFormat, ReflectionMap, RepeatWrapping, STLDefaultDataSource, STLLoaderPlugin, SceneModel, SceneModelMesh, SceneModelTransform, SectionPlane, SectionPlanesPlugin, ShortType, Skybox, SkyboxesPlugin, SpecularMaterial, SplineCurve, SpriteMarker, StoreyViewsPlugin, Texture, TextureTranscoder, TreeViewPlugin, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VBOGeometry, ViewCullPlugin, Viewer, WebIFCLoaderPlugin, WorkerPool$1 as WorkerPool, XKTDefaultDataSource, XKTLoaderPlugin, XML3DLoaderPlugin, ZoneEditControl, ZoneEditMouseControl, ZoneEditTouchControl, ZoneTranslateControl, ZoneTranslateMouseControl, ZoneTranslateTouchControl, ZonesMouseControl, ZonesPlugin, ZonesPolysurfaceMouseControl, ZonesPolysurfaceTouchControl, ZonesTouchControl, buildBoxGeometry, buildBoxLinesGeometry, buildBoxLinesGeometryFromAABB, buildCylinderGeometry, buildGridGeometry, buildLineGeometry, buildPlaneGeometry, buildPolylineGeometry, buildPolylineGeometryFromCurve, buildSphereGeometry, buildTorusGeometry, buildVectorTextGeometry, createRTCViewMat, frustumIntersectsAABB3, getKTX2TextureTranscoder, getPlaneRTCPos, load3DSGeometry, loadOBJGeometry, math, rtcToWorldPos, sRGBEncoding, setFrustum, stats, utils, worldToRTCPos, worldToRTCPositions };
141204
+ export { AlphaFormat, AmbientLight, AngleMeasurementEditMouseControl, AngleMeasurementEditTouchControl, AngleMeasurementsControl, AngleMeasurementsMouseControl, AngleMeasurementsPlugin, AngleMeasurementsTouchControl, AnnotationsPlugin, AxisGizmoPlugin, BCFViewpointsPlugin, Bitmap, ByteType, CameraMemento, CameraPath, CameraPathAnimation, CityJSONLoaderPlugin, ClampToEdgeWrapping, Component, CompressedMediaType, Configs, ContextMenu, CubicBezierCurve, Curve, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DirLight, DistanceMeasurementEditControl, DistanceMeasurementEditMouseControl, DistanceMeasurementEditTouchControl, DistanceMeasurementsControl, DistanceMeasurementsMouseControl, DistanceMeasurementsPlugin, DistanceMeasurementsTouchControl, DotBIMDefaultDataSource, DotBIMLoaderPlugin, EdgeMaterial, EmphasisMaterial, FaceAlignedSectionPlanesPlugin, FastNavPlugin, FloatType, Fresnel, Frustum$1 as Frustum, FrustumPlane, GIFMediaType, GLTFDefaultDataSource, GLTFLoaderPlugin, HalfFloatType, ImagePlane, IntType, JPEGMediaType, KTX2TextureTranscoder, LASLoaderPlugin, LambertMaterial, LightMap, LineSet, LinearEncoding, LinearFilter, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, Loader, LoadingManager, LocaleService, LuminanceAlphaFormat, LuminanceFormat, Map$1 as Map, Marker, MarqueePicker, MarqueePickerMouseControl, Mesh, MeshSurfaceArea, MeshVolume, MetallicMaterial, MirroredRepeatWrapping, ModelMemento, NavCubePlugin, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, Node$2 as Node, OBJLoaderPlugin, ObjectsKdTree3, ObjectsMemento, PNGMediaType, Path, PerformanceModel, PhongMaterial, PickResult, Plugin, PointLight, PointerCircle, PointerLens, QuadraticBezierCurve, Queue, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, ReadableGeometry, RedFormat, RedIntegerFormat, ReflectionMap, RepeatWrapping, STLDefaultDataSource, STLLoaderPlugin, SceneModel, SceneModelMesh, SceneModelTransform, SectionPlane, SectionPlanesPlugin, ShortType, Skybox, SkyboxesPlugin, SpecularMaterial, SplineCurve, SpriteMarker, StoreyViewsPlugin, Texture, TextureTranscoder, TreeViewPlugin, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VBOGeometry, ViewCullPlugin, Viewer, WebIFCLoaderPlugin, WorkerPool$1 as WorkerPool, XKTDefaultDataSource, XKTLoaderPlugin, XML3DLoaderPlugin, ZoneEditControl, ZoneEditMouseControl, ZoneEditTouchControl, ZoneTranslateControl, ZoneTranslateMouseControl, ZoneTranslateTouchControl, ZonesMouseControl, ZonesPlugin, ZonesPolysurfaceMouseControl, ZonesPolysurfaceTouchControl, ZonesTouchControl, buildBoxGeometry, buildBoxLinesGeometry, buildBoxLinesGeometryFromAABB, buildCylinderGeometry, buildGridGeometry, buildLineGeometry, buildPlaneGeometry, buildPolylineGeometry, buildPolylineGeometryFromCurve, buildSphereGeometry, buildTorusGeometry, buildVectorTextGeometry, createRTCViewMat, frustumIntersectsAABB3, getKTX2TextureTranscoder, getPlaneRTCPos, isTriangleMeshSolid, load3DSGeometry, loadOBJGeometry, math, meshSurfaceArea, meshVolume, rtcToWorldPos, sRGBEncoding, setFrustum, stats, utils, worldToRTCPos, worldToRTCPositions };