@xeokit/xeokit-sdk 2.6.73 → 2.6.77-slim-rc1

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 (77) hide show
  1. package/dist/xeokit-sdk.cjs.js +246 -126
  2. package/dist/xeokit-sdk.es.js +246 -126
  3. package/dist/xeokit-sdk.es5.js +316 -306
  4. package/dist/xeokit-sdk.min.cjs.js +8 -8
  5. package/dist/xeokit-sdk.min.es.js +8 -8
  6. package/dist/xeokit-sdk.min.es5.js +7 -7
  7. package/package.json +2 -1
  8. package/src/extras/ContextMenu/ContextMenu.js +25 -16
  9. package/src/extras/Skybox/Skybox.js +139 -0
  10. package/src/extras/index.js +2 -1
  11. package/src/plugins/CxConverterIFCLoaderPlugin/CxConverterIFCLoaderPlugin.js +81 -81
  12. package/src/plugins/CxConverterIFCLoaderPlugin/index.js +1 -1
  13. package/src/plugins/FastNavPlugin/FastNavPlugin.js +10 -18
  14. package/src/plugins/SectionPlanesPlugin/Control.js +1 -1
  15. package/src/plugins/TreeViewPlugin/RenderService.js +13 -4
  16. package/src/plugins/TreeViewPlugin/TreeViewPlugin.js +1 -1
  17. package/src/plugins/index.js +0 -1
  18. package/src/viewer/Viewer.js +0 -16
  19. package/src/viewer/scene/CameraControl/lib/controllers/PivotController.js +29 -8
  20. package/src/viewer/scene/LineSet/LineSet.js +7 -2
  21. package/src/viewer/scene/camera/CameraFlightAnimation.js +2 -2
  22. package/src/viewer/scene/canvas/Canvas.js +7 -4
  23. package/src/viewer/scene/index.js +0 -1
  24. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesColorRenderer.js +5 -0
  25. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorRenderer.js +5 -0
  26. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesFlatColorRenderer.js +5 -0
  27. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorRenderer.js +5 -0
  28. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatColorRenderer.js +5 -0
  29. package/types/plugins/FastNavPlugin/FastNavPlugin.d.ts +5 -0
  30. package/types/plugins/index.d.ts +0 -1
  31. package/types/viewer/scene/CameraControl/CameraControl.d.ts +168 -0
  32. package/types/viewer/scene/LineSet/LineSet.d.ts +1 -1
  33. package/types/viewer/scene/camera/CameraPath.d.ts +86 -6
  34. package/types/viewer/scene/camera/CameraPathAnimation.d.ts +2 -0
  35. package/types/viewer/scene/geometry/ReadableGeometry.d.ts +14 -0
  36. package/types/viewer/scene/geometry/VBOGeometry.d.ts +2 -0
  37. package/types/viewer/scene/geometry/index.d.ts +2 -1
  38. package/types/viewer/scene/geometry/loaders/index.d.ts +2 -0
  39. package/types/viewer/scene/geometry/loaders/load3DSGeometry.d.ts +17 -0
  40. package/types/viewer/scene/geometry/loaders/loadOBJGeometry.d.ts +18 -0
  41. package/types/viewer/scene/index.d.ts +1 -0
  42. package/types/viewer/scene/input/input.d.ts +117 -0
  43. package/types/viewer/scene/lights/AmbientLight.d.ts +41 -0
  44. package/types/viewer/scene/lights/CubeTexture.d.ts +27 -0
  45. package/types/viewer/scene/lights/DirLight.d.ts +77 -0
  46. package/types/viewer/scene/lights/LightMap.d.ts +27 -0
  47. package/types/viewer/scene/lights/PointLight.d.ts +135 -0
  48. package/types/viewer/scene/lights/ReflectionMap.d.ts +26 -0
  49. package/types/viewer/scene/lights/index.d.ts +4 -1
  50. package/types/viewer/scene/marker/Marker.d.ts +5 -0
  51. package/types/viewer/scene/materials/EmphasisMaterial.d.ts +5 -0
  52. package/types/viewer/scene/materials/Fresnel.d.ts +25 -62
  53. package/types/viewer/scene/materials/LambertMaterial.d.ts +192 -0
  54. package/types/viewer/scene/materials/MetallicMaterial.d.ts +359 -0
  55. package/types/viewer/scene/materials/PhongMaterial.d.ts +5 -0
  56. package/types/viewer/scene/materials/PointsMaterial.d.ts +5 -0
  57. package/types/viewer/scene/materials/SpecularMaterial.d.ts +342 -0
  58. package/types/viewer/scene/materials/Texture.d.ts +36 -78
  59. package/types/viewer/scene/materials/index.d.ts +2 -0
  60. package/types/viewer/scene/models/SceneModel.d.ts +134 -7
  61. package/types/viewer/scene/models/SceneModelEntity.d.ts +65 -0
  62. package/types/viewer/scene/models/SceneModelMesh.d.ts +12 -0
  63. package/types/viewer/scene/paths/CubicBezierCurve.d.ts +146 -0
  64. package/types/viewer/scene/paths/Curve.d.ts +75 -0
  65. package/types/viewer/scene/paths/Path.d.ts +119 -0
  66. package/types/viewer/scene/paths/QuadraticBezierCurve.d.ts +124 -0
  67. package/types/viewer/scene/paths/SplineCurve.d.ts +84 -0
  68. package/types/viewer/scene/paths/index.d.ts +5 -0
  69. package/types/viewer/scene/scene/Scene.d.ts +102 -0
  70. package/types/viewer/scene/sectionPlane/SectionPlane.d.ts +41 -0
  71. package/types/viewer/scene/webgl/PickResult.d.ts +19 -0
  72. package/src/plugins/SkyboxesPlugin/SkyboxesPlugin.js +0 -134
  73. package/src/plugins/SkyboxesPlugin/index.js +0 -1
  74. package/src/viewer/scene/skybox/Skybox.js +0 -123
  75. package/types/plugins/SkyboxesPlugin/SkyboxesPlugin.d.ts +0 -34
  76. package/types/plugins/SkyboxesPlugin/index.d.ts +0 -1
  77. /package/src/{viewer/scene/skybox → extras/Skybox}/index.js +0 -0
