@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
@@ -10460,7 +10460,7 @@ const tempVec4b$6 = math.vec4();
10460
10460
  * });
10461
10461
  *
10462
10462
  * // Create the Marker, associated with our Mesh Entity
10463
- * const myMarker = new Marker({
10463
+ * const myMarker = new Marker(viewer, {
10464
10464
  * entity: entity,
10465
10465
  * worldPos: [10,0,0],
10466
10466
  * occludable: true
@@ -10589,7 +10589,7 @@ class Marker extends Component {
10589
10589
  return;
10590
10590
  }
10591
10591
  if (this._onEntityDestroyed !== null) {
10592
- this._entity.off(this._onEntityDestroyed);
10592
+ this._entity.model.off(this._onEntityDestroyed);
10593
10593
  this._onEntityDestroyed = null;
10594
10594
  }
10595
10595
  if (this._onEntityModelDestroyed !== null) {
@@ -10605,7 +10605,7 @@ class Marker extends Component {
10605
10605
  this._onEntityModelDestroyed = null;
10606
10606
  });
10607
10607
  } else {
10608
- this._onEntityDestroyed = this._entity.on("destroyed", () => {
10608
+ this._onEntityDestroyed = this._entity.model.on("destroyed", () => {
10609
10609
  this._entity = null;
10610
10610
  this._onEntityDestroyed = null;
10611
10611
  });
@@ -10771,6 +10771,16 @@ class Marker extends Component {
10771
10771
  }
10772
10772
  }
10773
10773
 
10774
+ const os = {
10775
+ isIphoneSafari() {
10776
+ const userAgent = window.navigator.userAgent;
10777
+ const isIphone = /iPhone/i.test(userAgent);
10778
+ const isSafari = /Safari/i.test(userAgent) && !/Chrome/i.test(userAgent);
10779
+
10780
+ return isIphone && isSafari;
10781
+ }
10782
+ };
10783
+
10774
10784
  /** @private */
10775
10785
  class Wire {
10776
10786
 
@@ -10883,11 +10893,42 @@ class Wire {
10883
10893
  }
10884
10894
 
10885
10895
  if (cfg.onContextMenu) {
10886
- wireClickable.addEventListener('contextmenu', (event) => {
10887
- cfg.onContextMenu(event, this);
10888
- event.preventDefault();
10889
- event.stopPropagation();
10890
- });
10896
+ if(os.isIphoneSafari()){
10897
+ wireClickable.addEventListener('touchstart', (event) => {
10898
+ event.preventDefault();
10899
+ if(this._timeout){
10900
+ clearTimeout(this._timeout);
10901
+ this._timeout = null;
10902
+ }
10903
+ this._timeout = setTimeout(() => {
10904
+ event.clientX = event.touches[0].clientX;
10905
+ event.clientY = event.touches[0].clientY;
10906
+ cfg.onContextMenu(event, this);
10907
+ clearTimeout(this._timeout);
10908
+ this._timeout = null;
10909
+ }, 500);
10910
+ });
10911
+
10912
+ wireClickable.addEventListener('touchend', (event) => {
10913
+ event.preventDefault();
10914
+ //stops short touches from calling the timeout
10915
+ if(this._timeout) {
10916
+ clearTimeout(this._timeout);
10917
+ this._timeout = null;
10918
+ }
10919
+ } );
10920
+
10921
+ }
10922
+ else {
10923
+ wireClickable.addEventListener('contextmenu', (event) => {
10924
+ console.log(event);
10925
+ cfg.onContextMenu(event, this);
10926
+ event.preventDefault();
10927
+ event.stopPropagation();
10928
+ console.log("Label context menu");
10929
+ });
10930
+ }
10931
+
10891
10932
  }
10892
10933
 
10893
10934
  this._x1 = 0;
@@ -10962,7 +11003,7 @@ class Wire {
10962
11003
  }
10963
11004
 
10964
11005
  setClickable(clickable) {
10965
- this._wireClickable.style["pointer-events"] = (!!clickable) ? "all" : "none";
11006
+ this._wireClickable.style["pointer-events"] = (clickable) ? "all" : "none";
10966
11007
  }
10967
11008
 
10968
11009
  setHighlighted(highlighted) {
@@ -11082,11 +11123,42 @@ class Dot {
11082
11123
  }
11083
11124
 
11084
11125
  if (cfg.onContextMenu) {
11085
- dotClickable.addEventListener('contextmenu', (event) => {
11086
- cfg.onContextMenu(event, this);
11087
- event.preventDefault();
11088
- event.stopPropagation();
11089
- });
11126
+ if(os.isIphoneSafari()){
11127
+ dotClickable.addEventListener('touchstart', (event) => {
11128
+ event.preventDefault();
11129
+ if(this._timeout){
11130
+ clearTimeout(this._timeout);
11131
+ this._timeout = null;
11132
+ }
11133
+ this._timeout = setTimeout(() => {
11134
+ event.clientX = event.touches[0].clientX;
11135
+ event.clientY = event.touches[0].clientY;
11136
+ cfg.onContextMenu(event, this);
11137
+ clearTimeout(this._timeout);
11138
+ this._timeout = null;
11139
+ }, 500);
11140
+ });
11141
+
11142
+ dotClickable.addEventListener('touchend', (event) => {
11143
+ event.preventDefault();
11144
+ //stops short touches from calling the timeout
11145
+ if(this._timeout) {
11146
+ clearTimeout(this._timeout);
11147
+ this._timeout = null;
11148
+ }
11149
+ } );
11150
+
11151
+ }
11152
+ else {
11153
+ dotClickable.addEventListener('contextmenu', (event) => {
11154
+ console.log(event);
11155
+ cfg.onContextMenu(event, this);
11156
+ event.preventDefault();
11157
+ event.stopPropagation();
11158
+ console.log("Label context menu");
11159
+ });
11160
+ }
11161
+
11090
11162
  }
11091
11163
 
11092
11164
  this.setPos(cfg.x || 0, cfg.y || 0);
@@ -11135,7 +11207,7 @@ class Dot {
11135
11207
  }
11136
11208
 
11137
11209
  setClickable(clickable) {
11138
- this._dotClickable.style["pointer-events"] = (!!clickable) ? "all" : "none";
11210
+ this._dotClickable.style["pointer-events"] = (clickable) ? "all" : "none";
11139
11211
  }
11140
11212
 
11141
11213
  setHighlighted(highlighted) {
@@ -11176,6 +11248,7 @@ class Label {
11176
11248
 
11177
11249
  this._label = document.createElement('div');
11178
11250
  this._label.className += this._label.className ? ' viewer-ruler-label' : 'viewer-ruler-label';
11251
+ this._timeout = null;
11179
11252
 
11180
11253
  var label = this._label;
11181
11254
  var style = label.style;
@@ -11245,12 +11318,42 @@ class Label {
11245
11318
  }
11246
11319
 
11247
11320
  if (cfg.onContextMenu) {
11248
- label.addEventListener('contextmenu', (event) => {
11249
- cfg.onContextMenu(event, this);
11250
- event.preventDefault();
11251
- event.stopPropagation();
11252
- console.log("Label context menu");
11253
- });
11321
+ if(os.isIphoneSafari()){
11322
+ label.addEventListener('touchstart', (event) => {
11323
+ event.preventDefault();
11324
+ if(this._timeout){
11325
+ clearTimeout(this._timeout);
11326
+ this._timeout = null;
11327
+ }
11328
+ this._timeout = setTimeout(() => {
11329
+ event.clientX = event.touches[0].clientX;
11330
+ event.clientY = event.touches[0].clientY;
11331
+ cfg.onContextMenu(event, this);
11332
+ clearTimeout(this._timeout);
11333
+ this._timeout = null;
11334
+ }, 500);
11335
+ });
11336
+
11337
+ label.addEventListener('touchend', (event) => {
11338
+ event.preventDefault();
11339
+ //stops short touches from calling the timeout
11340
+ if(this._timeout) {
11341
+ clearTimeout(this._timeout);
11342
+ this._timeout = null;
11343
+ }
11344
+ } );
11345
+
11346
+ }
11347
+ else {
11348
+ label.addEventListener('contextmenu', (event) => {
11349
+ console.log(event);
11350
+ cfg.onContextMenu(event, this);
11351
+ event.preventDefault();
11352
+ event.stopPropagation();
11353
+ console.log("Label context menu");
11354
+ });
11355
+ }
11356
+
11254
11357
  }
11255
11358
  }
11256
11359
 
@@ -11325,7 +11428,14 @@ class Label {
11325
11428
  }
11326
11429
 
11327
11430
  setClickable(clickable) {
11328
- this._label.style["pointer-events"] = (!!clickable) ? "all" : "none";
11431
+ this._label.style["pointer-events"] = (clickable) ? "all" : "none";
11432
+ }
11433
+
11434
+ setPrefix(prefix) {
11435
+ if(this._prefix === prefix){
11436
+ return;
11437
+ }
11438
+ this._prefix = prefix;
11329
11439
  }
11330
11440
 
11331
11441
  destroy() {
@@ -11333,6 +11443,8 @@ class Label {
11333
11443
  this._label.parentElement.removeChild(this._label);
11334
11444
  }
11335
11445
  }
11446
+
11447
+
11336
11448
  }
11337
11449
 
11338
11450
  var originVec = math.vec3();
@@ -12130,6 +12242,16 @@ class AngleMeasurementsControl extends Component {
12130
12242
  reset() {
12131
12243
  }
12132
12244
 
12245
+ /**
12246
+ * Gets the {@link AngleMeasurement} under construction by this AngleMeasurementsControl, if any.
12247
+ *
12248
+ * @returns {null|AngleMeasurement}
12249
+ * @abstract
12250
+ */
12251
+ get currentMeasurement() {
12252
+ return null;
12253
+ }
12254
+
12133
12255
  /**
12134
12256
  * Destroys this AngleMeasurementsMouseControl.
12135
12257
  *
@@ -12580,6 +12702,15 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12580
12702
  this._mouseState = MOUSE_FINDING_ORIGIN;
12581
12703
  }
12582
12704
 
12705
+ /**
12706
+ * Gets the {@link AngleMeasurement} under construction by this AngleMeasurementsMouseControl, if any.
12707
+ *
12708
+ * @returns {null|AngleMeasurement}
12709
+ */
12710
+ get currentMeasurement() {
12711
+ return this._currentAngleMeasurement;
12712
+ }
12713
+
12583
12714
  /**
12584
12715
  * Destroys this AngleMeasurementsMouseControl.
12585
12716
  */
@@ -13933,6 +14064,15 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13933
14064
  }
13934
14065
  }
13935
14066
 
14067
+ /**
14068
+ * Gets the {@link AngleMeasurement} under construction by this AngleMeasurementsTouchControl, if any.
14069
+ *
14070
+ * @returns {null|AngleMeasurement}
14071
+ */
14072
+ get currentMeasurement() {
14073
+ return this._currentAngleMeasurement;
14074
+ }
14075
+
13936
14076
  /**
13937
14077
  * Destroys this AngleMeasurementsTouchControl.
13938
14078
  */
@@ -81028,10 +81168,11 @@ class SceneModelTransform {
81028
81168
  const tempVec3a$a = math.vec3();
81029
81169
 
81030
81170
  const tempOBB3 = math.OBB3();
81171
+ const tempQuaternion = math.vec4();
81031
81172
 
81032
81173
  const DEFAULT_SCALE = math.vec3([1, 1, 1]);
81033
81174
  const DEFAULT_POSITION = math.vec3([0, 0, 0]);
81034
- const DEFAULT_ROTATION = math.vec3([0, 0, 0]);
81175
+ math.vec3([0, 0, 0]);
81035
81176
  const DEFAULT_QUATERNION = math.identityQuaternion();
81036
81177
  const DEFAULT_MATRIX = math.identityMat4();
81037
81178
 
@@ -83708,6 +83849,7 @@ class SceneModel extends Component {
83708
83849
  * @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.
83709
83850
  * @param {Number[]} [cfg.scale=[1,1,1]] Scale of the mesh. Overridden by ````transformId````.
83710
83851
  * @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````.
83852
+ * @param {Number[]} [cfg.quaternion] Rotation of the mesh as a quaternion. Overridden by ````rotation````.
83711
83853
  * @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````.
83712
83854
  * @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````.
83713
83855
  * @param {Number} [cfg.opacity=1] Opacity in range ````[0..1]````. Overridden by texture set ````colorTexture````.
@@ -83782,12 +83924,15 @@ class SceneModel extends Component {
83782
83924
 
83783
83925
  if (cfg.matrix) {
83784
83926
  cfg.meshMatrix = cfg.matrix;
83785
- } else if (cfg.scale || cfg.rotation || cfg.position) {
83927
+ } else if (cfg.scale || cfg.rotation || cfg.position || cfg.quaternion) {
83786
83928
  const scale = cfg.scale || DEFAULT_SCALE;
83787
83929
  const position = cfg.position || DEFAULT_POSITION;
83788
- const rotation = cfg.rotation || DEFAULT_ROTATION;
83789
- math.eulerToQuaternion(rotation, "XYZ", DEFAULT_QUATERNION);
83790
- cfg.meshMatrix = math.composeMat4(position, DEFAULT_QUATERNION, scale, math.mat4());
83930
+ if (cfg.rotation) {
83931
+ math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion);
83932
+ cfg.meshMatrix = math.composeMat4(position, tempQuaternion, scale, math.mat4());
83933
+ } else {
83934
+ cfg.meshMatrix = math.composeMat4(position, cfg.quaternion || DEFAULT_QUATERNION, scale, math.mat4());
83935
+ }
83791
83936
  }
83792
83937
 
83793
83938
  if (cfg.positionsDecodeBoundary) {
@@ -83975,13 +84120,16 @@ class SceneModel extends Component {
83975
84120
  // MATRIX
83976
84121
 
83977
84122
  if (cfg.matrix) {
83978
- cfg.meshMatrix = cfg.matrix.slice();
83979
- } else {
84123
+ cfg.meshMatrix = cfg.matrix;
84124
+ } else if (cfg.scale || cfg.rotation || cfg.position || cfg.quaternion) {
83980
84125
  const scale = cfg.scale || DEFAULT_SCALE;
83981
84126
  const position = cfg.position || DEFAULT_POSITION;
83982
- const rotation = cfg.rotation || DEFAULT_ROTATION;
83983
- math.eulerToQuaternion(rotation, "XYZ", DEFAULT_QUATERNION);
83984
- cfg.meshMatrix = math.composeMat4(position, DEFAULT_QUATERNION, scale, math.mat4());
84127
+ if (cfg.rotation) {
84128
+ math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion);
84129
+ cfg.meshMatrix = math.composeMat4(position, tempQuaternion, scale, math.mat4());
84130
+ } else {
84131
+ cfg.meshMatrix = math.composeMat4(position, cfg.quaternion || DEFAULT_QUATERNION, scale, math.mat4());
84132
+ }
83985
84133
  }
83986
84134
 
83987
84135
  math.AABB3ToOBB3(cfg.geometry.aabb, tempOBB3);
@@ -86134,6 +86282,14 @@ const lengthWire = (x1, y1, x2, y2) => {
86134
86282
  return Math.sqrt(a * a + b * b);
86135
86283
  };
86136
86284
 
86285
+ function determineMeasurementOrientation(A, B, distance) {
86286
+ const yDiff = Math.abs(B[1] - A[1]);
86287
+
86288
+ return yDiff > distance ? 'Vertical' : 'Horizontal';
86289
+ }
86290
+
86291
+ // function findDistance
86292
+
86137
86293
  /**
86138
86294
  * @desc Measures the distance between two 3D points.
86139
86295
  *
@@ -86162,17 +86318,16 @@ class DistanceMeasurement extends Component {
86162
86318
  this._eventSubs = {};
86163
86319
 
86164
86320
  var scene = this.plugin.viewer.scene;
86165
-
86166
86321
  this._originMarker = new Marker(scene, cfg.origin);
86167
86322
  this._targetMarker = new Marker(scene, cfg.target);
86168
86323
 
86169
86324
  this._originWorld = math.vec3();
86170
86325
  this._targetWorld = math.vec3();
86171
86326
 
86172
- this._wp = new Float64Array(24);
86173
- this._vp = new Float64Array(24);
86327
+ this._wp = new Float64Array(24); //world position
86328
+ this._vp = new Float64Array(24); //view position
86174
86329
  this._pp = new Float64Array(24);
86175
- this._cp = new Float64Array(8);
86330
+ this._cp = new Float64Array(8); //canvas position
86176
86331
 
86177
86332
  this._xAxisLabelCulled = false;
86178
86333
  this._yAxisLabelCulled = false;
@@ -86346,6 +86501,7 @@ class DistanceMeasurement extends Component {
86346
86501
  onContextMenu
86347
86502
  });
86348
86503
 
86504
+ this._measurementOrientation = 'Horizontal';
86349
86505
  this._wpDirty = false;
86350
86506
  this._vpDirty = false;
86351
86507
  this._cpDirty = false;
@@ -86360,18 +86516,22 @@ class DistanceMeasurement extends Component {
86360
86516
  this._yAxisVisible = false;
86361
86517
  this._zAxisVisible = false;
86362
86518
  this._axisEnabled = true;
86519
+ this._xLabelEnabled = false;
86520
+ this._yLabelEnabled = false;
86521
+ this._zLabelEnabled = false;
86522
+ this._lengthLabelEnabled = false;
86363
86523
  this._labelsVisible = false;
86364
86524
  this._labelsOnWires = false;
86365
86525
  this._clickable = false;
86366
86526
 
86367
86527
  this._originMarker.on("worldPos", (value) => {
86368
- this._originWorld.set(value || [0, 0, 0]);
86528
+ this._originWorld.set(value || [0,0,0]);
86369
86529
  this._wpDirty = true;
86370
86530
  this._needUpdate(0); // No lag
86371
86531
  });
86372
86532
 
86373
86533
  this._targetMarker.on("worldPos", (value) => {
86374
- this._targetWorld.set(value || [0, 0, 0]);
86534
+ this._targetWorld.set(value || [0,0,0]);
86375
86535
  this._wpDirty = true;
86376
86536
  this._needUpdate(0); // No lag
86377
86537
  });
@@ -86420,6 +86580,10 @@ class DistanceMeasurement extends Component {
86420
86580
  this.xAxisVisible = cfg.xAxisVisible;
86421
86581
  this.yAxisVisible = cfg.yAxisVisible;
86422
86582
  this.zAxisVisible = cfg.zAxisVisible;
86583
+ this.xLabelEnabled = cfg.xLabelEnabled;
86584
+ this.yLabelEnabled = cfg.yLabelEnabled;
86585
+ this.zLabelEnabled = cfg.zLabelEnabled;
86586
+ this.lengthLabelEnabled = cfg.lengthLabelEnabled;
86423
86587
  this.labelsVisible = cfg.labelsVisible;
86424
86588
  this.labelsOnWires = cfg.labelsOnWires;
86425
86589
  }
@@ -86434,25 +86598,50 @@ class DistanceMeasurement extends Component {
86434
86598
 
86435
86599
  if (this._wpDirty) {
86436
86600
 
86437
- this._wp[0] = this._originWorld[0];
86438
- this._wp[1] = this._originWorld[1];
86439
- this._wp[2] = this._originWorld[2];
86440
- this._wp[3] = 1.0;
86601
+ this._measurementOrientation = determineMeasurementOrientation(this._originWorld, this._targetWorld, 1);
86602
+ if(this._measurementOrientation === 'Vertical'){
86603
+ this._wp[0] = this._originWorld[0];
86604
+ this._wp[1] = this._originWorld[1];
86605
+ this._wp[2] = this._originWorld[2];
86606
+ this._wp[3] = 1.0;
86441
86607
 
86442
- this._wp[4] = this._targetWorld[0];
86443
- this._wp[5] = this._originWorld[1];
86444
- this._wp[6] = this._originWorld[2];
86445
- this._wp[7] = 1.0;
86608
+ this._wp[4] = this._originWorld[0]; //x-axis
86609
+ this._wp[5] = this._originWorld[1];
86610
+ this._wp[6] = this._originWorld[2];
86611
+ this._wp[7] = 1.0;
86446
86612
 
86447
- this._wp[8] = this._targetWorld[0];
86448
- this._wp[9] = this._targetWorld[1];
86449
- this._wp[10] = this._originWorld[2];
86450
- this._wp[11] = 1.0;
86613
+ this._wp[8] = this._originWorld[0]; //x-axis
86614
+ this._wp[9] = this._targetWorld[1]; //y-axis
86615
+ this._wp[10] = this._originWorld[2];
86616
+ this._wp[11] = 1.0;
86451
86617
 
86452
- this._wp[12] = this._targetWorld[0];
86453
- this._wp[13] = this._targetWorld[1];
86454
- this._wp[14] = this._targetWorld[2];
86455
- this._wp[15] = 1.0;
86618
+ this._wp[12] = this._targetWorld[0];
86619
+ this._wp[13] = this._targetWorld[1];
86620
+ this._wp[14] = this._targetWorld[2];
86621
+ this._wp[15] = 1.0;
86622
+ }
86623
+ else {
86624
+ this._wp[0] = this._originWorld[0];
86625
+ this._wp[1] = this._originWorld[1];
86626
+ this._wp[2] = this._originWorld[2];
86627
+ this._wp[3] = 1.0;
86628
+
86629
+ this._wp[4] = this._targetWorld[0];
86630
+ this._wp[5] = this._originWorld[1];
86631
+ this._wp[6] = this._originWorld[2];
86632
+ this._wp[7] = 1.0;
86633
+
86634
+ this._wp[8] = this._targetWorld[0];
86635
+ this._wp[9] = this._targetWorld[1];
86636
+ this._wp[10] = this._originWorld[2];
86637
+ this._wp[11] = 1.0;
86638
+
86639
+ this._wp[12] = this._targetWorld[0];
86640
+ this._wp[13] = this._targetWorld[1];
86641
+ this._wp[14] = this._targetWorld[2];
86642
+ this._wp[15] = 1.0;
86643
+ }
86644
+
86456
86645
 
86457
86646
  this._wpDirty = false;
86458
86647
  this._vpDirty = true;
@@ -86623,7 +86812,14 @@ class DistanceMeasurement extends Component {
86623
86812
  }
86624
86813
 
86625
86814
  if (!this._zAxisLabelCulled) {
86626
- this._zAxisLabel.setText(tilde + Math.abs((this._targetWorld[2] - this._originWorld[2]) * scale).toFixed(2) + unitAbbrev);
86815
+ if(this._measurementOrientation === 'Vertical') {
86816
+ this._zAxisLabel.setPrefix("");
86817
+ 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);
86818
+ }
86819
+ else {
86820
+ this._zAxisLabel.setPrefix("Z");
86821
+ this._zAxisLabel.setText(tilde + Math.abs((this._targetWorld[2] - this._originWorld[2]) * scale).toFixed(2) + unitAbbrev);
86822
+ }
86627
86823
  this._zAxisLabel.setCulled(!this.axisVisible);
86628
86824
  } else {
86629
86825
  this._zAxisLabel.setCulled(true);
@@ -86743,7 +86939,7 @@ class DistanceMeasurement extends Component {
86743
86939
  this._originDot.setVisible(this._visible && this._originVisible);
86744
86940
  this._targetDot.setVisible(this._visible && this._targetVisible);
86745
86941
  this._lengthWire.setVisible(this._visible && this._wireVisible);
86746
- this._lengthLabel.setVisible(this._visible && this._wireVisible);
86942
+ this._lengthLabel.setVisible(this._visible && this._wireVisible && this._lengthLabelEnabled);
86747
86943
 
86748
86944
  const xAxisVisible = this._visible && this._axisVisible && this._xAxisVisible;
86749
86945
  const yAxisVisible = this._visible && this._axisVisible && this._yAxisVisible;
@@ -86753,9 +86949,9 @@ class DistanceMeasurement extends Component {
86753
86949
  this._yAxisWire.setVisible(yAxisVisible);
86754
86950
  this._zAxisWire.setVisible(zAxisVisible);
86755
86951
 
86756
- this._xAxisLabel.setVisible(xAxisVisible && !this._xAxisLabelCulled);
86757
- this._yAxisLabel.setVisible(yAxisVisible && !this._yAxisLabelCulled);
86758
- this._zAxisLabel.setVisible(zAxisVisible && !this._zAxisLabelCulled);
86952
+ this._xAxisLabel.setVisible(xAxisVisible && !this._xAxisLabelCulled && this._EnabledVisible);
86953
+ this._yAxisLabel.setVisible(yAxisVisible && !this._yAxisLabelCulled && this._yLabelEnabled);
86954
+ this._zAxisLabel.setVisible(zAxisVisible && !this._zAxisLabelCulled && this._zLabelEnabled);
86759
86955
 
86760
86956
  this._cpDirty = true;
86761
86957
 
@@ -86825,9 +87021,9 @@ class DistanceMeasurement extends Component {
86825
87021
  this._xAxisWire.setVisible(axisVisible && this._xAxisVisible);
86826
87022
  this._yAxisWire.setVisible(axisVisible && this._yAxisVisible);
86827
87023
  this._zAxisWire.setVisible(axisVisible && this._zAxisVisible);
86828
- this._xAxisLabel.setVisible(axisVisible && !this._xAxisLabelCulled&& this._xAxisVisible);
86829
- this._yAxisLabel.setVisible(axisVisible && !this._yAxisLabelCulled&& this._xAxisVisible);
86830
- this._zAxisLabel.setVisible(axisVisible && !this._zAxisLabelCulled&& this._xAxisVisible);
87024
+ this._xAxisLabel.setVisible(axisVisible && !this._xAxisLabelCulled&& this._xAxisVisible && this._xLabelEnabled);
87025
+ this._yAxisLabel.setVisible(axisVisible && !this._yAxisLabelCulled&& this._xAxisVisible && this._yLabelEnabled);
87026
+ this._zAxisLabel.setVisible(axisVisible && !this._zAxisLabelCulled&& this._xAxisVisible && this._zLabelEnabled);
86831
87027
  this._cpDirty = true;
86832
87028
  this._needUpdate();
86833
87029
  }
@@ -86887,7 +87083,7 @@ class DistanceMeasurement extends Component {
86887
87083
  this._xAxisVisible = value;
86888
87084
  const axisVisible = this._visible && this._axisVisible && this._xAxisVisible && this._axisEnabled;
86889
87085
  this._xAxisWire.setVisible(axisVisible);
86890
- this._xAxisLabel.setVisible(axisVisible && !this._xAxisLabelCulled);
87086
+ this._xAxisLabel.setVisible(axisVisible && !this._xAxisLabelCulled && this._xLabelEnabled);
86891
87087
  this._cpDirty = true;
86892
87088
  this._needUpdate();
86893
87089
  }
@@ -86915,7 +87111,7 @@ class DistanceMeasurement extends Component {
86915
87111
  this._yAxisVisible = value;
86916
87112
  const axisVisible = this._visible && this._axisVisible && this._yAxisVisible && this._axisEnabled;
86917
87113
  this._yAxisWire.setVisible(axisVisible);
86918
- this._yAxisLabel.setVisible(axisVisible && !this._yAxisLabelCulled);
87114
+ this._yAxisLabel.setVisible(axisVisible && !this._yAxisLabelCulled && this._yLabelEnabled);
86919
87115
  this._cpDirty = true;
86920
87116
  this._needUpdate();
86921
87117
  }
@@ -86943,7 +87139,7 @@ class DistanceMeasurement extends Component {
86943
87139
  this._zAxisVisible = value;
86944
87140
  const axisVisible = this._visible && this._axisVisible && this._zAxisVisible && this._axisEnabled;
86945
87141
  this._zAxisWire.setVisible(axisVisible);
86946
- this._zAxisLabel.setVisible(axisVisible && !this._zAxisLabelCulled);
87142
+ this._zAxisLabel.setVisible(axisVisible && !this._zAxisLabelCulled && this._zLabelEnabled);
86947
87143
  this._cpDirty = true;
86948
87144
  this._needUpdate();
86949
87145
  }
@@ -86968,7 +87164,7 @@ class DistanceMeasurement extends Component {
86968
87164
  value = value !== undefined ? Boolean(value) : this.plugin.defaultWireVisible;
86969
87165
  this._wireVisible = value;
86970
87166
  var wireVisible = this._visible && this._wireVisible;
86971
- this._lengthLabel.setVisible(wireVisible);
87167
+ this._lengthLabel.setVisible(wireVisible && this._lengthLabelEnabled);
86972
87168
  this._lengthWire.setVisible(wireVisible);
86973
87169
  }
86974
87170
 
@@ -86982,7 +87178,7 @@ class DistanceMeasurement extends Component {
86982
87178
  }
86983
87179
 
86984
87180
  /**
86985
- * Sets if the labels are visible.
87181
+ * Sets if the labels are visible except the length label.
86986
87182
  *
86987
87183
  * @type {Boolean}
86988
87184
  */
@@ -86990,10 +87186,10 @@ class DistanceMeasurement extends Component {
86990
87186
  value = value !== undefined ? Boolean(value) : this.plugin.defaultLabelsVisible;
86991
87187
  this._labelsVisible = value;
86992
87188
  var labelsVisible = this._visible && this._labelsVisible;
86993
- this._xAxisLabel.setVisible(labelsVisible && !this._xAxisLabelCulled && this._clickable && this._axisEnabled);
86994
- this._yAxisLabel.setVisible(labelsVisible && !this._yAxisLabelCulled && this._clickable && this._axisEnabled);
86995
- this._zAxisLabel.setVisible(labelsVisible && !this._zAxisLabelCulled && this._clickable && this._axisEnabled);
86996
- this._lengthLabel.setVisible(labelsVisible);
87189
+ this._xAxisLabel.setVisible(labelsVisible && !this._xAxisLabelCulled && this._clickable && this._axisEnabled && this._xLabelEnabled);
87190
+ this._yAxisLabel.setVisible(labelsVisible && !this._yAxisLabelCulled && this._clickable && this._axisEnabled && this._yLabelEnabled);
87191
+ this._zAxisLabel.setVisible(labelsVisible && !this._zAxisLabelCulled && this._clickable && this._axisEnabled && this._zLabelEnabled);
87192
+ this._lengthLabel.setVisible(labelsVisible && this._lengthLabelEnabled);
86997
87193
  this._cpDirty = true;
86998
87194
  this._needUpdate();
86999
87195
  }
@@ -87007,6 +87203,98 @@ class DistanceMeasurement extends Component {
87007
87203
  return this._labelsVisible;
87008
87204
  }
87009
87205
 
87206
+ /**
87207
+ * Sets if the x label is enabled.
87208
+ *
87209
+ * @type {Boolean}
87210
+ */
87211
+ set xLabelEnabled(value) {
87212
+ value = value !== undefined ? Boolean(value) : this.plugin.defaultXLabelEnabled;
87213
+ this._xLabelEnabled = value;
87214
+ var labelsVisible = this._visible && this._labelsVisible;
87215
+ this._xAxisLabel.setVisible(labelsVisible && !this._xAxisLabelCulled && this._clickable && this._axisEnabled && this._xLabelEnabled);
87216
+ this._cpDirty = true;
87217
+ this._needUpdate();
87218
+ }
87219
+
87220
+ /**
87221
+ * Gets if the x label is enabled.
87222
+ *
87223
+ * @type {Boolean}
87224
+ */
87225
+ get xLabelEnabled(){
87226
+ return this._xLabelEnabled;
87227
+ }
87228
+
87229
+ /**
87230
+ * Sets if the y label is enabled.
87231
+ *
87232
+ * @type {Boolean}
87233
+ */
87234
+ set yLabelEnabled(value) {
87235
+ value = value !== undefined ? Boolean(value) : this.plugin.defaultYLabelEnabled;
87236
+ this._yLabelEnabled = value;
87237
+ var labelsVisible = this._visible && this._labelsVisible;
87238
+ this._yAxisLabel.setVisible(labelsVisible && !this._yAxisLabelCulled && this._clickable && this._axisEnabled && this._yLabelEnabled);
87239
+ this._cpDirty = true;
87240
+ this._needUpdate();
87241
+ }
87242
+
87243
+ /**
87244
+ * Gets if the y label is enabled.
87245
+ *
87246
+ * @type {Boolean}
87247
+ */
87248
+ get yLabelEnabled(){
87249
+ return this._yLabelEnabled;
87250
+ }
87251
+
87252
+ /**
87253
+ * Sets if the z label is enabled.
87254
+ *
87255
+ * @type {Boolean}
87256
+ */
87257
+ set zLabelEnabled(value) {
87258
+ value = value !== undefined ? Boolean(value) : this.plugin.defaultZLabelEnabled;
87259
+ this._zLabelEnabled = value;
87260
+ var labelsVisible = this._visible && this._labelsVisible;
87261
+ this._zAxisLabel.setVisible(labelsVisible && !this._zAxisLabelCulled && this._clickable && this._axisEnabled && this._zLabelEnabled);
87262
+ this._cpDirty = true;
87263
+ this._needUpdate();
87264
+ }
87265
+
87266
+ /**
87267
+ * Gets if the z label is enabled.
87268
+ *
87269
+ * @type {Boolean}
87270
+ */
87271
+ get zLabelEnabled(){
87272
+ return this._zLabelEnabled;
87273
+ }
87274
+
87275
+ /**
87276
+ * Sets if the length label is enabled.
87277
+ *
87278
+ * @type {Boolean}
87279
+ */
87280
+ set lengthLabelEnabled(value) {
87281
+ value = value !== undefined ? Boolean(value) : this.plugin.defaultLengthLabelEnabled;
87282
+ this._lengthLabelEnabled = value;
87283
+ var labelsVisible = this._visible && this._labelsVisible;
87284
+ this._lengthLabel.setVisible(labelsVisible && !this._lengthAxisLabelCulled && this._clickable && this._axisEnabled && this._lengthLabelEnabled);
87285
+ this._cpDirty = true;
87286
+ this._needUpdate();
87287
+ }
87288
+
87289
+ /**
87290
+ * Gets if the length label is enabled.
87291
+ *
87292
+ * @type {Boolean}
87293
+ */
87294
+ get lengthLabelEnabled(){
87295
+ return this._lengthLabelEnabled;
87296
+ }
87297
+
87010
87298
  /**
87011
87299
  * Sets if labels should be positioned on the wires.
87012
87300
  *
@@ -87189,6 +87477,17 @@ class DistanceMeasurementsControl extends Component {
87189
87477
  reset() {
87190
87478
  }
87191
87479
 
87480
+ /**
87481
+ * Gets the {@link DistanceMeasurement} under construction by this DistanceMeasurementsControl, if any.
87482
+ *
87483
+ * @returns {null|DistanceMeasurement}
87484
+ *
87485
+ * @abstract
87486
+ */
87487
+ get currentMeasurement() {
87488
+ return null;
87489
+ }
87490
+
87192
87491
  /**
87193
87492
  * Destroys this DistanceMeasurementsControl.
87194
87493
  *
@@ -87595,6 +87894,17 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
87595
87894
  this._currentDistanceMeasurement.destroy();
87596
87895
  this._currentDistanceMeasurement = null;
87597
87896
  }
87897
+
87898
+ this._mouseState = MOUSE_FIRST_CLICK_EXPECTED;
87899
+ }
87900
+
87901
+ /**
87902
+ * Gets the {@link DistanceMeasurement} under construction by this DistanceMeasurementsMouseControl, if any.
87903
+ *
87904
+ * @returns {null|DistanceMeasurement}
87905
+ */
87906
+ get currentMeasurement() {
87907
+ return this._currentDistanceMeasurement;
87598
87908
  }
87599
87909
 
87600
87910
  /**
@@ -87882,6 +88192,10 @@ class DistanceMeasurementsPlugin extends Plugin {
87882
88192
  * @param {boolean} [cfg.defaultTargetVisible=true] The default value of the DistanceMeasurements `targetVisible` property.
87883
88193
  * @param {boolean} [cfg.defaultWireVisible=true] The default value of the DistanceMeasurements `wireVisible` property.
87884
88194
  * @param {boolean} [cfg.defaultLabelsVisible=true] The default value of the DistanceMeasurements `labelsVisible` property.
88195
+ * @param {boolean} [cfg.defaultXLabelEnabled=true] The default value of the DistanceMeasurements `xLabelEnabled` property.
88196
+ * @param {boolean} [cfg.defaultYLabelEnabled=true] The default value of the DistanceMeasurements `yLabelEnabled` property.
88197
+ * @param {boolean} [cfg.defaultZLabelEnabled=true] The default value of the DistanceMeasurements `zLabelEnabled` property.
88198
+ * @param {boolean} [cfg.defaultLengthLabelEnabled=true] The default value of the DistanceMeasurements `lengthLabelEnabled` property.
87885
88199
  * @param {boolean} [cfg.defaultAxisVisible=true] The default value of the DistanceMeasurements `axisVisible` property.
87886
88200
  * @param {boolean} [cfg.defaultXAxisVisible=true] The default value of the DistanceMeasurements `xAxisVisible` property.
87887
88201
  * @param {boolean} [cfg.defaultYAxisVisible=true] The default value of the DistanceMeasurements `yAxisVisible` property.
@@ -87904,11 +88218,14 @@ class DistanceMeasurementsPlugin extends Plugin {
87904
88218
  this._measurements = {};
87905
88219
 
87906
88220
  this.labelMinAxisLength = cfg.labelMinAxisLength;
87907
-
87908
88221
  this.defaultVisible = cfg.defaultVisible !== false;
87909
88222
  this.defaultOriginVisible = cfg.defaultOriginVisible !== false;
87910
88223
  this.defaultTargetVisible = cfg.defaultTargetVisible !== false;
87911
88224
  this.defaultWireVisible = cfg.defaultWireVisible !== false;
88225
+ this.defaultXLabelEnabled = cfg.defaultXLabelEnabled !== false;
88226
+ this.defaultYLabelEnabled = cfg.defaultYLabelEnabled !== false;
88227
+ this.defaultZLabelEnabled = cfg.defaultZLabelEnabled !== false;
88228
+ this.defaultLengthLabelEnabled = cfg.defaultLengthLabelEnabled !== false;
87912
88229
  this.defaultLabelsVisible = cfg.defaultLabelsVisible !== false;
87913
88230
  this.defaultAxisVisible = cfg.defaultAxisVisible !== false;
87914
88231
  this.defaultXAxisVisible = cfg.defaultXAxisVisible !== false;
@@ -88037,7 +88354,12 @@ class DistanceMeasurementsPlugin extends Plugin {
88037
88354
  * @param {Boolean} [params.xAxisVisible=true] Whether to initially show the X-axis-aligned wires between {@link DistanceMeasurement#origin} and {@link DistanceMeasurement#target}.
88038
88355
  * @param {Boolean} [params.yAxisVisible=true] Whether to initially show the Y-axis-aligned wires between {@link DistanceMeasurement#origin} and {@link DistanceMeasurement#target}.
88039
88356
  * @param {Boolean} [params.zAxisVisible=true] Whether to initially show the Z-axis-aligned wires between {@link DistanceMeasurement#origin} and {@link DistanceMeasurement#target}.
88357
+ * @param {Boolean} [params.xLabelEnabled=true] Whether to initially show the x label.
88358
+ * @param {Boolean} [params.yLabelEnabled=true] Whether to initially show the y label.
88359
+ * @param {Boolean} [params.zLabelEnabled=true] Whether to initially show the z label.
88360
+ * @param {Boolean} [params.lengthLabelEnabled=true] Whether to initially show the length label.
88040
88361
  * @param {Boolean} [params.labelsVisible=true] Whether to initially show the labels.
88362
+ * @param {Boolean} [params.lengthLabelVisible=true] Whether to initially show the labels.
88041
88363
  * @param {string} [params.color] The color of the length dot, wire and label.
88042
88364
  * @param {Boolean} [params.labelsOnWires=true] Determines if labels will be set on wires or one below the other.
88043
88365
  * @returns {DistanceMeasurement} The new {@link DistanceMeasurement}.
@@ -88067,6 +88389,10 @@ class DistanceMeasurementsPlugin extends Plugin {
88067
88389
  xAxisVisible: params.xAxisVisible !== false && this.defaultXAxisVisible !== false,
88068
88390
  yAxisVisible: params.yAxisVisible !== false && this.defaultYAxisVisible !== false,
88069
88391
  zAxisVisible: params.zAxisVisible !== false && this.defaultZAxisVisible !== false,
88392
+ xLabelEnabled: params.xLabelEnabled !== false && this.defaultXLabelEnabled !== false,
88393
+ yLabelEnabled: params.yLabelEnabled !== false && this.defaultYLabelEnabled !== false,
88394
+ zLabelEnabled: params.zLabelEnabled !== false && this.defaultZLabelEnabled !== false,
88395
+ lengthLabelEnabled: params.lengthLabelEnabled !== false && this.defaultLengthLabelEnabled !== false,
88070
88396
  labelsVisible: params.labelsVisible !== false && this.defaultLabelsVisible !== false,
88071
88397
  originVisible: params.originVisible,
88072
88398
  targetVisible: params.targetVisible,
@@ -88077,6 +88403,7 @@ class DistanceMeasurementsPlugin extends Plugin {
88077
88403
  onContextMenu: this._onContextMenu
88078
88404
  });
88079
88405
  this._measurements[measurement.id] = measurement;
88406
+ measurement.clickable = true;
88080
88407
  measurement.on("destroyed", () => {
88081
88408
  delete this._measurements[measurement.id];
88082
88409
  });
@@ -88812,6 +89139,10 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
88812
89139
  this._currentDistanceMeasurement.targetVisible = true;
88813
89140
  this._currentDistanceMeasurement.wireVisible = true;
88814
89141
  this._currentDistanceMeasurement.labelsVisible = true;
89142
+ this._currentDistanceMeasurement.xAxisVisible = true;
89143
+ this._currentDistanceMeasurement.yAxisVisible = true;
89144
+ this._currentDistanceMeasurement.zAxisVisible = true;
89145
+ this._currentDistanceMeasurement.clickable = true;
88815
89146
  this.distanceMeasurementsPlugin.fire("measurementEnd", this._currentDistanceMeasurement);
88816
89147
  this._currentDistanceMeasurement = null;
88817
89148
  } else {
@@ -88827,6 +89158,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
88827
89158
  break;
88828
89159
 
88829
89160
  case WAITING_FOR_TARGET_LONG_TOUCH_END:
89161
+ console.log('long touch');
88830
89162
  if (this.pointerLens) {
88831
89163
  this.pointerLens.visible = false;
88832
89164
  }
@@ -88894,6 +89226,16 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
88894
89226
  this._currentDistanceMeasurement.destroy();
88895
89227
  this._currentDistanceMeasurement = null;
88896
89228
  }
89229
+ this._mouseState = WAITING_FOR_ORIGIN_TOUCH_START;
89230
+ }
89231
+
89232
+ /**
89233
+ * Gets the {@link DistanceMeasurement} under construction by this DistanceMeasurementsTouchControl, if any.
89234
+ *
89235
+ * @returns {null|DistanceMeasurement}
89236
+ */
89237
+ get currentMeasurement() {
89238
+ return this._currentDistanceMeasurement;
88897
89239
  }
88898
89240
 
88899
89241
  /**
@@ -96618,8 +96960,8 @@ function getCanvasPosFromEvent$2(event, canvas, canvasPos) {
96618
96960
  canvasPos[1] = event.y;
96619
96961
  } else {
96620
96962
  const { left, top } = canvas.getBoundingClientRect();
96621
- canvasPos[0] = event.clientX - left - window.scrollX;
96622
- canvasPos[1] = event.clientY - top - window.scrollY;
96963
+ canvasPos[0] = event.clientX - left;
96964
+ canvasPos[1] = event.clientY - top;
96623
96965
  }
96624
96966
  return canvasPos;
96625
96967
  }
@@ -115813,6 +116155,7 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok) {
115813
116155
  }).then((gltfData) => {
115814
116156
  const ctx = {
115815
116157
  src: src,
116158
+ entityId: options.entityId,
115816
116159
  metaModelCorrections: metaModelJSON ? getMetaModelCorrections(metaModelJSON) : null,
115817
116160
  loadBuffer: options.loadBuffer,
115818
116161
  basePath: options.basePath,
@@ -116252,29 +116595,9 @@ function loadNode(ctx, node, depth, matrix) {
116252
116595
  meshCfg.origin = origin;
116253
116596
  }
116254
116597
 
116255
- // if (createEntity) {
116256
- // if (createEntity.colorize) {
116257
- // meshCfg.color = createEntity.colorize;
116258
- // }
116259
- // if (createEntity.opacity !== undefined && createEntity.opacity !== null) {
116260
- // meshCfg.opacity = createEntity.opacity;
116261
- // }
116262
- // }
116263
-
116264
116598
  sceneModel.createMesh(meshCfg);
116265
116599
  deferredMeshIds.push(meshCfg.id);
116266
116600
  }
116267
- // if (createEntity) {
116268
- // sceneModel.createEntity(utils.apply(createEntity, {
116269
- // meshIds: deferredMeshIds,
116270
- // isObject: true
116271
- // }));
116272
- // } else {
116273
- // sceneModel.createEntity({
116274
- // meshIds: deferredMeshIds,
116275
- // isObject: true
116276
- // });
116277
- // }
116278
116601
  }
116279
116602
  }
116280
116603
 
@@ -116288,48 +116611,62 @@ function loadNode(ctx, node, depth, matrix) {
116288
116611
 
116289
116612
  // Post-order visit scene node
116290
116613
 
116291
- const nodeName = node.name;
116292
- if (((nodeName !== undefined && nodeName !== null) || depth === 0) && deferredMeshIds.length > 0) {
116293
- if (nodeName === undefined || nodeName === null) {
116294
- ctx.log(`Warning: 'name' properties not found on glTF scene nodes - will randomly-generate object IDs in XKT`);
116614
+ if (ctx.entityId) {
116615
+ if (depth ===0) {
116616
+ sceneModel.createEntity({
116617
+ id: ctx.entityId,
116618
+ meshIds: deferredMeshIds,
116619
+ isObject: true
116620
+ });
116621
+ deferredMeshIds.length = 0;
116295
116622
  }
116296
- let entityId = nodeName; // Fall back on generated ID when `name` not found on glTF scene node(s)
116297
- // if (!!entityId && sceneModel.entities[entityId]) {
116298
- // ctx.log(`Warning: Two or more glTF nodes found with same 'name' attribute: '${nodeName} - will randomly-generating an object ID in XKT`);
116299
- // }
116300
- // while (!entityId || sceneModel.entities[entityId]) {
116301
- // entityId = "entity-" + ctx.nextId++;
116302
- // }
116303
- if (ctx.metaModelCorrections) {
116304
- // Merging meshes into XKTObjects that map to metaobjects
116305
- const rootMetaObject = ctx.metaModelCorrections.eachChildRoot[entityId];
116306
- if (rootMetaObject) {
116307
- const rootMetaObjectStats = ctx.metaModelCorrections.eachRootStats[rootMetaObject.id];
116308
- rootMetaObjectStats.countChildren++;
116309
- if (rootMetaObjectStats.countChildren >= rootMetaObjectStats.numChildren) {
116310
- sceneModel.createEntity({
116311
- id: rootMetaObject.id,
116312
- meshIds: deferredMeshIds
116313
- });
116314
- deferredMeshIds.length = 0;
116623
+ } else {
116624
+ const nodeName = node.name;
116625
+ if (((nodeName !== undefined && nodeName !== null) || depth === 0) && deferredMeshIds.length > 0) {
116626
+ if (nodeName === undefined || nodeName === null) {
116627
+ ctx.log(`Warning: 'name' properties not found on glTF scene nodes - will randomly-generate object IDs in XKT`);
116628
+ }
116629
+ let entityId = nodeName; // Fall back on generated ID when `name` not found on glTF scene node(s)
116630
+ // if (!!entityId && sceneModel.entities[entityId]) {
116631
+ // ctx.log(`Warning: Two or more glTF nodes found with same 'name' attribute: '${nodeName} - will randomly-generating an object ID in XKT`);
116632
+ // }
116633
+ // while (!entityId || sceneModel.entities[entityId]) {
116634
+ // entityId = "entity-" + ctx.nextId++;
116635
+ // }
116636
+ if (ctx.metaModelCorrections) {
116637
+ // Merging meshes into XKTObjects that map to metaobjects
116638
+ const rootMetaObject = ctx.metaModelCorrections.eachChildRoot[entityId];
116639
+ if (rootMetaObject) {
116640
+ const rootMetaObjectStats = ctx.metaModelCorrections.eachRootStats[rootMetaObject.id];
116641
+ rootMetaObjectStats.countChildren++;
116642
+ if (rootMetaObjectStats.countChildren >= rootMetaObjectStats.numChildren) {
116643
+ sceneModel.createEntity({
116644
+ id: rootMetaObject.id,
116645
+ meshIds: deferredMeshIds,
116646
+ isObject: true
116647
+ });
116648
+ deferredMeshIds.length = 0;
116649
+ }
116650
+ } else {
116651
+ const metaObject = ctx.metaModelCorrections.metaObjectsMap[entityId];
116652
+ if (metaObject) {
116653
+ sceneModel.createEntity({
116654
+ id: entityId,
116655
+ meshIds: deferredMeshIds,
116656
+ isObject: true
116657
+ });
116658
+ deferredMeshIds.length = 0;
116659
+ }
116315
116660
  }
116316
116661
  } else {
116317
- const metaObject = ctx.metaModelCorrections.metaObjectsMap[entityId];
116318
- if (metaObject) {
116319
- sceneModel.createEntity({
116320
- id: entityId,
116321
- meshIds: deferredMeshIds
116322
- });
116323
- deferredMeshIds.length = 0;
116324
- }
116662
+ // Create an XKTObject from the meshes at each named glTF node, don't care about metaobjects
116663
+ sceneModel.createEntity({
116664
+ id: entityId,
116665
+ meshIds: deferredMeshIds,
116666
+ isObject: true
116667
+ });
116668
+ deferredMeshIds.length = 0;
116325
116669
  }
116326
- } else {
116327
- // Create an XKTObject from the meshes at each named glTF node, don't care about metaobjects
116328
- sceneModel.createEntity({
116329
- id: entityId,
116330
- meshIds: deferredMeshIds
116331
- });
116332
- deferredMeshIds.length = 0;
116333
116670
  }
116334
116671
  }
116335
116672
  }
@@ -116506,6 +116843,79 @@ const IFCObjectDefaults = {
116506
116843
  * excludeTypes: ["IfcSpace"]
116507
116844
  * });
116508
116845
  * ````
116846
+ *
116847
+ * ## Showing a glTF model in TreeViewPlugin when metadata is not available
116848
+ *
116849
+ * When GLTFLoaderPlugin loads a glTF model, it creates an object Entity for each `node` in the glTF `scene` hierarchy that has a
116850
+ * `name` attribute, giving the Entity an ID that has the value of the `name` attribute.
116851
+ *
116852
+ * 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
116853
+ * ordinarily present in glTF that comes from other sources, such as LiDAR scanners. For such glTF models, GLTFLoaderPlugin
116854
+ * will create Entities, but they will have randomly-generated IDs, and therefore cannot be associated with MetaObjects in any
116855
+ * MetaModels that we create alongside the model.
116856
+ *
116857
+ * For glTF models containing `nodes` that don't have `name` attributes, we can use the `load()` method's `elementId` parameter
116858
+ * to make GLTFLoaderPlugin load the entire model into a single Entity that gets this ID.
116859
+ *
116860
+ * In conjunction with that parameter, we can then use the `load()` method's `metaModelJSON` parameter to create a MetaModel that
116861
+ * contains a MetaObject that corresponds to that Entity.
116862
+ *
116863
+ * When we've done that, then xeokit's {@link TreeViewPlugin} is able to have a node that represents the glTF model and controls
116864
+ * the visibility of that Entity (ie. to control the visibility of the entire model).
116865
+ *
116866
+ * The snippet below shows how this is done.
116867
+ *
116868
+ * ````javascript
116869
+ * import {Viewer, GLTFLoaderPlugin, NavCubePlugin, TreeViewPlugin} from "../../dist/xeokit-sdk.es.js";
116870
+ *
116871
+ * const viewer = new Viewer({
116872
+ * canvasId: "myCanvas",
116873
+ * transparent: true
116874
+ * });
116875
+ *
116876
+ * new TreeViewPlugin(viewer, {
116877
+ * containerElement: document.getElementById("treeViewContainer"),
116878
+ * hierarchy: "containment"
116879
+ * });
116880
+ *
116881
+ * const gltfLoader = new GLTFLoaderPlugin(viewer);
116882
+ *
116883
+ * const sceneModel = gltfLoader.load({ // Creates a SceneModel with ID "myScanModel"
116884
+ * id: "myScanModel",
116885
+ * src: "public-use-sample-apartment.glb",
116886
+ *
116887
+ * //-------------------------------------------------------------------------
116888
+ * // Specify an `elementId` parameter, which causes the
116889
+ * // entire model to be loaded into a single Entity that gets this ID.
116890
+ * //-------------------------------------------------------------------------
116891
+ *
116892
+ * entityId: "3toKckUfH2jBmd$7uhJHa4", // Creates an Entity with this ID
116893
+ *
116894
+ * //-------------------------------------------------------------------------
116895
+ * // Specify a `metaModelJSON` parameter, which creates a
116896
+ * // MetaModel with two MetaObjects, one of which corresponds
116897
+ * // to our Entity. Then the TreeViewPlugin is able to have a node
116898
+ * // that can represent the model and control the visibility of the Entity.
116899
+ * //--------------------------------------------------------------------------
116900
+ *
116901
+ * metaModelJSON: { // Creates a MetaModel with ID "myScanModel"
116902
+ * "metaObjects": [
116903
+ * {
116904
+ * "id": "3toKckUfH2jBmd$7uhJHa6", // Creates a MetaObject with this ID
116905
+ * "name": "My Project",
116906
+ * "type": "Default",
116907
+ * "parent": null
116908
+ * },
116909
+ * {
116910
+ * "id": "3toKckUfH2jBmd$7uhJHa4", // Creates a MetaObject with this ID (same ID as our Entity)
116911
+ * "name": "My Scan",
116912
+ * "type": "Default",
116913
+ * "parent": "3toKckUfH2jBmd$7uhJHa6"
116914
+ * }
116915
+ * ]
116916
+ * }
116917
+ * });
116918
+ * ````
116509
116919
  * @class GLTFLoaderPlugin
116510
116920
  */
116511
116921
  class GLTFLoaderPlugin extends Plugin {
@@ -116600,6 +117010,7 @@ class GLTFLoaderPlugin extends Plugin {
116600
117010
  * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable
116601
117011
  * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point
116602
117012
  * primitives. Only works while {@link DTX#enabled} is also ````true````.
117013
+ * @param {String} [params.entityId] When supplied, causes the entire model to be loaded into a single {@link Entity} that gets this ID.
116603
117014
  * @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}
116604
117015
  */
116605
117016
  load(params = {}) {
@@ -134772,6 +135183,60 @@ const MAX_VERTICES = 500000; // TODO: Rough estimate
134772
135183
  * });
134773
135184
  * ````
134774
135185
  *
135186
+ * ## Showing a LAS/LAZ model in TreeViewPlugin
135187
+ *
135188
+ * We can use the `load()` method's `elementId` parameter
135189
+ * to make LASLoaderPlugin load the entire model into a single Entity that gets this ID.
135190
+ *
135191
+ * In conjunction with that parameter, we can then use the `load()` method's `metaModelJSON` parameter to create a MetaModel that
135192
+ * contains a MetaObject that corresponds to that Entity.
135193
+ *
135194
+ * When we've done that, then xeokit's {@link TreeViewPlugin} is able to have a node that represents the model and controls
135195
+ * the visibility of that Entity (ie. to control the visibility of the entire model).
135196
+ *
135197
+ * The snippet below shows how this is done.
135198
+ *
135199
+ * ````javascript
135200
+ * import {Viewer, LASLoaderPlugin, NavCubePlugin, TreeViewPlugin} from "../../dist/xeokit-sdk.es.js";
135201
+ *
135202
+ * const viewer = new Viewer({
135203
+ * canvasId: "myCanvas",
135204
+ * transparent: true
135205
+ * });
135206
+ *
135207
+ * new TreeViewPlugin(viewer, {
135208
+ * containerElement: document.getElementById("treeViewContainer"),
135209
+ * hierarchy: "containment"
135210
+ * });
135211
+ *
135212
+ * const lasLoader = new LASLoaderPlugin(viewer);
135213
+ *
135214
+ * const sceneModel = lasLoader.load({ // Creates a SceneModel with ID "myScanModel"
135215
+ * id: "myScanModel",
135216
+ * src: "../../assets/models/las/Nalls_Pumpkin_Hill.laz",
135217
+ * rotation: [-90, 0, 0],
135218
+ *
135219
+ * entityId: "3toKckUfH2jBmd$7uhJHa4", // Creates an Entity with this ID
135220
+ *
135221
+ * metaModelJSON: { // Creates a MetaModel with ID "myScanModel"
135222
+ * "metaObjects": [
135223
+ * {
135224
+ * "id": "3toKckUfH2jBmd$7uhJHa6", // Creates this MetaObject with this ID
135225
+ * "name": "My Project",
135226
+ * "type": "Default",
135227
+ * "parent": null
135228
+ * },
135229
+ * {
135230
+ * "id": "3toKckUfH2jBmd$7uhJHa4", // Creates this MetaObject with this ID
135231
+ * "name": "My Scan",
135232
+ * "type": "Default",
135233
+ * "parent": "3toKckUfH2jBmd$7uhJHa6"
135234
+ * }
135235
+ * ]
135236
+ * }
135237
+ * });
135238
+ * ````
135239
+ *
134775
135240
  * @class LASLoaderPlugin
134776
135241
  * @since 2.0.17
134777
135242
  */
@@ -135122,7 +135587,7 @@ class LASLoaderPlugin extends Plugin {
135122
135587
  }
135123
135588
  */
135124
135589
 
135125
- const pointsObjectId = math.createUUID();
135590
+ const pointsObjectId = params.entityId || math.createUUID();
135126
135591
 
135127
135592
  sceneModel.createEntity({
135128
135593
  id: pointsObjectId,
@@ -135132,7 +135597,10 @@ class LASLoaderPlugin extends Plugin {
135132
135597
 
135133
135598
  sceneModel.finalize();
135134
135599
 
135135
- if (params.loadMetadata !== false) {
135600
+ if (params.metaModelJSON) {
135601
+ const metaModelId = sceneModel.id;
135602
+ this.viewer.metaScene.createMetaModel(metaModelId, params.metaModelJSON, options);
135603
+ } else if (params.loadMetadata !== false) {
135136
135604
  const rootMetaObjectId = math.createUUID();
135137
135605
  const metadata = {
135138
135606
  projectId: "",
@@ -136630,6 +137098,566 @@ class CityJSONLoaderPlugin extends Plugin {
136630
137098
  }
136631
137099
  }
136632
137100
 
137101
+ /**
137102
+ * Default data access strategy for {@link DotBIMLoaderPlugin}.
137103
+ *
137104
+ * This just loads assets using XMLHttpRequest.
137105
+ */
137106
+ class DotBIMDefaultDataSource {
137107
+
137108
+ constructor() {
137109
+ }
137110
+
137111
+ /**
137112
+ * Gets .BIM JSON.
137113
+ *
137114
+ * @param {String|Number} dotBIMSrc Identifies the .BIM JSON asset.
137115
+ * @param {Function} ok Fired on successful loading of the .BIM JSON asset.
137116
+ * @param {Function} error Fired on error while loading the .BIM JSON asset.
137117
+ */
137118
+ getDotBIM(dotBIMSrc, ok, error) {
137119
+ utils.loadJSON(dotBIMSrc,
137120
+ (json) => {
137121
+ ok(json);
137122
+ },
137123
+ function (errMsg) {
137124
+ error(errMsg);
137125
+ });
137126
+ }
137127
+ }
137128
+
137129
+ /**
137130
+ * {@link Viewer} plugin that loads models from [.bim](https://dotbim.net/) format.
137131
+ *
137132
+ * [<img src="https://xeokit.github.io/xeokit-sdk/assets/images/DotBIMLoaderPlugin-house.png">](https://xeokit.github.io/xeokit-sdk/examples/buildings/#dotbim_House)
137133
+ *
137134
+ * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/buildings/#dotbim_House)]
137135
+ *
137136
+ * * Creates an {@link Entity} representing each .bim model it loads, which will have {@link Entity#isModel} set ````true````
137137
+ * and will be registered by {@link Entity#id} in {@link Scene#models}.
137138
+ * * Creates an {@link Entity} for each object within the .bim model. Those Entities will have {@link Entity#isObject}
137139
+ * set ````true```` and will be registered by {@link Entity#id} in {@link Scene#objects}.
137140
+ * * When loading, can set the World-space position, scale and rotation of each model within World space,
137141
+ * along with initial properties for all the model's {@link Entity}s.
137142
+ * * Allows to mask which IFC types we want to load.
137143
+ * * Allows to configure initial viewer state for specified IFC types (color, visibility, selection, highlighted, X-rayed, pickable, etc).
137144
+ *
137145
+ * ## Usage
137146
+ *
137147
+ * In the example below we'll load a house model from a [.bim file](/assets/models/dotbim/House.bim).
137148
+ *
137149
+ * This will create a bunch of {@link Entity}s that represents the model and its objects, along with
137150
+ * a {@link MetaModel} and {@link MetaObject}s that hold their metadata.
137151
+ *
137152
+ * ````javascript
137153
+ * import {Viewer, DotBIMLoaderPlugin} from "xeokit-sdk.es.js";
137154
+ *
137155
+ * //------------------------------------------------------------------------------------------------------------------
137156
+ * // 1. Create a Viewer,
137157
+ * // 2. Arrange the camera,
137158
+ * // 3. Tweak the selection material (tone it down a bit)
137159
+ * //------------------------------------------------------------------------------------------------------------------
137160
+ *
137161
+ * // 1
137162
+ * const viewer = new Viewer({
137163
+ * canvasId: "myCanvas",
137164
+ * transparent: true
137165
+ * });
137166
+ *
137167
+ * // 2
137168
+ * viewer.camera.orbitPitch(20);
137169
+ * viewer.camera.orbitYaw(-45);
137170
+ *
137171
+ * // 3
137172
+ * viewer.scene.selectedMaterial.fillAlpha = 0.1;
137173
+ *
137174
+ * //------------------------------------------------------------------------------------------------------------------
137175
+ * // 1. Create a .bim loader plugin,
137176
+ * // 2. Load a .bim building model, emphasizing the edges to make it look nicer
137177
+ * //------------------------------------------------------------------------------------------------------------------
137178
+ *
137179
+ * // 1
137180
+ * const dotBIMLoader = new DotBIMLoaderPlugin(viewer);
137181
+ *
137182
+ * // 2
137183
+ * var model = dotBIMLoader.load({ // Returns an Entity that represents the model
137184
+ * id: "myModel",
137185
+ * src: "House.bim",
137186
+ * edges: true
137187
+ * });
137188
+ *
137189
+ * // Find the model Entity by ID
137190
+ * model = viewer.scene.models["myModel"];
137191
+ *
137192
+ * // Destroy the model
137193
+ * model.destroy();
137194
+ * ````
137195
+ *
137196
+ * ## Transforming
137197
+ *
137198
+ * We have the option to rotate, scale and translate each *````.bim````* model as we load it.
137199
+ *
137200
+ * This lets us load multiple models, or even multiple copies of the same model, and position them apart from each other.
137201
+ *
137202
+ * In the example below, we'll rotate our model 90 degrees about its local X-axis, then
137203
+ * translate it 100 units along its X axis.
137204
+ *
137205
+ * ````javascript
137206
+ * const model = dotBIMLoader.load({
137207
+ * src: "House.bim",
137208
+ * rotation: [90,0,0],
137209
+ * position: [100, 0, 0]
137210
+ * });
137211
+ * ````
137212
+ *
137213
+ * ## Including and excluding IFC types
137214
+ *
137215
+ * We can also load only those objects that have the specified IFC types. In the example below, we'll load only the
137216
+ * objects that represent walls.
137217
+ *
137218
+ * ````javascript
137219
+ * const model = dotBIMLoader.load({
137220
+ * id: "myModel",
137221
+ * src: "House.bim",
137222
+ * includeTypes: ["IfcWallStandardCase"]
137223
+ * });
137224
+ * ````
137225
+ *
137226
+ * We can also load only those objects that **don't** have the specified IFC types. In the example below, we'll load only the
137227
+ * objects that do not represent empty space.
137228
+ *
137229
+ * ````javascript
137230
+ * const model = dotBIMLoader.load({
137231
+ * id: "myModel",
137232
+ * src: "House.bim",
137233
+ * excludeTypes: ["IfcSpace"]
137234
+ * });
137235
+ * ````
137236
+ *
137237
+ * # Configuring initial IFC object appearances
137238
+ *
137239
+ * We can specify the custom initial appearance of loaded objects according to their IFC types.
137240
+ *
137241
+ * This is useful for things like:
137242
+ *
137243
+ * * setting the colors to our objects according to their IFC types,
137244
+ * * automatically hiding ````IfcSpace```` objects, and
137245
+ * * ensuring that ````IfcWindow```` objects are always transparent.
137246
+ * <br>
137247
+ * In the example below, we'll load a model, while configuring ````IfcSpace```` elements to be always initially invisible,
137248
+ * and ````IfcWindow```` types to be always translucent blue.
137249
+ *
137250
+ * ````javascript
137251
+ * const myObjectDefaults = {
137252
+ *
137253
+ * IfcSpace: {
137254
+ * visible: false
137255
+ * },
137256
+ * IfcWindow: {
137257
+ * colorize: [0.337255, 0.303922, 0.870588], // Blue
137258
+ * opacity: 0.3
137259
+ * },
137260
+ *
137261
+ * //...
137262
+ *
137263
+ * DEFAULT: {
137264
+ * colorize: [0.5, 0.5, 0.5]
137265
+ * }
137266
+ * };
137267
+ *
137268
+ * const model4 = dotBIMLoader.load({
137269
+ * id: "myModel4",
137270
+ * src: "House.bim",
137271
+ * objectDefaults: myObjectDefaults // Use our custom initial default states for object Entities
137272
+ * });
137273
+ * ````
137274
+ *
137275
+ * When we don't customize the appearance of IFC types, as just above, then IfcSpace elements tend to obscure other
137276
+ * elements, which can be confusing.
137277
+ *
137278
+ * It's often helpful to make IfcSpaces transparent and unpickable, like this:
137279
+ *
137280
+ * ````javascript
137281
+ * const dotBIMLoader = new DotBIMLoaderPlugin(viewer, {
137282
+ * objectDefaults: {
137283
+ * IfcSpace: {
137284
+ * pickable: false,
137285
+ * opacity: 0.2
137286
+ * }
137287
+ * }
137288
+ * });
137289
+ * ````
137290
+ *
137291
+ * Alternatively, we could just make IfcSpaces invisible, which also makes them unpickable:
137292
+ *
137293
+ * ````javascript
137294
+ * const dotBIMLoader = new DotBIMLoaderPlugin(viewer, {
137295
+ * objectDefaults: {
137296
+ * IfcSpace: {
137297
+ * visible: false
137298
+ * }
137299
+ * }
137300
+ * });
137301
+ * ````
137302
+ *
137303
+ * # Configuring a custom data source
137304
+ *
137305
+ * By default, DotBIMLoaderPlugin will load *````.bim````* files and metadata JSON over HTTP.
137306
+ *
137307
+ * In the example below, we'll customize the way DotBIMLoaderPlugin loads the files by configuring it with our own data source
137308
+ * object. For simplicity, our custom data source example also uses HTTP, using a couple of xeokit utility functions.
137309
+ *
137310
+ * ````javascript
137311
+ * import {utils} from "xeokit-sdk.es.js";
137312
+ *
137313
+ * class MyDataSource {
137314
+ *
137315
+ * constructor() {
137316
+ * }
137317
+ *
137318
+ * // Gets the contents of the given .bim file in a JSON object
137319
+ * getDotBIM(src, ok, error) {
137320
+ * utils.loadJSON(dotBIMSrc,
137321
+ * (json) => {
137322
+ * ok(json);
137323
+ * },
137324
+ * function (errMsg) {
137325
+ * error(errMsg);
137326
+ * });
137327
+ * }
137328
+ * }
137329
+ *
137330
+ * const dotBIMLoader2 = new DotBIMLoaderPlugin(viewer, {
137331
+ * dataSource: new MyDataSource()
137332
+ * });
137333
+ *
137334
+ * const model5 = dotBIMLoader2.load({
137335
+ * id: "myModel5",
137336
+ * src: "House.bim"
137337
+ * });
137338
+ * ````
137339
+ * @class DotBIMLoaderPlugin
137340
+ */
137341
+ class DotBIMLoaderPlugin extends Plugin {
137342
+
137343
+ /**
137344
+ * @constructor
137345
+ *
137346
+ * @param {Viewer} viewer The Viewer.
137347
+ * @param {Object} cfg Plugin configuration.
137348
+ * @param {String} [cfg.id="DotBIMLoader"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.
137349
+ * @param {Object} [cfg.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.
137350
+ * @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.
137351
+ */
137352
+ constructor(viewer, cfg = {}) {
137353
+
137354
+ super("DotBIMLoader", viewer, cfg);
137355
+
137356
+ this.dataSource = cfg.dataSource;
137357
+ this.objectDefaults = cfg.objectDefaults;
137358
+ }
137359
+
137360
+ /**
137361
+ * Sets a custom data source through which the DotBIMLoaderPlugin can .BIM files.
137362
+ *
137363
+ * Default value is {@link DotBIMDefaultDataSource}, which loads via an XMLHttpRequest.
137364
+ *
137365
+ * @type {Object}
137366
+ */
137367
+ set dataSource(value) {
137368
+ this._dataSource = value || new DotBIMDefaultDataSource();
137369
+ }
137370
+
137371
+ /**
137372
+ * Gets the custom data source through which the DotBIMLoaderPlugin can load .BIM files.
137373
+ *
137374
+ * Default value is {@link DotBIMDefaultDataSource}, which loads via an XMLHttpRequest.
137375
+ *
137376
+ * @type {Object}
137377
+ */
137378
+ get dataSource() {
137379
+ return this._dataSource;
137380
+ }
137381
+
137382
+ /**
137383
+ * Sets map of initial default states for each loaded {@link Entity} that represents an object.
137384
+ *
137385
+ * Default value is {@link IFCObjectDefaults}.
137386
+ *
137387
+ * @type {{String: Object}}
137388
+ */
137389
+ set objectDefaults(value) {
137390
+ this._objectDefaults = value || IFCObjectDefaults;
137391
+ }
137392
+
137393
+ /**
137394
+ * Gets map of initial default states for each loaded {@link Entity} that represents an object.
137395
+ *
137396
+ * Default value is {@link IFCObjectDefaults}.
137397
+ *
137398
+ * @type {{String: Object}}
137399
+ */
137400
+ get objectDefaults() {
137401
+ return this._objectDefaults;
137402
+ }
137403
+
137404
+ /**
137405
+ * Loads a .BIM model from a file into this DotBIMLoaderPlugin's {@link Viewer}.
137406
+ *
137407
+ * @param {*} params Loading parameters.
137408
+ * @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.
137409
+ * @param {String} [params.src] Path to a .BIM file, as an alternative to the ````bim```` parameter.
137410
+ * @param {*} [params.bim] .BIM JSON, as an alternative to the ````src```` parameter.
137411
+ * @param {{String:Object}} [params.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.
137412
+ * @param {String[]} [params.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
137413
+ * @param {String[]} [params.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.
137414
+ * @param {Number[]} [params.origin=[0,0,0]] The double-precision World-space origin of the model's coordinates.
137415
+ * @param {Number[]} [params.position=[0,0,0]] The single-precision position, relative to ````origin````.
137416
+ * @param {Number[]} [params.scale=[1,1,1]] The model's scale.
137417
+ * @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.
137418
+ * @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.
137419
+ * @param {Boolean} [params.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to
137420
+ * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable
137421
+ * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point
137422
+ * primitives. Only works while {@link DTX#enabled} is also ````true````.
137423
+ * @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}
137424
+ */
137425
+ load(params = {}) {
137426
+
137427
+ if (params.id && this.viewer.scene.components[params.id]) {
137428
+ this.error("Component with this ID already exists in viewer: " + params.id + " - will autogenerate this ID");
137429
+ delete params.id;
137430
+ }
137431
+
137432
+ const sceneModel = new SceneModel(this.viewer.scene, utils.apply(params, {
137433
+ isModel: true,
137434
+ backfaces: params.backfaces,
137435
+ dtxEnabled: params.dtxEnabled,
137436
+ rotation: params.rotation,
137437
+ origin: params.origin
137438
+ }));
137439
+
137440
+ const modelId = sceneModel.id; // In case ID was auto-generated
137441
+
137442
+ if (!params.src && !params.dotBIM) {
137443
+ this.error("load() param expected: src or dotBIM");
137444
+ return sceneModel; // Return new empty model
137445
+ }
137446
+
137447
+ const objectDefaults = params.objectDefaults || this._objectDefaults || IFCObjectDefaults;
137448
+
137449
+ let includeTypes;
137450
+ if (params.includeTypes) {
137451
+ includeTypes = {};
137452
+ for (let i = 0, len = params.includeTypes.length; i < len; i++) {
137453
+ includeTypes[params.includeTypes[i]] = true;
137454
+ }
137455
+ }
137456
+
137457
+ let excludeTypes;
137458
+ if (params.excludeTypes) {
137459
+ excludeTypes = {};
137460
+ if (!includeTypes) {
137461
+ includeTypes = {};
137462
+ }
137463
+ for (let i = 0, len = params.excludeTypes.length; i < len; i++) {
137464
+ includeTypes[params.excludeTypes[i]] = true;
137465
+ }
137466
+ }
137467
+
137468
+ const parseDotBIM = (ctx) => {
137469
+
137470
+ const fileData = ctx.fileData;
137471
+ const sceneModel = ctx.sceneModel;
137472
+
137473
+ const dbMeshIndices = {};
137474
+ const dbMeshLoaded = {};
137475
+
137476
+ const ifcProjectId = math.createUUID();
137477
+ const ifcSiteId = math.createUUID();
137478
+ const ifcBuildingId = math.createUUID();
137479
+ const ifcBuildingStoryId = math.createUUID();
137480
+
137481
+ const metaModelData = {
137482
+ metaObjects: [
137483
+ {
137484
+ id: ifcProjectId,
137485
+ name: "IfcProject",
137486
+ type: "IfcProject",
137487
+ parent: null
137488
+ },
137489
+ {
137490
+ id: ifcSiteId,
137491
+ name: "IfcSite",
137492
+ type: "IfcSite",
137493
+ parent: ifcProjectId
137494
+ },
137495
+ {
137496
+ id: ifcBuildingId,
137497
+ name: "IfcBuilding",
137498
+ type: "IfcBuilding",
137499
+ parent: ifcSiteId
137500
+ },
137501
+ {
137502
+ id: ifcBuildingStoryId,
137503
+ name: "IfcBuildingStorey",
137504
+ type: "IfcBuildingStorey",
137505
+ parent: ifcBuildingId
137506
+ }
137507
+ ],
137508
+ propertySets: []
137509
+ };
137510
+
137511
+ for (let i = 0, len = fileData.meshes.length; i < len; i++) {
137512
+ const dbMesh = fileData.meshes[i];
137513
+ dbMeshIndices[dbMesh.mesh_id] = i;
137514
+ }
137515
+
137516
+ const parseDBMesh = (dbMeshId) => {
137517
+ if (dbMeshLoaded[dbMeshId]) {
137518
+ return;
137519
+ }
137520
+ const dbMeshIndex = dbMeshIndices[dbMeshId];
137521
+ const dbMesh = fileData.meshes[dbMeshIndex];
137522
+ sceneModel.createGeometry({
137523
+ id: dbMeshId,
137524
+ primitive: "triangles",
137525
+ positions: dbMesh.coordinates,
137526
+ indices: dbMesh.indices
137527
+ });
137528
+ dbMeshLoaded[dbMeshId] = true;
137529
+ };
137530
+
137531
+ const dbElements = fileData.elements;
137532
+ for (let i = 0, len = dbElements.length; i < len; i++) {
137533
+ const element = dbElements[i];
137534
+ const elementType = element.type;
137535
+ if (excludeTypes && excludeTypes[elementType]) {
137536
+ continue;
137537
+
137538
+ }
137539
+ if (includeTypes && (!includeTypes[elementType])) {
137540
+ continue;
137541
+ }
137542
+ const info = element.info;
137543
+ const objectId =
137544
+ element.guid !== undefined
137545
+ ? `${element.guid}`
137546
+ : (info !== undefined && info.id !== undefined
137547
+ ? info.id
137548
+ : i);
137549
+
137550
+ const dbMeshId = element.mesh_id;
137551
+
137552
+ parseDBMesh(dbMeshId);
137553
+
137554
+ const meshId = `${objectId}-mesh`;
137555
+ const vector = element.vector;
137556
+ const rotation = element.rotation;
137557
+ const props = objectDefaults ? objectDefaults[elementType] || objectDefaults["DEFAULT"] : null;
137558
+
137559
+ let visible = true;
137560
+ let pickable = true;
137561
+ let color = element.color ? [element.color.r / 255, element.color.g / 255, element.color.b / 255] : [1, 1, 1];
137562
+ let opacity = element.color ? element.color.a / 255 : 1.0;
137563
+
137564
+ if (props) {
137565
+ if (props.visible === false) {
137566
+ visible = false;
137567
+ }
137568
+ if (props.pickable === false) {
137569
+ pickable = false;
137570
+ }
137571
+ if (props.colorize) {
137572
+ color = props.colorize;
137573
+ }
137574
+ if (props.opacity !== undefined && props.opacity !== null) {
137575
+ opacity = props.opacity;
137576
+ }
137577
+ }
137578
+
137579
+ sceneModel.createMesh({
137580
+ id: meshId,
137581
+ geometryId: dbMeshId,
137582
+ color,
137583
+ opacity,
137584
+ quaternion: rotation && (rotation.qz !== 0 || rotation.qy !== 0 || rotation.qx !== 0 || rotation.qw !== 1.0) ? [rotation.qx, rotation.qy, rotation.qz, rotation.qw] : undefined,
137585
+ position: vector ? [vector.x, vector.y, vector.z] : undefined
137586
+ });
137587
+
137588
+ sceneModel.createEntity({
137589
+ id: objectId,
137590
+ meshIds: [meshId],
137591
+ visible,
137592
+ pickable,
137593
+ isObject: true
137594
+ });
137595
+
137596
+ metaModelData.metaObjects.push({
137597
+ id: objectId,
137598
+ name: info && info.Name && info.Name !== "None" ? info.Name : `${element.type} ${objectId}`,
137599
+ type: element.type,
137600
+ parent: ifcBuildingStoryId
137601
+ });
137602
+ }
137603
+
137604
+ sceneModel.finalize();
137605
+
137606
+ this.viewer.metaScene.createMetaModel(modelId, metaModelData);
137607
+
137608
+ sceneModel.scene.once("tick", () => {
137609
+ if (sceneModel.destroyed) {
137610
+ return;
137611
+ }
137612
+ sceneModel.scene.fire("modelLoaded", sceneModel.id); // FIXME: Assumes listeners know order of these two events
137613
+ sceneModel.fire("loaded", true, false); // Don't forget the event, for late subscribers
137614
+ });
137615
+ };
137616
+
137617
+ if (params.src) {
137618
+ const src = params.src;
137619
+ this.viewer.scene.canvas.spinner.processes++;
137620
+ this._dataSource.getDotBIM(src, (fileData) => { // OK
137621
+ const ctx = {
137622
+ fileData,
137623
+ sceneModel,
137624
+ nextId: 0,
137625
+ error: function (errMsg) {
137626
+ }
137627
+ };
137628
+ parseDotBIM(ctx);
137629
+ this.viewer.scene.canvas.spinner.processes--;
137630
+ },
137631
+ (err) => {
137632
+ this.viewer.scene.canvas.spinner.processes--;
137633
+ this.error(err);
137634
+ });
137635
+ } else if (params.dotBIM) {
137636
+ const ctx = {
137637
+ fileData: params.dotBIM,
137638
+ sceneModel,
137639
+ nextId: 0,
137640
+ error: function (errMsg) {
137641
+ }
137642
+ };
137643
+ parseDotBIM(ctx);
137644
+ }
137645
+
137646
+ sceneModel.once("destroyed", () => {
137647
+ this.viewer.metaScene.destroyMetaModel(modelId);
137648
+ });
137649
+
137650
+ return sceneModel;
137651
+ }
137652
+
137653
+ /**
137654
+ * Destroys this DotBIMLoaderPlugin.
137655
+ */
137656
+ destroy() {
137657
+ super.destroy();
137658
+ }
137659
+ }
137660
+
136633
137661
  exports.AlphaFormat = AlphaFormat;
136634
137662
  exports.AmbientLight = AmbientLight;
136635
137663
  exports.AngleMeasurementsControl = AngleMeasurementsControl;
@@ -136660,6 +137688,8 @@ exports.DistanceMeasurementsControl = DistanceMeasurementsControl;
136660
137688
  exports.DistanceMeasurementsMouseControl = DistanceMeasurementsMouseControl;
136661
137689
  exports.DistanceMeasurementsPlugin = DistanceMeasurementsPlugin;
136662
137690
  exports.DistanceMeasurementsTouchControl = DistanceMeasurementsTouchControl;
137691
+ exports.DotBIMDefaultDataSource = DotBIMDefaultDataSource;
137692
+ exports.DotBIMLoaderPlugin = DotBIMLoaderPlugin;
136663
137693
  exports.EdgeMaterial = EdgeMaterial;
136664
137694
  exports.EmphasisMaterial = EmphasisMaterial;
136665
137695
  exports.FaceAlignedSectionPlanesPlugin = FaceAlignedSectionPlanesPlugin;