@xeokit/xeokit-sdk 2.6.28 → 2.6.30

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 (58) hide show
  1. package/README.md +1 -0
  2. package/dist/xeokit-sdk.cjs.js +1425 -649
  3. package/dist/xeokit-sdk.es.js +1420 -650
  4. package/dist/xeokit-sdk.es5.js +629 -552
  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/GLTFLoaderPlugin/GLTFLoaderPlugin.js +2 -110
  16. package/src/plugins/GLTFLoaderPlugin/GLTFSceneModelLoader.js +252 -222
  17. package/src/plugins/StoreyViewsPlugin/StoreyViewsPlugin.js +31 -1
  18. package/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js +20 -8
  19. package/src/plugins/ZonesPlugin/ZonesPlugin.js +1939 -0
  20. package/src/plugins/ZonesPlugin/index.js +1 -1875
  21. package/src/viewer/Viewer.js +2 -2
  22. package/src/viewer/metadata/MetaScene.js +0 -2
  23. package/src/viewer/scene/math/MeshSurfaceArea.js +90 -0
  24. package/src/viewer/scene/math/MeshVolume.js +102 -0
  25. package/src/viewer/scene/math/index.js +3 -0
  26. package/src/viewer/scene/math/isTriangleMeshSolid.js +162 -0
  27. package/src/viewer/scene/math/math.js +8 -0
  28. package/src/viewer/scene/model/SceneModel.js +73 -34
  29. package/src/viewer/scene/model/SceneModelEntity.js +46 -1
  30. package/src/viewer/scene/model/SceneModelMesh.js +74 -1
  31. package/src/viewer/scene/model/SceneModelTextureSet.js +5 -0
  32. package/src/viewer/scene/model/dtx/lines/DTXLinesLayer.js +7 -1
  33. package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +77 -1
  34. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapInitRenderer.js +8 -0
  35. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesSnapRenderer.js +8 -0
  36. package/src/viewer/scene/model/vbo/VBORenderer.js +10 -1
  37. package/src/viewer/scene/model/vbo/batching/lines/VBOBatchingLinesLayer.js +6 -1
  38. package/src/viewer/scene/model/vbo/batching/lines/renderers/VBOBatchingLinesSnapRenderer.js +1 -1
  39. package/src/viewer/scene/model/vbo/batching/points/VBOBatchingPointsLayer.js +6 -1
  40. package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesLayer.js +59 -18
  41. package/src/viewer/scene/model/vbo/batching/triangles/renderers/Renderers.js +40 -12
  42. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesBatchingRenderer.js +2 -3
  43. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorTextureRenderer.js +25 -7
  44. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesSnapRenderer.js +1 -1
  45. package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +6 -1
  46. package/src/viewer/scene/model/vbo/instancing/lines/renderers/VBOInstancingLinesSnapRenderer.js +1 -1
  47. package/src/viewer/scene/model/vbo/instancing/points/VBOInstancingPointsLayer.js +6 -1
  48. package/src/viewer/scene/model/vbo/instancing/triangles/VBOInstancingTrianglesLayer.js +48 -14
  49. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/Renderers.js +74 -47
  50. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorTextureRenderer.js +29 -14
  51. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesInstancingRenderer.js +5 -4
  52. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesSnapRenderer.js +1 -1
  53. package/src/viewer/scene/scene/Scene.js +16 -5
  54. package/src/viewer/scene/webgl/occlusion/OcclusionLayer.js +1 -1
  55. package/src/viewer/scene/webgl/occlusion/OcclusionTester.js +1 -5
  56. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.d.ts +7 -0
  57. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsPlugin.d.ts +26 -1
  58. package/types/plugins/DistanceMeasurementsPlugin/index.d.ts +3 -1
@@ -5284,6 +5284,14 @@ const math = {
5284
5284
  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];
5285
5285
  },
5286
5286
 
5287
+ point3AABB3AbsoluteIntersect(aabb, p) {
5288
+ return (
5289
+ aabb[0] <= p[0] && aabb[3] >= p[0] &&
5290
+ aabb[1] <= p[1] && aabb[4] >= p[1] &&
5291
+ aabb[2] <= p[2] && aabb[5] >= p[2]
5292
+ );
5293
+ },
5294
+
5287
5295
  /**
5288
5296
  *
5289
5297
  * @param dir
@@ -9289,7 +9297,7 @@ class PointerCircle {
9289
9297
  destroy() {
9290
9298
  if (!this._destroyed) {
9291
9299
  this.stop();
9292
- document.body.removeChild(this._circleDiv);
9300
+ this._circleDiv.parentElement.removeChild(this._circleDiv);
9293
9301
  this._destroyed = true;
9294
9302
  }
9295
9303
  }
@@ -10545,7 +10553,7 @@ class SceneModelEntity {
10545
10553
  for (let i = 0, len = this.meshes.length; i < len; i++) {
10546
10554
  this.meshes[i]._setOffset(this._offset);
10547
10555
  }
10548
- this._aabbDirty = true;
10556
+ this._aabbDirty = true;
10549
10557
  this.model._aabbDirty = true;
10550
10558
  this.scene._aabbDirty = true;
10551
10559
  this.scene._objectOffsetUpdated(this, offset);
@@ -10562,6 +10570,51 @@ class SceneModelEntity {
10562
10570
  }
10563
10571
  }
10564
10572
 
10573
+ getEachIndex(callback) {
10574
+ for (let i = 0, len = this.meshes.length; i < len; i++) {
10575
+ this.meshes[i].getEachIndex(callback);
10576
+ }
10577
+ }
10578
+
10579
+ /**
10580
+ * Returns the volume of this SceneModelEntity.
10581
+ *
10582
+ * Only works when {@link Scene.readableGeometryEnabled | Scene.readableGeometryEnabled} is `true` and the
10583
+ * SceneModelEntity contains solid triangle meshes; returns `0` otherwise.
10584
+ *
10585
+ * @returns {number}
10586
+ */
10587
+ get volume() {
10588
+ let volume = 0;
10589
+ for (let i = 0, len = this.meshes.length; i < len; i++) {
10590
+ const meshVolume = this.meshes[i].volume;
10591
+ if (meshVolume < 0) {
10592
+ return -1;
10593
+ }
10594
+ volume += meshVolume;
10595
+ }
10596
+ return volume;
10597
+ }
10598
+
10599
+ /**
10600
+ * Returns the surface area of this SceneModelEntity.
10601
+ *
10602
+ * Only works when {@link Scene.readableGeometryEnabled | Scene.readableGeometryEnabled} is `true` and the
10603
+ * SceneModelEntity contains triangle meshes; returns `0` otherwise.
10604
+ *
10605
+ * @returns {number}
10606
+ */
10607
+ get surfaceArea() {
10608
+ let surfaceArea = 0;
10609
+ for (let i = 0, len = this.meshes.length; i < len; i++) {
10610
+ const meshSurfaceArea = this.meshes[i].surfaceArea;
10611
+ if (meshSurfaceArea >= 0) {
10612
+ surfaceArea += meshSurfaceArea;
10613
+ }
10614
+ }
10615
+ return surfaceArea > 0 ? surfaceArea : -1;
10616
+ }
10617
+
10565
10618
  _getFlag(flag) {
10566
10619
  return !!(this._flags & flag);
10567
10620
  }
@@ -10626,7 +10679,7 @@ class SceneModelEntity {
10626
10679
  }
10627
10680
  }
10628
10681
 
10629
- const tempVec4a$9 = math.vec4();
10682
+ const tempVec4a$a = math.vec4();
10630
10683
  const tempVec4b$6 = math.vec4();
10631
10684
 
10632
10685
 
@@ -10786,9 +10839,9 @@ class Marker extends Component {
10786
10839
  this.fire("viewPos", this._viewPos);
10787
10840
  }
10788
10841
  if (this._canvasPosDirty) {
10789
- tempVec4a$9.set(this._viewPos);
10790
- tempVec4a$9[3] = 1.0;
10791
- math.transformPoint4(this.scene.camera.projMatrix, tempVec4a$9, tempVec4b$6);
10842
+ tempVec4a$a.set(this._viewPos);
10843
+ tempVec4a$a[3] = 1.0;
10844
+ math.transformPoint4(this.scene.camera.projMatrix, tempVec4a$a, tempVec4b$6);
10792
10845
  const aabb = this.scene.canvas.boundary;
10793
10846
  this._canvasPos[0] = Math.floor((1 + tempVec4b$6[0] / tempVec4b$6[3]) * aabb[2] / 2);
10794
10847
  this._canvasPos[1] = Math.floor((1 - tempVec4b$6[1] / tempVec4b$6[3]) * aabb[3] / 2);
@@ -12618,22 +12671,13 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12618
12671
  this.pointerLens = cfg.pointerLens;
12619
12672
 
12620
12673
  this._active = false;
12621
- this._mouseState = MOUSE_FINDING_ORIGIN;
12622
12674
 
12623
12675
  this._currentAngleMeasurement = null;
12624
12676
 
12625
- // init markerDiv element (think about making its style configurable)
12626
12677
  this._initMarkerDiv();
12627
12678
 
12628
- this._onMouseHoverSurface = null;
12629
- this._onHoverNothing = null;
12630
- this._onPickedNothing = null;
12631
- this._onPickedSurface = null;
12632
-
12633
- this._onInputMouseDown = null;
12634
- this._onInputMouseUp = null;
12635
-
12636
12679
  this._snapping = cfg.snapping !== false;
12680
+ this._mouseState = MOUSE_FINDING_ORIGIN;
12637
12681
 
12638
12682
  this._attachPlugin(angleMeasurementsPlugin, cfg);
12639
12683
  }
@@ -12698,20 +12742,10 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12698
12742
  *
12699
12743
  * This is `true` by default.
12700
12744
  *
12701
- * Internally, this deactivates then activates the AngleMeasurementsMouseControl when changed, which means that
12702
- * it will destroy any AngleMeasurements currently under construction, and incurs some overhead, since it unbinds
12703
- * and rebinds various input handlers.
12704
- *
12705
12745
  * @param {boolean} snapping Whether to enable snap-to-vertex and snap-edge for this AngleMeasurementsMouseControl.
12706
12746
  */
12707
12747
  set snapping(snapping) {
12708
- if (snapping !== this._snapping) {
12709
- this._snapping = snapping;
12710
- this.deactivate();
12711
- this.activate();
12712
- } else {
12713
- this._snapping = snapping;
12714
- }
12748
+ this._snapping = snapping;
12715
12749
  }
12716
12750
 
12717
12751
  /**
@@ -12755,11 +12789,7 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12755
12789
 
12756
12790
  const pagePos = math.vec2();
12757
12791
 
12758
- this._onMouseHoverSurface = cameraControl.on(
12759
- this._snapping
12760
- ? "hoverSnapOrSurface"
12761
- : "hoverSurface",
12762
- event => {
12792
+ const hoverOn = event => {
12763
12793
  if (event.snappedToVertex || event.snappedToEdge) {
12764
12794
  if (pointerLens) {
12765
12795
  pointerLens.visible = true;
@@ -12821,7 +12851,10 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12821
12851
  canvas.style.cursor = "pointer";
12822
12852
  break;
12823
12853
  }
12824
- });
12854
+ };
12855
+ this._onHoverSnapOrSurface = cameraControl.on("hoverSnapOrSurface", e => { if (this._snapping) hoverOn(e); });
12856
+ this._onHoverSurface = cameraControl.on("hoverSurface", e => { if (! this._snapping) hoverOn(e); });
12857
+
12825
12858
  canvas.addEventListener('mousedown', this._onMouseDown = (e) => {
12826
12859
  if (e.which !== 1) {
12827
12860
  return;
@@ -12909,11 +12942,8 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12909
12942
  break;
12910
12943
  }
12911
12944
  });
12912
- this._onMouseHoverOff = cameraControl.on(
12913
- this._snapping
12914
- ? "hoverSnapOrSurfaceOff"
12915
- : "hoverOff",
12916
- event => {
12945
+
12946
+ const hoverOff = event => {
12917
12947
  mouseHovering = false;
12918
12948
  if (pointerLens) {
12919
12949
  pointerLens.visible = true;
@@ -12943,7 +12973,10 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12943
12973
  }
12944
12974
  canvas.style.cursor = "default";
12945
12975
  }
12946
- });
12976
+ };
12977
+ this._onHoverSnapOrSurfaceOff = cameraControl.on("hoverSnapOrSurfaceOff", e => { if (this._snapping) hoverOff(e); });
12978
+ this._onHoverOff = cameraControl.on("hoverOff", e => { if (! this._snapping) hoverOff(e); });
12979
+
12947
12980
  this._active = true;
12948
12981
  }
12949
12982
 
@@ -12956,22 +12989,22 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12956
12989
  if (!this._active) {
12957
12990
  return;
12958
12991
  }
12992
+
12959
12993
  if (this.pointerLens) {
12960
12994
  this.pointerLens.visible = false;
12961
12995
  }
12962
- if (this.markerDiv) {
12963
- this._destroyMarkerDiv();
12964
- }
12996
+
12965
12997
  this.reset();
12998
+
12966
12999
  const canvas = this.scene.canvas.canvas;
12967
13000
  canvas.removeEventListener("mousedown", this._onMouseDown);
12968
13001
  canvas.removeEventListener("mouseup", this._onMouseUp);
12969
13002
  const cameraControl = this.angleMeasurementsPlugin.viewer.cameraControl;
12970
- cameraControl.off(this._onMouseHoverSurface);
12971
- cameraControl.off(this._onPickedSurface);
12972
- cameraControl.off(this._onHoverNothing);
12973
- cameraControl.off(this._onPickedNothing);
12974
- this._currentAngleMeasurement = null;
13003
+ cameraControl.off(this._onHoverSnapOrSurface);
13004
+ cameraControl.off(this._onHoverSurface);
13005
+ cameraControl.off(this._onHoverSnapOrSurfaceOff);
13006
+ cameraControl.off(this._onHoverOff);
13007
+
12975
13008
  this._active = false;
12976
13009
  }
12977
13010
 
@@ -12994,6 +13027,7 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12994
13027
  this._currentAngleMeasurement.destroy();
12995
13028
  this._currentAngleMeasurement = null;
12996
13029
  }
13030
+
12997
13031
  this._mouseState = MOUSE_FINDING_ORIGIN;
12998
13032
  }
12999
13033
 
@@ -13509,8 +13543,6 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13509
13543
 
13510
13544
  this._currentAngleMeasurement = null;
13511
13545
 
13512
- this._onCanvasTouchStart = null;
13513
- this._onCanvasTouchEnd = null;
13514
13546
  this._longTouchTimeoutMs = 300;
13515
13547
  this._snapping = cfg.snapping !== false;
13516
13548
  this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
@@ -13546,20 +13578,10 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13546
13578
  *
13547
13579
  * This is `true` by default.
13548
13580
  *
13549
- * Internally, this deactivates then activates the AngleMeasurementsMouseControl when changed, which means that
13550
- * it will destroy any AngleMeasurements currently under construction, and incurs some overhead, since it unbinds
13551
- * and rebinds various input handlers.
13552
- *
13553
13581
  * @param {boolean} snapping Whether to enable snap-to-vertex and snap-edge for this AngleMeasurementsMouseControl.
13554
13582
  */
13555
13583
  set snapping(snapping) {
13556
- if (snapping !== this._snapping) {
13557
- this._snapping = snapping;
13558
- this.deactivate();
13559
- this.activate();
13560
- } else {
13561
- this._snapping = snapping;
13562
- }
13584
+ this._snapping = snapping;
13563
13585
  }
13564
13586
 
13565
13587
  /**
@@ -14329,14 +14351,11 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14329
14351
  this.plugin.pointerLens.visible = false;
14330
14352
  }
14331
14353
  this.reset();
14354
+
14332
14355
  const canvas = this.plugin.viewer.scene.canvas.canvas;
14333
14356
  canvas.removeEventListener("touchstart", this._onCanvasTouchStart);
14334
14357
  canvas.removeEventListener("touchend", this._onCanvasTouchEnd);
14335
- if (this._currentAngleMeasurement) {
14336
- this.angleMeasurementsPlugin.fire("measurementCancel", this._currentAngleMeasurement);
14337
- this._currentAngleMeasurement.destroy();
14338
- this._currentAngleMeasurement = null;
14339
- }
14358
+
14340
14359
  this._active = false;
14341
14360
  this.plugin.viewer.cameraControl.active = true;
14342
14361
  }
@@ -17452,7 +17471,7 @@ class OcclusionLayer {
17452
17471
  for (let i = 0; i < this.numMarkers; i++) {
17453
17472
  if (this.markerList[i]) {
17454
17473
  const marker = this.markerList[i];
17455
- const worldPos = marker.worldPos;
17474
+ const worldPos = marker.rtcPos;
17456
17475
  this.positions[j++] = worldPos[0];
17457
17476
  this.positions[j++] = worldPos[1];
17458
17477
  this.positions[j++] = worldPos[2];
@@ -17894,10 +17913,7 @@ class OcclusionTester {
17894
17913
  continue;
17895
17914
  }
17896
17915
 
17897
- // The `origin` has been changed from `occlusionLayer.origin` to `[ 0, 0, 0 ]`
17898
- // because OcclusionLayer markers' transformation is being applied through the
17899
- // OcclusionLayer::positions array. See XEOK-33
17900
- const origin = [ 0, 0, 0 ];
17916
+ const origin = occlusionLayer.origin;
17901
17917
 
17902
17918
  gl.uniformMatrix4fv(this._uViewMatrix, false, createRTCViewMat(camera.viewMatrix, origin));
17903
17919
 
@@ -23519,7 +23535,7 @@ const tempVec3c$u = math.vec3();
23519
23535
  const tempVec3d$d = math.vec3();
23520
23536
  const tempVec3e$2 = math.vec3();
23521
23537
  const tempVec3f$2 = math.vec3();
23522
- const tempVec4a$8 = math.vec4();
23538
+ const tempVec4a$9 = math.vec4();
23523
23539
  const tempVec4b$5 = math.vec4();
23524
23540
  const tempVec4c$2 = math.vec4();
23525
23541
  const tempMat = math.mat4();
@@ -24385,7 +24401,7 @@ class Camera extends Component {
24385
24401
  * @returns {[number, number]} the canvas position
24386
24402
  */