@@ -1,7 +1,7 @@
1
1
  /**
2
- * xeokit-sdk v2.6.73
3
- * Commit: 3b3bb2ad8abfdf189cf4ba7f67d6798375772b7b
4
- * Built: 2025-04-10T16:46:49.684Z
2
+ * xeokit-sdk v2.6.76
3
+ * Commit: dd09d800ebb3a626d7767a83af023ed05e49f2fa
4
+ * Built: 2025-05-10T10:08:24.044Z
5
5
  */
6
6
 
7
7
  'use strict';
@@ -350,7 +350,8 @@ class ContextMenu {
350
350
  this._shown = false; // True when the ContextMenu is visible
351
351
  this._nextId = 0;
352
352
  this._parentNode = cfg.parentNode || document.body;
353
-
353
+ this._offsetParent = (this._parentNode instanceof ShadowRoot) ? this._parentNode.host : this._parentNode;
354
+
354
355
  /**
355
356
  * Subscriptions to events fired at this ContextMenu.
356
357
  * @private
@@ -562,7 +563,7 @@ class ContextMenu {
562
563
  for (let i = 0, len = this._menuList.length; i < len; i++) {
563
564
  const menu = this._menuList[i];
564
565
  const menuElement = menu.menuElement;
565
- menuElement.parentElement.removeChild(menuElement);
566
+ menuElement.remove();
566
567
  }
567
568
  this._itemsCfg = [];
568
569
  this._rootMenu = null;
@@ -790,21 +791,22 @@ class ContextMenu {
790
791
 
791
792
  const itemRect = itemElement.getBoundingClientRect();
792
793
  subMenuElement.getBoundingClientRect();
794
+ const offsetRect = self._offsetParent.getBoundingClientRect();
793
795
 
794
796
  const subMenuWidth = 200; // TODO
795
- const showOnRight = (itemRect.right + subMenuWidth) < window.innerWidth;
796
- const showOnLeft = (itemRect.left - subMenuWidth) > 0;
797
-
797
+ const showOnRight = (itemRect.right + subMenuWidth) < offsetRect.right;
798
+ const showOnLeft = (itemRect.left - subMenuWidth) > offsetRect.left;
799
+
798
800
  if(showOnRight)
799
- self._showMenu(subMenu.id, itemRect.right - 5, itemRect.top - 1);
801
+ self._showMenu(subMenu.id, itemRect.right + window.scrollX - 5, itemRect.top + window.scrollY - 1);
800
802
  else if (showOnLeft)
801
- self._showMenu(subMenu.id, itemRect.left - subMenuWidth, itemRect.top - 1);
803
+ self._showMenu(subMenu.id, itemRect.left - subMenuWidth + window.scrollX, itemRect.top + window.scrollY - 1);
802
804
  else {
803
- const spaceOnLeft = itemRect.left, spaceOnRight = window.innerWidth - itemRect.right;
805
+ const spaceOnLeft = itemRect.left - offsetRect.left, spaceOnRight = offsetRect.right - itemRect.right;
804
806
  if(spaceOnRight > spaceOnLeft)
805
- self._showMenu(subMenu.id, itemRect.right - 5 - (subMenuWidth - spaceOnRight), itemRect.top - 1);
807
+ self._showMenu(subMenu.id, itemRect.right - 5 - (subMenuWidth - spaceOnRight), itemRect.top + window.scrollY - 1);
806
808
  else
807
- self._showMenu(subMenu.id, itemRect.left - spaceOnLeft, itemRect.top - 1);
809
+ self._showMenu(subMenu.id, itemRect.left - spaceOnLeft, itemRect.top + window.scrollY - 1);
808
810
  }
809
811
 
810
812
  lastSubMenu = subMenu;
@@ -997,14 +999,21 @@ class ContextMenu {
997
999
  menuElement.style.display = 'block';
998
1000
  const menuHeight = menuElement.offsetHeight;
999
1001
  const menuWidth = menuElement.offsetWidth;
1000
- if ((pageY + menuHeight) > window.innerHeight) {
1001
- pageY = window.innerHeight - menuHeight;
1002
+
1003
+ const offsetRect = this._offsetParent.getBoundingClientRect();
1004
+
1005
+ const bottomContainerBorder = offsetRect.bottom + window.scrollY;
1006
+ const rightContainerBorder = offsetRect.right + window.scrollX;
1007
+ if ((pageY + menuHeight) > bottomContainerBorder) {
1008
+ pageY = bottomContainerBorder- menuHeight;
1002
1009
  }
1003
- if ((pageX + menuWidth) > window.innerWidth) {
1004
- pageX = window.innerWidth - menuWidth;
1010
+ if ((pageX + menuWidth) > rightContainerBorder) {
1011
+ pageX = rightContainerBorder - menuWidth;
1005
1012
  }
1006
- menuElement.style.left = pageX + 'px';
1007
- menuElement.style.top = pageY + 'px';
1013
+
1014
+
1015
+ menuElement.style.left = pageX - offsetRect.left - window.scrollX + 'px';
1016
+ menuElement.style.top = pageY - offsetRect.top - window.scrollY + 'px';
1008
1017
  }
1009
1018
 
1010
1019
  _hideMenuElement(menuElement) {
@@ -54930,6 +54939,11 @@ class TrianglesColorRenderer$1 extends TrianglesBatchingRenderer {
54930
54939
  src.push(" float dy = dFdy(vFragDepth);");
54931
54940
  src.push(" float diff = sqrt(dx*dx+dy*dy);");
54932
54941
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth + diff ) * logDepthBufFC * 0.5;");
54942
+ } else {
54943
+ src.push(" float dx = dFdx(gl_FragCoord.z);");
54944
+ src.push(" float dy = dFdy(gl_FragCoord.z);");
54945
+ src.push(" float diff = sqrt(dx*dx+dy*dy);");
54946
+ src.push(" gl_FragDepth = gl_FragCoord.z + diff;");
54933
54947
  }
54934
54948
 
54935
54949
  if (this._withSAO) {
@@ -55184,6 +55198,11 @@ class TrianglesFlatColorRenderer$1 extends TrianglesBatchingRenderer {
55184
55198
 
55185
55199
  if (scene.logarithmicDepthBufferEnabled) {
55186
55200
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
55201
+ } else {
55202
+ src.push(" float dx = dFdx(gl_FragCoord.z);");
55203
+ src.push(" float dy = dFdy(gl_FragCoord.z);");
55204
+ src.push(" float diff = sqrt(dx*dx+dy*dy);");
55205
+ src.push(" gl_FragDepth = gl_FragCoord.z + diff;");
55187
55206
  }
55188
55207
 
55189
55208
  src.push("}");
@@ -60286,6 +60305,11 @@ class TrianglesColorRenderer extends TrianglesInstancingRenderer {
60286
60305
  src.push(" float dy = dFdy(vFragDepth);");
60287
60306
  src.push(" float diff = sqrt(dx*dx+dy*dy);");
60288
60307
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth + diff ) * logDepthBufFC * 0.5;");
60308
+ } else {
60309
+ src.push(" float dx = dFdx(gl_FragCoord.z);");
60310
+ src.push(" float dy = dFdy(gl_FragCoord.z);");
60311
+ src.push(" float diff = sqrt(dx*dx+dy*dy);");
60312
+ src.push(" gl_FragDepth = gl_FragCoord.z + diff;");
60289
60313
  }
60290
60314
 
60291
60315
  // Doing SAO blend in the main solid fill draw shader just so that edge lines can be drawn over the top
@@ -60549,6 +60573,11 @@ class TrianglesFlatColorRenderer extends TrianglesInstancingRenderer {
60549
60573
 
60550
60574
  if (scene.logarithmicDepthBufferEnabled) {
60551
60575
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
60576
+ } else {
60577
+ src.push(" float dx = dFdx(gl_FragCoord.z);");
60578
+ src.push(" float dy = dFdy(gl_FragCoord.z);");
60579
+ src.push(" float diff = sqrt(dx*dx+dy*dy);");
60580
+ src.push(" gl_FragDepth = gl_FragCoord.z + diff;");
60552
60581
  }
60553
60582
 
60554
60583
  src.push("}");
@@ -75760,6 +75789,11 @@ class DTXTrianglesColorRenderer {
75760
75789
  if (scene.logarithmicDepthBufferEnabled) {
75761
75790
  src.push(" gl_FragDepth = isPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;");
75762
75791
  //src.push(" gl_FragDepth = log2( vFragDepth ) * logDepthBufFC * 0.5;");
75792
+ } else {
75793
+ src.push(" float dx = dFdx(gl_FragCoord.z);");
75794
+ src.push(" float dy = dFdy(gl_FragCoord.z);");
75795
+ src.push(" float diff = sqrt(dx*dx+dy*dy);");
75796
+ src.push(" gl_FragDepth = gl_FragCoord.z + diff;");
75763
75797
  }
75764
75798
 
75765
75799
  if (this._withSAO) {
@@ -89183,7 +89217,7 @@ class LineSet extends Component {
89183
89217
  * @param {String} [cfg.id] Optional ID, unique among all components in the parent {@link Scene}, generated automatically when omitted.
89184
89218
  * @param {Number[]} cfg.positions World-space 3D vertex positions.
89185
89219
  * @param {Number[]} [cfg.indices] Indices to connect ````positions```` into line segments. Note that these are separate line segments, not a polyline.
89186
- * @param {Number[]} [cfg.color=[0,0,0]] The color of this ````LineSet````. This is both emissive and diffuse.
89220
+ * @param {Number[]} [cfg.color=[1,1,1]] The color of this ````LineSet````. This is both emissive and diffuse.
89187
89221
  * @param {Boolean} [cfg.visible=true] Indicates whether or not this ````LineSet```` is visible.
89188
89222
  * @param {Number} [cfg.opacity=1.0] ````LineSet````'s initial opacity factor.
89189
89223
  */
@@ -89203,6 +89237,9 @@ class LineSet extends Component {
89203
89237
  }
89204
89238
  }
