@xeokit/xeokit-sdk 2.6.9 → 2.6.13

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 (38) hide show
  1. package/dist/web-ifc.wasm +0 -0
  2. package/dist/xeokit-sdk.cjs.js +1164 -134
  3. package/dist/xeokit-sdk.es.js +1163 -135
  4. package/dist/xeokit-sdk.es5.js +521 -53
  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/plugins/AngleMeasurementsPlugin/AngleMeasurementsControl.js +10 -0
  10. package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.js +9 -0
  11. package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +9 -0
  12. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.js +182 -42
  13. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsControl.js +11 -0
  14. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsMouseControl.js +11 -0
  15. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsPlugin.js +18 -1
  16. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +15 -0
  17. package/src/plugins/DotBIMLoaderPlugin/DotBIMDefaultDataSource.js +29 -0
  18. package/src/plugins/DotBIMLoaderPlugin/DotBIMLoaderPlugin.js +536 -0
  19. package/src/plugins/DotBIMLoaderPlugin/index.js +2 -0
  20. package/src/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.js +74 -0
  21. package/src/plugins/GLTFLoaderPlugin/GLTFSceneModelLoader.js +53 -58
  22. package/src/plugins/LASLoaderPlugin/LASLoaderPlugin.js +59 -2
  23. package/src/plugins/index.js +2 -1
  24. package/src/plugins/lib/html/Dot.js +38 -6
  25. package/src/plugins/lib/html/Label.js +48 -7
  26. package/src/plugins/lib/html/Wire.js +38 -6
  27. package/src/viewer/Viewer.js +1 -1
  28. package/src/viewer/scene/CameraControl/lib/handlers/MouseMiscHandler.js +2 -2
  29. package/src/viewer/scene/marker/Marker.js +3 -3
  30. package/src/viewer/scene/model/SceneModel.js +17 -9
  31. package/src/viewer/utils/os.js +11 -0
  32. package/types/plugins/AngleMeasurementsPlugin/AngleMeasurementsControl.d.ts +7 -0
  33. package/types/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.d.ts +8 -0
  34. package/types/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.d.ts +8 -0
  35. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.d.ts +70 -0
  36. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsControl.d.ts +7 -0
  37. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsMouseControl.d.ts +8 -0
  38. package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.d.ts +8 -0
@@ -10456,7 +10456,7 @@ const tempVec4b$6 = math.vec4();
10456
10456
  * });
10457
10457
  *
10458
10458
  * // Create the Marker, associated with our Mesh Entity