24387
24403
  projectWorldPos(worldPos) {
24388
- const _worldPos = tempVec4a$8;
24404
+ const _worldPos = tempVec4a$9;
24389
24405
  const viewPos = tempVec4b$5;
24390
24406
  const screenPos = tempVec4c$2;
24391
24407
  _worldPos[0] = worldPos[0];
@@ -30140,6 +30156,8 @@ class Scene extends Component {
30140
30156
 
30141
30157
  this._aabbDirty = true;
30142
30158
 
30159
+ this._readableGeometry = !!cfg.readableGeometryEnabled;
30160
+
30143
30161
  /**
30144
30162
  * The {@link Viewer} this Scene belongs to.
30145
30163
  * @type {Viewer}
@@ -31019,18 +31037,27 @@ class Scene extends Component {
31019
31037
  }
31020
31038
 
31021
31039
  /**
31022
- * Whether precision surface picking is enabled.
31040
+ * Whether geometry is readable.
31023
31041
  *
31024
31042
  * This is set via the {@link Viewer} constructor and is ````false```` by default.
31025
31043
  *
31026
- * The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.
31044
+ * The ````readableGeometryEnabled```` option for ````Scene#pick```` only works if this is set ````true````.
31027
31045
  *
31028
31046
  * Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer.
31029
31047
  *
31030
- * @returns {Boolean} True if precision picking is enabled.
31048
+ * @returns {Boolean} True if geometry is readable.
31049
+ */
31050
+ get readableGeometryEnabled() {
31051
+ return this._readableGeometry;
31052
+ }
31053
+
31054
+ /**
31055
+ * Whether precision surface picking is enabled.
31056
+ * @deprecated
31057
+ * @returns {*|boolean}
31031
31058
  */
31032
31059
  get pickSurfacePrecisionEnabled() {
31033
- return false; // Removed
31060
+ return this._readableGeometry;
31034
31061
  }
31035
31062
 
31036
31063
  /**
@@ -32008,7 +32035,7 @@ class Scene extends Component {
32008
32035
  *
32009
32036
  * @param {*} params Picking parameters.
32010
32037
  * @param {Boolean} [params.pickSurface=false] Whether to find the picked position on the surface of the Entity.
32011
- * @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.
32038
+ * @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.
32012
32039
  * @param {Boolean} [params.pickSurfaceNormal=false] Whether to find the picked normal on the surface of the Entity. Only works if ````pickSurface```` is given.
32013
32040
  * @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.
32014
32041
  * @param {Number[]} [params.origin] World-space ray origin when ray-picking. Ignored when canvasPos given.
@@ -50608,10 +50635,360 @@ class Bitmap extends Component {
50608
50635
  }
50609
50636
  }
50610
50637
 
50638
+ /**
50639
+ * Uses edge adjacency counts to identify if the given triangle mesh can be rendered with backface culling enabled.
50640
+ *
50641
+ * If all edges are connected to exactly two triangles, then the mesh will likely be a closed solid, and we can safely
50642
+ * render it with backface culling enabled.
50643
+ *
50644
+ * Otherwise, the mesh is a surface, and we must render it with backface culling disabled.
50645
+ *
50646
+ * @private
50647
+ */
50648
+ const isTriangleMeshSolid = (indices, positions) => {
50649
+
50650
+ const vertexIndexMapping = [];
50651
+ let edges = [];
50652
+
50653
+ function compareIndexPositions(a, b) {
50654
+ let posA, posB;
50655
+
50656
+ for (let i = 0; i < 3; i++) {
50657
+ posA = positions [a * 3 + i];
50658
+ posB = positions [b * 3 + i];
50659
+
50660
+ if (posA !== posB) {
50661
+ return posB - posA;
50662
+ }
50663
+ }
50664
+
50665
+ return 0;
50666
+ }
50667
+ // Group together indices corresponding to same position coordinates
50668
+ let newIndices = indices.slice().sort(compareIndexPositions);
50669
+
50670
+ // Calculate the mapping:
50671
+ // - from original index in indices array
50672
+ // - to indices-for-unique-positions
50673
+ let uniqueVertexIndex = null;
50674
+
50675
+ for (let i = 0, len = newIndices.length; i < len; i++) {
50676
+ if (i === 0 || 0 !== compareIndexPositions(
50677
+ newIndices[i],
50678
+ newIndices[i - 1],
50679
+ )) {
50680
+ // different position
50681
+ uniqueVertexIndex = newIndices [i];
50682
+ }
50683
+
50684
+ vertexIndexMapping [
50685
+ newIndices[i]
50686
+ ] = uniqueVertexIndex;
50687
+ }
50688
+
50689
+ // Generate the list of edges
50690
+ for (let i = 0, len = indices.length; i < len; i += 3) {
50691
+
50692
+ const a = vertexIndexMapping[indices[i]];
50693
+ const b = vertexIndexMapping[indices[i + 1]];
50694
+ const c = vertexIndexMapping[indices[i + 2]];
50695
+
50696
+ let a2 = a;
50697
+ let b2 = b;
50698
+ let c2 = c;
50699
+
50700
+ if (a > b && a > c) {
50701
+ if (b > c) {
50702
+ a2 = a;
50703
+ b2 = b;
50704
+ c2 = c;
50705
+ } else {
50706
+ a2 = a;
50707
+ b2 = c;
50708
+ c2 = b;
50709
+ }
50710
+ } else if (b > a && b > c) {
50711
+ if (a > c) {
50712
+ a2 = b;
50713
+ b2 = a;
50714
+ c2 = c;
50715
+ } else {
50716
+ a2 = b;
50717
+ b2 = c;
50718
+ c2 = a;
50719
+ }
50720
+ } else if (c > a && c > b) {
50721
+ if (a > b) {
50722
+ a2 = c;
50723
+ b2 = a;
50724
+ c2 = b;
50725
+ } else {
50726
+ a2 = c;
50727
+ b2 = b;
50728
+ c2 = a;
50729
+ }
50730
+ }
50731
+
50732
+ edges[i + 0] = [
50733
+ a2, b2
50734
+ ];
50735
+ edges[i + 1] = [
50736
+ b2, c2
50737
+ ];
50738
+
50739
+ if (a2 > c2) {
50740
+ const temp = c2;
50741
+ c2 = a2;
50742
+ a2 = temp;
50743
+ }
50744
+
50745
+ edges[i + 2] = [
50746
+ c2, a2
50747
+ ];
50748
+ }
50749
+
50750
+ // Group semantically equivalent edgdes together
50751
+ function compareEdges(e1, e2) {
50752
+ let a, b;
50753
+
50754
+ for (let i = 0; i < 2; i++) {
50755
+ a = e1[i];
50756
+ b = e2[i];
50757
+
50758
+ if (b !== a) {
50759
+ return b - a;
50760
+ }
50761
+ }
50762
+
50763
+ return 0;
50764
+ }
50765
+
50766
+ edges = edges.slice(0, indices.length);
50767
+
50768
+ edges.sort(compareEdges);
50769
+
50770
+ // Make sure each edge is used exactly twice
50771
+ let sameEdgeCount = 0;
50772
+
50773
+ for (let i = 0; i < edges.length; i++) {
50774
+ if (i === 0 || 0 !== compareEdges(
50775
+ edges[i], edges[i - 1]
50776
+ )) {
50777
+ // different edge
50778
+ if (0 !== i && sameEdgeCount !== 2) {
50779
+ return false;
50780
+ }
50781
+
50782
+ sameEdgeCount = 1;
50783
+ } else {
50784
+ // same edge
50785
+ sameEdgeCount++;
50786
+ }
50787
+ }
50788
+
50789
+ if (edges.length > 0 && sameEdgeCount !== 2) {
50790
+ return false;
50791
+ }
50792
+
50793
+ // Each edge is used exactly twice, this is a
50794
+ // watertight surface and hence a solid geometry.
50795
+ return true;
50796
+ };
50797
+
50798
+ const v1$1 = math.vec3();
50799
+ const v2$1 = math.vec3();
50800
+ const v3$1 = math.vec3();
50801
+
50802
+ /**
50803
+ * Calculates the volume of triangle meshes.
50804
+ */
50805
+ class MeshVolume {
50806
+ constructor() {
50807
+ this.vertices = [];
50808
+ this.indices = [];
50809
+ this.reset();
50810
+ }
50811
+
50812
+ /**
50813
+ * Resets, ready to add vertices and indices for a new mesh.
50814
+ */
50815
+ reset() {
50816
+ this.lenVertices = 0;
50817
+ this.lenIndices = 0;
50818
+ this.primitive = null;
50819
+ }
50820
+
50821
+ setPrimitive(primitive) {
50822
+ this.primitive = primitive;
50823
+ }
50824
+
50825
+ /**
50826
+ * Adds a vertex.
50827
+ * @param vertex
50828
+ */
50829
+ addVertex(vertex) {
50830
+ this.vertices[this.lenVertices++] = vertex[0];
50831
+ this.vertices[this.lenVertices++] = vertex[1];
50832
+ this.vertices[this.lenVertices++] = vertex[2];
50833
+ }
50834
+
50835
+ /**
50836
+ * Adds an index.
50837
+ * @param index
50838
+ */
50839
+ addIndex(index) {
50840
+ this.indices[this.lenIndices++] = index;
50841
+ }
50842
+
50843
+ /**
50844
+ * Gets the volume of the mesh.
50845
+ *
50846
+ * The mesh must be a closed solid.
50847
+ *
50848
+ * @returns {number} The volume of the mesh, or -1 if the mesh is not solid, in which case volume cannot be determined.
50849
+ */
50850
+ get volume() {
50851
+
50852
+ const vertices = this.vertices;
50853
+ const indices = this.indices;
50854
+
50855
+ if (this.primitive !== "solid" && this.primitive !== "surface" && this.primitive !== "triangles") {
50856
+ return -1;
50857
+ }
50858
+
50859
+ if (this.primitive !== "solid" && !isTriangleMeshSolid(indices, vertices)) {
50860
+ return -1;
50861
+ }
50862
+
50863
+ let volume = 0;
50864
+
50865
+ for (let i = 0; i < this.lenIndices; i += 3) {
50866
+
50867
+ const index1 = indices[i] * 3;
50868
+ const index2 = indices[i + 1] * 3;
50869
+ const index3 = indices[i + 2] * 3;
50870
+
50871
+ v1$1[0] = vertices[index1];
50872
+ v1$1[1] = vertices[index1 + 1];
50873
+ v1$1[2] = vertices[index1 + 2];
50874
+
50875
+ v2$1[0] = vertices[index2];
50876
+ v2$1[1] = vertices[index2 + 1];
50877
+ v2$1[2] = vertices[index2 + 2];
50878
+
50879
+ v3$1[0] = vertices[index3];
50880
+ v3$1[1] = vertices[index3 + 1];
50881
+ v3$1[2] = vertices[index3 + 2];
50882
+
50883
+ math.cross3Vec3(v1$1, v2$1, v1$1);
50884
+
50885
+ volume += math.dotVec3(v1$1, v3$1);
50886
+ }
50887
+
50888
+ return volume;
50889
+ }
50890
+ }
50891
+
50892
+ /**
50893
+ * Singleton instance of {@link MeshVolume}.
50894
+ * @type {MeshVolume}
50895
+ */
50896
+ const meshVolume = new MeshVolume();
50897
+
50898
+ const v1 = math.vec3();
50899
+ const v2 = math.vec3();
50900
+ const v3 = math.vec3();
50901
+ const v4 = math.vec3();
50902
+ const v5 = math.vec3();
50903
+ const v6 = math.vec3();
50904
+
50905
+ /**
50906
+ * Calculates the surface area of triangle meshes.
50907
+ */
50908
+ class MeshSurfaceArea {
50909
+ constructor() {
50910
+ this.vertices = [];
50911
+ this.indices = [];
50912
+ this.reset();
50913
+ }
50914
+
50915
+ /**
50916
+ * Resets, ready to add vertices and indices for a new mesh.
50917
+ */
50918
+ reset() {
50919
+ this.lenVertices = 0;
50920
+ this.lenIndices = 0;
50921
+ }
50922
+
50923
+ /**
50924
+ * Adds a vertex.
50925
+ * @param vertex
50926
+ */
50927
+ addVertex(vertex) {
50928
+ this.vertices[this.lenVertices++] = vertex[0];
50929
+ this.vertices[this.lenVertices++] = vertex[1];
50930
+ this.vertices[this.lenVertices++] = vertex[2];
50931
+ }
50932
+
50933
+ /**
50934
+ * Adds an index.
50935
+ * @param index
50936
+ */
50937
+ addIndex(index) {
50938
+ this.indices[this.lenIndices++] = index;
50939
+ }
50940
+
50941
+ /**
50942
+ * Gets the surface area of the mesh.
50943
+ *
50944
+ * @returns {number}
50945
+ */
50946
+ get surfaceArea() {
50947
+
50948
+ const vertices = this.vertices;
50949
+ const indices = this.indices;
50950
+
50951
+ let surfaceArea = 0;
50952
+
50953
+ for (let i = 0; i < this.lenIndices; i += 3) {
50954
+
50955
+ const index1 = indices[i] * 3;
50956
+ const index2 = indices[i + 1] * 3;
50957
+ const index3 = indices[i + 2] * 3;
50958
+
50959
+ v1[0] = vertices[index1];
50960
+ v1[1] = vertices[index1 + 1];
50961
+ v1[2] = vertices[index1 + 2];
50962
+
50963
+ v2[0] = vertices[index2];
50964
+ v2[1] = vertices[index2 + 1];
50965
+ v2[2] = vertices[index2 + 2];
50966
+
50967
+ v3[0] = vertices[index3];
50968
+ v3[1] = vertices[index3 + 1];
50969
+ v3[2] = vertices[index3 + 2];
50970
+
50971
+ math.subVec3(v1, v2, v4);
50972
+ math.subVec3(v3, v2, v5);
50973
+
50974
+ surfaceArea += math.lenVec3(math.cross3Vec3(v4, v5, v6)) * 0.5;
50975
+ }
50976
+
50977
+ return surfaceArea;
50978
+ }
50979
+ }
50980
+
50981
+ /**
50982
+ * Singleton instance of {@link MeshSurfaceArea}.
50983
+ * @type {MeshSurfaceArea}
50984
+ */
50985
+ const meshSurfaceArea = new MeshSurfaceArea();
50986
+
50611
50987
  const tempOBB3$1 = math.OBB3();
50612
50988
  const tempOBB3b = math.OBB3();
50613
50989
  const tempOBB3c = math.OBB3();
50614
50990
 
50991
+
50615
50992
  /**
50616
50993
  * A mesh within a {@link SceneModel}.
50617
50994
  *
@@ -50724,6 +51101,9 @@ class SceneModelMesh {
50724
51101
  if (transform) {
50725
51102
  transform._addMesh(this);
50726
51103
  }
51104
+
51105
+ this._volume = null;
51106
+ this._surfaceArea = null;
50727
51107
  }
50728
51108
 
50729
51109
  _sceneModelDirty() {
@@ -50902,7 +51282,75 @@ class SceneModelMesh {
50902
51282
  * @private
50903
51283
  */
50904
51284
  getEachVertex(callback) {
50905
- this.layer.getEachVertex(this.portionId, callback);
51285
+ if (this.layer.getEachVertex) {
51286
+ this.layer.getEachVertex(this.portionId, callback);
51287
+ }
51288
+ }
51289
+
51290
+ /**
51291
+ * @private
51292
+ */
51293
+ getEachIndex(callback) {
51294
+ if (this.layer.getEachIndex ) {
51295
+ this.layer.getEachIndex(this.portionId, callback);
51296
+ }
51297
+ }
51298
+
51299
+ /**
51300
+ * Returns the volume of this SceneModelMesh.
51301
+ * @returns {number}
51302
+ */
51303
+ get volume() {
51304
+ if (this._volume !== null) {
51305
+ return this._volume;
51306
+ }
51307
+ switch (this.layer.primitive) {
51308
+ case "solid":
51309
+ case "surface":
51310
+ case "triangles":
51311
+ meshVolume.reset();
51312
+ meshVolume.setPrimitive(this.layer.primitive);
51313
+ this.getEachVertex((vertex) =>{
51314
+ meshVolume.addVertex(vertex);
51315
+ });
51316
+ this.getEachIndex((index)=>{
51317
+ meshVolume.addIndex(index);
51318
+ });
51319
+ this._volume = meshVolume.volume;
51320
+ break;
51321
+ default:
51322
+ this._volume = 0;
51323
+ break;
51324
+ }
51325
+ return this._volume;
51326
+ }
51327
+
51328
+ /**
51329
+ * Returns the surface area of this SceneModelMesh.
51330
+ * @returns {number}
51331
+ */
51332
+ get surfaceArea() {
51333
+ if (this._surfaceArea !== null) {
51334
+ return this._surfaceArea;
51335
+ }
51336
+ switch (this.layer.primitive) {
51337
+ case "solid":
51338
+ case "surface":
51339
+ case "triangles":
51340
+ meshSurfaceArea.reset();
51341
+ this.getEachVertex((vertex) =>{
51342
+ meshSurfaceArea.addVertex(vertex);
51343
+ });
51344
+ this.getEachIndex((index)=>{
51345
+ meshSurfaceArea.addIndex(index);
51346
+ });
51347
+ this._surfaceArea = meshSurfaceArea.surfaceArea;
51348
+ break;
51349
+ default:
51350
+ this._surfaceArea = 0;
51351
+ break;
51352
+ }
51353
+ return this._surfaceArea;
50906
51354
  }
50907
51355
 
50908
51356
  /**
@@ -51055,11 +51503,12 @@ const tempMat4a$r = math.mat4();
51055
51503
  * @private
51056
51504
  */
51057
51505
  class VBORenderer {
51058
- constructor(scene, withSAO = false, {instancing = false, edges = false} = {}) {
51506
+ constructor(scene, withSAO = false, {instancing = false, edges = false, useAlphaCutoff = false} = {}) {
51059
51507
  this._scene = scene;
51060
51508
  this._withSAO = withSAO;
51061
51509
  this._instancing = instancing;
51062
51510
  this._edges = edges;
51511
+ this._useAlphaCutoff = useAlphaCutoff;
51063
51512
  this._hash = this._getHash();
51064
51513
 
51065
51514
  /**
@@ -51310,6 +51759,10 @@ class VBORenderer {
51310
51759
  this._uSAOParams = program.getLocation("uSAOParams");
51311
51760
  }
51312
51761
 
51762
+ if (this._useAlphaCutoff) {
51763
+ this._alphaCutoffLocation = program.getLocation("materialAlphaCutoff");
51764
+ }
51765
+
51313
51766
  if (scene.logarithmicDepthBufferEnabled) {
51314
51767
  this._uLogDepthBufFC = program.getLocation("logDepthBufFC");
51315
51768
  }
@@ -51647,6 +52100,10 @@ class VBORenderer {
51647
52100
  }
51648
52101
  }
51649
52102
 
52103
+ if (this._useAlphaCutoff) {
52104
+ gl.uniform1f(this._alphaCutoffLocation, textureSet.alphaCutoff);
52105
+ }
52106
+
51650
52107
  if (colorUniform) {
51651
52108
  const colorKey = this._edges ? "edgeColor" : "fillColor";
51652
52109
  const alphaKey = this._edges ? "edgeAlpha" : "fillAlpha";
@@ -51697,8 +52154,8 @@ class VBORenderer {
51697
52154
  */
51698
52155
  class TrianglesBatchingRenderer extends VBORenderer {
51699
52156
 
51700
- constructor(scene, withSAO, {edges = false} = {}) {
51701
- super(scene, withSAO, {instancing: false, edges});
52157
+ constructor(scene, withSAO, {edges = false, useAlphaCutoff = false} = {}) {
52158
+ super(scene, withSAO, {instancing: false, edges, useAlphaCutoff});
51702
52159
  }
51703
52160
 
51704
52161
  _draw(drawCfg) {
@@ -51715,7 +52172,6 @@ class TrianglesBatchingRenderer extends VBORenderer {
51715
52172
  } else {
51716
52173
  const count = frameCtx.pickElementsCount || state.indicesBuf.numItems;
51717
52174
  const offset = frameCtx.pickElementsOffset ? frameCtx.pickElementsOffset * state.indicesBuf.itemByteSize : 0;
51718
-
51719
52175
  gl.drawElements(gl.TRIANGLES, count, state.indicesBuf.itemType, offset);
51720
52176
 
51721
52177
  if (incrementDrawState) {
@@ -54168,6 +54624,7 @@ class TrianglesPickNormalsFlatRenderer$1 extends TrianglesBatchingRenderer {
54168
54624
  /**
54169
54625
  * @private
54170
54626
  */
54627
+
54171
54628
  class TrianglesColorTextureRenderer$1 extends TrianglesBatchingRenderer {
54172
54629
  _getHash() {
54173
54630
  const scene = this._scene;
@@ -54175,11 +54632,10 @@ class TrianglesColorTextureRenderer$1 extends TrianglesBatchingRenderer {
54175
54632
  }
54176
54633
 
54177
54634
  drawLayer(frameCtx, layer, renderPass) {
54178
- super.drawLayer(frameCtx, layer, renderPass, {incrementDrawState: true});
54635
+ super.drawLayer(frameCtx, layer, renderPass, { incrementDrawState: true });
54179
54636
  }
54180
54637
 
54181
54638
  _buildVertexShader() {
54182
-
54183
54639
  const scene = this._scene;
54184
54640
  const sectionPlanesState = scene._sectionPlanesState;
54185
54641
  const clipping = sectionPlanesState.getNumAllocatedSectionPlanes() > 0;
@@ -54234,6 +54690,7 @@ class TrianglesColorTextureRenderer$1 extends TrianglesBatchingRenderer {
54234
54690
  if (scene.entityOffsetsEnabled) {
54235
54691
  src.push("worldPosition.xyz = worldPosition.xyz + offset;");
54236
54692
  }
54693
+
54237
54694
  src.push("vec4 viewPosition = viewMatrix * worldPosition; ");
54238
54695
  src.push("vViewPosition = viewPosition;");
54239
54696
  src.push("vColor = vec4(float(color.r) / 255.0, float(color.g) / 255.0, float(color.b) / 255.0, float(color.a) / 255.0);");
@@ -54244,10 +54701,12 @@ class TrianglesColorTextureRenderer$1 extends TrianglesBatchingRenderer {
54244
54701
  src.push("vFragDepth = 1.0 + clipPos.w;");
54245
54702
  src.push("isPerspective = float (isPerspectiveMatrix(projMatrix));");
54246
54703
  }
54704
+
54247
54705
  if (clipping) {
54248
54706
  src.push("vWorldPosition = worldPosition;");
54249
54707
  src.push("vFlags = flags;");
54250
54708
  }
54709
+
54251
54710
  src.push("gl_Position = clipPos;");
54252
54711
  src.push("}");
54253
54712
  src.push("}");
@@ -54260,6 +54719,7 @@ class TrianglesColorTextureRenderer$1 extends TrianglesBatchingRenderer {
54260
54719
  const lightsState = scene._lightsState;
54261
54720
  const sectionPlanesState = scene._sectionPlanesState;
54262
54721
  const clipping = sectionPlanesState.getNumAllocatedSectionPlanes() > 0;
54722
+ const useAlphaCutoff = this._useAlphaCutoff;
54263
54723
  const src = [];
54264
54724
  src.push("#version 300 es");
54265
54725
  src.push("// Triangles batching color texture fragment shader");
@@ -54318,6 +54778,7 @@ class TrianglesColorTextureRenderer$1 extends TrianglesBatchingRenderer {
54318
54778
  src.push("uniform vec4 sliceColor;");
54319
54779
  }
54320
54780
  this._addMatricesUniformBlockLines(src);
54781
+
54321
54782
  src.push("uniform vec4 lightAmbient;");
54322
54783
  for (let i = 0, len = lightsState.lights.length; i < len; i++) {
54323
54784
  const light = lightsState.lights[i];
@@ -54337,6 +54798,10 @@ class TrianglesColorTextureRenderer$1 extends TrianglesBatchingRenderer {
54337
54798
  }
54338
54799
  }
54339
54800
 
54801
+ if (useAlphaCutoff) {
54802
+ src.push("uniform float materialAlphaCutoff;");
54803
+ }
54804
+
54340
54805
  src.push("in vec4 vViewPosition;");
54341
54806
  src.push("in vec4 vColor;");
54342
54807
  src.push("in vec2 vUV;");
@@ -54404,11 +54869,21 @@ class TrianglesColorTextureRenderer$1 extends TrianglesBatchingRenderer {
54404
54869
  }
54405
54870
 
54406
54871
  src.push("vec4 color = vec4((lightAmbient.rgb * lightAmbient.a * newColor.rgb) + (reflectedColor * newColor.rgb), newColor.a);");
54872
+
54873
+ src.push("vec4 sampleColor = texture(uColorMap, vUV);");
54874
+
54875
+ if (useAlphaCutoff) {
54876
+ src.push("if (sampleColor.a < materialAlphaCutoff) {");
54877
+ src.push(" discard;");
54878
+ src.push("}");
54879
+ }
54880
+
54407
54881
  if (gammaOutput) {
54408
- src.push("vec4 colorTexel = color * sRGBToLinear(texture(uColorMap, vUV));");
54409
- } else {
54410
- src.push("vec4 colorTexel = color * texture(uColorMap, vUV);");
54882
+ src.push("sampleColor = sRGBToLinear(sampleColor);");
54411
54883
  }
54884
+
54885
+ src.push("vec4 colorTexel = color * sampleColor;");
54886
+
54412
54887
  src.push("float opacity = color.a;");
54413
54888
 
54414
54889
  if (this._withSAO) {
@@ -54955,7 +55430,7 @@ class TrianglesSnapRenderer$1 extends VBORenderer{
54955
55430
 
54956
55431
  src.push(`int pickFlag = int(flags) >> 12 & 0xF;`);
54957
55432
  src.push(`if (pickFlag != renderPass) {`);
54958
- src.push(" gl_Position = vec4(0.0, 0.0, 0.0, 0.0);"); // Cull vertex
55433
+ src.push(" gl_Position = vec4(2.0, 0.0, 0.0, 0.0);"); // Cull vertex
54959
55434
  src.push(" } else {");
54960
55435
  src.push(" vec4 worldPosition = worldMatrix * (positionsDecodeMatrix * vec4(position, 1.0)); ");
54961
55436
  if (scene.entityOffsetsEnabled) {
@@ -55082,6 +55557,14 @@ class Renderers$1 {
55082
55557
  this._colorTextureRendererWithSAO.destroy();
55083
55558
  this._colorTextureRendererWithSAO = null;
55084
55559
  }
55560
+ if (this._colorTextureRendererAlphaCutoff && (!this._colorTextureRendererAlphaCutoff.getValid())) {
55561
+ this._colorTextureRendererAlphaCutoff.destroy();
55562
+ this._colorTextureRendererAlphaCutoff = null;
55563
+ }
55564
+ if (this._colorTextureRendererWithSAOAlphaCutoff && (!this._colorTextureRendererWithSAOAlphaCutoff.getValid())) {
55565
+ this._colorTextureRendererWithSAOAlphaCutoff.destroy();
55566
+ this._colorTextureRendererWithSAOAlphaCutoff = null;
55567
+ }
55085
55568
  if (this._pbrRenderer && (!this._pbrRenderer.getValid())) {
55086
55569
  this._pbrRenderer.destroy();
55087
55570
  this._pbrRenderer = null;
@@ -55209,6 +55692,20 @@ class Renderers$1 {
55209
55692
  return this._colorTextureRendererWithSAO;
55210
55693
  }
55211
55694
 
55695
+ get colorTextureRendererAlphaCutoff() {
55696
+ if (!this._colorTextureRendererAlphaCutoff) {
55697
+ this._colorTextureRendererAlphaCutoff = new TrianglesColorTextureRenderer$1(this._scene, false, { useAlphaCutoff: true });
55698
+ }
55699
+ return this._colorTextureRendererAlphaCutoff;
55700
+ }
55701
+
55702
+ get colorTextureRendererWithSAOAlphaCutoff() {
55703
+ if (!this._colorTextureRendererWithSAOAlphaCutoff) {
55704
+ this._colorTextureRendererWithSAOAlphaCutoff = new TrianglesColorTextureRenderer$1(this._scene, true, { useAlphaCutoff: true });
55705
+ }
55706
+ return this._colorTextureRendererWithSAOAlphaCutoff;
55707
+ }
55708
+
55212
55709
  get pbrRenderer() {
55213
55710
  if (!this._pbrRenderer) {
55214
55711
  this._pbrRenderer = new TrianglesPBRRenderer$1(this._scene, false);
@@ -55333,6 +55830,12 @@ class Renderers$1 {
55333
55830
  if (this._colorTextureRendererWithSAO) {
55334
55831
  this._colorTextureRendererWithSAO.destroy();
55335
55832
  }
55833
+ if (this._colorTextureRendererAlphaCutoff) {
55834
+ this._colorTextureRendererAlphaCutoff.destroy();
55835
+ }
55836
+ if (this._colorTextureRendererWithSAOAlphaCutoff) {
55837
+ this._colorTextureRendererWithSAOAlphaCutoff.destroy();
55838
+ }
55336
55839
  if (this._pbrRenderer) {
55337
55840
  this._pbrRenderer.destroy();
55338
55841
  }
@@ -55381,29 +55884,29 @@ class Renderers$1 {
55381
55884
  }
55382
55885
  }
55383
55886
 
55384
- const cachdRenderers$1 = {};
55887
+ const cachedRenderers$6 = {};
55385
55888
 
55386
55889
  /**
55387
55890
  * @private
55388
55891
  */
55389
55892
  function getRenderers$7(scene) {
55390
55893
  const sceneId = scene.id;
55391
- let batchingRenderers = cachdRenderers$1[sceneId];
55392
- if (!batchingRenderers) {
55393
- batchingRenderers = new Renderers$1(scene);
55394
- cachdRenderers$1[sceneId] = batchingRenderers;
55395
- batchingRenderers._compile();
55396
- batchingRenderers.eagerCreateRenders();
55894
+ let renderers = cachedRenderers$6[sceneId];
55895
+ if (!renderers) {
55896
+ renderers = new Renderers$1(scene);
55897
+ cachedRenderers$6[sceneId] = renderers;
55898
+ renderers._compile();
55899
+ renderers.eagerCreateRenders();
55397
55900
  scene.on("compile", () => {
55398
- batchingRenderers._compile();
55399
- batchingRenderers.eagerCreateRenders();
55901
+ renderers._compile();
55902
+ renderers.eagerCreateRenders();
55400
55903
  });
55401
55904
  scene.on("destroyed", () => {
55402
- delete cachdRenderers$1[sceneId];
55403
- batchingRenderers._destroy();
55905
+ delete cachedRenderers$6[sceneId];
55906
+ renderers._destroy();
55404
55907
  });
55405
55908
  }
55406
- return batchingRenderers;
55909
+ return renderers;
55407
55910
  }
55408
55911
 
55409
55912
  let maxDataTextureHeight = 1 << 16;
@@ -55706,7 +56209,7 @@ function octDecodeVec2(oct) { // Decode an oct-encoded normal
55706
56209
 
55707
56210
  const tempMat4$1 = math.mat4();
55708
56211
  const tempMat4b = math.mat4();
55709
- const tempVec4a$7 = math.vec4([0, 0, 0, 1]);
56212
+ const tempVec4a$8 = math.vec4([0, 0, 0, 1]);
55710
56213
 
55711
56214
  const tempVec3a$z = math.vec3();
55712
56215
  const tempVec3b$v = math.vec3();
@@ -55736,7 +56239,7 @@ class VBOBatchingTrianglesLayer {
55736
56239
  */
55737
56240
  constructor(cfg) {
55738
56241
 
55739
- console.info("Creating VBOBatchingTrianglesLayer");
56242
+ // console.info("Creating VBOBatchingTrianglesLayer");
55740
56243
 
55741
56244
  /**
55742
56245
  * Owner model
@@ -55826,6 +56329,11 @@ class VBOBatchingTrianglesLayer {
55826
56329
  * @type {boolean}
55827
56330
  */
55828
56331
  this.solid = !!cfg.solid;
56332
+
56333
+ /**
56334
+ * The type of primitives in this layer.
56335
+ */
56336
+ this.primitive = cfg.primitive;
55829
56337
  }
55830
56338
 
55831
56339
  get aabb() {
@@ -56022,7 +56530,7 @@ class VBOBatchingTrianglesLayer {
56022
56530
  numIndices: indices.length,
56023
56531
  };
56024
56532
 
56025
- if (scene.pickSurfacePrecisionEnabled) {
56533
+ if (scene.readableGeometryEnabled) {
56026
56534
  // Quantized in-memory positions are initialized in finalize()
56027
56535
 
56028
56536
  portion.indices = indices;
@@ -56059,7 +56567,7 @@ class VBOBatchingTrianglesLayer {
56059
56567
  ? new Uint16Array(buffer.positions)
56060
56568
  : quantizePositions(buffer.positions, this._modelAABB, this._state.positionsDecodeMatrix = math.mat4()); // BOTTLENECK
56061
56569
  state.positionsBuf = new ArrayBuf(gl, gl.ARRAY_BUFFER, quantizedPositions, quantizedPositions.length, 3, gl.STATIC_DRAW);
56062
- if (this.model.scene.pickSurfacePrecisionEnabled) {
56570
+ if (this.model.scene.readableGeometryEnabled) {
56063
56571
  for (let i = 0, numPortions = this._portions.length; i < numPortions; i++) {
56064
56572
  const portion = this._portions[i];
56065
56573
  const start = portion.vertsBaseIndex * 3;
@@ -56488,7 +56996,7 @@ class VBOBatchingTrianglesLayer {
56488
56996
  if (this._state.offsetsBuf) {
56489
56997
  this._state.offsetsBuf.setData(tempArray, firstOffset, lenOffsets);
56490
56998
  }
56491
- if (this.model.scene.pickSurfacePrecisionEnabled) {
56999
+ if (this.model.scene.readableGeometryEnabled) {
56492
57000
  portion.offset[0] = offset[0];
56493
57001
  portion.offset[1] = offset[1];
56494
57002
  portion.offset[2] = offset[2];
@@ -56496,7 +57004,7 @@ class VBOBatchingTrianglesLayer {
56496
57004
  }
56497
57005
 
56498
57006
  getEachVertex(portionId, callback) {
56499
- if (!this.model.scene.pickSurfacePrecisionEnabled) {
57007
+ if (!this.model.scene.readableGeometryEnabled) {
56500
57008
  return;
56501
57009
  }
56502
57010
  const state = this._state;
@@ -56507,18 +57015,19 @@ class VBOBatchingTrianglesLayer {
56507
57015
  }
56508
57016
  const positions = portion.quantizedPositions;
56509
57017
  const origin = state.origin;
56510
- const offset = portion.offset;
56511
- const offsetX = origin[0] + offset[0];
56512
- const offsetY = origin[1] + offset[1];
56513
- const offsetZ = origin[2] + offset[2];
56514
- const worldPos = tempVec4a$7;
57018
+ const offsetX = origin[0] ;
57019
+ const offsetY = origin[1] ;
57020
+ const offsetZ = origin[2] ;
57021
+ const worldPos = tempVec4a$8;
57022
+ const sceneModelMatrix = this.model.matrix;
57023
+ const positionsDecodeMatrix = state.positionsDecodeMatrix;
56515
57024
  for (let i = 0, len = positions.length; i < len; i += 3) {
56516
57025
  worldPos[0] = positions[i];
56517
57026
  worldPos[1] = positions[i + 1];
56518
57027
  worldPos[2] = positions[i + 2];
56519
57028
  worldPos[3] = 1.0;
56520
- math.decompressPosition(worldPos, state.positionsDecodeMatrix);
56521
- math.transformPoint4(this.model.worldMatrix, worldPos);
57029
+ math.decompressPosition(worldPos, positionsDecodeMatrix);
57030
+ math.transformPoint4(sceneModelMatrix, worldPos);
56522
57031
  worldPos[0] += offsetX;
56523
57032
  worldPos[1] += offsetY;
56524
57033
  worldPos[2] += offsetZ;
@@ -56526,6 +57035,21 @@ class VBOBatchingTrianglesLayer {
56526
57035
  }
56527
57036
  }
56528
57037
 
57038
+ getEachIndex(portionId, callback) {
57039
+ if (!this.model.scene.readableGeometryEnabled) {
57040
+ return;
57041
+ }
57042
+ const portion = this._portions[portionId];
57043
+ if (!portion) {
57044
+ this.model.error("portion not found: " + portionId);
57045
+ return;
57046
+ }
57047
+ const indices = portion.indices;
57048
+ for (let i = 0, len = indices.length; i < len; i++) {
57049
+ callback(indices[i]);
57050
+ }
57051
+ }
57052
+
56529
57053
  getElementsCountAndOffset(portionId) {
56530
57054
  let count = null;
56531
57055
  let offset = null;
@@ -56546,14 +57070,21 @@ class VBOBatchingTrianglesLayer {
56546
57070
  return;
56547
57071
  }
56548
57072
  this._updateBackfaceCull(renderFlags, frameCtx);
57073
+ const useAlphaCutoff = this._state.textureSet && (typeof(this._state.textureSet.alphaCutoff) === "number");
56549
57074
  if (frameCtx.withSAO && this.model.saoEnabled) {
56550
57075
  if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {
56551
57076
  if (this._renderers.pbrRendererWithSAO) {
56552
57077
  this._renderers.pbrRendererWithSAO.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
56553
57078
  }
56554
57079
  } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {
56555
- if (this._renderers.colorTextureRendererWithSAO) {
56556
- this._renderers.colorTextureRendererWithSAO.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
57080
+ if (useAlphaCutoff) {
57081
+ if (this._renderers.colorTextureRendererWithSAOAlphaCutoff) {
57082
+ this._renderers.colorTextureRendererWithSAOAlphaCutoff.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
57083
+ }
57084
+ } else {
57085
+ if (this._renderers.colorTextureRendererWithSAO) {
57086
+ this._renderers.colorTextureRendererWithSAO.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
57087
+ }
56557
57088
  }
56558
57089
  } else if (this._state.normalsBuf) {
56559
57090
  if (this._renderers.colorRendererWithSAO) {
@@ -56570,8 +57101,14 @@ class VBOBatchingTrianglesLayer {
56570
57101
  this._renderers.pbrRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
56571
57102
  }
56572
57103
  } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {
56573
- if (this._renderers.colorTextureRenderer) {
56574
- this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
57104
+ if (useAlphaCutoff) {
57105
+ if (this._renderers.colorTextureRendererAlphaCutoff) {
57106
+ this._renderers.colorTextureRendererAlphaCutoff.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
57107
+ }
57108
+ } else {
57109
+ if (this._renderers.colorTextureRenderer) {
57110
+ this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
57111
+ }
56575
57112
  }
56576
57113
  } else if (this._state.normalsBuf) {
56577
57114
  if (this._renderers.colorRenderer) {
@@ -56608,8 +57145,15 @@ class VBOBatchingTrianglesLayer {
56608
57145
  this._renderers.pbrRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_TRANSPARENT);
56609
57146
  }
56610
57147
  } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {
56611
- if (this._renderers.colorTextureRenderer) {
56612
- this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_TRANSPARENT);
57148
+ const useAlphaCutoff = this._state.textureSet && (typeof(this._state.textureSet.alphaCutoff) === "number");
57149
+ if (useAlphaCutoff) {
57150
+ if (this._renderers.colorTextureRendererAlphaCutoff) {
57151
+ this._renderers.colorTextureRendererAlphaCutoff.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_TRANSPARENT);
57152
+ }
57153
+ } else {
57154
+ if (this._renderers.colorTextureRenderer) {
57155
+ this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_TRANSPARENT);
57156
+ }
56613
57157
  }
56614
57158
  } else if (this._state.normalsBuf) {
56615
57159
  if (this._renderers.colorRenderer) {
@@ -56813,7 +57357,7 @@ class VBOBatchingTrianglesLayer {
56813
57357
 
56814
57358
  precisionRayPickSurface(portionId, worldRayOrigin, worldRayDir, worldSurfacePos, worldNormal) {
56815
57359
 
56816
- if (!this.model.scene.pickSurfacePrecisionEnabled) {
57360
+ if (!this.model.scene.readableGeometryEnabled) {
56817
57361
  return false;
56818
57362
  }
56819
57363
 
@@ -56953,8 +57497,8 @@ class VBOBatchingTrianglesLayer {
56953
57497
  * @private
56954
57498
  */
56955
57499
  class TrianglesInstancingRenderer extends VBORenderer {
56956
- constructor(scene, withSAO, {edges = false} = {}) {
56957
- super(scene, withSAO, {instancing: true, edges});
57500
+ constructor(scene, withSAO, {edges = false, useAlphaCutoff = false} = {}) {
57501
+ super(scene, withSAO, {instancing: true, edges, useAlphaCutoff});
56958
57502
  }
56959
57503
 
56960
57504
  _draw(drawCfg) {
@@ -56963,13 +57507,14 @@ class TrianglesInstancingRenderer extends VBORenderer {
56963
57507
  const {
56964
57508
  state,
56965
57509
  frameCtx,
56966
- incrementDrawState,
57510
+ incrementDrawState
56967
57511
  } = drawCfg;
56968
57512
 
56969
57513
  if (this._edges) {
56970
57514
  gl.drawElementsInstanced(gl.LINES, state.edgeIndicesBuf.numItems, state.edgeIndicesBuf.itemType, 0, state.numInstances);
56971
57515
  } else {
56972
57516
  gl.drawElementsInstanced(gl.TRIANGLES, state.indicesBuf.numItems, state.indicesBuf.itemType, 0, state.numInstances);
57517
+
56973
57518
  if (incrementDrawState) {
56974
57519
  frameCtx.drawElements++;
56975
57520
  }
@@ -59498,7 +60043,6 @@ class TrianglesPickNormalsFlatRenderer extends TrianglesInstancingRenderer {
59498
60043
  * @private
59499
60044
  */
59500
60045
 
59501
-
59502
60046
  class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59503
60047
  _getHash() {
59504
60048
  const scene = this._scene;
@@ -59567,7 +60111,7 @@ class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59567
60111
  src.push("vec4 worldPosition = positionsDecodeMatrix * vec4(position, 1.0); ");
59568
60112
  src.push("worldPosition = worldMatrix * vec4(dot(worldPosition, modelMatrixCol0), dot(worldPosition, modelMatrixCol1), dot(worldPosition, modelMatrixCol2), 1.0);");
59569
60113
  if (scene.entityOffsetsEnabled) {
59570
- src.push(" worldPosition.xyz = worldPosition.xyz + offset;");
60114
+ src.push("worldPosition.xyz = worldPosition.xyz + offset;");
59571
60115
  }
59572
60116
 
59573
60117
  src.push("vec4 viewPosition = viewMatrix * worldPosition; ");
@@ -59595,11 +60139,10 @@ class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59595
60139
  _buildFragmentShader() {
59596
60140
  const scene = this._scene;
59597
60141
  const gammaOutput = scene.gammaOutput; // If set, then it expects that all textures and colors need to be outputted in premultiplied gamma. Default is false.
59598
- const sectionPlanesState = scene._sectionPlanesState;
59599
60142
  const lightsState = scene._lightsState;
59600
- let i;
59601
- let len;
60143
+ const sectionPlanesState = scene._sectionPlanesState;
59602
60144
  const clipping = sectionPlanesState.getNumAllocatedSectionPlanes() > 0;
60145
+ const useAlphaCutoff = this._useAlphaCutoff;
59603
60146
  const src = [];
59604
60147
  src.push("#version 300 es");
59605
60148
  src.push("// Instancing geometry drawing fragment shader");
@@ -59611,6 +60154,7 @@ class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59611
60154
  src.push("precision mediump float;");
59612
60155
  src.push("precision mediump int;");
59613
60156
  src.push("#endif");
60157
+
59614
60158
  if (scene.logarithmicDepthBufferEnabled) {
59615
60159
  src.push("in float isPerspective;");
59616
60160
  src.push("uniform float logDepthBufFC;");
@@ -59659,7 +60203,7 @@ class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59659
60203
  this._addMatricesUniformBlockLines(src);
59660
60204
 
59661
60205
  src.push("uniform vec4 lightAmbient;");
59662
- for (i = 0, len = lightsState.lights.length; i < len; i++) {
60206
+ for (let i = 0, len = lightsState.lights.length; i < len; i++) {
59663
60207
  const light = lightsState.lights[i];
59664
60208
  if (light.type === "ambient") {
59665
60209
  continue;
@@ -59677,6 +60221,10 @@ class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59677
60221
  }
59678
60222
  }
59679
60223
 
60224
+ if (useAlphaCutoff) {
60225
+ src.push("uniform float materialAlphaCutoff;");
60226
+ }
60227
+
59680
60228
  src.push("in vec4 vViewPosition;");
59681
60229
  src.push("in vec4 vColor;");
59682
60230
  src.push("in vec2 vUV;");
@@ -59712,7 +60260,7 @@ class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59712
60260
  src.push("vec3 yTangent = dFdy( vViewPosition.xyz );");
59713
60261
  src.push("vec3 viewNormal = normalize( cross( xTangent, yTangent ) );");
59714
60262
 
59715
- for (i = 0, len = lightsState.lights.length; i < len; i++) {
60263
+ for (let i = 0, len = lightsState.lights.length; i < len; i++) {
59716
60264
  const light = lightsState.lights[i];
59717
60265
  if (light.type === "ambient") {
59718
60266
  continue;
@@ -59738,16 +60286,27 @@ class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59738
60286
  } else {
59739
60287
  continue;
59740
60288
  }
60289
+
59741
60290
  src.push("lambertian = max(dot(-viewNormal, viewLightDir), 0.0);");
59742
60291
  src.push("reflectedColor += lambertian * (lightColor" + i + ".rgb * lightColor" + i + ".a);");
59743
60292
  }
59744
60293
 
59745
60294
  src.push("vec4 color = vec4((lightAmbient.rgb * lightAmbient.a * newColor.rgb) + (reflectedColor * newColor.rgb), newColor.a);");
60295
+
60296
+ src.push("vec4 sampleColor = texture(uColorMap, vUV);");
60297
+
60298
+ if (useAlphaCutoff) {
60299
+ src.push("if (sampleColor.a < materialAlphaCutoff) {");
60300
+ src.push(" discard;");
60301
+ src.push("}");
60302
+ }
60303
+
59746
60304
  if (gammaOutput) {
59747
- src.push("vec4 colorTexel = color * sRGBToLinear(texture(uColorMap, vUV));");
59748
- } else {
59749
- src.push("vec4 colorTexel = color * texture(uColorMap, vUV);");
60305
+ src.push("sampleColor = sRGBToLinear(sampleColor);");
59750
60306
  }
60307
+
60308
+ src.push("vec4 colorTexel = color * sampleColor;");
60309
+
59751
60310
  src.push("float opacity = color.a;");
59752
60311
 
59753
60312
  if (this._withSAO) {
@@ -59759,9 +60318,10 @@ class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59759
60318
  src.push(" float blendFactor = uSAOParams[3];");
59760
60319
  src.push(" vec2 uv = vec2(gl_FragCoord.x / viewportWidth, gl_FragCoord.y / viewportHeight);");
59761
60320
  src.push(" float ambient = smoothstep(blendCutoff, 1.0, unpackRGBToFloat(texture(uOcclusionTexture, uv))) * blendFactor;");
59762
- src.push(" outColor = vec4(newColor.rgb * colorTexel.rgb * ambient, opacity);");
60321
+
60322
+ src.push(" outColor = vec4(colorTexel.rgb * ambient, opacity);");
59763
60323
  } else {
59764
- src.push(" outColor = vec4(newColor.rgb * colorTexel.rgb, opacity);");
60324
+ src.push(" outColor = vec4(colorTexel.rgb, opacity);");
59765
60325
  }
59766
60326
 
59767
60327
  if (gammaOutput) {
@@ -59769,7 +60329,7 @@ class TrianglesColorTextureRenderer extends TrianglesInstancingRenderer {
59769
60329
  }
59770
60330
 
59771
60331
  if (scene.logarithmicDepthBufferEnabled) {
59772
- src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
60332
+ src.push("gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
59773
60333
  }
59774
60334
 
59775
60335
  src.push("}");
@@ -60339,7 +60899,7 @@ class TrianglesSnapRenderer extends VBORenderer {
60339
60899
  // renderPass = PICK
60340
60900
  src.push(`int pickFlag = int(flags) >> 12 & 0xF;`);
60341
60901
  src.push(`if (pickFlag != renderPass) {`);
60342
- src.push(" gl_Position = vec4(0.0, 0.0, 0.0, 0.0);"); // Cull vertex
60902
+ src.push(" gl_Position = vec4(2.0, 0.0, 0.0, 0.0);"); // Cull vertex
60343
60903
  src.push("} else {");
60344
60904
  src.push(" vec4 worldPosition = positionsDecodeMatrix * vec4(position, 1.0); ");
60345
60905
  src.push(" worldPosition = worldMatrix * vec4(dot(worldPosition, modelMatrixCol0), dot(worldPosition, modelMatrixCol1), dot(worldPosition, modelMatrixCol2), 1.0);");
@@ -60459,14 +61019,6 @@ class Renderers {
60459
61019
  this._flatColorRendererWithSAO.destroy();
60460
61020
  this._flatColorRendererWithSAO = null;
60461
61021
  }
60462
- if (this._pbrRenderer && (!this._pbrRenderer.getValid())) {
60463
- this._pbrRenderer.destroy();
60464
- this._pbrRenderer = null;
60465
- }
60466
- if (this._pbrRendererWithSAO && (!this._pbrRendererWithSAO.getValid())) {
60467
- this._pbrRendererWithSAO.destroy();
60468
- this._pbrRendererWithSAO = null;
60469
- }
60470
61022
  if (this._colorTextureRenderer && (!this._colorTextureRenderer.getValid())) {
60471
61023
  this._colorTextureRenderer.destroy();
60472
61024
  this._colorTextureRenderer = null;
@@ -60475,6 +61027,22 @@ class Renderers {
60475
61027
  this._colorTextureRendererWithSAO.destroy();
60476
61028
  this._colorTextureRendererWithSAO = null;
60477
61029
  }
61030
+ if (this._colorTextureRendererAlphaCutoff && (!this._colorTextureRendererAlphaCutoff.getValid())) {
61031
+ this._colorTextureRendererAlphaCutoff.destroy();
61032
+ this._colorTextureRendererAlphaCutoff = null;
61033
+ }
61034
+ if (this._colorTextureRendererWithSAOAlphaCutoff && (!this._colorTextureRendererWithSAOAlphaCutoff.getValid())) {
61035
+ this._colorTextureRendererWithSAOAlphaCutoff.destroy();
61036
+ this._colorTextureRendererWithSAOAlphaCutoff = null;
61037
+ }
61038
+ if (this._pbrRenderer && (!this._pbrRenderer.getValid())) {
61039
+ this._pbrRenderer.destroy();
61040
+ this._pbrRenderer = null;
61041
+ }
61042
+ if (this._pbrRendererWithSAO && (!this._pbrRendererWithSAO.getValid())) {
61043
+ this._pbrRendererWithSAO.destroy();
61044
+ this._pbrRendererWithSAO = null;
61045
+ }
60478
61046
  if (this._depthRenderer && (!this._depthRenderer.getValid())) {
60479
61047
  this._depthRenderer.destroy();
60480
61048
  this._depthRenderer = null;
@@ -60507,7 +61075,7 @@ class Renderers {
60507
61075
  this._pickNormalsRenderer.destroy();
60508
61076
  this._pickNormalsRenderer = null;
60509
61077
  }
60510
- if (this._pickNormalsFlatRenderer && (!this._pickNormalsFlatRenderer.getValid())) {
61078
+ if (this._pickNormalsFlatRenderer && this._pickNormalsFlatRenderer.getValid() === false) {
60511
61079
  this._pickNormalsFlatRenderer.destroy();
60512
61080
  this._pickNormalsFlatRenderer = null;
60513
61081
  }
@@ -60580,20 +61148,6 @@ class Renderers {
60580
61148
  return this._flatColorRendererWithSAO;
60581
61149
  }
60582
61150
 
60583
- get pbrRenderer() {
60584
- if (!this._pbrRenderer) {
60585
- this._pbrRenderer = new TrianglesPBRRenderer(this._scene, false);
60586
- }
60587
- return this._pbrRenderer;
60588
- }
60589
-
60590
- get pbrRendererWithSAO() {
60591
- if (!this._pbrRendererWithSAO) {
60592
- this._pbrRendererWithSAO = new TrianglesPBRRenderer(this._scene, true);
60593
- }
60594
- return this._pbrRendererWithSAO;
60595
- }
60596
-
60597
61151
  get colorTextureRenderer() {
60598
61152
  if (!this._colorTextureRenderer) {
60599
61153
  this._colorTextureRenderer = new TrianglesColorTextureRenderer(this._scene, false);
@@ -60608,6 +61162,34 @@ class Renderers {
60608
61162
  return this._colorTextureRendererWithSAO;
60609
61163
  }
60610
61164
 
61165
+ get colorTextureRendererAlphaCutoff() {
61166
+ if (!this._colorTextureRendererAlphaCutoff) {
61167
+ this._colorTextureRendererAlphaCutoff = new TrianglesColorTextureRenderer(this._scene, false, { useAlphaCutoff: true });
61168
+ }
61169
+ return this._colorTextureRendererAlphaCutoff;
61170
+ }
61171
+
61172
+ get colorTextureRendererWithSAOAlphaCutoff() {
61173
+ if (!this._colorTextureRendererWithSAOAlphaCutoff) {
61174
+ this._colorTextureRendererWithSAOAlphaCutoff = new TrianglesColorTextureRenderer(this._scene, true, { useAlphaCutoff: true });
61175
+ }
61176
+ return this._colorTextureRendererWithSAOAlphaCutoff;
61177
+ }
61178
+
61179
+ get pbrRenderer() {
61180
+ if (!this._pbrRenderer) {
61181
+ this._pbrRenderer = new TrianglesPBRRenderer(this._scene, false);
61182
+ }
61183
+ return this._pbrRenderer;
61184
+ }
61185
+
61186
+ get pbrRendererWithSAO() {
61187
+ if (!this._pbrRendererWithSAO) {
61188
+ this._pbrRendererWithSAO = new TrianglesPBRRenderer(this._scene, true);
61189
+ }
61190
+ return this._pbrRendererWithSAO;
61191
+ }
61192
+
60611
61193
  get silhouetteRenderer() {
60612
61194
  if (!this._silhouetteRenderer) {
60613
61195
  this._silhouetteRenderer = new TrianglesSilhouetteRenderer(this._scene);
@@ -60685,13 +61267,6 @@ class Renderers {
60685
61267
  return this._shadowRenderer;
60686
61268
  }
60687
61269
 
60688
- get snapInitRenderer() {
60689
- if (!this._snapInitRenderer) {
60690
- this._snapInitRenderer = new TrianglesSnapInitRenderer(this._scene, false);
60691
- }
60692
- return this._snapInitRenderer;
60693
- }
60694
-
60695
61270
  get snapRenderer() {
60696
61271
  if (!this._snapRenderer) {
60697
61272
  this._snapRenderer = new TrianglesSnapRenderer(this._scene);
@@ -60699,6 +61274,13 @@ class Renderers {
60699
61274
  return this._snapRenderer;
60700
61275
  }
60701
61276
 
61277
+ get snapInitRenderer() {
61278
+ if (!this._snapInitRenderer) {
61279
+ this._snapInitRenderer = new TrianglesSnapInitRenderer(this._scene);
61280
+ }
61281
+ return this._snapInitRenderer;
61282
+ }
61283
+
60702
61284
  _destroy() {
60703
61285
  if (this._colorRenderer) {
60704
61286
  this._colorRenderer.destroy();
@@ -60712,18 +61294,24 @@ class Renderers {
60712
61294
  if (this._flatColorRendererWithSAO) {
60713
61295
  this._flatColorRendererWithSAO.destroy();
60714
61296
  }
60715
- if (this._pbrRenderer) {
60716
- this._pbrRenderer.destroy();
60717
- }
60718
- if (this._pbrRendererWithSAO) {
60719
- this._pbrRendererWithSAO.destroy();
60720
- }
60721
61297
  if (this._colorTextureRenderer) {
60722
61298
  this._colorTextureRenderer.destroy();
60723
61299
  }
60724
61300
  if (this._colorTextureRendererWithSAO) {
60725
61301
  this._colorTextureRendererWithSAO.destroy();
60726
61302
  }
61303
+ if (this._colorTextureRendererAlphaCutoff) {
61304
+ this._colorTextureRendererAlphaCutoff.destroy();
61305
+ }
61306
+ if (this._colorTextureRendererWithSAOAlphaCutoff) {
61307
+ this._colorTextureRendererWithSAOAlphaCutoff.destroy();
61308
+ }
61309
+ if (this._pbrRenderer) {
61310
+ this._pbrRenderer.destroy();
61311
+ }
61312
+ if (this._pbrRendererWithSAO) {
61313
+ this._pbrRendererWithSAO.destroy();
61314
+ }
60727
61315
  if (this._depthRenderer) {
60728
61316
  this._depthRenderer.destroy();
60729
61317
  }
@@ -60773,27 +61361,27 @@ const cachedRenderers$5 = {};
60773
61361
  */
60774
61362
  function getRenderers$6(scene) {
60775
61363
  const sceneId = scene.id;
60776
- let instancingRenderers = cachedRenderers$5[sceneId];
60777
- if (!instancingRenderers) {
60778
- instancingRenderers = new Renderers(scene);
60779
- cachedRenderers$5[sceneId] = instancingRenderers;
60780
- instancingRenderers._compile();
60781
- instancingRenderers.eagerCreateRenders();
61364
+ let renderers = cachedRenderers$5[sceneId];
61365
+ if (!renderers) {
61366
+ renderers = new Renderers(scene);
61367
+ cachedRenderers$5[sceneId] = renderers;
61368
+ renderers._compile();
61369
+ renderers.eagerCreateRenders();
60782
61370
  scene.on("compile", () => {
60783
- instancingRenderers._compile();
60784
- instancingRenderers.eagerCreateRenders();
61371
+ renderers._compile();
61372
+ renderers.eagerCreateRenders();
60785
61373
  });
60786
61374
  scene.on("destroyed", () => {
60787
61375
  delete cachedRenderers$5[sceneId];
60788
- instancingRenderers._destroy();
61376
+ renderers._destroy();
60789
61377
  });
60790
61378
  }
60791
- return instancingRenderers;
61379
+ return renderers;
60792
61380
  }
60793
61381
 
60794
61382
  const tempUint8Vec4$2 = new Uint8Array(4);
60795
61383
  const tempFloat32$2 = new Float32Array(1);
60796
- const tempVec4a$6 = math.vec4([0, 0, 0, 1]);
61384
+ const tempVec4a$7 = math.vec4([0, 0, 0, 1]);
60797
61385
  const tempVec3fa$2 = new Float32Array(3);
60798
61386
 
60799
61387
  const tempVec3a$w = math.vec3();
@@ -60821,7 +61409,7 @@ class VBOInstancingTrianglesLayer {
60821
61409
  */
60822
61410
  constructor(cfg) {
60823
61411
 
60824
- console.info("Creating VBOInstancingTrianglesLayer");
61412
+ // console.info("Creating VBOInstancingTrianglesLayer");
60825
61413
 
60826
61414
  /**
60827
61415
  * Owner model
@@ -60924,6 +61512,11 @@ class VBOInstancingTrianglesLayer {
60924
61512
  * @type {number|*}
60925
61513
  */
60926
61514
  this.numIndices = cfg.geometry.numIndices;
61515
+
61516
+ /**
61517
+ * The type of primitives in this layer.
61518
+ */
61519
+ this.primitive = cfg.geometry.primitive;
60927
61520
  }
60928
61521
 
60929
61522
  get aabb() {
@@ -61037,7 +61630,7 @@ class VBOInstancingTrianglesLayer {
61037
61630
 
61038
61631
  const portion = {};
61039
61632
 
61040
- if (this.model.scene.pickSurfacePrecisionEnabled) {
61633
+ if (this.model.scene.readableGeometryEnabled) {
61041
61634
  portion.matrix = meshMatrix.slice();
61042
61635
  portion.inverseMatrix = null; // Lazy-computed in precisionRayPickSurface
61043
61636
  portion.normalMatrix = null; // Lazy-computed in precisionRayPickSurface
@@ -61475,7 +62068,7 @@ class VBOInstancingTrianglesLayer {
61475
62068
  }
61476
62069
 
61477
62070
  getEachVertex(portionId, callback) {
61478
- if (!this.model.scene.pickSurfacePrecisionEnabled) {
62071
+ if (!this.model.scene.readableGeometryEnabled) {
61479
62072
  return false;
61480
62073
  }
61481
62074
  const state = this._state;
@@ -61487,13 +62080,12 @@ class VBOInstancingTrianglesLayer {
61487
62080
  }
61488
62081
  const positions = geometry.quantizedPositions;
61489
62082
  const origin = state.origin;
61490
- const offset = portion.offset;
61491
- const offsetX = origin[0] + offset[0];
61492
- const offsetY = origin[1] + offset[1];
61493
- const offsetZ = origin[2] + offset[2];
61494
- const worldPos = tempVec4a$6;
62083
+ const offsetX = origin[0] ;
62084
+ const offsetY = origin[1] ;
62085
+ const offsetZ = origin[2] ;
62086
+ const worldPos = tempVec4a$7;
61495
62087
  const portionMatrix = portion.matrix;
61496
- const sceneModelPatrix = this.model.sceneModelMatrix;
62088
+ const sceneModelMatrix = this.model.matrix;
61497
62089
  const positionsDecodeMatrix = state.positionsDecodeMatrix;
61498
62090
  for (let i = 0, len = positions.length; i < len; i += 3) {
61499
62091
  worldPos[0] = positions[i];
@@ -61501,7 +62093,7 @@ class VBOInstancingTrianglesLayer {
61501
62093
  worldPos[2] = positions[i + 2];
61502
62094
  math.decompressPosition(worldPos, positionsDecodeMatrix);
61503
62095
  math.transformPoint3(portionMatrix, worldPos);
61504
- math.transformPoint3(sceneModelPatrix, worldPos);
62096
+ math.transformPoint3(sceneModelMatrix, worldPos);
61505
62097
  worldPos[0] += offsetX;
61506
62098
  worldPos[1] += offsetY;
61507
62099
  worldPos[2] += offsetZ;
@@ -61509,6 +62101,23 @@ class VBOInstancingTrianglesLayer {
61509
62101
  }
61510
62102
  }
61511
62103
 
62104
+ getEachIndex(portionId, callback) {
62105
+ if (!this.model.scene.readableGeometryEnabled) {
62106
+ return false;
62107
+ }
62108
+ const state = this._state;
62109
+ const geometry = state.geometry;
62110
+ const portion = this._portions[portionId];
62111
+ if (!portion) {
62112
+ this.model.error("portion not found: " + portionId);
62113
+ return;
62114
+ }
62115
+ const indices = geometry.indices;
62116
+ for (let i = 0, len = indices.length; i < len; i++) {
62117
+ callback(indices[i]);
62118
+ }
62119
+ }
62120
+
61512
62121
  setMatrix(portionId, matrix) {
61513
62122
  if (!this._finalized) {
61514
62123
  throw "Not finalized";
@@ -61549,14 +62158,21 @@ class VBOInstancingTrianglesLayer {
61549
62158
  return;
61550
62159
  }
61551
62160
  this._updateBackfaceCull(renderFlags, frameCtx);
62161
+ const useAlphaCutoff = this._state.textureSet && (typeof(this._state.textureSet.alphaCutoff) === "number");
61552
62162
  if (frameCtx.withSAO && this.model.saoEnabled) {
61553
62163
  if (frameCtx.pbrEnabled && this.model.pbrEnabled && this._state.pbrSupported) {
61554
62164
  if (this._renderers.pbrRendererWithSAO) {
61555
62165
  this._renderers.pbrRendererWithSAO.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
61556
62166
  }
61557
62167
  } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {
61558
- if (this._renderers.colorTextureRendererWithSAO) {
61559
- this._renderers.colorTextureRendererWithSAO.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
62168
+ if (useAlphaCutoff) {
62169
+ if (this._renderers.colorTextureRendererWithSAOAlphaCutoff) {
62170
+ this._renderers.colorTextureRendererWithSAOAlphaCutoff.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
62171
+ }
62172
+ } else {
62173
+ if (this._renderers.colorTextureRendererWithSAO) {
62174
+ this._renderers.colorTextureRendererWithSAO.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
62175
+ }
61560
62176
  }
61561
62177
  } else if (this._state.normalsBuf) {
61562
62178
  if (this._renderers.colorRendererWithSAO) {
@@ -61572,8 +62188,14 @@ class VBOInstancingTrianglesLayer {
61572
62188
  this._renderers.pbrRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
61573
62189
  }
61574
62190
  } else if (frameCtx.colorTextureEnabled && this.model.colorTextureEnabled && this._state.colorTextureSupported) {
61575
- if (this._renderers.colorTextureRenderer) {
61576
- this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
62191
+ if (useAlphaCutoff) {
62192
+ if (this._renderers.colorTextureRendererAlphaCutoff) {
62193
+ this._renderers.colorTextureRendererAlphaCutoff.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
62194
+ }
62195
+ } else {
62196
+ if (this._renderers.colorTextureRenderer) {
62197
+ this._renderers.colorTextureRenderer.drawLayer(frameCtx, this, RENDER_PASSES.COLOR_OPAQUE);
62198
+ }
61577
62199
  }
61578
62200
  } else if (this._state.normalsBuf) {
61579
62201
  if (this._renderers.colorRenderer) {
@@ -61815,7 +62437,7 @@ class VBOInstancingTrianglesLayer {
61815
62437
 
61816
62438
  precisionRayPickSurface(portionId, worldRayOrigin, worldRayDir, worldSurfacePos, worldNormal) {
61817
62439
 
61818
- if (!this.model.scene.pickSurfacePrecisionEnabled) {
62440
+ if (!this.model.scene.readableGeometryEnabled) {
61819
62441
  return false;
61820
62442
  }
61821
62443
 
@@ -62748,7 +63370,7 @@ class VBOBatchingLinesSnapRenderer extends VBORenderer{
62748
63370
 
62749
63371
  src.push(`int pickFlag = int(flags) >> 12 & 0xF;`);
62750
63372
  src.push(`if (pickFlag != renderPass) {`);
62751
- src.push(" gl_Position = vec4(0.0, 0.0, 0.0, 0.0);"); // Cull vertex
63373
+ src.push(" gl_Position = vec4(2.0, 0.0, 0.0, 0.0);"); // Cull vertex
62752
63374
  src.push(" } else {");
62753
63375
  src.push(" vec4 worldPosition = worldMatrix * (positionsDecodeMatrix * vec4(position, 1.0)); ");
62754
63376
  if (scene.entityOffsetsEnabled) {
@@ -62972,7 +63594,7 @@ class VBOBatchingLinesLayer {
62972
63594
  */
62973
63595
  constructor(cfg) {
62974
63596
 
62975
- console.info("Creating VBOBatchingLinesLayer");
63597
+ // console.info("Creating VBOBatchingLinesLayer");
62976
63598
 
62977
63599
  /**
62978
63600
  * Index of this LinesBatchingLayer in {@link VBOSceneModel#_layerList}.
@@ -63027,6 +63649,11 @@ class VBOBatchingLinesLayer {
63027
63649
  if (cfg.origin) {
63028
63650
  this._state.origin = math.vec3(cfg.origin);
63029
63651
  }
63652
+
63653
+ /**
63654
+ * The type of primitives in this layer.
63655
+ */
63656
+ this.primitive = cfg.primitive;
63030
63657
  }
63031
63658
 
63032
63659
  get aabb() {
@@ -64485,7 +65112,7 @@ class VBOInstancingLinesSnapRenderer extends VBORenderer {
64485
65112
  // renderPass = PICK
64486
65113
  src.push(`int pickFlag = int(flags) >> 12 & 0xF;`);
64487
65114
  src.push(`if (pickFlag != renderPass) {`);
64488
- src.push(" gl_Position = vec4(0.0, 0.0, 0.0, 0.0);"); // Cull vertex
65115
+ src.push(" gl_Position = vec4(2.0, 0.0, 0.0, 0.0);"); // Cull vertex
64489
65116
  src.push("} else {");
64490
65117
  src.push(" vec4 worldPosition = positionsDecodeMatrix * vec4(position, 1.0); ");
64491
65118
  src.push(" worldPosition = worldMatrix * vec4(dot(worldPosition, modelMatrixCol0), dot(worldPosition, modelMatrixCol1), dot(worldPosition, modelMatrixCol2), 1.0);");
@@ -64735,7 +65362,7 @@ class VBOInstancingLinesLayer {
64735
65362
  */
64736
65363
  constructor(cfg) {
64737
65364
 
64738
- console.info("VBOInstancingLinesLayer");
65365
+ // console.info("VBOInstancingLinesLayer");
64739
65366
 
64740
65367
  /**
64741
65368
  * Owner model
@@ -64815,6 +65442,11 @@ class VBOInstancingLinesLayer {
64815
65442
  }
64816
65443
 
64817
65444
  this._finalized = false;
65445
+
65446
+ /**
65447
+ * The type of primitives in this layer.
65448
+ */
65449
+ this.primitive = cfg.primitive;
64818
65450
  }
64819
65451
 
64820
65452
  get aabb() {
@@ -66948,7 +67580,7 @@ class VBOBatchingPointsLayer {
66948
67580
  */
66949
67581
  constructor(cfg) {
66950
67582
 
66951
- console.info("Creating VBOBatchingPointsLayer");
67583
+ // console.info("Creating VBOBatchingPointsLayer");
66952
67584
 
66953
67585
  /**
66954
67586
  * Owner model
@@ -69545,7 +70177,7 @@ class VBOInstancingPointsLayer {
69545
70177
  */
69546
70178
  constructor(cfg) {
69547
70179
 
69548
- console.info("VBOInstancingPointsLayer");
70180
+ // console.info("VBOInstancingPointsLayer");
69549
70181
 
69550
70182
  /**
69551
70183
  * Owner model
@@ -69619,6 +70251,11 @@ class VBOInstancingPointsLayer {
69619
70251
  this.aabbDirty = true;
69620
70252
 
69621
70253
  this._finalized = false;
70254
+
70255
+ /**
70256
+ * The type of primitives in this layer.
70257
+ */
70258
+ this.primitive = cfg.geometry.primitive;
69622
70259
  }
69623
70260
 
69624
70261
  get aabb() {
@@ -71280,7 +71917,7 @@ class DTXLinesLayer {
71280
71917
 
71281
71918
  constructor(model, cfg) {
71282
71919
 
71283
- console.info("Creating DTXLinesLayer");
71920
+ // console.info("Creating DTXLinesLayer");
71284
71921
 
71285
71922
  dataTextureRamStats$1.numberOfLayers++;
71286
71923
 
@@ -71319,6 +71956,12 @@ class DTXLinesLayer {
71319
71956
  this._aabb = math.collapseAABB3();
71320
71957
  this.aabbDirty = true;
71321
71958
  this._numUpdatesInFrame = 0;
71959
+
71960
+ /**
71961
+ * The type of primitives in this layer.
71962
+ */
71963
+ this.primitive = cfg.primitive;
71964
+
71322
71965
  this._finalized = false;
71323
71966
  }
71324
71967
 
@@ -72144,7 +72787,7 @@ const tempVec3b$i = math.vec3();
72144
72787
  const tempVec3c$e = math.vec3();
72145
72788
  math.vec3();
72146
72789
 
72147
- const tempVec4a$5 = math.vec4();
72790
+ const tempVec4a$6 = math.vec4();
72148
72791
 
72149
72792
  const tempMat4a$c = math.mat4();
72150
72793
 
@@ -72423,11 +73066,11 @@ class DTXTrianglesColorRenderer {
72423
73066
  if (saoEnabled) {
72424
73067
  const viewportWidth = gl.drawingBufferWidth;
72425
73068
  const viewportHeight = gl.drawingBufferHeight;
72426
- tempVec4a$5[0] = viewportWidth;
72427
- tempVec4a$5[1] = viewportHeight;
72428
- tempVec4a$5[2] = sao.blendCutoff;
72429
- tempVec4a$5[3] = sao.blendFactor;
72430
- gl.uniform4fv(this._uSAOParams, tempVec4a$5);
73069
+ tempVec4a$6[0] = viewportWidth;
73070
+ tempVec4a$6[1] = viewportHeight;
73071
+ tempVec4a$6[2] = sao.blendCutoff;
73072
+ tempVec4a$6[3] = sao.blendFactor;
73073
+ gl.uniform4fv(this._uSAOParams, tempVec4a$6);
72431
73074
  this._program.bindTexture(this._uOcclusionTexture, frameCtx.occlusionTexture, 10);
72432
73075
  }
72433
73076
  }
@@ -75236,6 +75879,14 @@ class DTXTrianglesSnapRenderer {
75236
75879
  src.push("uvec4 flags = texelFetch (uObjectPerObjectColorsAndFlags, ivec2(objectIndexCoords.x*8+2, objectIndexCoords.y), 0);");
75237
75880
  src.push("uvec4 flags2 = texelFetch (uObjectPerObjectColorsAndFlags, ivec2(objectIndexCoords.x*8+3, objectIndexCoords.y), 0);");
75238
75881
 
75882
+ // flags.w = NOT_RENDERED | PICK
75883
+ // renderPass = PICK
75884
+
75885
+ src.push(`if (int(flags.w) != renderPass) {`);
75886
+ src.push(" gl_Position = vec4(3.0, 3.0, 3.0, 1.0);"); // Cull vertex
75887
+ src.push(" return;"); // Cull vertex
75888
+ src.push("}");
75889
+
75239
75890
  src.push("{");
75240
75891
 
75241
75892
  // get vertex base
@@ -75651,6 +76302,14 @@ class DTXTrianglesSnapInitRenderer {
75651
76302
  src.push("uvec4 flags = texelFetch (uObjectPerObjectColorsAndFlags, ivec2(objectIndexCoords.x*8+2, objectIndexCoords.y), 0);");
75652
76303
  src.push("uvec4 flags2 = texelFetch (uObjectPerObjectColorsAndFlags, ivec2(objectIndexCoords.x*8+3, objectIndexCoords.y), 0);");
75653
76304
 
76305
+ // flags.w = NOT_RENDERED | PICK
76306
+ // renderPass = PICK
76307
+
76308
+ src.push(`if (int(flags.w) != renderPass) {`);
76309
+ src.push(" gl_Position = vec4(3.0, 3.0, 3.0, 1.0);"); // Cull vertex
76310
+ src.push(" return;"); // Cull vertex
76311
+ src.push("}");
76312
+
75654
76313
  src.push("{");
75655
76314
 
75656
76315
  // get color
@@ -78654,6 +79313,7 @@ const INDICES_EDGE_INDICES_ALIGNEMENT_SIZE = 8;
78654
79313
  */
78655
79314
  const MAX_OBJECT_UPDATES_IN_FRAME_WITHOUT_BATCHED_UPDATE = 10;
78656
79315
 
79316
+ const tempVec4a$5 = math.vec4();
78657
79317
  const tempMat4a = new Float32Array(16);
78658
79318
  const tempUint8Array4 = new Uint8Array(4);
78659
79319
  const tempFloat32Array3 = new Float32Array(3);
@@ -78669,7 +79329,7 @@ class DTXTrianglesLayer {
78669
79329
 
78670
79330
  constructor(model, cfg) {
78671
79331
 
78672
- console.info("Creating DTXTrianglesLayer");
79332
+ //console.info("Creating DTXTrianglesLayer");
78673
79333
 
78674
79334
  dataTextureRamStats.numberOfLayers++;
78675
79335
 
@@ -78709,6 +79369,10 @@ class DTXTrianglesLayer {
78709
79369
 
78710
79370
  this._subPortions = [];
78711
79371
 
79372
+ if (this.model.scene.readableGeometryEnabled) {
79373
+ this._subPortionReadableGeometries = {};
79374
+ }
79375
+
78712
79376
  /**
78713
79377
  * Due to `index rebucketting` process in ```prepareMeshGeometry``` function, it's possible that a single
78714
79378
  * portion is expanded to more than 1 real sub-portion.
@@ -78738,6 +79402,11 @@ class DTXTrianglesLayer {
78738
79402
  */
78739
79403
  this._numUpdatesInFrame = 0;
78740
79404
 
79405
+ /**
79406
+ * The type of primitives in this layer.
79407
+ */
79408
+ this.primitive = cfg.primitive;
79409
+
78741
79410
  this._finalized = false;
78742
79411
  }
78743
79412
 
@@ -79042,6 +79711,15 @@ class DTXTrianglesLayer {
79042
79711
  numVertices: bucketGeometry.numTriangles
79043
79712
  });
79044
79713
 
79714
+ if (this.model.scene.readableGeometryEnabled) {
79715
+ this._subPortionReadableGeometries[subPortionId] = {
79716
+ indices: bucket.indices,
79717
+ positionsCompressed: bucket.positionsCompressed,
79718
+ positionsDecodeMatrix: portionCfg.positionsDecodeMatrix,
79719
+ meshMatrix: portionCfg.meshMatrix
79720
+ };
79721
+ }
79722
+
79045
79723
  this._numPortions++;
79046
79724
 
79047
79725
  dataTextureRamStats.numberOfPortions++;
@@ -79692,6 +80370,63 @@ class DTXTrianglesLayer {
79692
80370
  // gl.bindTexture (gl.TEXTURE_2D, null);
79693
80371
  }
79694
80372
 
80373
+ getEachVertex(portionId, callback) {
80374
+ if (!this.model.scene.readableGeometryEnabled) {
80375
+ return;
80376
+ }
80377
+ const state = this._state;
80378
+ const subPortionIds = this._portionToSubPortionsMap[portionId];
80379
+ if (!subPortionIds) {
80380
+ this.model.error("portion not found: " + portionId);
80381
+ return;
80382
+ }
80383
+ for (let i = 0, len = subPortionIds.length; i < len; i++) {
80384
+ const subPortionId = subPortionIds[i];
80385
+ const subPortionReadableGeometry = this._subPortionReadableGeometries[subPortionId];
80386
+ const positions = subPortionReadableGeometry.positionsCompressed;
80387
+ const positionsDecodeMatrix = subPortionReadableGeometry.positionsDecodeMatrix;
80388
+ subPortionReadableGeometry.meshMatrix;
80389
+ const origin = state.origin;
80390
+ const offsetX = origin[0] ;
80391
+ const offsetY = origin[1] ;
80392
+ const offsetZ = origin[2] ;
80393
+ const worldPos = tempVec4a$5;
80394
+ for (let i = 0, len = positions.length; i < len; i += 3) {
80395
+ worldPos[0] = positions[i];
80396
+ worldPos[1] = positions[i + 1];
80397
+ worldPos[2] = positions[i + 2];
80398
+ worldPos[3] = 1.0;
80399
+ math.decompressPosition(worldPos, positionsDecodeMatrix);
80400
+ math.transformPoint4(this.model.worldMatrix, worldPos);
80401
+ math.transformPoint4(this.model.worldMatrix, worldPos);
80402
+ worldPos[0] += offsetX;
80403
+ worldPos[1] += offsetY;
80404
+ worldPos[2] += offsetZ;
80405
+ callback(worldPos);
80406
+ }
80407
+ }
80408
+ }
80409
+
80410
+ getEachIndex(portionId, callback) {
80411
+ if (!this.model.scene.readableGeometryEnabled) {
80412
+ return;
80413
+ }
80414
+ const subPortionIds = this._portionToSubPortionsMap[portionId];
80415
+ if (!subPortionIds) {
80416
+ this.model.error("portion not found: " + portionId);
80417
+ return;
80418
+ }
80419
+ for (let i = 0, len = subPortionIds.length; i < len; i++) {
80420
+ const subPortionId = subPortionIds[i];
80421
+ const subPortionReadableGeometry = this._subPortionReadableGeometries[subPortionId];
80422
+ const indices = subPortionReadableGeometry.indices;
80423
+ for (let i = 0, len = indices.length; i < len; i++) {
80424
+ callback(indices[i]);
80425
+ }
80426
+ }
80427
+ }
80428
+
80429
+
79695
80430
  // ---------------------- COLOR RENDERING -----------------------------------
79696
80431
 
79697
80432
  drawColorOpaque(renderFlags, frameCtx) {
@@ -79967,6 +80702,11 @@ class SceneModelTextureSet {
79967
80702
  */
79968
80703
  this.colorTexture = cfg.colorTexture;
79969
80704
 
80705
+ /**
80706
+ * The alpha cutoff [float]
80707
+ */
80708
+ this.alphaCutoff = cfg.alphaCutoff;
80709
+
79970
80710
  /**
79971
80711
  * The metallic-roughness texture.
79972
80712
  * @type {SceneModelTexture|*}
@@ -83034,7 +83774,10 @@ class SceneModel extends Component {
83034
83774
  this._meshList = [];
83035
83775
 
83036
83776
  this.layerList = []; // For GL state efficiency when drawing, InstancingLayers are in first part, BatchingLayers are in second
83777
+ this._layersToFinalize = [];
83778
+
83037
83779
  this._entityList = [];
83780
+ this._entitiesToFinalize = [];
83038
83781
 
83039
83782
  this._geometries = {};
83040
83783
  this._dtxBuckets = {}; // Geometries with optimizations used for data texture representation
@@ -83110,6 +83853,7 @@ class SceneModel extends Component {
83110
83853
  this._numTriangles = 0;
83111
83854
  this._numLines = 0;
83112
83855
  this._numPoints = 0;
83856
+ this._layersFinalized = false;
83113
83857
 
83114
83858
  this._edgeThreshold = cfg.edgeThreshold || 10;
83115
83859
 
@@ -84519,6 +85263,7 @@ class SceneModel extends Component {
84519
85263
  id: textureSetId,
84520
85264
  model: this,
84521
85265
  colorTexture,
85266
+ alphaCutoff: cfg.alphaCutoff,
84522
85267
  metallicRoughnessTexture,
84523
85268
  normalsTexture,
84524
85269
  emissiveTexture,
@@ -84952,6 +85697,14 @@ class SceneModel extends Component {
84952
85697
  return this._createMesh(cfg);
84953
85698
  }
84954
85699
 
85700
+ _createDefaultIndices(numIndices) {
85701
+ const indices = [];
85702
+ for (let i = 0; i < numIndices; i++) {
85703
+ indices.push(i);
85704
+ }
85705
+ return indices;
85706
+ }
85707
+
84955
85708
  _createMesh(cfg) {
84956
85709
  const mesh = new SceneModelMesh(this, cfg.id, cfg.color, cfg.opacity, cfg.transform, cfg.textureSet);
84957
85710
  mesh.pickId = this.scene._renderer.getPickID(mesh);
@@ -85051,7 +85804,7 @@ class SceneModel extends Component {
85051
85804
  let dtxLayer = this._dtxLayers[layerId];
85052
85805
  if (dtxLayer) {
85053
85806
  if (!dtxLayer.canCreatePortion(cfg)) {
85054
- dtxLayer.finalize();
85807
+ // dtxLayer.finalize();
85055
85808
  delete this._dtxLayers[layerId];
85056
85809
  dtxLayer = null;
85057
85810
  } else {
@@ -85062,16 +85815,17 @@ class SceneModel extends Component {
85062
85815
  case "triangles":
85063
85816
  case "solid":
85064
85817
  case "surface":
85065
- dtxLayer = new DTXTrianglesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()
85818
+ dtxLayer = new DTXTrianglesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
85066
85819
  break;
85067
85820
  case "lines":
85068
- dtxLayer = new DTXLinesLayer(this, {layerIndex: 0, origin}); // layerIndex is set in #finalize()
85821
+ dtxLayer = new DTXLinesLayer(this, {layerIndex: 0, origin, primitive}); // layerIndex is set in #finalize()
85069
85822
  break;
85070
85823
  default:
85071
85824
  return;
85072
85825
  }
85073
85826
  this._dtxLayers[layerId] = dtxLayer;
85074
85827
  this.layerList.push(dtxLayer);
85828
+ this._layersToFinalize.push(dtxLayer);
85075
85829
  return dtxLayer;
85076
85830
  }
85077
85831
 
@@ -85103,7 +85857,8 @@ class SceneModel extends Component {
85103
85857
  origin,
85104
85858
  maxGeometryBatchSize: this._maxGeometryBatchSize,
85105
85859
  solid: (cfg.primitive === "solid"),
85106
- autoNormals: true
85860
+ autoNormals: true,
85861
+ primitive: cfg.primitive
85107
85862
  });
85108
85863
  break;
85109
85864
  case "solid":
@@ -85118,7 +85873,8 @@ class SceneModel extends Component {
85118
85873
  origin,
85119
85874
  maxGeometryBatchSize: this._maxGeometryBatchSize,
85120
85875
  solid: (cfg.primitive === "solid"),
85121
- autoNormals: true
85876
+ autoNormals: true,
85877
+ primitive: cfg.primitive
85122
85878
  });
85123
85879
  break;
85124
85880
  case "surface":
@@ -85133,7 +85889,8 @@ class SceneModel extends Component {
85133
85889
  origin,
85134
85890
  maxGeometryBatchSize: this._maxGeometryBatchSize,
85135
85891
  solid: (cfg.primitive === "solid"),
85136
- autoNormals: true
85892
+ autoNormals: true,
85893
+ primitive: cfg.primitive
85137
85894
  });
85138
85895
  break;
85139
85896
  case "lines":
@@ -85145,7 +85902,8 @@ class SceneModel extends Component {
85145
85902
  positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
85146
85903
  uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
85147
85904
  origin,
85148
- maxGeometryBatchSize: this._maxGeometryBatchSize
85905
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
85906
+ primitive: cfg.primitive
85149
85907
  });
85150
85908
  break;
85151
85909
  case "points":
@@ -85157,7 +85915,8 @@ class SceneModel extends Component {
85157
85915
  positionsDecodeMatrix: cfg.positionsDecodeMatrix, // Can be undefined
85158
85916
  uvDecodeMatrix: cfg.uvDecodeMatrix, // Can be undefined
85159
85917
  origin,
85160
- maxGeometryBatchSize: this._maxGeometryBatchSize
85918
+ maxGeometryBatchSize: this._maxGeometryBatchSize,
85919
+ primitive: cfg.primitive
85161
85920
  });
85162
85921
  break;
85163
85922
  }
@@ -85173,6 +85932,7 @@ class SceneModel extends Component {
85173
85932
  }
85174
85933
  this._vboBatchingLayers[layerId] = vboBatchingLayer;
85175
85934
  this.layerList.push(vboBatchingLayer);
85935
+ this._layersToFinalize.push(vboBatchingLayer);
85176
85936
  return vboBatchingLayer;
85177
85937
  }
85178
85938
 
@@ -85265,6 +86025,7 @@ class SceneModel extends Component {
85265
86025
  }
85266
86026
  this._vboInstancingLayers[layerId] = vboInstancingLayer;
85267
86027
  this.layerList.push(vboInstancingLayer);
86028
+ this._layersToFinalize.push(vboInstancingLayer);
85268
86029
  return vboInstancingLayer;
85269
86030
  }
85270
86031
 
@@ -85365,38 +86126,47 @@ class SceneModel extends Component {
85365
86126
  lodCullable); // Internally sets SceneModelEntity#parent to this SceneModel
85366
86127
  this._entityList.push(entity);
85367
86128
  this._entities[cfg.id] = entity;
86129
+ this._entitiesToFinalize.push(entity);
85368
86130
  this.numEntities++;
85369
86131
  }
85370
86132
 
85371
86133
  /**
85372
- * Finalizes this SceneModel.
85373
- *
85374
- * Once finalized, you can't add anything more to this SceneModel.
86134
+ * Pre-renders all meshes that have been added, even if the SceneModel has not bee finalized yet.
86135
+ * This is use for progressively showing the SceneModel while it is being loaded or constructed.
86136
+ * @returns {boolean}
85375
86137
  */
85376
- finalize() {
86138
+ preFinalize() {
85377
86139
  if (this.destroyed) {
85378
- return;
86140
+ return false;
86141
+ }
86142
+ if (this._layersToFinalize.length === 0) {
86143
+ return false;
85379
86144
  }
85380
86145
  this._createDummyEntityForUnusedMeshes();
85381
- for (let i = 0, len = this.layerList.length; i < len; i++) {
85382
- const layer = this.layerList[i];
86146
+ for (let i = 0, len = this._layersToFinalize.length; i < len; i++) {
86147
+ const layer = this._layersToFinalize[i];
85383
86148
  layer.finalize();
85384
86149
  }
85385
- this._geometries = {};
85386
- this._dtxBuckets = {};
85387
- this._textures = {};
85388
- this._textureSets = {};
85389
- this._dtxLayers = {};
85390
- this._vboInstancingLayers = {};
85391
86150
  this._vboBatchingLayers = {};
85392
- for (let i = 0, len = this._entityList.length; i < len; i++) {
85393
- const entity = this._entityList[i];
86151
+ this._vboInstancingLayers = {};
86152
+ this._dtxLayers = {};
86153
+ this._layersToFinalize = [];
86154
+ for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
86155
+ const entity = this._entitiesToFinalize[i];
85394
86156
  entity._finalize();
85395
86157
  }
85396
- for (let i = 0, len = this._entityList.length; i < len; i++) {
85397
- const entity = this._entityList[i];
86158
+ for (let i = 0, len = this._entitiesToFinalize.length; i < len; i++) {
86159
+ const entity = this._entitiesToFinalize[i];
85398
86160
  entity._finalize2();
85399
86161
  }
86162
+ this._entitiesToFinalize = [];
86163
+ this.scene._aabbDirty = true;
86164
+ this._viewMatrixDirty = true;
86165
+ this._matrixDirty = true;
86166
+ this._aabbDirty = true;
86167
+ this._setWorldMatrixDirty();
86168
+ this._sceneModelDirty();
86169
+ this.position = this._position;
85400
86170
  // Sort layers to reduce WebGL shader switching when rendering them
85401
86171
  this.layerList.sort((a, b) => {
85402
86172
  if (a.sortId < b.sortId) {
@@ -85412,15 +86182,23 @@ class SceneModel extends Component {
85412
86182
  layer.layerIndex = i;
85413
86183
  }
85414
86184
  this.glRedraw();
85415
- this.scene._aabbDirty = true;
85416
- this._viewMatrixDirty = true;
85417
- this._matrixDirty = true;
85418
- this._aabbDirty = true;
85419
-
85420
- this._setWorldMatrixDirty();
85421
- this._sceneModelDirty();
86185
+ this._layersFinalized = true;
86186
+ }
85422
86187
 
85423
- this.position = this._position;
86188
+ /**
86189
+ * Finalizes this SceneModel.
86190
+ *
86191
+ * Once finalized, you can't add anything more to this SceneModel.
86192
+ */
86193
+ finalize() {
86194
+ if (this.destroyed) {
86195
+ return;
86196
+ }
86197
+ this.preFinalize();
86198
+ this._geometries = {};
86199
+ this._dtxBuckets = {};
86200
+ this._textures = {};
86201
+ this._textureSets = {};
85424
86202
  }
85425
86203
 
85426
86204
  /** @private */
@@ -85458,7 +86236,7 @@ class SceneModel extends Component {
85458
86236
  _createDummyEntityForUnusedMeshes() {
85459
86237
  const unusedMeshIds = Object.keys(this._unusedMeshes);
85460
86238
  if (unusedMeshIds.length > 0) {
85461
- const entityId = `${this.id}-dummyEntityForUnusedMeshes`;
86239
+ const entityId = `${this.id}-${math.createUUID()}`;
85462
86240
  this.warn(`Creating dummy SceneModelEntity "${entityId}" for unused SceneMeshes: [${unusedMeshIds.join(",")}]`);
85463
86241
  this.createEntity({
85464
86242
  id: entityId,
@@ -85830,6 +86608,7 @@ class SceneModel extends Component {
85830
86608
  for (let i = 0, len = this._entityList.length; i < len; i++) {
85831
86609
  this._entityList[i]._destroy();
85832
86610
  }
86611
+ this._layersToFinalize = {};
85833
86612
  // Object.entries(this._geometries).forEach(([id, geometry]) => {
85834
86613
  // geometry.destroy();
85835
86614
  // });
@@ -88327,12 +89106,6 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88327
89106
 
88328
89107
  this._initMarkerDiv();
88329
89108
 
88330
- this._onCameraControlHoverSnapOrSurface = null;
88331
- this._onCameraControlHoverSnapOrSurfaceOff = null;
88332
- this._onMouseDown = null;
88333
- this._onMouseUp = null;
88334
- this._onCanvasTouchStart = null;
88335
- this._onCanvasTouchEnd = null;
88336
89109
  this._snapping = cfg.snapping !== false;
88337
89110
  this._mouseState = MOUSE_FIRST_CLICK_EXPECTED;
88338
89111
 
@@ -88396,20 +89169,10 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88396
89169
  *
88397
89170
  * This is `true` by default.
88398
89171
  *
88399
- * Internally, this deactivates then activates the DistanceMeasurementsMouseControl when changed, which means that
88400
- * it will destroy any DistanceMeasurements currently under construction, and incurs some overhead, since it unbinds
88401
- * and rebinds various input handlers.
88402
- *
88403
89172
  * @param snapping
88404
89173
  */
88405
89174
  set snapping(snapping) {
88406
- if (snapping !== this._snapping) {
88407
- this._snapping = snapping;
88408
- this.deactivate();
88409
- this.activate();
88410
- } else {
88411
- this._snapping = snapping;
88412
- }
89175
+ this._snapping = snapping;
88413
89176
  }
88414
89177
 
88415
89178
  /**
@@ -88421,7 +89184,7 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88421
89184
  get snapping() {
88422
89185
  return this._snapping;
88423
89186
  }
88424
-
89187
+
88425
89188
  /**
88426
89189
  * Activates this DistanceMeasurementsMouseControl, ready to respond to input.
88427
89190
  */
@@ -88456,11 +89219,8 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88456
89219
  const getLeft = el => el.offsetLeft + (el.offsetParent && (el.offsetParent !== canvas.parentNode) && getLeft(el.offsetParent));
88457
89220
 
88458
89221
  const pagePos = math.vec2();
88459
-
88460
- this._onCameraControlHoverSnapOrSurface = cameraControl.on(
88461
- this._snapping
88462
- ? "hoverSnapOrSurface"
88463
- : "hoverSurface", event => {
89222
+
89223
+ const hoverOn = event => {
88464
89224
  const canvasPos = event.snappedCanvasPos || event.canvasPos;
88465
89225
  mouseHovering = true;
88466
89226
  pointerWorldPos.set(event.worldPos);
@@ -88513,7 +89273,9 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88513
89273
  this._markerDiv.style.left = `-10000px`;
88514
89274
  this._markerDiv.style.top = `-10000px`;
88515
89275
  }
88516
- });
89276
+ };
89277
+ this._onHoverSnapOrSurface = cameraControl.on("hoverSnapOrSurface", e => { if (this._snapping) hoverOn(e); });
89278
+ this._onHoverSurface = cameraControl.on("hoverSurface", e => { if (! this._snapping) hoverOn(e); });
88517
89279
 
88518
89280
  canvas.addEventListener('mousedown', this._onMouseDown = (e) => {
88519
89281
  if (e.which !== 1) {
@@ -88574,10 +89336,7 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88574
89336
  }
88575
89337
  });
88576
89338
 
88577
- this._onCameraControlHoverSnapOrSurfaceOff = cameraControl.on(
88578
- this._snapping
88579
- ? "hoverSnapOrSurfaceOff"
88580
- : "hoverOff", event => {
89339
+ const hoverOff = event => {
88581
89340
  if (this.pointerLens) {
88582
89341
  this.pointerLens.visible = true;
88583
89342
  this.pointerLens.canvasPos = event.canvasPos;
@@ -88592,7 +89351,9 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88592
89351
  this._currentDistanceMeasurement.axisVisible = false;
88593
89352
  }
88594
89353
  canvas.style.cursor = "default";
88595
- });
89354
+ };
89355
+ this._onHoverSnapOrSurfaceOff = cameraControl.on("hoverSnapOrSurfaceOff", e => { if (this._snapping) hoverOff(e); });
89356
+ this._onHoverOff = cameraControl.on("hoverOff", e => { if (! this._snapping) hoverOff(e); });
88596
89357
 
88597
89358
  this._active = true;
88598
89359
  }
@@ -88606,27 +89367,24 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
88606
89367
  if (!this._active) {
88607
89368
  return;
88608
89369
  }
88609
-
89370
+
88610
89371
  this.fire("activated", false);
88611
89372
 
88612
89373
  if (this.pointerLens) {
88613
89374
  this.pointerLens.visible = false;
88614
89375
  }
88615
- // if (this._markerDiv) {
88616
- // this._destroyMarkerDiv()
88617
- // }
88618
- // this.reset();
89376
+
89377
+ this.reset();
89378
+
88619
89379
  const canvas = this.scene.canvas.canvas;
88620
89380
  canvas.removeEventListener("mousedown", this._onMouseDown);
88621
89381
  canvas.removeEventListener("mouseup", this._onMouseUp);
88622
89382
  const cameraControl = this.distanceMeasurementsPlugin.viewer.cameraControl;
88623
- cameraControl.off(this._onCameraControlHoverSnapOrSurface);
88624
- cameraControl.off(this._onCameraControlHoverSnapOrSurfaceOff);
88625
- // if (this._currentDistanceMeasurement) {
88626
- // this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
88627
- // this._currentDistanceMeasurement.destroy();
88628
- // this._currentDistanceMeasurement = null;
88629
- // }
89383
+ cameraControl.off(this._onHoverSnapOrSurface);
89384
+ cameraControl.off(this._onHoverSurface);
89385
+ cameraControl.off(this._onHoverSnapOrSurfaceOff);
89386
+ cameraControl.off(this._onHoverOff);
89387
+
88630
89388
  this._active = false;
88631
89389
  }
88632
89390
 
@@ -89310,11 +90068,8 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
89310
90068
  targetVisible: null,
89311
90069
  };
89312
90070
 
89313
- this._onCanvasTouchStart = null;
89314
- this._onCanvasTouchEnd = null;
89315
90071
  this._longTouchTimeoutMs = 300;
89316
90072
  this._snapping = cfg.snapping !== false;
89317
- this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
89318
90073
 
89319
90074
  this._attachPlugin(distanceMeasurementsPlugin, cfg);
89320
90075
  }
@@ -89347,20 +90102,10 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
89347
90102
  *
89348
90103
  * This is `true` by default.
89349
90104
  *
89350
- * Internally, this deactivates then activates the DistanceMeasurementsTouchControl when changed, which means that
89351
- * it will destroy any DistanceMeasurements currently under construction, and incurs some overhead, since it unbinds
89352
- * and rebinds various input handlers.
89353
- *
89354
90105
  * @param {boolean} snapping Whether to enable snap-to-vertex and snap-edge for this DistanceMeasurementsTouchControl.
89355
90106
  */
89356
90107
  set snapping(snapping) {
89357
- if (snapping !== this._snapping) {
89358
- this._snapping = snapping;
89359
- this.deactivate();
89360
- this.activate();
89361
- } else {
89362
- this._snapping = snapping;
89363
- }
90108
+ this._snapping = snapping;
89364
90109
  }
89365
90110
 
89366
90111
  /**
@@ -89972,14 +90717,11 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
89972
90717
  this.plugin.pointerLens.visible = false;
89973
90718
  }
89974
90719
  this.reset();
90720
+
89975
90721
  const canvas = this.plugin.viewer.scene.canvas.canvas;
89976
90722
  canvas.removeEventListener("touchstart", this._onCanvasTouchStart);
89977
90723
  canvas.removeEventListener("touchend", this._onCanvasTouchEnd);
89978
- if (this._currentDistanceMeasurement) {
89979
- this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
89980
- this._currentDistanceMeasurement.destroy();
89981
- this._currentDistanceMeasurement = null;
89982
- }
90724
+
89983
90725
  this._active = false;
89984
90726
  this.plugin.viewer.cameraControl.active = true;
89985
90727
  }
@@ -89995,12 +90737,12 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
89995
90737
  if (!this._active) {
89996
90738
  return;
89997
90739
  }
90740
+
89998
90741
  if (this._currentDistanceMeasurement) {
89999
90742
  this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
90000
90743
  this._currentDistanceMeasurement.destroy();
90001
90744
  this._currentDistanceMeasurement = null;
90002
90745
  }
90003
- this._mouseState = WAITING_FOR_ORIGIN_TOUCH_START;
90004
90746
  }
90005
90747
 
90006
90748
  /**
@@ -101012,8 +101754,6 @@ class MetaScene {
101012
101754
  * @param {String} modelId ID for the new {@link MetaModel}, which will have {@link MetaModel#id} set to this value.
101013
101755
  * @param {Object} metaModelData Data for the {@link MetaModel}.
101014
101756
  * @param {Object} [options] Options for creating the {@link MetaModel}.
101015
- * @param {Object} [options.includeTypes] When provided, only create {@link MetaObject}s with types in this list.
101016
- * @param {Object} [options.excludeTypes] When provided, never create {@link MetaObject}s with types in this list.
101017
101757
  * @param {Boolean} [options.globalizeObjectIds=false] Whether to globalize each {@link MetaObject#id}. Set this ````true```` when you need to load multiple instances of the same meta model, to avoid ID clashes between the meta objects in the different instances.
101018
101758
  * @returns {MetaModel} The new MetaModel.
101019
101759
  */
@@ -109086,7 +109826,7 @@ class Viewer {
109086
109826
  * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.
109087
109827
  * @param {Boolean} [cfg.alphaDepthMask=true] Whether writing into the depth buffer is enabled or disabled when rendering transparent objects.
109088
109828
  * @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}.
109089
- * @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````.
109829
+ * @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````.
109090
109830
  * @param {Boolean} [cfg.logarithmicDepthBufferEnabled=false] Whether to enable logarithmic depth buffer. When this is true,
109091
109831
  * you can set huge values for {@link Perspective#far} and {@link Ortho#far}, to push the far clipping plane back so
109092
109832
  * that it does not clip huge models.
@@ -109156,7 +109896,7 @@ class Viewer {
109156
109896
  saoEnabled: cfg.saoEnabled,
109157
109897
  alphaDepthMask: (cfg.alphaDepthMask !== false),
109158
109898
  entityOffsetsEnabled: (!!cfg.entityOffsetsEnabled),
109159
- pickSurfacePrecisionEnabled: (!!cfg.pickSurfacePrecisionEnabled),
109899
+ readableGeometryEnabled: (!!cfg.readableGeometryEnabled),
109160
109900
  logarithmicDepthBufferEnabled: (!!cfg.logarithmicDepthBufferEnabled),
109161
109901
  pbrEnabled: (!!cfg.pbrEnabled),
109162
109902
  colorTextureEnabled: (cfg.colorTextureEnabled !== false),
@@ -116999,40 +117739,6 @@ class GLTFSceneModelLoader {
116999
117739
  }
117000
117740
  }
117001
117741
 
117002
- function getMetaModelCorrections(metaModelJSON) {
117003
- const eachRootStats = {};
117004
- const eachChildRoot = {};
117005
- const metaObjects = metaModelJSON.metaObjects || [];
117006
- const metaObjectsMap = {};
117007
- for (let i = 0, len = metaObjects.length; i < len; i++) {
117008
- const metaObject = metaObjects[i];
117009
- metaObjectsMap[metaObject.id] = metaObject;
117010
- }
117011
- for (let i = 0, len = metaObjects.length; i < len; i++) {
117012
- const metaObject = metaObjects[i];
117013
- if (metaObject.parent !== undefined && metaObject.parent !== null) {
117014
- const metaObjectParent = metaObjectsMap[metaObject.parent];
117015
- if (metaObject.type === metaObjectParent.type) {
117016
- let rootMetaObject = metaObjectParent;
117017
- while (rootMetaObject.parent && metaObjectsMap[rootMetaObject.parent].type === rootMetaObject.type) {
117018
- rootMetaObject = metaObjectsMap[rootMetaObject.parent];
117019
- }
117020
- const rootStats = eachRootStats[rootMetaObject.id] || (eachRootStats[rootMetaObject.id] = {
117021
- numChildren: 0,
117022
- countChildren: 0
117023
- });
117024
- rootStats.numChildren++;
117025
- eachChildRoot[metaObject.id] = rootMetaObject;
117026
- }
117027
- }
117028
- }
117029
- return {
117030
- metaObjectsMap,
117031
- eachRootStats,
117032
- eachChildRoot
117033
- };
117034
- }
117035
-
117036
117742
  function loadGLTF(plugin, src, metaModelJSON, options, sceneModel, ok, error) {
117037
117743
  const spinner = plugin.viewer.scene.canvas.spinner;
117038
117744
  spinner.processes++;
@@ -117074,7 +117780,9 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok) {
117074
117780
  const ctx = {
117075
117781
  src: src,
117076
117782
  entityId: options.entityId,
117077
- metaModelCorrections: metaModelJSON ? getMetaModelCorrections(metaModelJSON) : null,
117783
+ metaModelJSON,
117784
+ autoMetaModel: options.autoMetaModel,
117785
+ metaObjects: [],
117078
117786
  loadBuffer: options.loadBuffer,
117079
117787
  basePath: options.basePath,
117080
117788
  handlenode: options.handlenode,
@@ -117093,8 +117801,20 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok) {
117093
117801
  };
117094
117802
  loadTextures(ctx);
117095
117803
  loadMaterials(ctx);
117804
+ if (options.autoMetaModel) {
117805
+ ctx.metaObjects.push({
117806
+ id: sceneModel.id,
117807
+ type: "Default",
117808
+ name: sceneModel.id
117809
+ });
117810
+ }
117096
117811
  loadDefaultScene(ctx);
117097
117812
  sceneModel.finalize();
117813
+ if (options.autoMetaModel) {
117814
+ plugin.viewer.metaScene.createMetaModel(sceneModel.id, {
117815
+ metaObjects: ctx.metaObjects
117816
+ });
117817
+ }
117098
117818
  spinner.processes--;
117099
117819
  ok();
117100
117820
  });
@@ -117223,23 +117943,17 @@ function loadTextureSet(ctx, material) {
117223
117943
  if (material.emissiveTexture) {
117224
117944
  textureSetCfg.emissiveTextureId = material.emissiveTexture.texture._textureId;
117225
117945
  }
117226
- // const alphaMode = material.alphaMode;
117227
- // switch (alphaMode) {
117228
- // case "NORMAL_OPAQUE":
117229
- // materialCfg.alphaMode = "opaque";
117230
- // break;
117231
- // case "MASK":
117232
- // materialCfg.alphaMode = "mask";
117233
- // break;
117234
- // case "BLEND":
117235
- // materialCfg.alphaMode = "blend";
117236
- // break;
117237
- // default:
117238
- // }
117239
- // const alphaCutoff = material.alphaCutoff;
117240
- // if (alphaCutoff !== undefined) {
117241
- // materialCfg.alphaCutoff = alphaCutoff;
117242
- // }
117946
+
117947
+ switch (material.alphaMode) {
117948
+ case "OPAQUE":
117949
+ break;
117950
+ case "MASK":
117951
+ const alphaCutoff = material.alphaCutoff;
117952
+ // Default from the spec https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-material
117953
+ textureSetCfg.alphaCutoff = (alphaCutoff !== undefined) ? alphaCutoff : 0.5;
117954
+ break;
117955
+ }
117956
+
117243
117957
  const metallicPBR = material.pbrMetallicRoughness;
117244
117958
  if (material.pbrMetallicRoughness) {
117245
117959
  const pbrMetallicRoughness = material.pbrMetallicRoughness;
@@ -117285,7 +117999,7 @@ function loadMaterialAttributes(ctx, material) { // Substitute RGBA for material
117285
117999
  opacity: 1,
117286
118000
  metallic: 0,
117287
118001
  roughness: 1,
117288
- doubleSided : true
118002
+ doubleSided: true
117289
118003
  };
117290
118004
  if (extensions) {
117291
118005
  const specularPBR = extensions["KHR_materials_pbrSpecularGlossiness"];
@@ -117359,9 +118073,22 @@ function loadScene(ctx, scene) {
117359
118073
  const node = nodes[i];
117360
118074
  countMeshUsage(ctx, node);
117361
118075
  }
117362
- for (let i = 0, len = nodes.length; i < len; i++) {
118076
+ for (let i = 0, len = nodes.length; i < len && !ctx.nodesHaveNames; i++) {
117363
118077
  const node = nodes[i];
117364
- loadNode(ctx, node, 0, null);
118078
+ if (testIfNodesHaveNames(node)) {
118079
+ ctx.nodesHaveNames = true;
118080
+ }
118081
+ }
118082
+ if (!ctx.nodesHaveNames) {
118083
+ for (let i = 0, len = nodes.length; i < len; i++) {
118084
+ const node = nodes[i];
118085
+ parseNodesWithoutNames(ctx, node, 0, null);
118086
+ }
118087
+ } else {
118088
+ for (let i = 0, len = nodes.length; i < len; i++) {
118089
+ const node = nodes[i];
118090
+ parseNodesWithNames(ctx, node, 0, null);
118091
+ }
117365
118092
  }
117366
118093
  }
117367
118094
 
@@ -117383,10 +118110,131 @@ function countMeshUsage(ctx, node) {
117383
118110
  }
117384
118111
  }
117385
118112
 
117386
- const deferredMeshIds = [];
118113
+ function testIfNodesHaveNames(node) {
118114
+ if (node.name) {
118115
+ return true;
118116
+ }
118117
+ if (node.children) {
118118
+ const children = node.children;
118119
+ for (let i = 0, len = children.length; i < len; i++) {
118120
+ const childNode = children[i];
118121
+ if (testIfNodesHaveNames(childNode)) {
118122
+ return true;
118123
+ }
118124
+ }
118125
+ }
118126
+ return false;
118127
+ }
118128
+
118129
+ /**
118130
+ * Parses a glTF node hierarchy that is known to NOT contain "name" attributes on the nodes.
118131
+ * Create a SceneMesh for each mesh primitive, and a single SceneObject.
118132
+ */
118133
+ const parseNodesWithoutNames = (function () {
118134
+ const meshIds = [];
118135
+ return function (ctx, node, depth, matrix, parentNode) {
118136
+ matrix = parseNodeMatrix(node, matrix);
118137
+ if (node.mesh) {
118138
+ parseNodeMesh(node, ctx, matrix, meshIds);
118139
+ }
118140
+ if (node.children) {
118141
+ const children = node.children;
118142
+ for (let i = 0, len = children.length; i < len; i++) {
118143
+ const childNode = children[i];
118144
+ parseNodesWithoutNames(ctx, childNode, depth + 1, matrix, node);
118145
+ }
118146
+ }
118147
+ if (depth === 0) {
118148
+ let entityId = "entity-" + ctx.nextId++;
118149
+ if (meshIds && meshIds.length > 0) {
118150
+ ctx.sceneModel.createEntity({
118151
+ id: entityId,
118152
+ meshIds,
118153
+ isObject: true
118154
+ });
118155
+ if (ctx.autoMetaModel) {
118156
+ ctx.metaObjects.push({
118157
+ id: entityId,
118158
+ type: "Default",
118159
+ name: entityId,
118160
+ parent: ctx.sceneModel.id
118161
+ });
118162
+ }
118163
+ meshIds.length = 0;
118164
+ }
118165
+ }
118166
+ }
118167
+ })();
117387
118168
 
117388
- function loadNode(ctx, node, depth, matrix) {
117389
- ctx.gltfData;
118169
+ const parseNodesWithNames = (function () {
118170
+
118171
+ const objectIdStack = [];
118172
+ const meshIdsStack = [];
118173
+ let meshIds = null;
118174
+
118175
+ return function (ctx, node, depth, matrix) {
118176
+ matrix = parseNodeMatrix(node, matrix);
118177
+ if (meshIds && node.mesh) {
118178
+ parseNodeMesh(node, ctx, matrix, meshIds);
118179
+ }
118180
+
118181
+ if (node.name) {
118182
+ meshIds = [];
118183
+ let entityId = node.name;
118184
+ if (!!entityId && ctx.sceneModel.objects[entityId]) ;
118185
+ while (!entityId || ctx.sceneModel.objects[entityId]) {
118186
+ entityId = "entity-" + ctx.nextId++;
118187
+ }
118188
+ objectIdStack.push(entityId);
118189
+ meshIdsStack.push(meshIds);
118190
+ }
118191
+
118192
+ if (node.children) {
118193
+ const children = node.children;
118194
+ for (let i = 0, len = children.length; i < len; i++) {
118195
+ const childNode = children[i];
118196
+ parseNodesWithNames(ctx, childNode, depth + 1, matrix);
118197
+ }
118198
+ }
118199
+
118200
+ // Post-order visit scene node
118201
+
118202
+ const nodeName = node.name;
118203
+ if ((nodeName !== undefined && nodeName !== null) || depth === 0) {
118204
+ let entityId = objectIdStack.pop();
118205
+ if (!entityId) { // For when there are no nodes with names
118206
+ entityId = "entity-" + ctx.nextId++;
118207
+ }
118208
+ let entityMeshIds = meshIdsStack.pop();
118209
+ if (meshIds && meshIds.length > 0) {
118210
+ ctx.sceneModel.createEntity({
118211
+ id: entityId,
118212
+ meshIds: entityMeshIds,
118213
+ isObject: true
118214
+ });
118215
+ if (ctx.autoMetaModel) {
118216
+ ctx.metaObjects.push({
118217
+ id: entityId,
118218
+ type: "Default",
118219
+ name: entityId,
118220
+ parent: ctx.sceneModel.id
118221
+ });
118222
+ }
118223
+ }
118224
+ meshIds = meshIdsStack.length > 0 ? meshIdsStack[meshIdsStack.length - 1] : null;
118225
+ }
118226
+ };
118227
+ })();
118228
+
118229
+
118230
+ /**
118231
+ * Parses transform at the given glTF node.
118232
+ *
118233
+ * @param node the glTF node
118234
+ * @param matrix Transfor matrix from parent nodes
118235
+ * @returns {*} Transform matrix for the node
118236
+ */
118237
+ function parseNodeMatrix(node, matrix) {
117390
118238
  let localMatrix;
117391
118239
  if (node.matrix) {
117392
118240
  localMatrix = node.matrix;
@@ -117420,171 +118268,92 @@ function loadNode(ctx, node, depth, matrix) {
117420
118268
  matrix = localMatrix;
117421
118269
  }
117422
118270
  }
118271
+ return matrix;
118272
+ }
117423
118273
 
117424
- const sceneModel = ctx.sceneModel;
117425
- if (node.mesh) {
117426
- const mesh = node.mesh;
117427
- if (ctx.handlenode) {
117428
- const actions = {};
117429
- if (!ctx.handlenode(ctx.sceneModel.id, node, actions)) {
117430
- return;
117431
- }
117432
- if (actions.createEntity) ;
117433
- }
117434
- const worldMatrix = matrix ? matrix.slice() : math.identityMat4();
117435
- const numPrimitives = mesh.primitives.length;
117436
-
117437
- if (numPrimitives > 0) {
117438
-
117439
- for (let i = 0; i < numPrimitives; i++) {
117440
-
117441
- const primitive = mesh.primitives[i];
117442
- if (primitive.mode < 4) {
117443
- continue;
117444
- }
117445
-
117446
- const meshCfg = {
117447
- id: sceneModel.id + "." + ctx.numObjects++
117448
- };
117449
-
117450
- const material = primitive.material;
117451
- if (material) {
117452
- meshCfg.textureSetId = material._textureSetId;
117453
- meshCfg.color = material._attributes.color;
117454
- meshCfg.opacity = material._attributes.opacity;
117455
- meshCfg.metallic = material._attributes.metallic;
117456
- meshCfg.roughness = material._attributes.roughness;
117457
- } else {
117458
- meshCfg.color = new Float32Array([1.0, 1.0, 1.0]);
117459
- meshCfg.opacity = 1.0;
117460
- }
117461
-
117462
- const backfaces = ((ctx.backfaces !== false) || (material && material.doubleSided !== false));
117463
-
117464
- switch (primitive.mode) {
117465
- case 0: // POINTS
117466
- meshCfg.primitive = "points";
117467
- break;
117468
- case 1: // LINES
117469
- meshCfg.primitive = "lines";
117470
- break;
117471
- case 2: // LINE_LOOP
117472
- meshCfg.primitive = "lines";
117473
- break;
117474
- case 3: // LINE_STRIP
117475
- meshCfg.primitive = "lines";
117476
- break;
117477
- case 4: // TRIANGLES
117478
- meshCfg.primitive = backfaces ? "triangles" : "solid";
117479
- break;
117480
- case 5: // TRIANGLE_STRIP
117481
- meshCfg.primitive = backfaces ? "triangles" : "solid";
117482
- break;
117483
- case 6: // TRIANGLE_FAN
117484
- meshCfg.primitive = backfaces ? "triangles" : "solid";
117485
- break;
117486
- default:
117487
- meshCfg.primitive = backfaces ? "triangles" : "solid";
117488
- }
117489
-
117490
- const POSITION = primitive.attributes.POSITION;
117491
- if (!POSITION) {
117492
- continue;
117493
- }
117494
- meshCfg.localPositions = POSITION.value;
117495
- meshCfg.positions = new Float64Array(meshCfg.localPositions.length);
117496
-
117497
- if (primitive.attributes.NORMAL) {
117498
- meshCfg.normals = primitive.attributes.NORMAL.value;
117499
- }
117500
-
117501
- if (primitive.attributes.TEXCOORD_0) {
117502
- meshCfg.uv = primitive.attributes.TEXCOORD_0.value;
117503
- }
117504
-
117505
- if (primitive.indices) {
117506
- meshCfg.indices = primitive.indices.value;
117507
- }
117508
-
117509
- math.transformPositions3(worldMatrix, meshCfg.localPositions, meshCfg.positions);
117510
- const origin = math.vec3();
117511
- const rtcNeeded = worldToRTCPositions(meshCfg.positions, meshCfg.positions, origin); // Small cellsize guarantees better accuracy
117512
- if (rtcNeeded) {
117513
- meshCfg.origin = origin;
117514
- }
117515
-
117516
- sceneModel.createMesh(meshCfg);
117517
- deferredMeshIds.push(meshCfg.id);
117518
- }
117519
- }
117520
- }
117521
-
117522
- if (node.children) {
117523
- const children = node.children;
117524
- for (let i = 0, len = children.length; i < len; i++) {
117525
- const childNode = children[i];
117526
- loadNode(ctx, childNode, depth + 1, matrix);
117527
- }
118274
+ /**
118275
+ * Parses primitives referenced by the mesh belonging to the given node, creating XKTMeshes in the XKTModel.
118276
+ *
118277
+ * @param node glTF node
118278
+ * @param ctx Parsing context
118279
+ * @param matrix Matrix for the XKTMeshes
118280
+ * @param meshIds returns IDs of the new XKTMeshes
118281
+ */
118282
+ function parseNodeMesh(node, ctx, matrix, meshIds) {
118283
+ const mesh = node.mesh;
118284
+ if (!mesh) {
118285
+ return;
117528
118286
  }
117529
-
117530
- // Post-order visit scene node
117531
-
117532
- if (ctx.entityId) {
117533
- if (depth ===0) {
117534
- sceneModel.createEntity({
117535
- id: ctx.entityId,
117536
- meshIds: deferredMeshIds,
117537
- isObject: true
117538
- });
117539
- deferredMeshIds.length = 0;
117540
- }
117541
- } else {
117542
- const nodeName = node.name;
117543
- if (((nodeName !== undefined && nodeName !== null) || depth === 0) && deferredMeshIds.length > 0) {
117544
- if (nodeName === undefined || nodeName === null) {
117545
- ctx.log(`Warning: 'name' properties not found on glTF scene nodes - will randomly-generate object IDs in XKT`);
118287
+ const numPrimitives = mesh.primitives.length;
118288
+ if (numPrimitives > 0) {
118289
+ for (let i = 0; i < numPrimitives; i++) {
118290
+ const primitive = mesh.primitives[i];
118291
+ if (primitive.mode < 4) {
118292
+ continue;
117546
118293
  }
117547
- let entityId = nodeName; // Fall back on generated ID when `name` not found on glTF scene node(s)
117548
- // if (!!entityId && sceneModel.entities[entityId]) {
117549
- // ctx.log(`Warning: Two or more glTF nodes found with same 'name' attribute: '${nodeName} - will randomly-generating an object ID in XKT`);
117550
- // }
117551
- // while (!entityId || sceneModel.entities[entityId]) {
117552
- // entityId = "entity-" + ctx.nextId++;
117553
- // }
117554
- if (ctx.metaModelCorrections) {
117555
- // Merging meshes into XKTObjects that map to metaobjects
117556
- const rootMetaObject = ctx.metaModelCorrections.eachChildRoot[entityId];
117557
- if (rootMetaObject) {
117558
- const rootMetaObjectStats = ctx.metaModelCorrections.eachRootStats[rootMetaObject.id];
117559
- rootMetaObjectStats.countChildren++;
117560
- if (rootMetaObjectStats.countChildren >= rootMetaObjectStats.numChildren) {
117561
- sceneModel.createEntity({
117562
- id: rootMetaObject.id,
117563
- meshIds: deferredMeshIds,
117564
- isObject: true
117565
- });
117566
- deferredMeshIds.length = 0;
117567
- }
117568
- } else {
117569
- const metaObject = ctx.metaModelCorrections.metaObjectsMap[entityId];
117570
- if (metaObject) {
117571
- sceneModel.createEntity({
117572
- id: entityId,
117573
- meshIds: deferredMeshIds,
117574
- isObject: true
117575
- });
117576
- deferredMeshIds.length = 0;
117577
- }
117578
- }
118294
+ const meshCfg = {
118295
+ id: ctx.sceneModel.id + "." + ctx.numObjects++
118296
+ };
118297
+ const material = primitive.material;
118298
+ if (material) {
118299
+ meshCfg.textureSetId = material._textureSetId;
118300
+ meshCfg.color = material._attributes.color;
118301
+ meshCfg.opacity = material._attributes.opacity;
118302
+ meshCfg.metallic = material._attributes.metallic;
118303
+ meshCfg.roughness = material._attributes.roughness;
117579
118304
  } else {
117580
- // Create an XKTObject from the meshes at each named glTF node, don't care about metaobjects
117581
- sceneModel.createEntity({
117582
- id: entityId,
117583
- meshIds: deferredMeshIds,
117584
- isObject: true
117585
- });
117586
- deferredMeshIds.length = 0;
118305
+ meshCfg.color = new Float32Array([1.0, 1.0, 1.0]);
118306
+ meshCfg.opacity = 1.0;
118307
+ }
118308
+ const backfaces = ((ctx.backfaces !== false) || (material && material.doubleSided !== false));
118309
+ switch (primitive.mode) {
118310
+ case 0: // POINTS
118311
+ meshCfg.primitive = "points";
118312
+ break;
118313
+ case 1: // LINES
118314
+ meshCfg.primitive = "lines";
118315
+ break;
118316
+ case 2: // LINE_LOOP
118317
+ meshCfg.primitive = "lines";
118318
+ break;
118319
+ case 3: // LINE_STRIP
118320
+ meshCfg.primitive = "lines";
118321
+ break;
118322
+ case 4: // TRIANGLES
118323
+ meshCfg.primitive = backfaces ? "triangles" : "solid";
118324
+ break;
118325
+ case 5: // TRIANGLE_STRIP
118326
+ meshCfg.primitive = backfaces ? "triangles" : "solid";
118327
+ break;
118328
+ case 6: // TRIANGLE_FAN
118329
+ meshCfg.primitive = backfaces ? "triangles" : "solid";
118330
+ break;
118331
+ default:
118332
+ meshCfg.primitive = backfaces ? "triangles" : "solid";
118333
+ }
118334
+ const POSITION = primitive.attributes.POSITION;
118335
+ if (!POSITION) {
118336
+ continue;
118337
+ }
118338
+ meshCfg.localPositions = POSITION.value;
118339
+ meshCfg.positions = new Float64Array(meshCfg.localPositions.length);
118340
+ if (primitive.attributes.NORMAL) {
118341
+ meshCfg.normals = primitive.attributes.NORMAL.value;
118342
+ }
118343
+ if (primitive.attributes.TEXCOORD_0) {
118344
+ meshCfg.uv = primitive.attributes.TEXCOORD_0.value;
117587
118345
  }
118346
+ if (primitive.indices) {
118347
+ meshCfg.indices = primitive.indices.value;
118348
+ }
118349
+ math.transformPositions3(matrix, meshCfg.localPositions, meshCfg.positions);
118350
+ const origin = math.vec3();
118351
+ const rtcNeeded = worldToRTCPositions(meshCfg.positions, meshCfg.positions, origin); // Small cellsize guarantees better accuracy
118352
+ if (rtcNeeded) {
118353
+ meshCfg.origin = origin;
118354
+ }
118355
+ ctx.sceneModel.createMesh(meshCfg);
118356
+ meshIds.push(meshCfg.id);
117588
118357
  }
117589
118358
  }
117590
118359
  }
@@ -117911,8 +118680,6 @@ class GLTFLoaderPlugin extends Plugin {
117911
118680
  * @param {String} [params.metaModelSrc] Path to an optional metadata file, as an alternative to the ````metaModelJSON```` parameter.
117912
118681
  * @param {*} [params.metaModelJSON] JSON model metadata, as an alternative to the ````metaModelSrc```` parameter.
117913
118682
  * @param {{String:Object}} [params.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.
117914
- * @param {String[]} [params.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
117915
- * @param {String[]} [params.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
117916
118683
  * @param {Boolean} [params.edges=false] Whether or not xeokit renders the model with edges emphasized.
117917
118684
  * @param {Number[]} [params.origin=[0,0,0]] The double-precision World-space origin of the model's coordinates.
117918
118685
  * @param {Number[]} [params.position=[0,0,0]] The single-precision position, relative to ````origin````.
@@ -117928,150 +118695,47 @@ class GLTFLoaderPlugin extends Plugin {
117928
118695
  * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable
117929
118696
  * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point
117930
118697
  * primitives. Only works while {@link DTX#enabled} is also ````true````.
117931
- * @param {String} [params.entityId] When supplied, causes the entire model to be loaded into a single {@link Entity} that gets this ID.
118698
+ * @param {Boolean} [params.autoMetaModel] When supplied, creates a default MetaModel with a single MetaObject.
117932
118699
  * @returns {Entity} Entity representing the model, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}
117933
118700
  */
117934
118701
  load(params = {}) {
117935
-
117936
118702
  if (params.id && this.viewer.scene.components[params.id]) {
117937
118703
  this.error("Component with this ID already exists in viewer: " + params.id + " - will autogenerate this ID");
117938
118704
  delete params.id;
117939
118705
  }
117940
-
117941
118706
  const sceneModel = new SceneModel(this.viewer.scene, utils.apply(params, {
117942
118707
  isModel: true,
117943
118708
  dtxEnabled: params.dtxEnabled
117944
118709
  }));
117945
-
117946
118710
  const modelId = sceneModel.id; // In case ID was auto-generated
117947
-
117948
118711
  if (!params.src && !params.gltf) {
117949
118712
  this.error("load() param expected: src or gltf");
117950
118713
  return sceneModel; // Return new empty model
117951
118714
  }
117952
-
117953
118715
  if (params.metaModelSrc || params.metaModelJSON) {
117954
-
117955
- const objectDefaults = params.objectDefaults || this._objectDefaults || IFCObjectDefaults;
117956
-
117957
118716
  const processMetaModelJSON = (metaModelJSON) => {
117958
-
117959
- this.viewer.metaScene.createMetaModel(modelId, metaModelJSON, {
117960
- includeTypes: params.includeTypes,
117961
- excludeTypes: params.excludeTypes
117962
- });
117963
-
118717
+ this.viewer.metaScene.createMetaModel(modelId, metaModelJSON, {});
117964
118718
  this.viewer.scene.canvas.spinner.processes--;
117965
-
117966
- let includeTypes;
117967
- if (params.includeTypes) {
117968
- includeTypes = {};
117969
- for (let i = 0, len = params.includeTypes.length; i < len; i++) {
117970
- includeTypes[params.includeTypes[i]] = true;
117971
- }
117972
- }
117973
- if (params.excludeTypes) {
117974
- if (!includeTypes) {
117975
- includeTypes = {};
117976
- }
117977
- for (let i = 0, len = params.excludeTypes.length; i < len; i++) {
117978
- includeTypes[params.excludeTypes[i]] = true;
117979
- }
117980
- }
117981
-
117982
- params.readableGeometry = false;
117983
-
117984
- params.handleGLTFNode = (modelId, glTFNode, actions) => {
117985
-
117986
- const name = glTFNode.name;
117987
-
117988
- if (!name) {
117989
- return true; // Continue descending this node subtree
117990
- }
117991
-
117992
- const nodeId = name;
117993
- const metaObject = this.viewer.metaScene.metaObjects[nodeId];
117994
- const type = (metaObject ? metaObject.type : "DEFAULT") || "DEFAULT";
117995
-
117996
- actions.createEntity = {
117997
- id: nodeId,
117998
- isObject: true // Registers the Entity in Scene#objects
117999
- };
118000
-
118001
- const props = objectDefaults[type];
118002
-
118003
- if (props) { // Set Entity's initial rendering state for recognized type
118004
-
118005
- if (props.visible === false) {
118006
- actions.createEntity.visible = false;
118007
- }
118008
-
118009
- if (props.colorize) {
118010
- actions.createEntity.colorize = props.colorize;
118011
- }
118012
-
118013
- if (props.pickable === false) {
118014
- actions.createEntity.pickable = false;
118015
- }
118016
-
118017
- if (props.opacity !== undefined && props.opacity !== null) {
118018
- actions.createEntity.opacity = props.opacity;
118019
- }
118020
- }
118021
-
118022
- return true; // Continue descending this glTF node subtree
118023
- };
118024
-
118025
118719
  if (params.src) {
118026
118720
  this._sceneModelLoader.load(this, params.src, metaModelJSON, params, sceneModel);
118027
118721
  } else {
118028
118722
  this._sceneModelLoader.parse(this, params.gltf, metaModelJSON, params, sceneModel);
118029
118723
  }
118030
118724
  };
118031
-
118032
118725
  if (params.metaModelSrc) {
118033
-
118034
118726
  const metaModelSrc = params.metaModelSrc;
118035
-
118036
118727
  this.viewer.scene.canvas.spinner.processes++;
118037
-
118038
118728
  this._dataSource.getMetaModel(metaModelSrc, (metaModelJSON) => {
118039
-
118040
118729
  this.viewer.scene.canvas.spinner.processes--;
118041
-
118042
118730
  processMetaModelJSON(metaModelJSON);
118043
-
118044
118731
  }, (errMsg) => {
118045
118732
  this.error(`load(): Failed to load model metadata for model '${modelId} from '${metaModelSrc}' - ${errMsg}`);
118046
118733
  this.viewer.scene.canvas.spinner.processes--;
118047
118734
  });
118048
-
118049
118735
  } else if (params.metaModelJSON) {
118050
-
118051
118736
  processMetaModelJSON(params.metaModelJSON);
118052
118737
  }
118053
-
118054
118738
  } else {
118055
-
118056
- params.handleGLTFNode = (modelId, glTFNode, actions) => {
118057
-
118058
- const name = glTFNode.name;
118059
-
118060
- if (!name) {
118061
- return true; // Continue descending this node subtree
118062
- }
118063
-
118064
- const id = name;
118065
-
118066
- actions.createEntity = { // Create an Entity for this glTF scene node
118067
- id: id,
118068
- isObject: true // Registers the Entity in Scene#objects
118069
- };
118070
-
118071
- return true; // Continue descending this glTF node subtree
118072
- };
118073
-
118074
-
118075
118739
  if (params.src) {
118076
118740
  this._sceneModelLoader.load(this, params.src, null, params, sceneModel);
118077
118741
  } else {
@@ -122942,13 +123606,43 @@ class StoreyViewsPlugin extends Plugin {
122942
123606
  getStoreyContainingWorldPos(worldPos) {
122943
123607
  for (var storeyId in this.storeys) {
122944
123608
  const storey = this.storeys[storeyId];
122945
- if (math.point3AABB3Intersect(storey.storeyAABB, worldPos)) {
123609
+ if (math.point3AABB3AbsoluteIntersect(storey.storeyAABB, worldPos)) {
122946
123610
  return storeyId;
122947
123611
  }
122948
123612
  }
122949
123613
  return null;
122950
123614
  }
122951
123615
 
123616
+ /**
123617
+ * Gets the ID of the storey which's bounding box contains the y point of the world position
123618
+ *
123619
+ * @param {Number[]} worldPos 3D World-space position.
123620
+ * @returns {String} ID of the storey containing the position, or null if the position falls outside all the storeys.
123621
+ */
123622
+ getStoreyInVerticalRange(worldPos) {
123623
+ for(let storeyId in this.storeys) {
123624
+ const storey = this.storeys[storeyId];
123625
+ const aabb = [0,0,0,0,0,0], pos = [0,0,0];
123626
+ aabb[1] = storey.storeyAABB[1];
123627
+ aabb[4] = storey.storeyAABB[4];
123628
+ pos[1] = worldPos[1];
123629
+ if (math.point3AABB3AbsoluteIntersect(aabb, pos)) {
123630
+ return storeyId;
123631
+ }
123632
+ }
123633
+ return null;
123634
+ }
123635
+
123636
+ isPositionAboveOrBelowBuilding(worldPos){
123637
+ const keys = Object.keys(this.storeys);
123638
+ const ids = [keys[0], keys[keys.length-1]];
123639
+ if(worldPos[1] < this.storeys[ids[0]].storeyAABB[1])
123640
+ return ids[0];
123641
+ else if (worldPos[1] > this.storeys[ids[1]].storeyAABB[4])
123642
+ return ids[1];
123643
+ return null;
123644
+ }
123645
+
122952
123646
  /**
122953
123647
  * Converts a 3D World-space position to a 2D position within a StoreyMap image.
122954
123648
  *
@@ -131836,6 +132530,9 @@ class XKTLoaderPlugin extends Plugin {
131836
132530
  this.viewer.scene.canvas.spinner.processes++;
131837
132531
 
131838
132532
  const finish = () => {
132533
+ if (sceneModel.destroyed) {
132534
+ return;
132535
+ }
131839
132536
  // this._createDefaultMetaModelIfNeeded(sceneModel, params, options);
131840
132537
  sceneModel.finalize();
131841
132538
  metaModel.finalize();
@@ -131917,7 +132614,9 @@ class XKTLoaderPlugin extends Plugin {
131917
132614
  const loadJSONs = (metaDataFiles, done, error) => {
131918
132615
  let i = 0;
131919
132616
  const loadNext = () => {
131920
- if (i >= metaDataFiles.length) {
132617
+ if (sceneModel.destroyed) {
132618
+ done();
132619
+ } else if (i >= metaDataFiles.length) {
131921
132620
  done();
131922
132621
  } else {
131923
132622
  this._dataSource.getMetaModel(`${baseDir}${metaDataFiles[i]}`, (metaModelData) => {
@@ -131927,7 +132626,7 @@ class XKTLoaderPlugin extends Plugin {
131927
132626
  globalizeObjectIds: options.globalizeObjectIds
131928
132627
  });
131929
132628
  i++;
131930
- this.scheduleTask(loadNext, 100);
132629
+ this.scheduleTask(loadNext, 200);
131931
132630
  }, error);
131932
132631
  }
131933
132632
  };
@@ -131936,13 +132635,16 @@ class XKTLoaderPlugin extends Plugin {
131936
132635
  const loadXKTs_excludeTheirMetaModels = (xktFiles, done, error) => { // Load XKTs, ignore metamodels in the XKT
131937
132636
  let i = 0;
131938
132637
  const loadNext = () => {
131939
- if (i >= xktFiles.length) {
132638
+ if (sceneModel.destroyed) {
132639
+ done();
132640
+ } else if (i >= xktFiles.length) {
131940
132641
  done();
131941
132642
  } else {
131942
132643
  this._dataSource.getXKT(`${baseDir}${xktFiles[i]}`, (arrayBuffer) => {
131943
132644
  this._parseModel(arrayBuffer, params, options, sceneModel, null /* Ignore metamodel in XKT */, manifestCtx);
132645
+ sceneModel.preFinalize();
131944
132646
  i++;
131945
- this.scheduleTask(loadNext, 100);
132647
+ this.scheduleTask(loadNext, 200);
131946
132648
  }, error);
131947
132649
  }
131948
132650
  };
@@ -131951,13 +132653,16 @@ class XKTLoaderPlugin extends Plugin {
131951
132653
  const loadXKTs_includeTheirMetaModels = (xktFiles, done, error) => { // Load XKTs, parse metamodels from the XKT
131952
132654
  let i = 0;
131953
132655
  const loadNext = () => {
131954
- if (i >= xktFiles.length) {
132656
+ if (sceneModel.destroyed) {
132657
+ done();
132658
+ } else if (i >= xktFiles.length) {
131955
132659
  done();
131956
132660
  } else {
131957
132661
  this._dataSource.getXKT(`${baseDir}${xktFiles[i]}`, (arrayBuffer) => {
131958
132662
  this._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);
132663
+ sceneModel.preFinalize();
131959
132664
  i++;
131960
- this.scheduleTask(loadNext, 100);
132665
+ this.scheduleTask(loadNext, 200);
131961
132666
  }, error);
131962
132667
  }
131963
132668
  };
@@ -132007,11 +132712,12 @@ class XKTLoaderPlugin extends Plugin {
132007
132712
  _loadModel(src, params, options, sceneModel, metaModel, manifestCtx, done, error) {
132008
132713
  this._dataSource.getXKT(params.src, (arrayBuffer) => {
132009
132714
  this._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);
132715
+ sceneModel.preFinalize();
132010
132716
  done();
132011
132717
  }, error);
132012
132718
  }
132013
132719
 
132014
- _parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {
132720
+ async _parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {
132015
132721
  if (sceneModel.destroyed) {
132016
132722
  return;
132017
132723
  }
@@ -132023,7 +132729,7 @@ class XKTLoaderPlugin extends Plugin {
132023
132729
  this.error("Unsupported .XKT file version: " + xktVersion + " - this XKTLoaderPlugin supports versions " + Object.keys(parsers));
132024
132730
  return;
132025
132731
  }
132026
- this.log("Loading .xkt V" + xktVersion);
132732
+ // this.log("Loading .xkt V" + xktVersion);
132027
132733
  const numElements = dataView.getUint32(4, true);
132028
132734
  const elements = [];
132029
132735
  let byteOffset = (numElements + 2) * 4;
@@ -138785,7 +139491,7 @@ const triangulateEarClipping = function(planeCoords) {
138785
139491
  next.prev = ear.prev;
138786
139492
  }
138787
139493
 
138788
- return [ planeCoords, baseTriangles ];
139494
+ return [ planeCoords, baseTriangles, isCCW ];
138789
139495
  };
138790
139496
 
138791
139497
  const marker3D = function(scene, color) {
@@ -139307,7 +140013,7 @@ class Zone extends Component {
139307
140013
  const altitude = this._geometry.altitude + (downward ? this._geometry.height : 0);
139308
140014
  const height = this._geometry.height * (downward ? -1 : 1);
139309
140015
 
139310
- const [ baseVertices, baseTriangles ] = triangulateEarClipping(planeCoords); // TODO: prevent crossing edges
140016
+ const [ baseVertices, baseTriangles, isCCW ] = triangulateEarClipping(planeCoords); // TODO: prevent crossing edges
139311
140017
 
139312
140018
  const pos = [ ];
139313
140019
  const ind = [ ];
@@ -139331,7 +140037,7 @@ class Zone extends Component {
139331
140037
  // sides
139332
140038
  for (let i = 0; i < baseVertices.length; ++i) {
139333
140039
  const a = baseVertices[i];
139334
- const b = baseVertices[(i+1) % baseVertices.length];
140040
+ const b = baseVertices[(baseVertices.length + i + (isCCW ? 1 : -1)) % baseVertices.length];
139335
140041
  const f = altitude;
139336
140042
  const c = altitude + height;
139337
140043
 
@@ -139374,6 +140080,28 @@ class Zone extends Component {
139374
140080
 
139375
140081
  this._zoneMesh.zone = this;
139376
140082
 
140083
+ {
140084
+ const u = math.vec2();
140085
+ const v = math.vec2();
140086
+
140087
+ let baseArea = 0;
140088
+
140089
+ for (let t of baseTriangles) {
140090
+ const p0 = baseVertices[t[0]];
140091
+ const p1 = baseVertices[t[1]];
140092
+ const p2 = baseVertices[t[2]];
140093
+
140094
+ math.subVec2(p1, p0, u);
140095
+ math.subVec2(p2, p0, v);
140096
+
140097
+ baseArea += Math.abs(u[0] * v[1] - u[1] * v[0]);
140098
+ }
140099
+
140100
+ this._baseArea = baseArea / 2;
140101
+ }
140102
+
140103
+ this._metrics = null;
140104
+
139377
140105
 
139378
140106
  const min = idx => Math.min(...pos.map(p => p[idx]));
139379
140107
  const max = idx => Math.max(...pos.map(p => p[idx]));
@@ -139388,6 +140116,48 @@ class Zone extends Component {
139388
140116
  this._center = math.vec3([ (xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2 ]);
139389
140117
  }
139390
140118
 
140119
+ get baseArea() {
140120
+ return this._baseArea;
140121
+ }
140122
+
140123
+ get area() {
140124
+ return this._getMetrics().area;
140125
+ }
140126
+
140127
+ get volume() {
140128
+ return this._getMetrics().volume;
140129
+ }
140130
+
140131
+ _getMetrics() {
140132
+ if (this._metrics === null) {
140133
+ // Sum the volume of tetrahedrons formed by the origin and face triangles
140134
+ let volume = 0;
140135
+ let area = 0;
140136
+ const geo = this._zoneMesh.geometry;
140137
+ const pts = [ math.vec3(), math.vec3(), math.vec3() ];
140138
+ const tmpVec3 = math.vec3();
140139
+ for (let i = 0; i < geo.indices.length; i += 3) {
140140
+ for (let off = 0; off < 3; ++off) {
140141
+ const p = pts[off];
140142
+ const pIdx = 3 * geo.indices[i + off];
140143
+ for (let c = 0; c < 3; ++c) {
140144
+ p[c] = geo.positions[pIdx + c];
140145
+ }
140146
+ }
140147
+ volume += math.dotVec3(pts[0], math.cross3Vec3(pts[1], pts[2], tmpVec3));
140148
+ math.subVec3(pts[1], pts[0], pts[1]);
140149
+ math.subVec3(pts[2], pts[0], pts[2]);
140150
+ area += math.lenVec3(math.cross3Vec3(pts[1], pts[2], tmpVec3));
140151
+ }
140152
+
140153
+ this._metrics = {
140154
+ area: area / 2,
140155
+ volume: volume / 6
140156
+ };
140157
+ }
140158
+ return this._metrics;
140159
+ }
140160
+
139391
140161
  sectionedAverage(sectionPlanes) {
139392
140162
  const planeCoords = this._geometry.planeCoordinates.slice();
139393
140163
 
@@ -140544,6 +141314,7 @@ exports.DefaultLoadingManager = DefaultLoadingManager;
140544
141314
  exports.DepthFormat = DepthFormat;
140545
141315
  exports.DepthStencilFormat = DepthStencilFormat;
140546
141316
  exports.DirLight = DirLight;
141317
+ exports.DistanceMeasurementEditControl = DistanceMeasurementEditControl;
140547
141318
  exports.DistanceMeasurementEditMouseControl = DistanceMeasurementEditMouseControl;
140548
141319
  exports.DistanceMeasurementEditTouchControl = DistanceMeasurementEditTouchControl;
140549
141320
  exports.DistanceMeasurementsControl = DistanceMeasurementsControl;
@@ -140588,6 +141359,8 @@ exports.Marker = Marker;
140588
141359
  exports.MarqueePicker = MarqueePicker;
140589
141360
  exports.MarqueePickerMouseControl = MarqueePickerMouseControl;
140590
141361
  exports.Mesh = Mesh;
141362
+ exports.MeshSurfaceArea = MeshSurfaceArea;
141363
+ exports.MeshVolume = MeshVolume;
140591
141364
  exports.MetallicMaterial = MetallicMaterial;
140592
141365
  exports.MirroredRepeatWrapping = MirroredRepeatWrapping;
140593
141366
  exports.ModelMemento = ModelMemento;
@@ -140706,9 +141479,12 @@ exports.createRTCViewMat = createRTCViewMat;
140706
141479
  exports.frustumIntersectsAABB3 = frustumIntersectsAABB3;
140707
141480
  exports.getKTX2TextureTranscoder = getKTX2TextureTranscoder;
140708
141481
  exports.getPlaneRTCPos = getPlaneRTCPos;
141482
+ exports.isTriangleMeshSolid = isTriangleMeshSolid;
140709
141483
  exports.load3DSGeometry = load3DSGeometry;
140710
141484
  exports.loadOBJGeometry = loadOBJGeometry;
140711
141485
  exports.math = math;
141486
+ exports.meshSurfaceArea = meshSurfaceArea;
141487
+ exports.meshVolume = meshVolume;
140712
141488
  exports.rtcToWorldPos = rtcToWorldPos;
140713
141489
  exports.sRGBEncoding = sRGBEncoding;
140714
141490
  exports.setFrustum = setFrustum;