89205
89239
 
89240
+ this._color = cfg.color || [1, 1, 1];
89241
+ this._opacity = cfg.opacity || 1.0;
89242
+
89206
89243
  this._sceneModel = new SceneModel(this, {
89207
89244
  isModel: false // Don't register in Scene.models
89208
89245
  });
@@ -89211,7 +89248,9 @@ class LineSet extends Component {
89211
89248
  id: "linesMesh",
89212
89249
  primitive: "lines",
89213
89250
  positions: this._positions,
89214
- indices: this._indices
89251
+ indices: this._indices,
89252
+ color: this._color,
89253
+ opacity: this._opacity,
89215
89254
  });
89216
89255
 
89217
89256
  this._sceneModel.createEntity({
@@ -92939,6 +92978,7 @@ class FastNavPlugin extends Plugin {
92939
92978
  * @param {Number} [cfg.scaleCanvasResolutionFactor=0.6] The factor by which we downscale the canvas resolution whenever we interact with the Viewer.
92940
92979
  * @param {Boolean} [cfg.delayBeforeRestore=true] Whether to temporarily have a delay before restoring normal rendering after we stop interacting with the Viewer.
92941
92980
  * @param {Number} [cfg.delayBeforeRestoreSeconds=0.5] Delay in seconds before restoring normal rendering after we stop interacting with the Viewer.
92981
+ * @param {Function} [cfg.onMoved] Optional callback function fired during moving mode, should return the callback function that will be fired when the interaction stops.
92942
92982
  */
92943
92983
  constructor(viewer, cfg = {}) {
92944
92984
 
@@ -92954,6 +92994,8 @@ class FastNavPlugin extends Plugin {
92954
92994
  this._scaleCanvasResolutionFactor = cfg.scaleCanvasResolutionFactor || 0.6;
92955
92995
  this._delayBeforeRestore = (cfg.delayBeforeRestore !== false);
92956
92996
  this._delayBeforeRestoreSeconds = cfg.delayBeforeRestoreSeconds || 0.5;
92997
+ this._onMoved = cfg.onMoved;
92998
+ this._onStopped = null;
92957
92999
 
92958
93000
  let timer = this._delayBeforeRestoreSeconds * 1000;
92959
93001
  let fastMode = false;
@@ -92972,6 +93014,10 @@ class FastNavPlugin extends Plugin {
92972
93014
  } else {
92973
93015
  viewer.scene.canvas.resolutionScale = this._defaultScaleCanvasResolutionFactor;
92974
93016
  }
93017
+ if (this._onMoved) {
93018
+ this._onStopped = this._onMoved();
93019
+ }
93020
+
92975
93021
  fastMode = true;
92976
93022
  }
92977
93023
  };
@@ -92983,10 +93029,12 @@ class FastNavPlugin extends Plugin {
92983
93029
  viewer.scene._renderer.setPBREnabled(true);
92984
93030
  viewer.scene._renderer.setSAOEnabled(true);
92985
93031
  viewer.scene._renderer.setTransparentEnabled(true);
93032
+ if (this._onStopped) {
93033
+ this._onStopped();
93034
+ }
92986
93035
  fastMode = false;
92987
93036
  };
92988
93037
 
92989
- this._onCanvasBoundary = viewer.scene.canvas.on("boundary", switchToLowQuality);
92990
93038
  this._onCameraMatrix = viewer.scene.camera.on("matrix", switchToLowQuality);
92991
93039
 
92992
93040
  this._onSceneTick = viewer.scene.on("tick", (tickEvent) => {
@@ -92998,23 +93046,6 @@ class FastNavPlugin extends Plugin {
92998
93046
  switchToHighQuality();
92999
93047
  }
93000
93048
  });
93001
-
93002
- let down = false;
93003
-
93004
- this._onSceneMouseDown = viewer.scene.input.on("mousedown", () => {
93005
- down = true;
93006
- });
93007
-
93008
- this._onSceneMouseUp = viewer.scene.input.on("mouseup", () => {
93009
- down = false;
93010
- });
93011
-
93012
- this._onSceneMouseMove = viewer.scene.input.on("mousemove", () => {
93013
- if (!down) {
93014
- return;
93015
- }
93016
- switchToLowQuality();
93017
- });
93018
93049
  }
93019
93050
 
93020
93051
  /**
@@ -98309,8 +98340,8 @@ class Skybox extends Component {
98309
98340
  * @param {Component} owner Owner component. When destroyed, the owner will destroy this PointLight as well.
98310
98341
  * @param {*} [cfg] Skybox configuration
98311
98342
  * @param {String} [cfg.id] Optional ID, unique among all components in the parent {Scene}, generated automatically when omitted.
98312
- * @param {String} [cfg.src=null] Path to skybox texture
98313
- * @param {String} [cfg.encoding="linear"] Texture encoding format. See the {@link Texture#encoding} property for more info.
98343
+ * @param {String | String[]} [cfg.src=null] Path to skybox texture
98344
+ * @param {Number} [cfg.encoding=LinearEncoding] Texture encoding format. See the {@link Texture#encoding} property for more info.
98314
98345
  * @param {Number} [cfg.size=1000] Size of this Skybox, given as the distance from the center at ````[0,0,0]```` to each face.
98315
98346
  * @param {Boolean} [cfg.active=true] True when this Skybox is visible.
98316
98347
  */
@@ -98318,6 +98349,32 @@ class Skybox extends Component {
98318
98349
 
98319
98350
  super(owner, cfg);
98320
98351
 
98352
+ const useMultipleTexture = typeof cfg.src === "object" && cfg.src !== null;
98353
+
98354
+ if (useMultipleTexture) {
98355
+ this._createCombinedTexture(cfg).then(combinedTexture => {
98356
+ this._createSkyboxMesh(cfg, combinedTexture);
98357
+ }).catch(e => this.error(e));
98358
+ } else {
98359
+ this._createSkyboxMesh(cfg);
98360
+ }
98361
+ }
98362
+
98363
+ /**
98364
+ *
98365
+ * @private
98366
+ * @param {*} cfg
98367
+ * @param {Texture} combinedTexture
98368
+ */
98369
+ _createSkyboxMesh(cfg, combinedTexture = null) {
98370
+ const texture = combinedTexture || new Texture(this, {
98371
+ src: cfg.src,
98372
+ flipY: true,
98373
+ wrapS: ClampToEdgeWrapping,
98374
+ wrapT: ClampToEdgeWrapping,
98375
+ encoding: cfg.encoding || LinearEncoding
98376
+ });
98377
+
98321
98378
  this._skyboxMesh = new Mesh(this, {
98322
98379
 
98323
98380
  geometry: new ReadableGeometry(this, { // Box-shaped geometry
@@ -98348,13 +98405,7 @@ class Skybox extends Component {
98348
98405
  diffuse: [0, 0, 0],
98349
98406
  specular: [0, 0, 0],
98350
98407
  emissive: [1, 1, 1],
98351
- emissiveMap: new Texture(this, {
98352
- src: cfg.src,
98353
- flipY: true,
98354
- wrapS: "clampToEdge",
98355
- wrapT: "clampToEdge",
98356
- encoding: cfg.encoding || "sRGB"
98357
- }),
98408
+ emissiveMap: texture,
98358
98409
  backfaces: true // Show interior faces of our skybox geometry
98359
98410
  }),
98360
98411
  // stationary: true,
@@ -98368,6 +98419,86 @@ class Skybox extends Component {
98368
98419
  this.active = cfg.active;
98369
98420
  }
98370
98421
 
98422
+ /**
98423
+ *
98424
+ * @private
98425
+ * @param {*} cfg
98426
+ * @returns {Texture}
98427
+ */
98428
+ async _createCombinedTexture(cfg) {
98429
+ const [
98430
+ posX,
98431
+ negX,
98432
+ posY,
98433
+ negY,
98434
+ posZ,
98435
+ negZ
98436
+ ] = cfg.src;
98437
+
98438
+ if (!posX || !negX || !posY || !negY || !posZ || !negZ) {
98439
+ throw new Error("All six skybox textures must be provided");
98440
+ }
98441
+
98442
+ const canvas = document.createElement('canvas');
98443
+ const ctx = canvas.getContext('2d');
98444
+
98445
+ const loadImage = src => {
98446
+ return new Promise((resolve, reject) => {
98447
+ const img = new Image();
98448
+ img.crossOrigin = "anonymous";
98449
+ img.onload = () => resolve(img);
98450
+ img.onerror = () => reject(new Error(`Failed to load image: ${src}`));
98451
+ img.src = src;
98452
+ });
98453
+ };
98454
+
98455
+ try {
98456
+ const [imgPosX, imgNegX, imgPosY, imgNegY, imgPosZ, imgNegZ] = await Promise.all([
98457
+ loadImage(posX),
98458
+ loadImage(negX),
98459
+ loadImage(posY),
98460
+ loadImage(negY),
98461
+ loadImage(posZ),
98462
+ loadImage(negZ)
98463
+ ]);
98464
+
98465
+ const imageSize = imgPosX.width;
98466
+ if (
98467
+ imgNegX.width !== imageSize || imgPosY.width !== imageSize ||
98468
+ imgNegY.width !== imageSize || imgPosZ.width !== imageSize ||
98469
+ imgNegZ.width !== imageSize
98470
+ ) {
98471
+ throw new Error("All skybox textures must have the same dimensions");
98472
+ }
98473
+
98474
+ // Set canvas size for the Christ cross layout (3×4 grid)
98475
+ canvas.width = imageSize * 4;
98476
+ canvas.height = imageSize * 3;
98477
+
98478
+ ctx.fillStyle = 'black';
98479
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
98480
+
98481
+ ctx.drawImage(imgNegX, imageSize * 0, imageSize * 1, imageSize, imageSize); // -X (left)
98482
+ ctx.drawImage(imgPosX, imageSize * 2, imageSize * 1, imageSize, imageSize); // +X (right)
98483
+ ctx.drawImage(imgPosY, imageSize * 1, imageSize * 0, imageSize, imageSize); // +Y (top)
98484
+ ctx.drawImage(imgNegY, imageSize * 1, imageSize * 2, imageSize, imageSize); // -Y (bottom)
98485
+ ctx.drawImage(imgPosZ, imageSize * 1, imageSize * 1, imageSize, imageSize); // +Z (front)
98486
+ ctx.drawImage(imgNegZ, imageSize * 3, imageSize * 1, imageSize, imageSize); // -Z (back)
98487
+
98488
+ const combinedTexture = new Texture(this, {
98489
+ image: canvas,
98490
+ flipY: true,
98491
+ wrapS: ClampToEdgeWrapping,
98492
+ wrapT: ClampToEdgeWrapping,
98493
+ encoding: cfg.encoding || LinearEncoding
98494
+ });
98495
+
98496
+ return combinedTexture;
98497
+ } catch (error) {
98498
+ console.error("Error creating combined skybox texture:", error);
98499
+ throw error;
98500
+ }
98501
+ }
98371
98502
 
98372
98503
  /**
98373
98504
  * Sets the size of this Skybox, given as the distance from the center at [0,0,0] to each face.
@@ -98562,6 +98693,9 @@ const tempVec4a$5 = math.vec4();
98562
98693
  const tempVec4b$5 = math.vec4();
98563
98694
  const tempVec4c = math.vec4();
98564
98695
 
98696
+ const TOP_LIMIT = 0.001;
98697
+ const BOTTOM_LIMIT = Math.PI - 0.001;
98698
+
98565
98699
 
98566
98700
  /** @private */
98567
98701
  class PivotController {
@@ -98737,14 +98871,9 @@ class PivotController {
98737
98871
  */
98738
98872
  startPivot() {
98739
98873
 
98740
- if (this._cameraLookingDownwards()) {
98741
- this._pivoting = false;
98742
- return false;
98743
- }
98744
-
98745
98874
  const camera = this._scene.camera;
98746
98875
 
98747
- let lookat = math.lookAtMat4v(camera.eye, camera.look, camera.worldUp);
98876
+ let lookat = math.lookAtMat4v(camera.eye, camera.look, camera.up);
98748
98877
  math.transformPoint3(lookat, this.getPivotPos(), this._cameraOffset);
98749
98878
 
98750
98879
  const pivotPos = this.getPivotPos();
@@ -98847,8 +98976,31 @@ class PivotController {
98847
98976
  dx = -dx;
98848
98977
  }
98849
98978
  this._azimuth += -dx * .01;
98850
- this._polar += dy * .01;
98851
- this._polar = math.clamp(this._polar, .001, Math.PI - .001);
98979
+
98980
+ const isMovingUp = dy < 0;
98981
+ const isMovingDown = dy > 0;
98982
+
98983
+ // Track if we're at limits - only check if we're very close to the limit
98984
+ const atTopLimit = Math.abs(this._polar - TOP_LIMIT) < 0.005;
98985
+ const atBottomLimit = Math.abs(this._polar - BOTTOM_LIMIT) < 0.005;
98986
+
98987
+ let newPolar = this._polar + dy * .01;
98988
+
98989
+ // Case 1: At top limit and trying to go beyond
98990
+ if (atTopLimit && isMovingUp) {
98991
+ newPolar = TOP_LIMIT;
98992
+ }
98993
+ // Case 2: At bottom limit and trying to go beyond
98994
+ else if (atBottomLimit && isMovingDown) {
98995
+ newPolar = BOTTOM_LIMIT;
98996
+ }
98997
+ // Case 3: Normal rotation or moving away from a limit
98998
+ else {
98999
+ newPolar = math.clamp(newPolar, TOP_LIMIT, BOTTOM_LIMIT);
99000
+ }
99001
+
99002
+ this._polar = newPolar;
99003
+
98852
99004
  const pos = [
98853
99005
  this._radius * Math.sin(this._polar) * Math.sin(this._azimuth),
98854
99006
  this._radius * Math.cos(this._polar),
@@ -112398,22 +112550,6 @@ class Viewer {
112398
112550
  this.sendToPlugins("snapshotStarting"); // Tells plugins to hide things that shouldn't be in snapshot
112399
112551
  }
112400
112552
 
112401
- const captured = {};
112402
- for (let i = 0, len = this._plugins.length; i < len; i++) {
112403
- const plugin = this._plugins[i];
112404
- if (plugin.getContainerElement) {
112405
- const container = plugin.getContainerElement();
112406
- if (container !== document.body) {
112407
- if (!captured[container.id]) {
112408
- captured[container.id] = true;
112409
- html2canvas(container).then(function (canvas) {
112410
- document.body.appendChild(canvas);
112411
- });
112412
- }
112413
- }
112414
- }
112415
- }
112416
-
112417
112553
  // firing "rendering" is necessary to trigger DTX{Lines,Triangles}Layer::_uploadDeferredFlags
112418
112554
  this.scene.fire("rendering", { }, true);
112419
112555
 
@@ -130064,46 +130200,27 @@ class FaceAlignedSectionPlanesPlugin extends Plugin {
130064
130200
  * });
130065
130201
  *
130066
130202
  * // Add a GLTFModelsPlugin
130067
- * var gltfLoaderPlugin = new GLTFModelsPlugin(viewer, {
130068
- * id: "GLTFModels" // Default value
130069
- * });
130203
+ * var xktLoaderPlugin = new XKTLoaderPlugin(viewer);
130070
130204
  *
130071
130205
  * // Add a SkyboxesPlugin
130072
- * var skyboxesPlugin = new SkyboxesPlugin(viewer, {
130073
- * id: "Skyboxes" // Default value
130074
- * });
130206
+ * var skyboxesPlugin = new SkyboxesPlugin(viewer);
130207
+ *
130208
+ * // Create a skybox
130209
+ * skyBoxesPlugin.createSkybox({
130210
+ * src: [
130211
+ * "./assets/images/posx.jpg",
130212
+ * "./assets/images/negx.jpg",
130213
+ * "./assets/images/posy.jpg",
130214
+ * "./assets/images/negy.jpg",
130215
+ * "./assets/images/posz.jpg",
130216
+ * "./assets/images/negz.jpg"
130217
+ * ]
130218
+ * })
130075
130219
  *
130076
- * // Load a glTF model
130077
- * const model = gltfLoaderPlugin.load({
130220
+ * // Load an XKT model
130221
+ * const model = xktLoaderPlugin.load({
130078
130222
  * id: "myModel",
130079
- * src: "./models/gltf/mygltfmodel.gltf"
130080
- * });
130081
- *
130082
- * // Create three directional World-space lights. "World" means that they will appear as if part
130083
- * // of the world, instead of "View", where they move with the user's head.
130084
- *
130085
- * skyboxesPlugin.createLight({
130086
- * id: "keyLight",
130087
- * dir: [0.8, -0.6, -0.8],
130088
- * color: [1.0, 0.3, 0.3],
130089
- * intensity: 1.0,
130090
- * space: "world"
130091
- * });
130092
- *
130093
- * skyboxesPlugin.createLight({
130094
- * id: "fillLight",
130095
- * dir: [-0.8, -0.4, -0.4],
130096
- * color: [0.3, 1.0, 0.3],
130097
- * intensity: 1.0,
130098
- * space: "world"
130099
- * });
130100
- *
130101
- * skyboxesPlugin.createDirLight({
130102
- * id: "rimLight",
130103
- * dir: [0.2, -0.8, 0.8],
130104
- * color: [0.6, 0.6, 0.6],
130105
- * intensity: 1.0,
130106
- * space: "world"
130223
+ * src: "./models/xkt/myModel.xkt"
130107
130224
  * });
130108
130225
  *
130109
130226
  * @class SkyboxesPlugin
@@ -130129,23 +130246,17 @@ class SkyboxesPlugin extends Plugin {
130129
130246
  /**
130130
130247
  Creates a skybox.
130131
130248
 
130132
- @param {String} id Unique ID to assign to the skybox.
130133
130249
  @param {Object} params Skybox configuration.
130250
+ @param {String} [params.id] Optional ID, unique among all components in the parent {Scene}, generated automatically when omitted.
130251
+ @param {String | String[]} [params.src=null] Path to skybox texture
130252
+ @param {Number} [params.encoding=LinearEncoding] Texture encoding format. See the {@link Texture#encoding} property for more info.
130253
+ @param {Number} [params.size=1000] Size of this Skybox, given as the distance from the center at ````[0,0,0]```` to each face.
130134
130254
  @param {Boolean} [params.active=true] Whether the skybox plane is initially active. Only skyboxes while this is true.
130135
130255
  @returns {Skybox} The new skybox.
130136
130256
  */
130137
- createSkybox(id, params) {
130138
- if (this.viewer.scene.components[id]) {
130139
- this.error("Component with this ID already exists: " + id);
130140
- return this;
130141
- }
130142
- var skybox = new Skybox(this.viewer.scene, {
130143
- id: id,
130144
- pos: params.pos,
130145
- dir: params.dir,
130146
- active: true
130147
- });
130148
- this.skyboxes[id] = skybox;
130257
+ createSkybox(params) {
130258
+ const skybox = new Skybox(this.viewer.scene, params);
130259
+ this.skyboxes[skybox.id] = skybox;
130149
130260
  return skybox;
130150
130261
  }
130151
130262
 
@@ -130808,6 +130919,15 @@ class STLLoaderPlugin extends Plugin {
130808
130919
  */
130809
130920
  class RenderService {
130810
130921
 
130922
+ /**
130923
+ * @constructor
130924
+ *
130925
+ * @param {HTMLElement} treeViewContainer Container element for the tree which uses this render service.
130926
+ */
130927
+ constructor(treeViewContainer) {
130928
+ this._treeViewContainer = treeViewContainer;
130929
+ }
130930
+
130811
130931
  /*
130812
130932
  * Creates the root node of the tree.
130813
130933
  * @return {HTMLElement} The root node of the tree.
@@ -130932,7 +131052,7 @@ class RenderService {
130932
131052
  }
130933
131053
 
130934
131054
  getSwitchElement(nodeId) {
130935
- return document.getElementById(`switch-${nodeId}`);
131055
+ return this._treeViewContainer.querySelector(`[id="switch-${nodeId}"]`);
130936
131056
  }
130937
131057
 
130938
131058
  isChecked(element) {
@@ -130940,7 +131060,7 @@ class RenderService {
130940
131060
  }
130941
131061
 
130942
131062
  setCheckbox(nodeId, checked, indeterminate = false) {
130943
- const checkbox = document.getElementById(`checkbox-${nodeId}`);
131063
+ const checkbox = this._treeViewContainer.querySelector(`[id="checkbox-${nodeId}"]`);
130944
131064
  if (checkbox) {
130945
131065
  if (checked !== checkbox.checked) {
130946
131066
  checkbox.checked = checked;
@@ -130955,7 +131075,7 @@ class RenderService {
130955
131075
  }
130956
131076
 
130957
131077
  setXRayed(nodeId, xrayed) {
130958
- const treeNode = document.getElementById(nodeId);
131078
+ const treeNode = this._treeViewContainer.querySelector(`[id="${nodeId}"]`);
130959
131079
  if (treeNode) {
130960
131080
  if (xrayed) {
130961
131081
  treeNode.classList.add('xrayed-node');
@@ -130966,7 +131086,7 @@ class RenderService {
130966
131086
  }
130967
131087
 
130968
131088
  setHighlighted(nodeId, highlighted) {
130969
- const treeNode = document.getElementById(nodeId);
131089
+ const treeNode = this._treeViewContainer.querySelector(`[id="${nodeId}"]`);
130970
131090
  if (treeNode) {
130971
131091
  if (highlighted) {
130972
131092
  treeNode.scrollIntoView({block: "center"});
@@ -131392,7 +131512,7 @@ class TreeViewPlugin extends Plugin {
131392
131512
  this._sortNodes = cfg.sortNodes;
131393
131513
  this._pruneEmptyNodes = cfg.pruneEmptyNodes;
131394
131514
  this._showListItemElementId = null;
131395
- this._renderService = cfg.renderService || new RenderService();
131515
+ this._renderService = cfg.renderService || new RenderService(this._containerElement);
131396
131516
  this._showIndeterminate = cfg.showIndeterminate ?? false;
131397
131517
  this._showProjectNode = cfg.showProjectNode ?? false;
131398
131518
  this._elevationSortFunction = cfg.elevationSortFunction ?? undefined;