10459
- * const myMarker = new Marker({
10459
+ * const myMarker = new Marker(viewer, {
10460
10460
  * entity: entity,
10461
10461
  * worldPos: [10,0,0],
10462
10462
  * occludable: true
@@ -10585,7 +10585,7 @@ class Marker extends Component {
10585
10585
  return;
10586
10586
  }
10587
10587
  if (this._onEntityDestroyed !== null) {
10588
- this._entity.off(this._onEntityDestroyed);
10588
+ this._entity.model.off(this._onEntityDestroyed);
10589
10589
  this._onEntityDestroyed = null;
10590
10590
  }
10591
10591
  if (this._onEntityModelDestroyed !== null) {
@@ -10601,7 +10601,7 @@ class Marker extends Component {
10601
10601
  this._onEntityModelDestroyed = null;
10602
10602
  });
10603
10603
  } else {
10604
- this._onEntityDestroyed = this._entity.on("destroyed", () => {
10604
+ this._onEntityDestroyed = this._entity.model.on("destroyed", () => {
10605
10605
  this._entity = null;
10606
10606
  this._onEntityDestroyed = null;
10607
10607
  });
@@ -10767,6 +10767,16 @@ class Marker extends Component {
10767
10767
  }
10768
10768
  }
10769
10769
 
10770
+ const os = {
10771
+ isIphoneSafari() {
10772
+ const userAgent = window.navigator.userAgent;
10773
+ const isIphone = /iPhone/i.test(userAgent);
10774
+ const isSafari = /Safari/i.test(userAgent) && !/Chrome/i.test(userAgent);
10775
+
10776
+ return isIphone && isSafari;
10777
+ }
10778
+ };
10779
+
10770
10780
  /** @private */
10771
10781
  class Wire {
10772
10782
 
@@ -10879,11 +10889,42 @@ class Wire {
10879
10889
  }
10880
10890
 
10881
10891
  if (cfg.onContextMenu) {
10882
- wireClickable.addEventListener('contextmenu', (event) => {
10883
- cfg.onContextMenu(event, this);
10884
- event.preventDefault();
10885
- event.stopPropagation();
10886
- });
10892
+ if(os.isIphoneSafari()){
10893
+ wireClickable.addEventListener('touchstart', (event) => {
10894
+ event.preventDefault();
10895
+ if(this._timeout){
10896
+ clearTimeout(this._timeout);
10897
+ this._timeout = null;
10898
+ }
10899
+ this._timeout = setTimeout(() => {
10900
+ event.clientX = event.touches[0].clientX;
10901
+ event.clientY = event.touches[0].clientY;
10902
+ cfg.onContextMenu(event, this);
10903
+ clearTimeout(this._timeout);
10904
+ this._timeout = null;
10905
+ }, 500);
10906
+ });
10907
+
10908
+ wireClickable.addEventListener('touchend', (event) => {
10909
+ event.preventDefault();
10910
+ //stops short touches from calling the timeout
10911
+ if(this._timeout) {
10912
+ clearTimeout(this._timeout);
10913
+ this._timeout = null;
10914
+ }
10915
+ } );
10916
+
10917
+ }
10918
+ else {
10919
+ wireClickable.addEventListener('contextmenu', (event) => {
10920
+ console.log(event);
10921
+ cfg.onContextMenu(event, this);
10922
+ event.preventDefault();
10923
+ event.stopPropagation();
10924
+ console.log("Label context menu");
10925
+ });
10926
+ }
10927
+
10887
10928
  }
10888
10929
 
10889
10930
  this._x1 = 0;
@@ -10958,7 +10999,7 @@ class Wire {
10958
10999
  }
10959
11000
 
10960
11001
  setClickable(clickable) {
10961
- this._wireClickable.style["pointer-events"] = (!!clickable) ? "all" : "none";
11002
+ this._wireClickable.style["pointer-events"] = (clickable) ? "all" : "none";
10962
11003
  }
10963
11004
 
10964
11005
  setHighlighted(highlighted) {
@@ -11078,11 +11119,42 @@ class Dot {
11078
11119
  }
11079
11120
 
11080
11121
  if (cfg.onContextMenu) {
11081
- dotClickable.addEventListener('contextmenu', (event) => {
11082
- cfg.onContextMenu(event, this);
11083
- event.preventDefault();
11084
- event.stopPropagation();
11085
- });
11122
+ if(os.isIphoneSafari()){
11123
+ dotClickable.addEventListener('touchstart', (event) => {
11124
+ event.preventDefault();
11125
+ if(this._timeout){
11126
+ clearTimeout(this._timeout);
11127
+ this._timeout = null;
11128
+ }
11129
+ this._timeout = setTimeout(() => {
11130
+ event.clientX = event.touches[0].clientX;
11131
+ event.clientY = event.touches[0].clientY;
11132
+ cfg.onContextMenu(event, this);
11133
+ clearTimeout(this._timeout);
11134
+ this._timeout = null;
11135
+ }, 500);
11136
+ });
11137
+
11138
+ dotClickable.addEventListener('touchend', (event) => {
11139
+ event.preventDefault();
11140
+ //stops short touches from calling the timeout
11141
+ if(this._timeout) {
11142
+ clearTimeout(this._timeout);
11143
+ this._timeout = null;
11144
+ }
11145
+ } );
11146
+
11147
+ }
11148
+ else {
11149
+ dotClickable.addEventListener('contextmenu', (event) => {
11150
+ console.log(event);
11151
+ cfg.onContextMenu(event, this);
11152
+ event.preventDefault();
11153
+ event.stopPropagation();
11154
+ console.log("Label context menu");
11155
+ });
11156
+ }
11157
+
11086
11158
  }
11087
11159
 
11088
11160
  this.setPos(cfg.x || 0, cfg.y || 0);
@@ -11131,7 +11203,7 @@ class Dot {
11131
11203
  }
11132
11204
 
11133
11205
  setClickable(clickable) {
11134
- this._dotClickable.style["pointer-events"] = (!!clickable) ? "all" : "none";
11206
+ this._dotClickable.style["pointer-events"] = (clickable) ? "all" : "none";
11135
11207
  }
11136
11208
 
11137
11209
  setHighlighted(highlighted) {
@@ -11172,6 +11244,7 @@ class Label {
11172
11244
 
11173
11245
  this._label = document.createElement('div');
11174
11246
  this._label.className += this._label.className ? ' viewer-ruler-label' : 'viewer-ruler-label';
11247
+ this._timeout = null;
11175
11248
 
11176
11249
  var label = this._label;
11177
11250
  var style = label.style;
@@ -11241,12 +11314,42 @@ class Label {
11241
11314
  }
11242
11315
 
11243
11316
  if (cfg.onContextMenu) {
11244
- label.addEventListener('contextmenu', (event) => {
11245
- cfg.onContextMenu(event, this);
11246
- event.preventDefault();
11247
- event.stopPropagation();
11248
- console.log("Label context menu");
11249
- });
11317
+ if(os.isIphoneSafari()){
11318
+ label.addEventListener('touchstart', (event) => {
11319
+ event.preventDefault();
11320
+ if(this._timeout){
11321
+ clearTimeout(this._timeout);
11322
+ this._timeout = null;
11323
+ }
11324
+ this._timeout = setTimeout(() => {
11325
+ event.clientX = event.touches[0].clientX;
11326
+ event.clientY = event.touches[0].clientY;
11327
+ cfg.onContextMenu(event, this);
11328
+ clearTimeout(this._timeout);
11329
+ this._timeout = null;
11330
+ }, 500);
11331
+ });
11332
+
11333
+ label.addEventListener('touchend', (event) => {
11334
+ event.preventDefault();
11335
+ //stops short touches from calling the timeout
11336
+ if(this._timeout) {
11337
+ clearTimeout(this._timeout);
11338
+ this._timeout = null;
11339
+ }
11340
+ } );
11341
+
11342
+ }
11343
+ else {
11344
+ label.addEventListener('contextmenu', (event) => {
11345
+ console.log(event);
11346
+ cfg.onContextMenu(event, this);
11347
+ event.preventDefault();
11348
+ event.stopPropagation();
11349
+ console.log("Label context menu");
11350
+ });
11351
+ }
11352
+
11250
11353
  }
11251
11354
  }
11252
11355
 
@@ -11321,7 +11424,14 @@ class Label {
11321
11424
  }
11322
11425
 
11323
11426
  setClickable(clickable) {
11324
- this._label.style["pointer-events"] = (!!clickable) ? "all" : "none";
11427
+ this._label.style["pointer-events"] = (clickable) ? "all" : "none";
11428
+ }
11429
+
11430
+ setPrefix(prefix) {
11431
+ if(this._prefix === prefix){
11432
+ return;
11433
+ }
11434
+ this._prefix = prefix;
11325
11435
  }
11326
11436
 
11327
11437
  destroy() {
@@ -11329,6 +11439,8 @@ class Label {
11329
11439
  this._label.parentElement.removeChild(this._label);
11330
11440
  }
11331
11441
  }
11442
+
11443
+
11332
11444
  }
11333
11445
 
11334
11446
  var originVec = math.vec3();
@@ -12126,6 +12238,16 @@ class AngleMeasurementsControl extends Component {
12126
12238
  reset() {
12127
12239
  }
12128
12240
 
12241
+ /**
12242
+ * Gets the {@link AngleMeasurement} under construction by this AngleMeasurementsControl, if any.
12243
+ *
12244
+ * @returns {null|AngleMeasurement}
12245
+ * @abstract
12246
+ */
12247
+ get currentMeasurement() {
12248
+ return null;
12249
+ }
12250
+
12129
12251
  /**
12130
12252
  * Destroys this AngleMeasurementsMouseControl.
12131
12253
  *
@@ -12576,6 +12698,15 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12576
12698
  this._mouseState = MOUSE_FINDING_ORIGIN;
12577
12699
  }
12578
12700
 
12701
+ /**
12702
+ * Gets the {@link AngleMeasurement} under construction by this AngleMeasurementsMouseControl, if any.
12703
+ *
12704
+ * @returns {null|AngleMeasurement}
12705
+ */
12706
+ get currentMeasurement() {
12707
+ return this._currentAngleMeasurement;
12708
+ }
12709
+
12579
12710
  /**
12580
12711
  * Destroys this AngleMeasurementsMouseControl.
12581
12712
  */
@@ -13929,6 +14060,15 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13929
14060
  }
13930
14061
  }
13931
14062
 
14063
+ /**
14064
+ * Gets the {@link AngleMeasurement} under construction by this AngleMeasurementsTouchControl, if any.
14065
+ *
14066
+ * @returns {null|AngleMeasurement}
14067
+ */
14068
+ get currentMeasurement() {
14069
+ return this._currentAngleMeasurement;
14070
+ }
14071
+
13932
14072
  /**
13933
14073
  * Destroys this AngleMeasurementsTouchControl.
13934
14074
  */
@@ -81024,10 +81164,11 @@ class SceneModelTransform {
81024
81164
  const tempVec3a$a = math.vec3();
81025
81165
 
81026
81166
  const tempOBB3 = math.OBB3();
81167
+ const tempQuaternion = math.vec4();
81027
81168
 
81028
81169
  const DEFAULT_SCALE = math.vec3([1, 1, 1]);
81029
81170
  const DEFAULT_POSITION = math.vec3([0, 0, 0]);
81030
- const DEFAULT_ROTATION = math.vec3([0, 0, 0]);
81171
+ math.vec3([0, 0, 0]);
81031
81172
  const DEFAULT_QUATERNION = math.identityQuaternion();
81032
81173
  const DEFAULT_MATRIX = math.identityMat4();
81033
81174
 
@@ -83704,6 +83845,7 @@ class SceneModel extends Component {
83704
83845
  * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.
83705
83846
  * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the mesh. Overridden by ````transformId````.
83706
83847
  * @param {Number[]} [cfg.rotation=[0,0,0]] Rotation of the mesh as Euler angles given in degrees, for each of the X, Y and Z axis. Overridden by ````transformId````.
83848
+ * @param {Number[]} [cfg.quaternion] Rotation of the mesh as a quaternion. Overridden by ````rotation````.
83707
83849
  * @param {Number[]} [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] Mesh modelling transform matrix. Overrides the ````position````, ````scale```` and ````rotation```` parameters. Also overridden by ````transformId````.
83708
83850
  * @param {Number[]} [cfg.color=[1,1,1]] RGB color in range ````[0..1, 0..1, 0..1]````. Overridden by texture set ````colorTexture````. Overrides ````colors```` and ````colorsCompressed````.
83709
83851
  * @param {Number} [cfg.opacity=1] Opacity in range ````[0..1]````. Overridden by texture set ````colorTexture````.
@@ -83778,12 +83920,15 @@ class SceneModel extends Component {
83778
83920
 
83779
83921
  if (cfg.matrix) {
83780
83922
  cfg.meshMatrix = cfg.matrix;
83781
- } else if (cfg.scale || cfg.rotation || cfg.position) {
83923
+ } else if (cfg.scale || cfg.rotation || cfg.position || cfg.quaternion) {
83782
83924
  const scale = cfg.scale || DEFAULT_SCALE;
83783
83925
  const position = cfg.position || DEFAULT_POSITION;
83784
- const rotation = cfg.rotation || DEFAULT_ROTATION;
83785
- math.eulerToQuaternion(rotation, "XYZ", DEFAULT_QUATERNION);
83786
- cfg.meshMatrix = math.composeMat4(position, DEFAULT_QUATERNION, scale, math.mat4());
83926
+ if (cfg.rotation) {
83927
+ math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion);
83928
+ cfg.meshMatrix = math.composeMat4(position, tempQuaternion, scale, math.mat4());
83929
+ } else {
83930
+ cfg.meshMatrix = math.composeMat4(position, cfg.quaternion || DEFAULT_QUATERNION, scale, math.mat4());
83931
+ }
83787
83932
  }
83788
83933
 
83789
83934
  if (cfg.positionsDecodeBoundary) {
@@ -83971,13 +84116,16 @@ class SceneModel extends Component {
83971
84116
  // MATRIX
83972
84117
 
83973
84118
  if (cfg.matrix) {
83974
- cfg.meshMatrix = cfg.matrix.slice();
83975
- } else {
84119
+ cfg.meshMatrix = cfg.matrix;
84120
+ } else if (cfg.scale || cfg.rotation || cfg.position || cfg.quaternion) {
83976
84121
  const scale = cfg.scale || DEFAULT_SCALE;
83977
84122
  const position = cfg.position || DEFAULT_POSITION;
83978
- const rotation = cfg.rotation || DEFAULT_ROTATION;
83979
- math.eulerToQuaternion(rotation, "XYZ", DEFAULT_QUATERNION);
83980
- cfg.meshMatrix = math.composeMat4(position, DEFAULT_QUATERNION, scale, math.mat4());
84123
+ if (cfg.rotation) {
84124
+ math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion);
84125
+ cfg.meshMatrix = math.composeMat4(position, tempQuaternion, scale, math.mat4());
84126
+ } else {
84127
+ cfg.meshMatrix = math.composeMat4(position, cfg.quaternion || DEFAULT_QUATERNION, scale, math.mat4());
84128
+ }
83981
84129
  }
83982
84130
 
83983
84131
  math.AABB3ToOBB3(cfg.geometry.aabb, tempOBB3);
@@ -86130,6 +86278,14 @@ const lengthWire = (x1, y1, x2, y2) => {
86130
86278
  return Math.sqrt(a * a + b * b);
86131
86279
  };
86132
86280
 
86281
+ function determineMeasurementOrientation(A, B, distance) {
86282
+ const yDiff = Math.abs(B[1] - A[1]);
86283
+
86284
+ return yDiff > distance ? 'Vertical' : 'Horizontal';
86285
+ }
86286
+
86287
+ // function findDistance
86288
+
86133
86289
  /**
86134
86290
  * @desc Measures the distance between two 3D points.
86135
86291
  *
@@ -86158,17 +86314,16 @@ class DistanceMeasurement extends Component {
86158
86314
  this._eventSubs = {};
86159
86315
 
86160
86316
  var scene = this.plugin.viewer.scene;
86161
-
86162
86317
  this._originMarker = new Marker(scene, cfg.origin);
86163
86318
  this._targetMarker = new Marker(scene, cfg.target);
86164
86319
 
86165
86320
  this._originWorld = math.vec3();
86166
86321
  this._targetWorld = math.vec3();
86167
86322
 
86168
- this._wp = new Float64Array(24);
86169
- this._vp = new Float64Array(24);
86323
+ this._wp = new Float64Array(24); //world position
86324
+ this._vp = new Float64Array(24); //view position
86170
86325
  this._pp = new Float64Array(24);
86171
- this._cp = new Float64Array(8);
86326
+ this._cp = new Float64Array(8); //canvas position
86172
86327
 
86173
86328
  this._xAxisLabelCulled = false;
86174
86329
  this._yAxisLabelCulled = false;
@@ -86342,6 +86497,7 @@ class DistanceMeasurement extends Component {
86342
86497
  onContextMenu
86343
86498
  });
86344
86499
 
86500
+ this._measurementOrientation = 'Horizontal';
86345
86501
  this._wpDirty = false;
86346
86502
  this._vpDirty = false;
86347
86503
  this._cpDirty = false;
@@ -86356,18 +86512,22 @@ class DistanceMeasurement extends Component {
86356
86512
  this._yAxisVisible = false;
86357
86513
  this._zAxisVisible = false;
86358
86514
  this._axisEnabled = true;
86515
+ this._xLabelEnabled = false;
86516
+ this._yLabelEnabled = false;
86517
+ this._zLabelEnabled = false;
86518
+ this._lengthLabelEnabled = false;
86359
86519
  this._labelsVisible = false;
86360
86520
  this._labelsOnWires = false;
86361
86521
  this._clickable = false;
86362
86522
 
86363
86523
  this._originMarker.on("worldPos", (value) => {
86364
- this._originWorld.set(value || [0, 0, 0]);
86524
+ this._originWorld.set(value || [0,0,0]);
86365
86525
  this._wpDirty = true;
86366
86526
  this._needUpdate(0); // No lag
86367
86527
  });
86368
86528
 
86369
86529
  this._targetMarker.on("worldPos", (value) => {
86370
- this._targetWorld.set(value || [0, 0, 0]);
86530
+ this._targetWorld.set(value || [0,0,0]);
86371
86531
  this._wpDirty = true;
86372
86532
  this._needUpdate(0); // No lag
86373
86533
  });
@@ -86416,6 +86576,10 @@ class DistanceMeasurement extends Component {
86416
86576
  this.xAxisVisible = cfg.xAxisVisible;
86417
86577
  this.yAxisVisible = cfg.yAxisVisible;
86418
86578
  this.zAxisVisible = cfg.zAxisVisible;
86579
+ this.xLabelEnabled = cfg.xLabelEnabled;
86580
+ this.yLabelEnabled = cfg.yLabelEnabled;
86581
+ this.zLabelEnabled = cfg.zLabelEnabled;
86582
+ this.lengthLabelEnabled = cfg.lengthLabelEnabled;
86419
86583
  this.labelsVisible = cfg.labelsVisible;
86420
86584
  this.labelsOnWires = cfg.labelsOnWires;
86421
86585
  }
@@ -86430,25 +86594,50 @@ class DistanceMeasurement extends Component {
86430
86594
 
86431
86595
  if (this._wpDirty) {
86432
86596
 
86433
- this._wp[0] = this._originWorld[0];
86434
- this._wp[1] = this._originWorld[1];
86435
- this._wp[2] = this._originWorld[2];
86436
- this._wp[3] = 1.0;
86597
+ this._measurementOrientation = determineMeasurementOrientation(this._originWorld, this._targetWorld, 1);
86598
+ if(this._measurementOrientation === 'Vertical'){
86599
+ this._wp[0] = this._originWorld[0];
86600
+ this._wp[1] = this._originWorld[1];
86601
+ this._wp[2] = this._originWorld[2];
86602
+ this._wp[3] = 1.0;
86437
86603
 
86438
- this._wp[4] = this._targetWorld[0];
86439
- this._wp[5] = this._originWorld[1];
86440
- this._wp[6] = this._originWorld[2];
86441
- this._wp[7] = 1.0;
86604
+ this._wp[4] = this._originWorld[0]; //x-axis
86605
+ this._wp[5] = this._originWorld[1];
86606
+ this._wp[6] = this._originWorld[2];
86607
+ this._wp[7] = 1.0;
86442
86608
 
86443
- this._wp[8] = this._targetWorld[0];
86444
- this._wp[9] = this._targetWorld[1];
86445
- this._wp[10] = this._originWorld[2];
86446
- this._wp[11] = 1.0;
86609
+ this._wp[8] = this._originWorld[0]; //x-axis
86610
+ this._wp[9] = this._targetWorld[1]; //y-axis
86611
+ this._wp[10] = this._originWorld[2];
86612
+ this._wp[11] = 1.0;
86447
86613
 
86448
- this._wp[12] = this._targetWorld[0];
86449
- this._wp[13] = this._targetWorld[1];
86450
- this._wp[14] = this._targetWorld[2];
86451
- this._wp[15] = 1.0;
86614
+ this._wp[12] = this._targetWorld[0];
86615
+ this._wp[13] = this._targetWorld[1];
86616
+ this._wp[14] = this._targetWorld[2];
86617
+ this._wp[15] = 1.0;
86618
+ }
86619
+ else {
86620
+ this._wp[0] = this._originWorld[0];
86621
+ this._wp[1] = this._originWorld[1];
86622
+ this._wp[2] = this._originWorld[2];
86623
+ this._wp[3] = 1.0;
86624
+
86625
+ this._wp[4] = this._targetWorld[0];
86626
+ this._wp[5] = this._originWorld[1];
86627
+ this._wp[6] = this._originWorld[2];
86628
+ this._wp[7] = 1.0;
86629
+
86630
+ this._wp[8] = this._targetWorld[0];
86631
+ this._wp[9] = this._targetWorld[1];
86632
+ this._wp[10] = this._originWorld[2];
86633
+ this._wp[11] = 1.0;
86634
+
86635
+ this._wp[12] = this._targetWorld[0];
86636
+ this._wp[13] = this._targetWorld[1];
86637
+ this._wp[14] = this._targetWorld[2];
86638
+ this._wp[15] = 1.0;
86639
+ }
86640
+
86452
86641
 
86453
86642
  this._wpDirty = false;
86454
86643
  this._vpDirty = true;
@@ -86619,7 +86808,14 @@ class DistanceMeasurement extends Component {
86619
86808
  }
86620
86809
 
86621
86810
  if (!this._zAxisLabelCulled) {
86622
- this._zAxisLabel.setText(tilde + Math.abs((this._targetWorld[2] - this._originWorld[2]) * scale).toFixed(2) + unitAbbrev);
86811
+ if(this._measurementOrientation === 'Vertical') {
86812
+ this._zAxisLabel.setPrefix("");
86813
+ this._zAxisLabel.setText(tilde + Math.abs(math.lenVec3(math.subVec3(this._targetWorld, [this._originWorld[0], this._targetWorld[1], this._originWorld[2]], distVec3)) * scale).toFixed(2) + unitAbbrev);
86814
+ }
86815
+ else {
86816
+ this._zAxisLabel.setPrefix("Z");
86817
+ this._zAxisLabel.setText(tilde + Math.abs((this._targetWorld[2] - this._originWorld[2]) * scale).toFixed(2) + unitAbbrev);
86818
+ }
86623
86819
  this._zAxisLabel.setCulled(!this.axisVisible);
86624
86820
  } else {
86625
86821
  this._zAxisLabel.setCulled(true);
@@ -86739,7 +86935,7 @@ class DistanceMeasurement extends Component {
86739
86935
  this._originDot.setVisible(this._visible && this._originVisible);
86740
86936
  this._targetDot.setVisible(this._visible && this._targetVisible);
86741
86937
  this._lengthWire.setVisible(this._visible && this._wireVisible);
86742
- this._lengthLabel.setVisible(this._visible && this._wireVisible);
86938
+ this._lengthLabel.setVisible(this._visible && this._wireVisible && this._lengthLabelEnabled);
86743
86939
 
86744
86940
  const xAxisVisible = this._visible && this._axisVisible && this._xAxisVisible;
86745
86941
  const yAxisVisible = this._visible && this._axisVisible && this._yAxisVisible;
@@ -86749,9 +86945,9 @@ class DistanceMeasurement extends Component {
86749
86945
  this._yAxisWire.setVisible(yAxisVisible);
86750
86946
  this._zAxisWire.setVisible(zAxisVisible);
86751
86947
 
86752
- this._xAxisLabel.setVisible(xAxisVisible && !this._xAxisLabelCulled);
86753
- this._yAxisLabel.setVisible(yAxisVisible && !this._yAxisLabelCulled);
86754
- this._zAxisLabel.setVisible(zAxisVisible && !this._zAxisLabelCulled);
86948
+ this._xAxisLabel.setVisible(xAxisVisible && !this._xAxisLabelCulled && this._EnabledVisible);
86949
+ this._yAxisLabel.setVisible(yAxisVisible && !this._yAxisLabelCulled && this._yLabelEnabled);
86950
+ this._zAxisLabel.setVisible(zAxisVisible && !this._zAxisLabelCulled && this._zLabelEnabled);
86755
86951
 
86756
86952
  this._cpDirty = true;
86757
86953
 
@@ -86821,9 +87017,9 @@ class DistanceMeasurement extends Component {
86821
87017
  this._xAxisWire.setVisible(axisVisible && this._xAxisVisible);
86822
87018
  this._yAxisWire.setVisible(axisVisible && this._yAxisVisible);
86823
87019
  this._zAxisWire.setVisible(axisVisible && this._zAxisVisible);
86824
- this._xAxisLabel.setVisible(axisVisible && !this._xAxisLabelCulled&& this._xAxisVisible);
86825
- this._yAxisLabel.setVisible(axisVisible && !this._yAxisLabelCulled&& this._xAxisVisible);
86826
- this._zAxisLabel.setVisible(axisVisible && !this._zAxisLabelCulled&& this._xAxisVisible);
87020
+ this._xAxisLabel.setVisible(axisVisible && !this._xAxisLabelCulled&& this._xAxisVisible && this._xLabelEnabled);
87021
+ this._yAxisLabel.setVisible(axisVisible && !this._yAxisLabelCulled&& this._xAxisVisible && this._yLabelEnabled);
87022
+ this._zAxisLabel.setVisible(axisVisible && !this._zAxisLabelCulled&& this._xAxisVisible && this._zLabelEnabled);
86827
87023
  this._cpDirty = true;
86828
87024
  this._needUpdate();
86829
87025
  }
@@ -86883,7 +87079,7 @@ class DistanceMeasurement extends Component {
86883
87079
  this._xAxisVisible = value;
86884
87080
  const axisVisible = this._visible && this._axisVisible && this._xAxisVisible && this._axisEnabled;
86885
87081
  this._xAxisWire.setVisible(axisVisible);
86886
- this._xAxisLabel.setVisible(axisVisible && !this._xAxisLabelCulled);
87082
+ this._xAxisLabel.setVisible(axisVisible && !this._xAxisLabelCulled && this._xLabelEnabled);
86887
87083
  this._cpDirty = true;
86888
87084
  this._needUpdate();
86889
87085
  }
@@ -86911,7 +87107,7 @@ class DistanceMeasurement extends Component {
86911
87107
  this._yAxisVisible = value;
86912
87108
  const axisVisible = this._visible && this._axisVisible && this._yAxisVisible && this._axisEnabled;
86913
87109
  this._yAxisWire.setVisible(axisVisible);
86914
- this._yAxisLabel.setVisible(axisVisible && !this._yAxisLabelCulled);
87110
+ this._yAxisLabel.setVisible(axisVisible && !this._yAxisLabelCulled && this._yLabelEnabled);
86915
87111
  this._cpDirty = true;
86916
87112
  this._needUpdate();
86917
87113
  }
@@ -86939,7 +87135,7 @@ class DistanceMeasurement extends Component {
86939
87135
  this._zAxisVisible = value;
86940
87136
  const axisVisible = this._visible && this._axisVisible && this._zAxisVisible && this._axisEnabled;
86941
87137
  this._zAxisWire.setVisible(axisVisible);
86942
- this._zAxisLabel.setVisible(axisVisible && !this._zAxisLabelCulled);
87138
+ this._zAxisLabel.setVisible(axisVisible && !this._zAxisLabelCulled && this._zLabelEnabled);
86943
87139
  this._cpDirty = true;
86944
87140
  this._needUpdate();
86945
87141
  }
@@ -86964,7 +87160,7 @@ class DistanceMeasurement extends Component {
86964
87160
  value = value !== undefined ? Boolean(value) : this.plugin.defaultWireVisible;
86965
87161
  this._wireVisible = value;
86966
87162
  var wireVisible = this._visible && this._wireVisible;
86967
- this._lengthLabel.setVisible(wireVisible);
87163
+ this._lengthLabel.setVisible(wireVisible && this._lengthLabelEnabled);
86968
87164
  this._lengthWire.setVisible(wireVisible);
86969
87165
  }
86970
87166
 
@@ -86978,7 +87174,7 @@ class DistanceMeasurement extends Component {
86978
87174
  }
86979
87175
 
86980
87176
  /**
86981
- * Sets if the labels are visible.
87177
+ * Sets if the labels are visible except the length label.
86982
87178
  *
86983
87179
  * @type {Boolean}
86984
87180
  */
@@ -86986,10 +87182,10 @@ class DistanceMeasurement extends Component {
86986
87182
  value = value !== undefined ? Boolean(value) : this.plugin.defaultLabelsVisible;
86987
87183
  this._labelsVisible = value;
86988
87184
  var labelsVisible = this._visible && this._labelsVisible;
86989
- this._xAxisLabel.setVisible(labelsVisible && !this._xAxisLabelCulled && this._clickable && this._axisEnabled);
86990
- this._yAxisLabel.setVisible(labelsVisible && !this._yAxisLabelCulled && this._clickable && this._axisEnabled);
86991
- this._zAxisLabel.setVisible(labelsVisible && !this._zAxisLabelCulled && this._clickable && this._axisEnabled);
86992
- this._lengthLabel.setVisible(labelsVisible);
87185
+ this._xAxisLabel.setVisible(labelsVisible && !this._xAxisLabelCulled && this._clickable && this._axisEnabled && this._xLabelEnabled);
87186
+ this._yAxisLabel.setVisible(labelsVisible && !this._yAxisLabelCulled && this._clickable && this._axisEnabled && this._yLabelEnabled);
87187
+ this._zAxisLabel.setVisible(labelsVisible && !this._zAxisLabelCulled && this._clickable && this._axisEnabled && this._zLabelEnabled);
87188
+ this._lengthLabel.setVisible(labelsVisible && this._lengthLabelEnabled);
86993
87189
  this._cpDirty = true;
86994
87190
  this._needUpdate();
86995
87191
  }
@@ -87003,6 +87199,98 @@ class DistanceMeasurement extends Component {
87003
87199
  return this._labelsVisible;
87004
87200
  }
87005
87201
 
87202
+ /**
87203
+ * Sets if the x label is enabled.
87204
+ *
87205
+ * @type {Boolean}
87206
+ */
87207
+ set xLabelEnabled(value) {
87208
+ value = value !== undefined ? Boolean(value) : this.plugin.defaultXLabelEnabled;
87209
+ this._xLabelEnabled = value;
87210
+ var labelsVisible = this._visible && this._labelsVisible;
87211
+ this._xAxisLabel.setVisible(labelsVisible && !this._xAxisLabelCulled && this._clickable && this._axisEnabled && this._xLabelEnabled);
87212
+ this._cpDirty = true;
87213
+ this._needUpdate();
87214
+ }
87215
+
87216
+ /**
87217
+ * Gets if the x label is enabled.
87218
+ *
87219
+ * @type {Boolean}
87220
+ */
87221
+ get xLabelEnabled(){
87222
+ return this._xLabelEnabled;
87223
+ }
87224
+
87225
+ /**
87226
+ * Sets if the y label is enabled.
87227
+ *
87228
+ * @type {Boolean}
87229
+ */
87230
+ set yLabelEnabled(value) {
87231
+ value = value !== undefined ? Boolean(value) : this.plugin.defaultYLabelEnabled;
87232
+ this._yLabelEnabled = value;
87233
+ var labelsVisible = this._visible && this._labelsVisible;
87234
+ this._yAxisLabel.setVisible(labelsVisible && !this._yAxisLabelCulled && this._clickable && this._axisEnabled && this._yLabelEnabled);
87235
+ this._cpDirty = true;
87236
+ this._needUpdate();
87237
+ }
87238
+
87239
+ /**
87240
+ * Gets if the y label is enabled.
87241
+ *
87242
+ * @type {Boolean}
87243
+ */
87244
+ get yLabelEnabled(){
87245
+ return this._yLabelEnabled;
87246
+ }
87247
+
87248
+ /**
87249
+ * Sets if the z label is enabled.
87250
+ *
87251
+ * @type {Boolean}
87252
+ */
87253
+ set zLabelEnabled(value) {
87254
+ value = value !== undefined ? Boolean(value) : this.plugin.defaultZLabelEnabled;
87255
+ this._zLabelEnabled = value;
87256
+ var labelsVisible = this._visible && this._labelsVisible;
87257
+ this._zAxisLabel.setVisible(labelsVisible && !this._zAxisLabelCulled && this._clickable && this._axisEnabled && this._zLabelEnabled);
87258
+ this._cpDirty = true;
87259
+ this._needUpdate();
87260
+ }
87261
+
87262
+ /**
87263
+ * Gets if the z label is enabled.
87264
+ *
87265
+ * @type {Boolean}
87266
+ */
87267
+ get zLabelEnabled(){
87268
+ return this._zLabelEnabled;
87269
+ }
87270
+
87271
+ /**
87272
+ * Sets if the length label is enabled.
87273
+ *
87274
+ * @type {Boolean}
87275
+ */
87276
+ set lengthLabelEnabled(value) {
87277
+ value = value !== undefined ? Boolean(value) : this.plugin.defaultLengthLabelEnabled;
87278
+ this._lengthLabelEnabled = value;
87279
+ var labelsVisible = this._visible && this._labelsVisible;
87280
+ this._lengthLabel.setVisible(labelsVisible && !this._lengthAxisLabelCulled && this._clickable && this._axisEnabled && this._lengthLabelEnabled);
87281
+ this._cpDirty = true;
87282
+ this._needUpdate();
87283
+ }
87284
+
87285
+ /**
87286
+ * Gets if the length label is enabled.
87287
+ *
87288
+ * @type {Boolean}
87289
+ */
87290
+ get lengthLabelEnabled(){
87291
+ return this._lengthLabelEnabled;
87292
+ }
87293
+
87006
87294
  /**
87007
87295
  * Sets if labels should be positioned on the wires.
87008
87296
  *
@@ -87185,6 +87473,17 @@ class DistanceMeasurementsControl extends Component {
87185
87473
  reset() {
87186
87474
  }
87187
87475
 
87476
+ /**
87477
+ * Gets the {@link DistanceMeasurement} under construction by this DistanceMeasurementsControl, if any.
87478
+ *
87479
+ * @returns {null|DistanceMeasurement}
87480
+ *
87481
+ * @abstract
87482
+ */
87483
+ get currentMeasurement() {
87484
+ return null;
87485
+ }
87486
+
87188
87487
  /**
87189
87488
  * Destroys this DistanceMeasurementsControl.
87190
87489
  *
@@ -87591,6 +87890,17 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
87591
87890
  this._currentDistanceMeasurement.destroy();
87592
87891
  this._currentDistanceMeasurement = null;
87593
87892
  }
87893
+
87894
+ this._mouseState = MOUSE_FIRST_CLICK_EXPECTED;
87895
+ }
87896
+
87897
+ /**
87898
+ * Gets the {@link DistanceMeasurement} under construction by this DistanceMeasurementsMouseControl, if any.
87899
+ *
87900
+ * @returns {null|DistanceMeasurement}
87901
+ */
87902
+ get currentMeasurement() {
87903
+ return this._currentDistanceMeasurement;
87594
87904
  }
87595
87905
 
87596
87906
  /**
@@ -87878,6 +88188,10 @@ class DistanceMeasurementsPlugin extends Plugin {
87878
88188
  * @param {boolean} [cfg.defaultTargetVisible=true] The default value of the DistanceMeasurements `targetVisible` property.
87879
88189
  * @param {boolean} [cfg.defaultWireVisible=true] The default value of the DistanceMeasurements `wireVisible` property.
87880
88190
  * @param {boolean} [cfg.defaultLabelsVisible=true] The default value of the DistanceMeasurements `labelsVisible` property.
88191
+ * @param {boolean} [cfg.defaultXLabelEnabled=true] The default value of the DistanceMeasurements `xLabelEnabled` property.
88192
+ * @param {boolean} [cfg.defaultYLabelEnabled=true] The default value of the DistanceMeasurements `yLabelEnabled` property.
88193
+ * @param {boolean} [cfg.defaultZLabelEnabled=true] The default value of the DistanceMeasurements `zLabelEnabled` property.
88194
+ * @param {boolean} [cfg.defaultLengthLabelEnabled=true] The default value of the DistanceMeasurements `lengthLabelEnabled` property.
87881
88195
  * @param {boolean} [cfg.defaultAxisVisible=true] The default value of the DistanceMeasurements `axisVisible` property.
87882
88196
  * @param {boolean} [cfg.defaultXAxisVisible=true] The default value of the DistanceMeasurements `xAxisVisible` property.
87883
88197
  * @param {boolean} [cfg.defaultYAxisVisible=true] The default value of the DistanceMeasurements `yAxisVisible` property.
@@ -87900,11 +88214,14 @@ class DistanceMeasurementsPlugin extends Plugin {
87900
88214
  this._measurements = {};
87901
88215
 
87902
88216
  this.labelMinAxisLength = cfg.labelMinAxisLength;
87903
-
87904
88217
  this.defaultVisible = cfg.defaultVisible !== false;
87905
88218
  this.defaultOriginVisible = cfg.defaultOriginVisible !== false;
87906
88219
  this.defaultTargetVisible = cfg.defaultTargetVisible !== false;
87907
88220
  this.defaultWireVisible = cfg.defaultWireVisible !== false;
88221
+ this.defaultXLabelEnabled = cfg.defaultXLabelEnabled !== false;
88222
+ this.defaultYLabelEnabled = cfg.defaultYLabelEnabled !== false;
88223
+ this.defaultZLabelEnabled = cfg.defaultZLabelEnabled !== false;
88224
+ this.defaultLengthLabelEnabled = cfg.defaultLengthLabelEnabled !== false;
87908
88225
  this.defaultLabelsVisible = cfg.defaultLabelsVisible !== false;
87909
88226
  this.defaultAxisVisible = cfg.defaultAxisVisible !== false;
87910
88227
  this.defaultXAxisVisible = cfg.defaultXAxisVisible !== false;
@@ -88033,7 +88350,12 @@ class DistanceMeasurementsPlugin extends Plugin {
88033
88350
  * @param {Boolean} [params.xAxisVisible=true] Whether to initially show the X-axis-aligned wires between {@link DistanceMeasurement#origin} and {@link DistanceMeasurement#target}.
88034
88351
  * @param {Boolean} [params.yAxisVisible=true] Whether to initially show the Y-axis-aligned wires between {@link DistanceMeasurement#origin} and {@link DistanceMeasurement#target}.
88035
88352
  * @param {Boolean} [params.zAxisVisible=true] Whether to initially show the Z-axis-aligned wires between {@link DistanceMeasurement#origin} and {@link DistanceMeasurement#target}.
88353
+ * @param {Boolean} [params.xLabelEnabled=true] Whether to initially show the x label.
88354
+ * @param {Boolean} [params.yLabelEnabled=true] Whether to initially show the y label.
88355
+ * @param {Boolean} [params.zLabelEnabled=true] Whether to initially show the z label.
88356
+ * @param {Boolean} [params.lengthLabelEnabled=true] Whether to initially show the length label.
88036
88357
  * @param {Boolean} [params.labelsVisible=true] Whether to initially show the labels.
88358
+ * @param {Boolean} [params.lengthLabelVisible=true] Whether to initially show the labels.
88037
88359
  * @param {string} [params.color] The color of the length dot, wire and label.
88038
88360
  * @param {Boolean} [params.labelsOnWires=true] Determines if labels will be set on wires or one below the other.
88039
88361
  * @returns {DistanceMeasurement} The new {@link DistanceMeasurement}.
@@ -88063,6 +88385,10 @@ class DistanceMeasurementsPlugin extends Plugin {
88063
88385
  xAxisVisible: params.xAxisVisible !== false && this.defaultXAxisVisible !== false,
88064
88386
  yAxisVisible: params.yAxisVisible !== false && this.defaultYAxisVisible !== false,
88065
88387
  zAxisVisible: params.zAxisVisible !== false && this.defaultZAxisVisible !== false,
88388
+ xLabelEnabled: params.xLabelEnabled !== false && this.defaultXLabelEnabled !== false,
88389
+ yLabelEnabled: params.yLabelEnabled !== false && this.defaultYLabelEnabled !== false,
88390
+ zLabelEnabled: params.zLabelEnabled !== false && this.defaultZLabelEnabled !== false,
88391
+ lengthLabelEnabled: params.lengthLabelEnabled !== false && this.defaultLengthLabelEnabled !== false,
88066
88392
  labelsVisible: params.labelsVisible !== false && this.defaultLabelsVisible !== false,
88067
88393
  originVisible: params.originVisible,
88068
88394
  targetVisible: params.targetVisible,
@@ -88073,6 +88399,7 @@ class DistanceMeasurementsPlugin extends Plugin {
88073
88399
  onContextMenu: this._onContextMenu
88074
88400
  });
88075
88401
  this._measurements[measurement.id] = measurement;
88402
+ measurement.clickable = true;
88076
88403
  measurement.on("destroyed", () => {
88077
88404
  delete this._measurements[measurement.id];
88078
88405
  });
@@ -88808,6 +89135,10 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
88808
89135
  this._currentDistanceMeasurement.targetVisible = true;
88809
89136
  this._currentDistanceMeasurement.wireVisible = true;
88810
89137
  this._currentDistanceMeasurement.labelsVisible = true;
89138
+ this._currentDistanceMeasurement.xAxisVisible = true;
89139
+ this._currentDistanceMeasurement.yAxisVisible = true;
89140
+ this._currentDistanceMeasurement.zAxisVisible = true;
89141
+ this._currentDistanceMeasurement.clickable = true;
88811
89142
  this.distanceMeasurementsPlugin.fire("measurementEnd", this._currentDistanceMeasurement);
88812
89143
  this._currentDistanceMeasurement = null;
88813
89144
  } else {
@@ -88823,6 +89154,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
88823
89154
  break;
88824
89155
 
88825
89156
  case WAITING_FOR_TARGET_LONG_TOUCH_END:
89157
+ console.log('long touch');
88826
89158
  if (this.pointerLens) {
88827
89159
  this.pointerLens.visible = false;
88828
89160
  }
@@ -88890,6 +89222,16 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
88890
89222
  this._currentDistanceMeasurement.destroy();
88891
89223
  this._currentDistanceMeasurement = null;
88892
89224
  }
89225
+ this._mouseState = WAITING_FOR_ORIGIN_TOUCH_START;
89226
+ }
89227
+
89228
+ /**
89229
+ * Gets the {@link DistanceMeasurement} under construction by this DistanceMeasurementsTouchControl, if any.
89230
+ *
89231
+ * @returns {null|DistanceMeasurement}
89232
+ */
89233
+ get currentMeasurement() {
89234
+ return this._currentDistanceMeasurement;
88893
89235
  }
88894
89236
 
88895
89237
  /**
@@ -96614,8 +96956,8 @@ function getCanvasPosFromEvent$2(event, canvas, canvasPos) {
96614
96956
  canvasPos[1] = event.y;
96615
96957
  } else {
96616
96958
  const { left, top } = canvas.getBoundingClientRect();
96617
- canvasPos[0] = event.clientX - left - window.scrollX;
96618
- canvasPos[1] = event.clientY - top - window.scrollY;
96959
+ canvasPos[0] = event.clientX - left;
96960
+ canvasPos[1] = event.clientY - top;
96619
96961
  }
96620
96962
  return canvasPos;
96621
96963
  }
@@ -115809,6 +116151,7 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok) {
115809
116151
  }).then((gltfData) => {
115810
116152
  const ctx = {
115811
116153
  src: src,
116154
+ entityId: options.entityId,
115812
116155
  metaModelCorrections: metaModelJSON ? getMetaModelCorrections(metaModelJSON) : null,
115813
116156
  loadBuffer: options.loadBuffer,
115814
116157
  basePath: options.basePath,
@@ -116248,29 +116591,9 @@ function loadNode(ctx, node, depth, matrix) {
116248
116591
  meshCfg.origin = origin;
116249
116592
  }
116250
116593
 
116251
- // if (createEntity) {
116252
- // if (createEntity.colorize) {
116253
- // meshCfg.color = createEntity.colorize;
116254
- // }
116255
- // if (createEntity.opacity !== undefined && createEntity.opacity !== null) {
116256
- // meshCfg.opacity = createEntity.opacity;
116257
- // }
116258
- // }
116259
-
116260
116594
  sceneModel.createMesh(meshCfg);
116261
116595
  deferredMeshIds.push(meshCfg.id);
116262
116596
  }
116263
- // if (createEntity) {
116264
- // sceneModel.createEntity(utils.apply(createEntity, {
116265
- // meshIds: deferredMeshIds,
116266
- // isObject: true
116267
- // }));
116268
- // } else {
116269
- // sceneModel.createEntity({
116270
- // meshIds: deferredMeshIds,
116271
- // isObject: true
116272
- // });
116273
- // }
116274
116597
  }
116275
116598
  }
116276
116599
 
@@ -116284,48 +116607,62 @@ function loadNode(ctx, node, depth, matrix) {
116284
116607
 
116285
116608
  // Post-order visit scene node
116286
116609
 
116287
- const nodeName = node.name;
116288
- if (((nodeName !== undefined && nodeName !== null) || depth === 0) && deferredMeshIds.length > 0) {
116289
- if (nodeName === undefined || nodeName === null) {
116290
- ctx.log(`Warning: 'name' properties not found on glTF scene nodes - will randomly-generate object IDs in XKT`);
116610
+ if (ctx.entityId) {
116611
+ if (depth ===0) {
116612
+ sceneModel.createEntity({
116613
+ id: ctx.entityId,
116614
+ meshIds: deferredMeshIds,
116615
+ isObject: true
116616
+ });
116617
+ deferredMeshIds.length = 0;
116291
116618
  }
116292
- let entityId = nodeName; // Fall back on generated ID when `name` not found on glTF scene node(s)
116293
- // if (!!entityId && sceneModel.entities[entityId]) {
116294
- // ctx.log(`Warning: Two or more glTF nodes found with same 'name' attribute: '${nodeName} - will randomly-generating an object ID in XKT`);
116295
- // }
116296
- // while (!entityId || sceneModel.entities[entityId]) {
116297
- // entityId = "entity-" + ctx.nextId++;
116298
- // }
116299
- if (ctx.metaModelCorrections) {
116300
- // Merging meshes into XKTObjects that map to metaobjects
116301
- const rootMetaObject = ctx.metaModelCorrections.eachChildRoot[entityId];
116302
- if (rootMetaObject) {
116303
- const rootMetaObjectStats = ctx.metaModelCorrections.eachRootStats[rootMetaObject.id];
116304
- rootMetaObjectStats.countChildren++;
116305
- if (rootMetaObjectStats.countChildren >= rootMetaObjectStats.numChildren) {
116306
- sceneModel.createEntity({
116307
- id: rootMetaObject.id,
116308
- meshIds: deferredMeshIds
116309
- });
116310
- deferredMeshIds.length = 0;
116619
+ } else {
116620
+ const nodeName = node.name;
116621
+ if (((nodeName !== undefined && nodeName !== null) || depth === 0) && deferredMeshIds.length > 0) {
116622
+ if (nodeName === undefined || nodeName === null) {
116623
+ ctx.log(`Warning: 'name' properties not found on glTF scene nodes - will randomly-generate object IDs in XKT`);
116624
+ }
116625
+ let entityId = nodeName; // Fall back on generated ID when `name` not found on glTF scene node(s)
116626
+ // if (!!entityId && sceneModel.entities[entityId]) {
116627
+ // ctx.log(`Warning: Two or more glTF nodes found with same 'name' attribute: '${nodeName} - will randomly-generating an object ID in XKT`);
116628
+ // }
116629
+ // while (!entityId || sceneModel.entities[entityId]) {
116630
+ // entityId = "entity-" + ctx.nextId++;
116631
+ // }
116632
+ if (ctx.metaModelCorrections) {
116633
+ // Merging meshes into XKTObjects that map to metaobjects
116634
+ const rootMetaObject = ctx.metaModelCorrections.eachChildRoot[entityId];
116635
+ if (rootMetaObject) {
116636
+ const rootMetaObjectStats = ctx.metaModelCorrections.eachRootStats[rootMetaObject.id];
116637
+ rootMetaObjectStats.countChildren++;
116638
+ if (rootMetaObjectStats.countChildren >= rootMetaObjectStats.numChildren) {
116639
+ sceneModel.createEntity({
116640
+ id: rootMetaObject.id,
116641
+ meshIds: deferredMeshIds,
116642
+ isObject: true
116643
+ });
116644
+ deferredMeshIds.length = 0;
116645
+ }
116646
+ } else {
116647
+ const metaObject = ctx.metaModelCorrections.metaObjectsMap[entityId];
116648
+ if (metaObject) {
116649
+ sceneModel.createEntity({
116650
+ id: entityId,
116651
+ meshIds: deferredMeshIds,
116652
+ isObject: true
116653
+ });
116654
+ deferredMeshIds.length = 0;
116655
+ }
116311
116656
  }
116312
116657
  } else {
116313
- const metaObject = ctx.metaModelCorrections.metaObjectsMap[entityId];
116314
- if (metaObject) {
116315
- sceneModel.createEntity({
116316
- id: entityId,
116317
- meshIds: deferredMeshIds
116318
- });
116319
- deferredMeshIds.length = 0;
116320
- }
116658
+ // Create an XKTObject from the meshes at each named glTF node, don't care about metaobjects
116659
+ sceneModel.createEntity({
116660
+ id: entityId,
116661
+ meshIds: deferredMeshIds,
116662
+ isObject: true
116663
+ });
116664
+ deferredMeshIds.length = 0;
116321
116665
  }
116322
- } else {
116323
- // Create an XKTObject from the meshes at each named glTF node, don't care about metaobjects
116324
- sceneModel.createEntity({
116325
- id: entityId,
116326
- meshIds: deferredMeshIds
116327
- });
116328
- deferredMeshIds.length = 0;
116329
116666
  }
116330
116667
  }
116331
116668
  }
@@ -116502,6 +116839,79 @@ const IFCObjectDefaults = {
116502
116839
  * excludeTypes: ["IfcSpace"]
116503
116840
  * });
116504
116841
  * ````
116842
+ *
116843
+ * ## Showing a glTF model in TreeViewPlugin when metadata is not available
116844
+ *
116845
+ * When GLTFLoaderPlugin loads a glTF model, it creates an object Entity for each `node` in the glTF `scene` hierarchy that has a
116846
+ * `name` attribute, giving the Entity an ID that has the value of the `name` attribute.
116847
+ *
116848
+ * Those name attributes are created by converter tools, such as by [IFC2GLTFCxConverter](https://github.com/Creoox/creoox-ifc2gltfcxconverter) when it generates glTF from IFC files. However, those name attributes are not
116849
+ * ordinarily present in glTF that comes from other sources, such as LiDAR scanners. For such glTF models, GLTFLoaderPlugin
116850
+ * will create Entities, but they will have randomly-generated IDs, and therefore cannot be associated with MetaObjects in any
116851
+ * MetaModels that we create alongside the model.
116852
+ *
116853
+ * For glTF models containing `nodes` that don't have `name` attributes, we can use the `load()` method's `elementId` parameter
116854
+ * to make GLTFLoaderPlugin load the entire model into a single Entity that gets this ID.
116855
+ *
116856
+ * In conjunction with that parameter, we can then use the `load()` method's `metaModelJSON` parameter to create a MetaModel that
116857
+ * contains a MetaObject that corresponds to that Entity.
116858
+ *
116859
+ * When we've done that, then xeokit's {@link TreeViewPlugin} is able to have a node that represents the glTF model and controls
116860
+ * the visibility of that Entity (ie. to control the visibility of the entire model).
116861
+ *
116862
+ * The snippet below shows how this is done.
116863
+ *
116864
+ * ````javascript
116865
+ * import {Viewer, GLTFLoaderPlugin, NavCubePlugin, TreeViewPlugin} from "../../dist/xeokit-sdk.es.js";
116866
+ *
116867
+ * const viewer = new Viewer({
116868
+ * canvasId: "myCanvas",
116869
+ * transparent: true
116870
+ * });
116871
+ *
116872
+ * new TreeViewPlugin(viewer, {
116873
+ * containerElement: document.getElementById("treeViewContainer"),
116874
+ * hierarchy: "containment"
116875
+ * });
116876
+ *
116877
+ * const gltfLoader = new GLTFLoaderPlugin(viewer);
116878
+ *
116879
+ * const sceneModel = gltfLoader.load({ // Creates a SceneModel with ID "myScanModel"
116880
+ * id: "myScanModel",
116881
+ * src: "public-use-sample-apartment.glb",
116882
+ *
116883
+ * //-------------------------------------------------------------------------
116884
+ * // Specify an `elementId` parameter, which causes the
116885
+ * // entire model to be loaded into a single Entity that gets this ID.
116886
+ * //-------------------------------------------------------------------------
116887
+ *
116888
+ * entityId: "3toKckUfH2jBmd$7uhJHa4", // Creates an Entity with this ID
116889
+ *
116890
+ * //-------------------------------------------------------------------------
116891
+ * // Specify a `metaModelJSON` parameter, which creates a
116892
+ * // MetaModel with two MetaObjects, one of which corresponds
116893
+ * // to our Entity. Then the TreeViewPlugin is able to have a node
116894
+ * // that can represent the model and control the visibility of the Entity.
116895
+ * //--------------------------------------------------------------------------
116896
+ *
116897
+ * metaModelJSON: { // Creates a MetaModel with ID "myScanModel"
116898
+ * "metaObjects": [
116899
+ * {
116900
+ * "id": "3toKckUfH2jBmd$7uhJHa6", // Creates a MetaObject with this ID
116901
+ * "name": "My Project",
116902
+ * "type": "Default",
116903
+ * "parent": null
116904
+ * },
116905
+ * {
116906
+ * "id": "3toKckUfH2jBmd$7uhJHa4", // Creates a MetaObject with this ID (same ID as our Entity)
116907
+ * "name": "My Scan",
116908
+ * "type": "Default",
116909
+ * "parent": "3toKckUfH2jBmd$7uhJHa6"
116910
+ * }
116911
+ * ]
116912
+ * }
116913
+ * });
116914
+ * ````
116505
116915
  * @class GLTFLoaderPlugin
116506
116916
  */
116507
116917
  class GLTFLoaderPlugin extends Plugin {
@@ -116596,6 +117006,7 @@ class GLTFLoaderPlugin extends Plugin {
116596
117006
  * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable
116597
117007
  * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point
116598
117008
  * primitives. Only works while {@link DTX#enabled} is also ````true````.
117009
+ * @param {String} [params.entityId] When supplied, causes the entire model to be loaded into a single {@link Entity} that gets this ID.
116599
117010
  * @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}
116600
117011
  */
116601
117012
  load(params = {}) {
@@ -134768,6 +135179,60 @@ const MAX_VERTICES = 500000; // TODO: Rough estimate
134768
135179
  * });
134769
135180
  * ````
134770
135181
  *
135182
+ * ## Showing a LAS/LAZ model in TreeViewPlugin
135183
+ *
135184
+ * We can use the `load()` method's `elementId` parameter
135185
+ * to make LASLoaderPlugin load the entire model into a single Entity that gets this ID.
135186
+ *
135187
+ * In conjunction with that parameter, we can then use the `load()` method's `metaModelJSON` parameter to create a MetaModel that
135188
+ * contains a MetaObject that corresponds to that Entity.
135189
+ *
135190
+ * When we've done that, then xeokit's {@link TreeViewPlugin} is able to have a node that represents the model and controls
135191
+ * the visibility of that Entity (ie. to control the visibility of the entire model).
135192
+ *
135193
+ * The snippet below shows how this is done.
135194
+ *
135195
+ * ````javascript
135196
+ * import {Viewer, LASLoaderPlugin, NavCubePlugin, TreeViewPlugin} from "../../dist/xeokit-sdk.es.js";
135197
+ *
135198
+ * const viewer = new Viewer({
135199
+ * canvasId: "myCanvas",
135200
+ * transparent: true
135201
+ * });
135202
+ *
135203
+ * new TreeViewPlugin(viewer, {
135204
+ * containerElement: document.getElementById("treeViewContainer"),
135205
+ * hierarchy: "containment"
135206
+ * });
135207
+ *
135208
+ * const lasLoader = new LASLoaderPlugin(viewer);
135209
+ *
135210
+ * const sceneModel = lasLoader.load({ // Creates a SceneModel with ID "myScanModel"
135211
+ * id: "myScanModel",
135212
+ * src: "../../assets/models/las/Nalls_Pumpkin_Hill.laz",
135213
+ * rotation: [-90, 0, 0],
135214
+ *
135215
+ * entityId: "3toKckUfH2jBmd$7uhJHa4", // Creates an Entity with this ID
135216
+ *
135217
+ * metaModelJSON: { // Creates a MetaModel with ID "myScanModel"
135218
+ * "metaObjects": [
135219
+ * {
135220
+ * "id": "3toKckUfH2jBmd$7uhJHa6", // Creates this MetaObject with this ID
135221
+ * "name": "My Project",
135222
+ * "type": "Default",
135223
+ * "parent": null
135224
+ * },
135225
+ * {
135226
+ * "id": "3toKckUfH2jBmd$7uhJHa4", // Creates this MetaObject with this ID
135227
+ * "name": "My Scan",
135228
+ * "type": "Default",
135229
+ * "parent": "3toKckUfH2jBmd$7uhJHa6"
135230
+ * }
135231
+ * ]
135232
+ * }
135233
+ * });
135234
+ * ````
135235
+ *
134771
135236
  * @class LASLoaderPlugin
134772
135237
  * @since 2.0.17
134773
135238
  */
@@ -135118,7 +135583,7 @@ class LASLoaderPlugin extends Plugin {
135118
135583
  }
135119
135584
  */
135120
135585
 
135121
- const pointsObjectId = math.createUUID();
135586
+ const pointsObjectId = params.entityId || math.createUUID();
135122
135587
 
135123
135588
  sceneModel.createEntity({
135124
135589
  id: pointsObjectId,
@@ -135128,7 +135593,10 @@ class LASLoaderPlugin extends Plugin {
135128
135593
 
135129
135594
  sceneModel.finalize();
135130
135595
 
135131
- if (params.loadMetadata !== false) {
135596
+ if (params.metaModelJSON) {
135597
+ const metaModelId = sceneModel.id;
135598
+ this.viewer.metaScene.createMetaModel(metaModelId, params.metaModelJSON, options);
135599
+ } else if (params.loadMetadata !== false) {
135132
135600
  const rootMetaObjectId = math.createUUID();
135133
135601
  const metadata = {
135134
135602
  projectId: "",
@@ -136626,4 +137094,564 @@ class CityJSONLoaderPlugin extends Plugin {
136626
137094
  }
136627
137095
  }
136628
137096
 
136629
- export { AlphaFormat, AmbientLight, AngleMeasurementsControl, AngleMeasurementsMouseControl, AngleMeasurementsPlugin, AngleMeasurementsTouchControl, AnnotationsPlugin, AxisGizmoPlugin, BCFViewpointsPlugin, Bitmap, ByteType, CameraMemento, CameraPath, CameraPathAnimation, CityJSONLoaderPlugin, ClampToEdgeWrapping, Component, CompressedMediaType, Configs, ContextMenu, CubicBezierCurve, Curve, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DirLight, DistanceMeasurementsControl, DistanceMeasurementsMouseControl, DistanceMeasurementsPlugin, DistanceMeasurementsTouchControl, EdgeMaterial, EmphasisMaterial, FaceAlignedSectionPlanesPlugin, FastNavPlugin, FloatType, Fresnel, Frustum$1 as Frustum, FrustumPlane, GIFMediaType, GLTFDefaultDataSource, GLTFLoaderPlugin, HalfFloatType, ImagePlane, IntType, JPEGMediaType, KTX2TextureTranscoder, LASLoaderPlugin, LambertMaterial, LightMap, LineSet, LinearEncoding, LinearFilter, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, Loader, LoadingManager, LocaleService, LuminanceAlphaFormat, LuminanceFormat, Map$1 as Map, Marker, MarqueePicker, MarqueePickerMouseControl, Mesh, MetallicMaterial, MirroredRepeatWrapping, ModelMemento, NavCubePlugin, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, Node$2 as Node, OBJLoaderPlugin, ObjectsKdTree3, ObjectsMemento, PNGMediaType, Path, PerformanceModel, PhongMaterial, PickResult, Plugin, PointLight, PointerCircle, PointerLens, QuadraticBezierCurve, Queue, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, ReadableGeometry, RedFormat, RedIntegerFormat, ReflectionMap, RepeatWrapping, STLDefaultDataSource, STLLoaderPlugin, SceneModel, SceneModelMesh, SceneModelTransform, SectionPlane, SectionPlanesPlugin, ShortType, Skybox, SkyboxesPlugin, SpecularMaterial, SplineCurve, SpriteMarker, StoreyViewsPlugin, Texture, TextureTranscoder, TreeViewPlugin, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VBOGeometry, ViewCullPlugin, Viewer, WebIFCLoaderPlugin, WorkerPool$1 as WorkerPool, XKTDefaultDataSource, XKTLoaderPlugin, XML3DLoaderPlugin, buildBoxGeometry, buildBoxLinesGeometry, buildBoxLinesGeometryFromAABB, buildCylinderGeometry, buildGridGeometry, buildPlaneGeometry, buildPolylineGeometry, buildPolylineGeometryFromCurve, buildSphereGeometry, buildTorusGeometry, buildVectorTextGeometry, createRTCViewMat, frustumIntersectsAABB3, getKTX2TextureTranscoder, getPlaneRTCPos, load3DSGeometry, loadOBJGeometry, math, rtcToWorldPos, sRGBEncoding, setFrustum, stats, utils, worldToRTCPos, worldToRTCPositions };
137097
+ /**
137098
+ * Default data access strategy for {@link DotBIMLoaderPlugin}.
137099
+ *
137100
+ * This just loads assets using XMLHttpRequest.
137101
+ */
137102
+ class DotBIMDefaultDataSource {
137103
+
137104
+ constructor() {
137105
+ }
137106
+
137107
+ /**
137108
+ * Gets .BIM JSON.
137109
+ *
137110
+ * @param {String|Number} dotBIMSrc Identifies the .BIM JSON asset.
137111
+ * @param {Function} ok Fired on successful loading of the .BIM JSON asset.
137112
+ * @param {Function} error Fired on error while loading the .BIM JSON asset.
137113
+ */
137114
+ getDotBIM(dotBIMSrc, ok, error) {
137115
+ utils.loadJSON(dotBIMSrc,
137116
+ (json) => {
137117
+ ok(json);
137118
+ },
137119
+ function (errMsg) {
137120
+ error(errMsg);
137121
+ });
137122
+ }
137123
+ }
137124
+
137125
+ /**
137126
+ * {@link Viewer} plugin that loads models from [.bim](https://dotbim.net/) format.
137127
+ *
137128
+ * [<img src="https://xeokit.github.io/xeokit-sdk/assets/images/DotBIMLoaderPlugin-house.png">](https://xeokit.github.io/xeokit-sdk/examples/buildings/#dotbim_House)
137129
+ *
137130
+ * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/buildings/#dotbim_House)]
137131
+ *
137132
+ * * Creates an {@link Entity} representing each .bim model it loads, which will have {@link Entity#isModel} set ````true````
137133
+ * and will be registered by {@link Entity#id} in {@link Scene#models}.
137134
+ * * Creates an {@link Entity} for each object within the .bim model. Those Entities will have {@link Entity#isObject}
137135
+ * set ````true```` and will be registered by {@link Entity#id} in {@link Scene#objects}.
137136
+ * * When loading, can set the World-space position, scale and rotation of each model within World space,
137137
+ * along with initial properties for all the model's {@link Entity}s.
137138
+ * * Allows to mask which IFC types we want to load.
137139
+ * * Allows to configure initial viewer state for specified IFC types (color, visibility, selection, highlighted, X-rayed, pickable, etc).
137140
+ *
137141
+ * ## Usage
137142
+ *
137143
+ * In the example below we'll load a house model from a [.bim file](/assets/models/dotbim/House.bim).
137144
+ *
137145
+ * This will create a bunch of {@link Entity}s that represents the model and its objects, along with
137146
+ * a {@link MetaModel} and {@link MetaObject}s that hold their metadata.
137147
+ *
137148
+ * ````javascript
137149
+ * import {Viewer, DotBIMLoaderPlugin} from "xeokit-sdk.es.js";
137150
+ *
137151
+ * //------------------------------------------------------------------------------------------------------------------
137152
+ * // 1. Create a Viewer,
137153
+ * // 2. Arrange the camera,
137154
+ * // 3. Tweak the selection material (tone it down a bit)
137155
+ * //------------------------------------------------------------------------------------------------------------------
137156
+ *
137157
+ * // 1
137158
+ * const viewer = new Viewer({
137159
+ * canvasId: "myCanvas",
137160
+ * transparent: true
137161
+ * });
137162
+ *
137163
+ * // 2
137164
+ * viewer.camera.orbitPitch(20);
137165
+ * viewer.camera.orbitYaw(-45);
137166
+ *
137167
+ * // 3
137168
+ * viewer.scene.selectedMaterial.fillAlpha = 0.1;
137169
+ *
137170
+ * //------------------------------------------------------------------------------------------------------------------
137171
+ * // 1. Create a .bim loader plugin,
137172
+ * // 2. Load a .bim building model, emphasizing the edges to make it look nicer
137173
+ * //------------------------------------------------------------------------------------------------------------------
137174
+ *
137175
+ * // 1
137176
+ * const dotBIMLoader = new DotBIMLoaderPlugin(viewer);
137177
+ *
137178
+ * // 2
137179
+ * var model = dotBIMLoader.load({ // Returns an Entity that represents the model
137180
+ * id: "myModel",
137181
+ * src: "House.bim",
137182
+ * edges: true
137183
+ * });
137184
+ *
137185
+ * // Find the model Entity by ID
137186
+ * model = viewer.scene.models["myModel"];
137187
+ *
137188
+ * // Destroy the model
137189
+ * model.destroy();
137190
+ * ````
137191
+ *
137192
+ * ## Transforming
137193
+ *
137194
+ * We have the option to rotate, scale and translate each *````.bim````* model as we load it.
137195
+ *
137196
+ * This lets us load multiple models, or even multiple copies of the same model, and position them apart from each other.
137197
+ *
137198
+ * In the example below, we'll rotate our model 90 degrees about its local X-axis, then
137199
+ * translate it 100 units along its X axis.
137200
+ *
137201
+ * ````javascript
137202
+ * const model = dotBIMLoader.load({
137203
+ * src: "House.bim",
137204
+ * rotation: [90,0,0],
137205
+ * position: [100, 0, 0]
137206
+ * });
137207
+ * ````
137208
+ *
137209
+ * ## Including and excluding IFC types
137210
+ *
137211
+ * We can also load only those objects that have the specified IFC types. In the example below, we'll load only the
137212
+ * objects that represent walls.
137213
+ *
137214
+ * ````javascript
137215
+ * const model = dotBIMLoader.load({
137216
+ * id: "myModel",
137217
+ * src: "House.bim",
137218
+ * includeTypes: ["IfcWallStandardCase"]
137219
+ * });
137220
+ * ````
137221
+ *
137222
+ * We can also load only those objects that **don't** have the specified IFC types. In the example below, we'll load only the
137223
+ * objects that do not represent empty space.
137224
+ *
137225
+ * ````javascript
137226
+ * const model = dotBIMLoader.load({
137227
+ * id: "myModel",
137228
+ * src: "House.bim",
137229
+ * excludeTypes: ["IfcSpace"]
137230
+ * });
137231
+ * ````
137232
+ *
137233
+ * # Configuring initial IFC object appearances
137234
+ *
137235
+ * We can specify the custom initial appearance of loaded objects according to their IFC types.
137236
+ *
137237
+ * This is useful for things like:
137238
+ *
137239
+ * * setting the colors to our objects according to their IFC types,
137240
+ * * automatically hiding ````IfcSpace```` objects, and
137241
+ * * ensuring that ````IfcWindow```` objects are always transparent.
137242
+ * <br>
137243
+ * In the example below, we'll load a model, while configuring ````IfcSpace```` elements to be always initially invisible,
137244
+ * and ````IfcWindow```` types to be always translucent blue.
137245
+ *
137246
+ * ````javascript
137247
+ * const myObjectDefaults = {
137248
+ *
137249
+ * IfcSpace: {
137250
+ * visible: false
137251
+ * },
137252
+ * IfcWindow: {
137253
+ * colorize: [0.337255, 0.303922, 0.870588], // Blue
137254
+ * opacity: 0.3
137255
+ * },
137256
+ *
137257
+ * //...
137258
+ *
137259
+ * DEFAULT: {
137260
+ * colorize: [0.5, 0.5, 0.5]
137261
+ * }
137262
+ * };
137263
+ *
137264
+ * const model4 = dotBIMLoader.load({
137265
+ * id: "myModel4",
137266
+ * src: "House.bim",
137267
+ * objectDefaults: myObjectDefaults // Use our custom initial default states for object Entities
137268
+ * });
137269
+ * ````
137270
+ *
137271
+ * When we don't customize the appearance of IFC types, as just above, then IfcSpace elements tend to obscure other
137272
+ * elements, which can be confusing.
137273
+ *
137274
+ * It's often helpful to make IfcSpaces transparent and unpickable, like this:
137275
+ *
137276
+ * ````javascript
137277
+ * const dotBIMLoader = new DotBIMLoaderPlugin(viewer, {
137278
+ * objectDefaults: {
137279
+ * IfcSpace: {
137280
+ * pickable: false,
137281
+ * opacity: 0.2
137282
+ * }
137283
+ * }
137284
+ * });
137285
+ * ````
137286
+ *
137287
+ * Alternatively, we could just make IfcSpaces invisible, which also makes them unpickable:
137288
+ *
137289
+ * ````javascript
137290
+ * const dotBIMLoader = new DotBIMLoaderPlugin(viewer, {
137291
+ * objectDefaults: {
137292
+ * IfcSpace: {
137293
+ * visible: false
137294
+ * }
137295
+ * }
137296
+ * });
137297
+ * ````
137298
+ *
137299
+ * # Configuring a custom data source
137300
+ *
137301
+ * By default, DotBIMLoaderPlugin will load *````.bim````* files and metadata JSON over HTTP.
137302
+ *
137303
+ * In the example below, we'll customize the way DotBIMLoaderPlugin loads the files by configuring it with our own data source
137304
+ * object. For simplicity, our custom data source example also uses HTTP, using a couple of xeokit utility functions.
137305
+ *
137306
+ * ````javascript
137307
+ * import {utils} from "xeokit-sdk.es.js";
137308
+ *
137309
+ * class MyDataSource {
137310
+ *
137311
+ * constructor() {
137312
+ * }
137313
+ *
137314
+ * // Gets the contents of the given .bim file in a JSON object
137315
+ * getDotBIM(src, ok, error) {
137316
+ * utils.loadJSON(dotBIMSrc,
137317
+ * (json) => {
137318
+ * ok(json);
137319
+ * },
137320
+ * function (errMsg) {
137321
+ * error(errMsg);
137322
+ * });
137323
+ * }
137324
+ * }
137325
+ *
137326
+ * const dotBIMLoader2 = new DotBIMLoaderPlugin(viewer, {
137327
+ * dataSource: new MyDataSource()
137328
+ * });
137329
+ *
137330
+ * const model5 = dotBIMLoader2.load({
137331
+ * id: "myModel5",
137332
+ * src: "House.bim"
137333
+ * });
137334
+ * ````
137335
+ * @class DotBIMLoaderPlugin
137336
+ */
137337
+ class DotBIMLoaderPlugin extends Plugin {
137338
+
137339
+ /**
137340
+ * @constructor
137341
+ *
137342
+ * @param {Viewer} viewer The Viewer.
137343
+ * @param {Object} cfg Plugin configuration.
137344
+ * @param {String} [cfg.id="DotBIMLoader"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.
137345
+ * @param {Object} [cfg.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.
137346
+ * @param {Object} [cfg.dataSource] A custom data source through which the DotBIMLoaderPlugin can load metadata, glTF and binary attachments. Defaults to an instance of {@link DotBIMDefaultDataSource}, which loads over HTTP.
137347
+ */
137348
+ constructor(viewer, cfg = {}) {
137349
+
137350
+ super("DotBIMLoader", viewer, cfg);
137351
+
137352
+ this.dataSource = cfg.dataSource;
137353
+ this.objectDefaults = cfg.objectDefaults;
137354
+ }
137355
+
137356
+ /**
137357
+ * Sets a custom data source through which the DotBIMLoaderPlugin can .BIM files.
137358
+ *
137359
+ * Default value is {@link DotBIMDefaultDataSource}, which loads via an XMLHttpRequest.
137360
+ *
137361
+ * @type {Object}
137362
+ */
137363
+ set dataSource(value) {
137364
+ this._dataSource = value || new DotBIMDefaultDataSource();
137365
+ }
137366
+
137367
+ /**
137368
+ * Gets the custom data source through which the DotBIMLoaderPlugin can load .BIM files.
137369
+ *
137370
+ * Default value is {@link DotBIMDefaultDataSource}, which loads via an XMLHttpRequest.
137371
+ *
137372
+ * @type {Object}
137373
+ */
137374
+ get dataSource() {
137375
+ return this._dataSource;
137376
+ }
137377
+
137378
+ /**
137379
+ * Sets map of initial default states for each loaded {@link Entity} that represents an object.
137380
+ *
137381
+ * Default value is {@link IFCObjectDefaults}.
137382
+ *
137383
+ * @type {{String: Object}}
137384
+ */
137385
+ set objectDefaults(value) {
137386
+ this._objectDefaults = value || IFCObjectDefaults;
137387
+ }
137388
+
137389
+ /**
137390
+ * Gets map of initial default states for each loaded {@link Entity} that represents an object.
137391
+ *
137392
+ * Default value is {@link IFCObjectDefaults}.
137393
+ *
137394
+ * @type {{String: Object}}
137395
+ */
137396
+ get objectDefaults() {
137397
+ return this._objectDefaults;
137398
+ }
137399
+
137400
+ /**
137401
+ * Loads a .BIM model from a file into this DotBIMLoaderPlugin's {@link Viewer}.
137402
+ *
137403
+ * @param {*} params Loading parameters.
137404
+ * @param {String} [params.id] ID to assign to the root {@link Entity#id}, unique among all components in the Viewer's {@link Scene}, generated automatically by default.
137405
+ * @param {String} [params.src] Path to a .BIM file, as an alternative to the ````bim```` parameter.
137406
+ * @param {*} [params.bim] .BIM JSON, as an alternative to the ````src```` parameter.
137407
+ * @param {{String:Object}} [params.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.
137408
+ * @param {String[]} [params.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
137409
+ * @param {String[]} [params.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
137410
+ * @param {Number[]} [params.origin=[0,0,0]] The double-precision World-space origin of the model's coordinates.
137411
+ * @param {Number[]} [params.position=[0,0,0]] The single-precision position, relative to ````origin````.
137412
+ * @param {Number[]} [params.scale=[1,1,1]] The model's scale.
137413
+ * @param {Number[]} [params.rotation=[0,0,0]] The model's orientation, as Euler angles given in degrees, for each of the X, Y and Z axis.
137414
+ * @param {Boolean} [params.backfaces=true] When true, always show backfaces, even on objects for which the .BIM material is single-sided. When false, only show backfaces on geometries whenever the .BIM material is double-sided.
137415
+ * @param {Boolean} [params.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to
137416
+ * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable
137417
+ * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point
137418
+ * primitives. Only works while {@link DTX#enabled} is also ````true````.
137419
+ * @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}
137420
+ */
137421
+ load(params = {}) {
137422
+
137423
+ if (params.id && this.viewer.scene.components[params.id]) {
137424
+ this.error("Component with this ID already exists in viewer: " + params.id + " - will autogenerate this ID");
137425
+ delete params.id;
137426
+ }
137427
+
137428
+ const sceneModel = new SceneModel(this.viewer.scene, utils.apply(params, {
137429
+ isModel: true,
137430
+ backfaces: params.backfaces,
137431
+ dtxEnabled: params.dtxEnabled,
137432
+ rotation: params.rotation,
137433
+ origin: params.origin
137434
+ }));
137435
+
137436
+ const modelId = sceneModel.id; // In case ID was auto-generated
137437
+
137438
+ if (!params.src && !params.dotBIM) {
137439
+ this.error("load() param expected: src or dotBIM");
137440
+ return sceneModel; // Return new empty model
137441
+ }
137442
+
137443
+ const objectDefaults = params.objectDefaults || this._objectDefaults || IFCObjectDefaults;
137444
+
137445
+ let includeTypes;
137446
+ if (params.includeTypes) {
137447
+ includeTypes = {};
137448
+ for (let i = 0, len = params.includeTypes.length; i < len; i++) {
137449
+ includeTypes[params.includeTypes[i]] = true;
137450
+ }
137451
+ }
137452
+
137453
+ let excludeTypes;
137454
+ if (params.excludeTypes) {
137455
+ excludeTypes = {};
137456
+ if (!includeTypes) {
137457
+ includeTypes = {};
137458
+ }
137459
+ for (let i = 0, len = params.excludeTypes.length; i < len; i++) {
137460
+ includeTypes[params.excludeTypes[i]] = true;
137461
+ }
137462
+ }
137463
+
137464
+ const parseDotBIM = (ctx) => {
137465
+
137466
+ const fileData = ctx.fileData;
137467
+ const sceneModel = ctx.sceneModel;
137468
+
137469
+ const dbMeshIndices = {};
137470
+ const dbMeshLoaded = {};
137471
+
137472
+ const ifcProjectId = math.createUUID();
137473
+ const ifcSiteId = math.createUUID();
137474
+ const ifcBuildingId = math.createUUID();
137475
+ const ifcBuildingStoryId = math.createUUID();
137476
+
137477
+ const metaModelData = {
137478
+ metaObjects: [
137479
+ {
137480
+ id: ifcProjectId,
137481
+ name: "IfcProject",
137482
+ type: "IfcProject",
137483
+ parent: null
137484
+ },
137485
+ {
137486
+ id: ifcSiteId,
137487
+ name: "IfcSite",
137488
+ type: "IfcSite",
137489
+ parent: ifcProjectId
137490
+ },
137491
+ {
137492
+ id: ifcBuildingId,
137493
+ name: "IfcBuilding",
137494
+ type: "IfcBuilding",
137495
+ parent: ifcSiteId
137496
+ },
137497
+ {
137498
+ id: ifcBuildingStoryId,
137499
+ name: "IfcBuildingStorey",
137500
+ type: "IfcBuildingStorey",
137501
+ parent: ifcBuildingId
137502
+ }
137503
+ ],
137504
+ propertySets: []
137505
+ };
137506
+
137507
+ for (let i = 0, len = fileData.meshes.length; i < len; i++) {
137508
+ const dbMesh = fileData.meshes[i];
137509
+ dbMeshIndices[dbMesh.mesh_id] = i;
137510
+ }
137511
+
137512
+ const parseDBMesh = (dbMeshId) => {
137513
+ if (dbMeshLoaded[dbMeshId]) {
137514
+ return;
137515
+ }
137516
+ const dbMeshIndex = dbMeshIndices[dbMeshId];
137517
+ const dbMesh = fileData.meshes[dbMeshIndex];
137518
+ sceneModel.createGeometry({
137519
+ id: dbMeshId,
137520
+ primitive: "triangles",
137521
+ positions: dbMesh.coordinates,
137522
+ indices: dbMesh.indices
137523
+ });
137524
+ dbMeshLoaded[dbMeshId] = true;
137525
+ };
137526
+
137527
+ const dbElements = fileData.elements;
137528
+ for (let i = 0, len = dbElements.length; i < len; i++) {
137529
+ const element = dbElements[i];
137530
+ const elementType = element.type;
137531
+ if (excludeTypes && excludeTypes[elementType]) {
137532
+ continue;
137533
+
137534
+ }
137535
+ if (includeTypes && (!includeTypes[elementType])) {
137536
+ continue;
137537
+ }
137538
+ const info = element.info;
137539
+ const objectId =
137540
+ element.guid !== undefined
137541
+ ? `${element.guid}`
137542
+ : (info !== undefined && info.id !== undefined
137543
+ ? info.id
137544
+ : i);
137545
+
137546
+ const dbMeshId = element.mesh_id;
137547
+
137548
+ parseDBMesh(dbMeshId);
137549
+
137550
+ const meshId = `${objectId}-mesh`;
137551
+ const vector = element.vector;
137552
+ const rotation = element.rotation;
137553
+ const props = objectDefaults ? objectDefaults[elementType] || objectDefaults["DEFAULT"] : null;
137554
+
137555
+ let visible = true;
137556
+ let pickable = true;
137557
+ let color = element.color ? [element.color.r / 255, element.color.g / 255, element.color.b / 255] : [1, 1, 1];
137558
+ let opacity = element.color ? element.color.a / 255 : 1.0;
137559
+
137560
+ if (props) {
137561
+ if (props.visible === false) {
137562
+ visible = false;
137563
+ }
137564
+ if (props.pickable === false) {
137565
+ pickable = false;
137566
+ }
137567
+ if (props.colorize) {
137568
+ color = props.colorize;
137569
+ }
137570
+ if (props.opacity !== undefined && props.opacity !== null) {
137571
+ opacity = props.opacity;
137572
+ }
137573
+ }
137574
+
137575
+ sceneModel.createMesh({
137576
+ id: meshId,
137577
+ geometryId: dbMeshId,
137578
+ color,
137579
+ opacity,
137580
+ quaternion: rotation && (rotation.qz !== 0 || rotation.qy !== 0 || rotation.qx !== 0 || rotation.qw !== 1.0) ? [rotation.qx, rotation.qy, rotation.qz, rotation.qw] : undefined,
137581
+ position: vector ? [vector.x, vector.y, vector.z] : undefined
137582
+ });
137583
+
137584
+ sceneModel.createEntity({
137585
+ id: objectId,
137586
+ meshIds: [meshId],
137587
+ visible,
137588
+ pickable,
137589
+ isObject: true
137590
+ });
137591
+
137592
+ metaModelData.metaObjects.push({
137593
+ id: objectId,
137594
+ name: info && info.Name && info.Name !== "None" ? info.Name : `${element.type} ${objectId}`,
137595
+ type: element.type,
137596
+ parent: ifcBuildingStoryId
137597
+ });
137598
+ }
137599
+
137600
+ sceneModel.finalize();
137601
+
137602
+ this.viewer.metaScene.createMetaModel(modelId, metaModelData);
137603
+
137604
+ sceneModel.scene.once("tick", () => {
137605
+ if (sceneModel.destroyed) {
137606
+ return;
137607
+ }
137608
+ sceneModel.scene.fire("modelLoaded", sceneModel.id); // FIXME: Assumes listeners know order of these two events
137609
+ sceneModel.fire("loaded", true, false); // Don't forget the event, for late subscribers
137610
+ });
137611
+ };
137612
+
137613
+ if (params.src) {
137614
+ const src = params.src;
137615
+ this.viewer.scene.canvas.spinner.processes++;
137616
+ this._dataSource.getDotBIM(src, (fileData) => { // OK
137617
+ const ctx = {
137618
+ fileData,
137619
+ sceneModel,
137620
+ nextId: 0,
137621
+ error: function (errMsg) {
137622
+ }
137623
+ };
137624
+ parseDotBIM(ctx);
137625
+ this.viewer.scene.canvas.spinner.processes--;
137626
+ },
137627
+ (err) => {
137628
+ this.viewer.scene.canvas.spinner.processes--;
137629
+ this.error(err);
137630
+ });
137631
+ } else if (params.dotBIM) {
137632
+ const ctx = {
137633
+ fileData: params.dotBIM,
137634
+ sceneModel,
137635
+ nextId: 0,
137636
+ error: function (errMsg) {
137637
+ }
137638
+ };
137639
+ parseDotBIM(ctx);
137640
+ }
137641
+
137642
+ sceneModel.once("destroyed", () => {
137643
+ this.viewer.metaScene.destroyMetaModel(modelId);
137644
+ });
137645
+
137646
+ return sceneModel;
137647
+ }
137648
+
137649
+ /**
137650
+ * Destroys this DotBIMLoaderPlugin.
137651
+ */
137652
+ destroy() {
137653
+ super.destroy();
137654
+ }
137655
+ }
137656
+
137657
+ export { AlphaFormat, AmbientLight, AngleMeasurementsControl, AngleMeasurementsMouseControl, AngleMeasurementsPlugin, AngleMeasurementsTouchControl, AnnotationsPlugin, AxisGizmoPlugin, BCFViewpointsPlugin, Bitmap, ByteType, CameraMemento, CameraPath, CameraPathAnimation, CityJSONLoaderPlugin, ClampToEdgeWrapping, Component, CompressedMediaType, Configs, ContextMenu, CubicBezierCurve, Curve, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DirLight, DistanceMeasurementsControl, DistanceMeasurementsMouseControl, DistanceMeasurementsPlugin, DistanceMeasurementsTouchControl, DotBIMDefaultDataSource, DotBIMLoaderPlugin, EdgeMaterial, EmphasisMaterial, FaceAlignedSectionPlanesPlugin, FastNavPlugin, FloatType, Fresnel, Frustum$1 as Frustum, FrustumPlane, GIFMediaType, GLTFDefaultDataSource, GLTFLoaderPlugin, HalfFloatType, ImagePlane, IntType, JPEGMediaType, KTX2TextureTranscoder, LASLoaderPlugin, LambertMaterial, LightMap, LineSet, LinearEncoding, LinearFilter, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, Loader, LoadingManager, LocaleService, LuminanceAlphaFormat, LuminanceFormat, Map$1 as Map, Marker, MarqueePicker, MarqueePickerMouseControl, Mesh, MetallicMaterial, MirroredRepeatWrapping, ModelMemento, NavCubePlugin, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, Node$2 as Node, OBJLoaderPlugin, ObjectsKdTree3, ObjectsMemento, PNGMediaType, Path, PerformanceModel, PhongMaterial, PickResult, Plugin, PointLight, PointerCircle, PointerLens, QuadraticBezierCurve, Queue, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, ReadableGeometry, RedFormat, RedIntegerFormat, ReflectionMap, RepeatWrapping, STLDefaultDataSource, STLLoaderPlugin, SceneModel, SceneModelMesh, SceneModelTransform, SectionPlane, SectionPlanesPlugin, ShortType, Skybox, SkyboxesPlugin, SpecularMaterial, SplineCurve, SpriteMarker, StoreyViewsPlugin, Texture, TextureTranscoder, TreeViewPlugin, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VBOGeometry, ViewCullPlugin, Viewer, WebIFCLoaderPlugin, WorkerPool$1 as WorkerPool, XKTDefaultDataSource, XKTLoaderPlugin, XML3DLoaderPlugin, buildBoxGeometry, buildBoxLinesGeometry, buildBoxLinesGeometryFromAABB, buildCylinderGeometry, buildGridGeometry, buildPlaneGeometry, buildPolylineGeometry, buildPolylineGeometryFromCurve, buildSphereGeometry, buildTorusGeometry, buildVectorTextGeometry, createRTCViewMat, frustumIntersectsAABB3, getKTX2TextureTranscoder, getPlaneRTCPos, load3DSGeometry, loadOBJGeometry, math, rtcToWorldPos, sRGBEncoding, setFrustum, stats, utils, worldToRTCPos, worldToRTCPositions };