@inweb/viewer-three 26.12.5 → 26.12.7

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 (45) hide show
  1. package/dist/extensions/loaders/GLTFFileLoader.js +1 -1
  2. package/dist/extensions/loaders/GLTFFileLoader.js.map +1 -1
  3. package/dist/extensions/loaders/GLTFFileLoader.min.js +1 -1
  4. package/dist/extensions/loaders/GLTFFileLoader.module.js +1 -1
  5. package/dist/extensions/loaders/GLTFFileLoader.module.js.map +1 -1
  6. package/dist/extensions/loaders/IFCXLoader.js +2 -2
  7. package/dist/extensions/loaders/IFCXLoader.js.map +1 -1
  8. package/dist/extensions/loaders/IFCXLoader.min.js +1 -1
  9. package/dist/extensions/loaders/IFCXLoader.module.js +2 -2
  10. package/dist/extensions/loaders/IFCXLoader.module.js.map +1 -1
  11. package/dist/viewer-three.js +467 -164
  12. package/dist/viewer-three.js.map +1 -1
  13. package/dist/viewer-three.min.js +3 -3
  14. package/dist/viewer-three.module.js +465 -162
  15. package/dist/viewer-three.module.js.map +1 -1
  16. package/extensions/loaders/GLTFFileLoader.ts +1 -1
  17. package/extensions/loaders/IFCX/IFCXCloudLoader.ts +1 -1
  18. package/extensions/loaders/IFCX/IFCXFileLoader.ts +1 -1
  19. package/lib/Viewer/components/ExtentsComponent.d.ts +1 -1
  20. package/lib/Viewer/components/ResetComponent.d.ts +1 -1
  21. package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +3 -3
  22. package/lib/Viewer/measurement/Snapper.d.ts +1 -0
  23. package/lib/Viewer/measurement/UnitConverter.d.ts +20 -13
  24. package/lib/Viewer/models/IModelImpl.d.ts +2 -6
  25. package/lib/Viewer/models/ModelImpl.d.ts +4 -6
  26. package/package.json +5 -5
  27. package/src/Viewer/Viewer.ts +15 -11
  28. package/src/Viewer/commands/GetSelected2.ts +2 -2
  29. package/src/Viewer/commands/ResetView.ts +0 -5
  30. package/src/Viewer/commands/ZoomTo.ts +3 -3
  31. package/src/Viewer/components/CameraComponent.ts +4 -4
  32. package/src/Viewer/components/ExtentsComponent.ts +3 -3
  33. package/src/Viewer/components/HighlighterComponent.ts +11 -17
  34. package/src/Viewer/components/ResetComponent.ts +5 -2
  35. package/src/Viewer/components/SelectionComponent.ts +14 -13
  36. package/src/Viewer/draggers/MeasureLineDragger.ts +1 -0
  37. package/src/Viewer/draggers/OrbitDragger.ts +2 -0
  38. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +285 -10
  39. package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +94 -18
  40. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +1 -1
  41. package/src/Viewer/measurement/Snapper.ts +6 -3
  42. package/src/Viewer/measurement/UnitConverter.ts +19 -12
  43. package/src/Viewer/measurement/UnitFormatter.ts +2 -2
  44. package/src/Viewer/models/IModelImpl.ts +2 -10
  45. package/src/Viewer/models/ModelImpl.ts +111 -61
@@ -33829,6 +33829,7 @@ void main() {
33829
33829
  this.changed = false;
33830
33830
  this.viewer = viewer;
33831
33831
  this.viewer.addEventListener("databasechunk", this.updateControls);
33832
+ this.viewer.addEventListener("clear", this.updateControls);
33832
33833
  this.viewer.on("viewposition", this.updateControls);
33833
33834
  this.viewer.addEventListener("zoom", this.updateControls);
33834
33835
  this.viewer.addEventListener("drawviewpoint", this.updateControls);
@@ -33840,6 +33841,7 @@ void main() {
33840
33841
  initialize() { }
33841
33842
  dispose() {
33842
33843
  this.viewer.removeEventListener("databasechunk", this.updateControls);
33844
+ this.viewer.removeEventListener("clear", this.updateControls);
33843
33845
  this.viewer.off("viewposition", this.updateControls);
33844
33846
  this.viewer.removeEventListener("zoom", this.updateControls);
33845
33847
  this.viewer.removeEventListener("drawviewpoint", this.updateControls);
@@ -33937,20 +33939,25 @@ void main() {
33937
33939
  }
33938
33940
  }
33939
33941
 
33942
+ const DisplayUnits = {
33943
+ Meters: { name: "Meters", symbol: "m", scale: 1.0 },
33944
+ Centimeters: { name: "Centimeters", symbol: "cm", scale: 0.01 },
33945
+ Millimeters: { name: "Millimeters", symbol: "mm", scale: 0.001 },
33946
+ Feet: { name: "Feet", symbol: "ft", scale: 0.3048 },
33947
+ Inches: { name: "Inches", symbol: "in", scale: 0.0254 },
33948
+ Yards: { name: "Yards", symbol: "yd", scale: 0.9144 },
33949
+ Kilometers: { name: "Kilometers", symbol: "km", scale: 1000.0 },
33950
+ Miles: { name: "Miles", symbol: "mi", scale: 1609.344 },
33951
+ Micrometers: { name: "Micrometers", symbol: "µm", scale: 0.000001 },
33952
+ Mils: { name: "Mils", symbol: "mil", scale: 0.0000254 },
33953
+ MicroInches: { name: "Micro-inches", symbol: "µin", scale: 0.0000000254 },
33954
+ Default: { name: "File units", symbol: "", scale: 1.0 },
33955
+ };
33940
33956
  const ModelUnits = {
33941
- Meters: { name: "Meters", type: "m", scale: 1.0 },
33942
- Centimeters: { name: "Centimeters", type: "cm", scale: 0.01 },
33943
- Millimeters: { name: "Millimeters", type: "mm", scale: 0.001 },
33944
- Feet: { name: "Feet", type: "ft", scale: 0.3048 },
33945
- Inches: { name: "Inches", type: "in", scale: 0.0254 },
33946
- Yards: { name: "Yards", type: "yd", scale: 0.9144 },
33947
- Kilometers: { name: "Kilometers", type: "km", scale: 1000.0 },
33948
- Miles: { name: "Miles", type: "mi", scale: 1609.344 },
33949
- Micrometers: { name: "Micrometers", type: "µm", scale: 0.000001 },
33950
- Mils: { name: "Mils", type: "mil", scale: 0.0000254 },
33951
- MicroInches: { name: "Micro-inches", type: "µin", scale: 0.0000000254 },
33952
- Default: { name: "File units", type: "unit", scale: 1.0 },
33957
+ Default: { name: "", symbol: "", scale: 1.0 },
33953
33958
  };
33959
+ Object.keys(DisplayUnits).forEach((key) => (ModelUnits[key] = DisplayUnits[key]));
33960
+ Object.keys(DisplayUnits).forEach((key) => (ModelUnits[DisplayUnits[key].symbol] = DisplayUnits[key]));
33954
33961
  function convertUnits(fromUnits, toUnits, distance) {
33955
33962
  const fromFactor = 1 / (ModelUnits[fromUnits] || ModelUnits.Default).scale;
33956
33963
  const toFactor = (ModelUnits[toUnits] || ModelUnits.Default).scale || 1;
@@ -33958,7 +33965,7 @@ void main() {
33958
33965
  }
33959
33966
 
33960
33967
  function getDisplayUnit(units) {
33961
- return (ModelUnits[units] || ModelUnits.Default).type;
33968
+ return (ModelUnits[units] || ModelUnits.Default).symbol;
33962
33969
  }
33963
33970
  function calculatePrecision(value) {
33964
33971
  const distance = Math.abs(value);
@@ -33995,7 +34002,7 @@ void main() {
33995
34002
  else if (digits > 10)
33996
34003
  digits = 10;
33997
34004
  if (ModelUnits[units]) {
33998
- return formatNumber(distance, digits, precision) + " " + ModelUnits[units].type;
34005
+ return formatNumber(distance, digits, precision) + " " + ModelUnits[units].symbol;
33999
34006
  }
34000
34007
  else if (units) {
34001
34008
  return formatNumber(distance, digits, precision) + " " + units;
@@ -34018,6 +34025,7 @@ void main() {
34018
34025
  this.camera = camera;
34019
34026
  this.renderer = renderer;
34020
34027
  this.canvas = canvas;
34028
+ this.threshold = 0.0001;
34021
34029
  this.raycaster = new Raycaster();
34022
34030
  this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
34023
34031
  this.edgesCache = new WeakMap();
@@ -34038,10 +34046,10 @@ void main() {
34038
34046
  this.raycaster.setFromCamera(coords, this.camera);
34039
34047
  this.raycaster.params = {
34040
34048
  Mesh: {},
34041
- Line: { threshold: 0.05 },
34042
- Line2: { threshold: 0.05 },
34049
+ Line: { threshold: this.threshold },
34050
+ Line2: { threshold: this.threshold },
34043
34051
  LOD: {},
34044
- Points: { threshold: 0.01 },
34052
+ Points: { threshold: this.threshold },
34045
34053
  Sprite: {},
34046
34054
  };
34047
34055
  let intersects = this.raycaster.intersectObjects(objects, false);
@@ -34210,6 +34218,7 @@ void main() {
34210
34218
  this.line = new MeasureLine(this.overlay, this.scale, this.units, this.precision);
34211
34219
  this.overlay.addLine(this.line);
34212
34220
  this.snapper = new Snapper(viewer.camera, viewer.renderer, viewer.canvas);
34221
+ this.snapper.threshold = viewer.extents.getSize(new Vector3()).length() / 10000;
34213
34222
  this.objects = [];
34214
34223
  this.updateObjects();
34215
34224
  this.updateUnits();
@@ -35213,7 +35222,7 @@ void main() {
35213
35222
  const boxCenter = box.getCenter(new Vector3());
35214
35223
  const boxSize = box.getBoundingSphere(new Sphere()).radius;
35215
35224
  const rendererSize = viewer.renderer.getSize(new Vector2());
35216
- const aspect = rendererSize.x / rendererSize.y;
35225
+ const aspectRatio = rendererSize.x / rendererSize.y;
35217
35226
  const camera = viewer.camera;
35218
35227
  if (camera.isPerspectiveCamera) {
35219
35228
  const offset = new Vector3(0, 0, 1)
@@ -35225,8 +35234,8 @@ void main() {
35225
35234
  if (camera.isOrthographicCamera) {
35226
35235
  camera.top = boxSize;
35227
35236
  camera.bottom = -boxSize;
35228
- camera.left = camera.bottom * aspect;
35229
- camera.right = camera.top * aspect;
35237
+ camera.left = camera.bottom * aspectRatio;
35238
+ camera.right = camera.top * aspectRatio;
35230
35239
  camera.zoom = 1;
35231
35240
  camera.updateProjectionMatrix();
35232
35241
  const offset = new Vector3(0, 0, 1)
@@ -35287,9 +35296,9 @@ void main() {
35287
35296
  function getSelected2(viewer) {
35288
35297
  const handles2 = [];
35289
35298
  viewer.models.forEach((model) => {
35290
- handles2.push(...model.getHandlesByObjects(viewer.selected));
35299
+ handles2.push(model.getHandlesByObjects(viewer.selected));
35291
35300
  });
35292
- return handles2;
35301
+ return handles2.flat();
35293
35302
  }
35294
35303
 
35295
35304
  function hideSelected(viewer) {
@@ -35313,7 +35322,6 @@ void main() {
35313
35322
  }
35314
35323
 
35315
35324
  function resetView(viewer) {
35316
- const reset = viewer.getComponent("ResetComponent");
35317
35325
  viewer.executeCommand("setActiveDragger");
35318
35326
  viewer.executeCommand("clearSlices");
35319
35327
  viewer.executeCommand("clearOverlay");
@@ -35322,7 +35330,6 @@ void main() {
35322
35330
  viewer.executeCommand("showAll");
35323
35331
  viewer.executeCommand("explode", 0);
35324
35332
  viewer.executeCommand("zoomToExtents", true);
35325
- reset.resetCameraPosition();
35326
35333
  viewer.emit({ type: "resetview" });
35327
35334
  }
35328
35335
 
@@ -35515,15 +35522,15 @@ void main() {
35515
35522
  switchCamera(camera) {
35516
35523
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius * 2 || 1;
35517
35524
  const rendererSize = this.viewer.renderer.getSize(new Vector2());
35518
- const aspect = rendererSize.x / rendererSize.y;
35525
+ const aspectRatio = rendererSize.x / rendererSize.y;
35519
35526
  if (camera.isPerspectiveCamera) {
35520
- camera.aspect = aspect;
35527
+ camera.aspect = aspectRatio;
35521
35528
  camera.near = extentsSize / 1000;
35522
35529
  camera.far = extentsSize * 1000;
35523
35530
  }
35524
35531
  if (camera.isOrthographicCamera) {
35525
- camera.left = camera.bottom * aspect;
35526
- camera.right = camera.top * aspect;
35532
+ camera.left = camera.bottom * aspectRatio;
35533
+ camera.right = camera.top * aspectRatio;
35527
35534
  camera.near = 0;
35528
35535
  camera.far = extentsSize * 1000;
35529
35536
  }
@@ -35571,10 +35578,12 @@ void main() {
35571
35578
 
35572
35579
  class ExtentsComponent {
35573
35580
  constructor(viewer) {
35574
- this.syncExtents = () => {
35581
+ this.syncExtents = (event) => {
35575
35582
  const extents = new Box3();
35576
35583
  this.viewer.models.forEach((model) => model.getExtents(extents));
35577
35584
  this.viewer.extents.copy(extents);
35585
+ if (event.type !== "databasechunk" && event.target !== "clear")
35586
+ return;
35578
35587
  if (this.viewer.models.length > 1)
35579
35588
  return;
35580
35589
  this.viewer.extents.getCenter(this.viewer.target);
@@ -36580,12 +36589,12 @@ void main() {
36580
36589
  const { edgesVisibility } = this.viewer.options;
36581
36590
  if (!Array.isArray(objects))
36582
36591
  objects = [objects];
36583
- if (!objects.length)
36592
+ if (objects.length === 0)
36584
36593
  return;
36585
36594
  objects
36586
36595
  .filter((object) => !object.userData.isEdge)
36587
36596
  .forEach((object) => {
36588
- if (object.isHighlighted)
36597
+ if (object.userData.isHighlighted)
36589
36598
  return;
36590
36599
  if (object.isLine || object.isLineSegments) {
36591
36600
  const positions = object.geometry.attributes.position.array;
@@ -36594,43 +36603,39 @@ void main() {
36594
36603
  ? HighlighterUtils.fromIndexedLine(positions, indices)
36595
36604
  : HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
36596
36605
  const wireframe = new Wireframe(lineGeometry, this.lineGlowMaterial);
36597
- wireframe.position.copy(object.position);
36598
- wireframe.rotation.copy(object.rotation);
36599
- wireframe.scale.copy(object.scale);
36600
36606
  wireframe.visible = edgesVisibility;
36601
- object.parent.add(wireframe);
36607
+ wireframe.userData.isHighlightWireframe = true;
36608
+ object.add(wireframe);
36602
36609
  object.userData.highlightWireframe = wireframe;
36603
36610
  object.userData.originalMaterial = object.material;
36604
36611
  object.material = this.lineMaterial;
36605
- object.isHighlighted = true;
36612
+ object.userData.isHighlighted = true;
36606
36613
  }
36607
36614
  else if (object.isMesh) {
36608
36615
  const edgesGeometry = new EdgesGeometry(object.geometry, 89);
36609
36616
  const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
36610
36617
  const wireframe = new Wireframe(lineGeometry, this.edgesMaterial);
36611
- wireframe.position.copy(object.position);
36612
- wireframe.rotation.copy(object.rotation);
36613
- wireframe.scale.copy(object.scale);
36614
36618
  wireframe.visible = edgesVisibility;
36615
- object.parent.add(wireframe);
36619
+ wireframe.userData.isHighlightWireframe = true;
36620
+ object.add(wireframe);
36616
36621
  object.userData.highlightWireframe = wireframe;
36617
36622
  object.userData.originalMaterial = object.material;
36618
36623
  object.material = this.facesMaterial;
36619
- object.isHighlighted = true;
36624
+ object.userData.isHighlighted = true;
36620
36625
  }
36621
36626
  });
36622
36627
  }
36623
36628
  unhighlight(objects) {
36624
36629
  if (!Array.isArray(objects))
36625
36630
  objects = [objects];
36626
- if (!objects.length)
36631
+ if (objects.length === 0)
36627
36632
  return;
36628
36633
  objects.forEach((object) => {
36629
- if (!object.isHighlighted)
36634
+ if (!object.userData.isHighlighted)
36630
36635
  return;
36631
- object.isHighlighted = false;
36632
36636
  object.material = object.userData.originalMaterial;
36633
36637
  object.userData.highlightWireframe.removeFromParent();
36638
+ delete object.userData.isHighlighted;
36634
36639
  delete object.userData.originalMaterial;
36635
36640
  delete object.userData.highlightWireframe;
36636
36641
  });
@@ -36678,6 +36683,7 @@ void main() {
36678
36683
  if (upPosition.distanceTo(this.downPosition) !== 0)
36679
36684
  return;
36680
36685
  const snapper = new Snapper(this.viewer.camera, this.viewer.renderer, this.viewer.canvas);
36686
+ snapper.threshold = this.viewer.extents.getSize(new Vector3()).length() / 10000;
36681
36687
  let intersections = [];
36682
36688
  this.viewer.models.forEach((model) => {
36683
36689
  const objects = model.getVisibleObjects();
@@ -36732,12 +36738,12 @@ void main() {
36732
36738
  }
36733
36739
  if (!Array.isArray(objects))
36734
36740
  objects = [objects];
36735
- if (!objects.length)
36741
+ if (objects.length === 0)
36736
36742
  return;
36737
- model.showOriginalObjects(objects);
36743
+ model.highlightObjects(objects);
36738
36744
  this.highlighter.highlight(objects);
36739
36745
  objects.forEach((object) => this.viewer.selected.push(object));
36740
- objects.forEach((object) => (object.isSelected = true));
36746
+ objects.forEach((object) => (object.userData.isSelected = true));
36741
36747
  }
36742
36748
  deselect(objects, model) {
36743
36749
  if (!model) {
@@ -36746,29 +36752,29 @@ void main() {
36746
36752
  }
36747
36753
  if (!Array.isArray(objects))
36748
36754
  objects = [objects];
36749
- if (!objects.length)
36755
+ if (objects.length === 0)
36750
36756
  return;
36757
+ model.unhighlightObjects(objects);
36751
36758
  this.highlighter.unhighlight(objects);
36752
- model.hideOriginalObjects(objects);
36753
36759
  this.viewer.selected = this.viewer.selected.filter((x) => !objects.includes(x));
36754
- objects.forEach((object) => (object.isSelected = false));
36760
+ objects.forEach((object) => (object.userData.isSelected = false));
36755
36761
  }
36756
36762
  toggleSelection(objects, model) {
36757
36763
  if (!Array.isArray(objects))
36758
36764
  objects = [objects];
36759
- if (!objects.length)
36765
+ if (objects.length === 0)
36760
36766
  return;
36761
- if (objects[0].isSelected)
36767
+ if (objects[0].userData.isSelected)
36762
36768
  this.deselect(objects, model);
36763
36769
  else
36764
36770
  this.select(objects, model);
36765
36771
  }
36766
36772
  clearSelection() {
36767
- if (!this.viewer.selected.length)
36773
+ if (this.viewer.selected.length === 0)
36768
36774
  return;
36775
+ this.viewer.models.forEach((model) => model.unhighlightObjects(this.viewer.selected));
36769
36776
  this.highlighter.unhighlight(this.viewer.selected);
36770
- this.viewer.models.forEach((model) => model.hideOriginalObjects(this.viewer.selected));
36771
- this.viewer.selected.forEach((object) => (object.isSelected = false));
36777
+ this.viewer.selected.forEach((object) => (object.userData.isSelected = false));
36772
36778
  this.viewer.selected.length = 0;
36773
36779
  }
36774
36780
  }
@@ -36896,19 +36902,22 @@ void main() {
36896
36902
  direction: this.viewer.camera.getWorldDirection(new Vector3()),
36897
36903
  };
36898
36904
  };
36905
+ this.resetCameraPosition = () => {
36906
+ if (this.savedCameraPosition) {
36907
+ this.viewer.camera.position.copy(this.savedCameraPosition.position);
36908
+ this.viewer.camera.up.copy(this.savedCameraPosition.up);
36909
+ this.viewer.camera.lookAt(this.savedCameraPosition.position.clone().add(this.savedCameraPosition.direction));
36910
+ this.viewer.camera.updateProjectionMatrix();
36911
+ }
36912
+ };
36899
36913
  this.viewer = viewer;
36900
36914
  this.viewer.addEventListener("databasechunk", this.onDatabaseChunk);
36915
+ this.viewer.on("resetview", this.resetCameraPosition);
36901
36916
  }
36902
36917
  dispose() {
36918
+ this.viewer.off("resetview", this.resetCameraPosition);
36903
36919
  this.viewer.removeEventListener("databasechunk", this.onDatabaseChunk);
36904
36920
  }
36905
- resetCameraPosition() {
36906
- if (this.savedCameraPosition) {
36907
- this.viewer.camera.position.copy(this.savedCameraPosition.position);
36908
- this.viewer.camera.up.copy(this.savedCameraPosition.up);
36909
- this.viewer.camera.lookAt(this.savedCameraPosition.position.clone().add(this.savedCameraPosition.direction));
36910
- }
36911
- }
36912
36921
  }
36913
36922
 
36914
36923
  const components = componentsRegistry("threejs");
@@ -36927,6 +36936,20 @@ void main() {
36927
36936
  class ModelImpl {
36928
36937
  constructor(scene) {
36929
36938
  this.scene = scene;
36939
+ this.handleToObjects = new Map();
36940
+ this.originalObjects = new Set();
36941
+ this.scene.traverse((object) => {
36942
+ this.originalObjects.add(object);
36943
+ const handle = object.userData.handle;
36944
+ if (!handle)
36945
+ return;
36946
+ let objects = this.handleToObjects.get(handle);
36947
+ if (!objects) {
36948
+ objects = new Set();
36949
+ this.handleToObjects.set(handle, objects);
36950
+ }
36951
+ objects.add(object);
36952
+ });
36930
36953
  }
36931
36954
  dispose() {
36932
36955
  function disposeMaterial(material) {
@@ -36942,6 +36965,8 @@ void main() {
36942
36965
  if (object.material)
36943
36966
  disposeMaterials(object.material);
36944
36967
  }
36968
+ this.handleToObjects = undefined;
36969
+ this.originalObjects = undefined;
36945
36970
  this.scene.traverse(disposeObject);
36946
36971
  this.scene.clear();
36947
36972
  }
@@ -37084,67 +37109,56 @@ void main() {
37084
37109
  return info;
37085
37110
  }
37086
37111
  getExtents(target) {
37087
- this.scene.traverseVisible((object) => !object.children.length && target.expandByObject(object));
37112
+ this.scene.traverseVisible((object) => target.expandByObject(object));
37088
37113
  return target;
37089
37114
  }
37090
37115
  getObjects() {
37091
- const objects = [];
37092
- this.scene.traverse((object) => objects.push(object));
37093
- return objects;
37116
+ return Array.from(this.originalObjects);
37094
37117
  }
37095
37118
  getVisibleObjects() {
37096
37119
  const objects = [];
37097
37120
  this.scene.traverseVisible((object) => objects.push(object));
37098
- return objects;
37099
- }
37100
- hasObject(object) {
37101
- while (object) {
37102
- if (object === this.scene)
37103
- return true;
37104
- object = object.parent;
37105
- }
37106
- return false;
37107
- }
37108
- hasHandle(handle) {
37109
- return !handle.includes(":") || handle.split(":", 1)[0] === this.id + "";
37121
+ return objects.filter((object) => object.userData.handle);
37110
37122
  }
37111
- getOwnObjects(objects) {
37112
- if (!Array.isArray(objects))
37113
- objects = [objects];
37114
- return objects.filter((object) => this.hasObject(object));
37115
- }
37116
- getOwnHandles(handles) {
37123
+ getObjectsByHandles(handles) {
37117
37124
  if (!Array.isArray(handles))
37118
37125
  handles = [handles];
37119
- return handles.filter((handle) => this.hasHandle(handle));
37120
- }
37121
- getObjectsByHandles(handles) {
37122
- const ownHandles = this.getOwnHandles(handles);
37123
- if (ownHandles.length === 0)
37124
- return [];
37125
- const handleSet = new Set(ownHandles.map((handle) => handle.slice(handle.indexOf(":") + 1)));
37126
+ const ownHandles = [];
37127
+ handles.forEach((handle) => {
37128
+ const index = handle.indexOf(":");
37129
+ if (index !== -1) {
37130
+ if (handle.slice(0, index) !== this.id)
37131
+ return;
37132
+ handle = handle.slice(index + 1);
37133
+ }
37134
+ ownHandles.push(handle);
37135
+ });
37136
+ const handlesSet = new Set(ownHandles);
37126
37137
  const objects = [];
37127
- this.scene.traverse((object) => {
37128
- const handle = object.userData.handle;
37129
- if (handle && handleSet.has(handle))
37130
- objects.push(object);
37138
+ handlesSet.forEach((handle) => {
37139
+ objects.push(Array.from(this.handleToObjects.get(handle) || []));
37131
37140
  });
37132
- return objects;
37141
+ return objects.flat();
37133
37142
  }
37134
37143
  getHandlesByObjects(objects) {
37135
- const ownObjects = this.getOwnObjects(objects);
37136
- if (ownObjects.length === 0)
37137
- return [];
37144
+ if (!Array.isArray(objects))
37145
+ objects = [objects];
37138
37146
  const handleSet = new Set();
37139
- ownObjects.forEach((object) => {
37140
- const handle = object.userData.handle;
37141
- if (handle)
37142
- handleSet.add(`${this.id}:${handle}`);
37147
+ objects
37148
+ .filter((object) => this.originalObjects.has(object))
37149
+ .forEach((object) => {
37150
+ handleSet.add(`${this.id}:${object.userData.handle}`);
37143
37151
  });
37144
37152
  return Array.from(handleSet);
37145
37153
  }
37146
37154
  hideObjects(objects) {
37147
- this.getOwnObjects(objects).forEach((object) => (object.visible = false));
37155
+ if (!Array.isArray(objects))
37156
+ objects = [objects];
37157
+ objects
37158
+ .filter((object) => this.originalObjects.has(object))
37159
+ .forEach((object) => {
37160
+ object.visible = false;
37161
+ });
37148
37162
  return this;
37149
37163
  }
37150
37164
  hideAllObjects() {
@@ -37154,12 +37168,20 @@ void main() {
37154
37168
  if (!Array.isArray(objects))
37155
37169
  objects = [objects];
37156
37170
  const visibleSet = new Set(objects);
37157
- this.getOwnObjects(objects).forEach((object) => object.traverseAncestors((parent) => visibleSet.add(parent)));
37171
+ objects
37172
+ .filter((object) => this.originalObjects.has(object))
37173
+ .forEach((object) => {
37174
+ object.traverseAncestors((parent) => visibleSet.add(parent));
37175
+ });
37158
37176
  this.scene.traverse((object) => (object.visible = visibleSet.has(object)));
37159
37177
  return this;
37160
37178
  }
37161
37179
  showObjects(objects) {
37162
- this.getOwnObjects(objects).forEach((object) => {
37180
+ if (!Array.isArray(objects))
37181
+ objects = [objects];
37182
+ objects
37183
+ .filter((object) => this.originalObjects.has(object))
37184
+ .forEach((object) => {
37163
37185
  object.visible = true;
37164
37186
  object.traverseAncestors((parent) => (parent.visible = true));
37165
37187
  });
@@ -37169,36 +37191,55 @@ void main() {
37169
37191
  this.scene.traverse((object) => (object.visible = true));
37170
37192
  return this;
37171
37193
  }
37172
- showOriginalObjects(objects) {
37194
+ highlightObjects(objects) {
37173
37195
  return this;
37174
37196
  }
37175
- hideOriginalObjects(objects) {
37197
+ unhighlightObjects(objects) {
37176
37198
  return this;
37177
37199
  }
37178
37200
  explode(scale = 0, coeff = 4) {
37201
+ const centers = new Map();
37202
+ const getObjectCenter = (object, target) => {
37203
+ const extents = new Box3().setFromObject(object);
37204
+ const handle = object.userData.handle;
37205
+ if (!handle)
37206
+ return extents.getCenter(target);
37207
+ const center = centers.get(handle);
37208
+ if (center)
37209
+ return target.copy(center);
37210
+ const objects = this.getObjectsByHandles(handle);
37211
+ objects.forEach((x) => extents.expandByObject(x));
37212
+ extents.getCenter(target);
37213
+ centers.set(handle, target.clone());
37214
+ return target;
37215
+ };
37179
37216
  function calcExplodeDepth(object, depth) {
37180
- let res = depth;
37217
+ let result = depth;
37181
37218
  object.children.forEach((x) => {
37182
37219
  const objectDepth = calcExplodeDepth(x, depth + 1);
37183
- if (res < objectDepth)
37184
- res = objectDepth;
37220
+ if (result < objectDepth)
37221
+ result = objectDepth;
37185
37222
  });
37186
37223
  object.userData.originalPosition = object.position.clone();
37187
- object.userData.originalCenter = new Box3().setFromObject(object).getCenter(new Vector3());
37188
- object.userData.isExplodeLocked = depth > 2 && object.children.length === 0;
37189
- return res;
37190
- }
37191
- scale /= 100;
37192
- if (!this.scene.userData.explodeDepth)
37193
- this.scene.userData.explodeDepth = calcExplodeDepth(this.scene, 1);
37194
- const maxDepth = this.scene.userData.explodeDepth;
37195
- const scaledExplodeDepth = scale * maxDepth + 1;
37224
+ object.userData.originalCenter = getObjectCenter(object, new Vector3());
37225
+ return result;
37226
+ }
37227
+ const explodeScale = scale / 100;
37228
+ const explodeRoot = this.scene;
37229
+ if (!explodeRoot.userData.explodeDepth)
37230
+ explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
37231
+ const maxDepth = explodeRoot.userData.explodeDepth;
37232
+ const scaledExplodeDepth = explodeScale * maxDepth + 1;
37196
37233
  const explodeDepth = 0 | scaledExplodeDepth;
37197
37234
  const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
37198
37235
  function explodeObject(object, depth) {
37236
+ if (object.isCamera)
37237
+ return;
37238
+ if (object.userData.isHighlightWireframe)
37239
+ return;
37199
37240
  object.position.copy(object.userData.originalPosition);
37200
- if (depth > 0 && depth <= explodeDepth && !object.userData.isExplodeLocked) {
37201
- let objectScale = scale * coeff;
37241
+ if (depth > 0 && depth <= explodeDepth) {
37242
+ let objectScale = explodeScale * coeff;
37202
37243
  if (depth === explodeDepth)
37203
37244
  objectScale *= currentSegmentFraction;
37204
37245
  const parentCenter = object.parent.userData.originalCenter;
@@ -37208,7 +37249,7 @@ void main() {
37208
37249
  }
37209
37250
  object.children.forEach((x) => explodeObject(x, depth + 1));
37210
37251
  }
37211
- explodeObject(this.scene, 0);
37252
+ explodeObject(explodeRoot, 0);
37212
37253
  this.scene.updateMatrixWorld();
37213
37254
  return this;
37214
37255
  }
@@ -37246,29 +37287,24 @@ void main() {
37246
37287
  getVisibleObjects() {
37247
37288
  return this.gltfLoader.getOriginalObjectForSelect();
37248
37289
  }
37249
- hasObject(object) {
37250
- return this.gltfLoader.originalObjects.has(object);
37251
- }
37252
37290
  getObjectsByHandles(handles) {
37253
- const ownHandles = this.getOwnHandles(handles);
37254
- if (ownHandles.length === 0)
37255
- return [];
37256
- const handlesSet = new Set(ownHandles);
37291
+ if (!Array.isArray(handles))
37292
+ handles = [handles];
37293
+ const handlesSet = new Set(handles);
37257
37294
  const objects = [];
37258
37295
  handlesSet.forEach((handle) => {
37259
- objects.push(...this.gltfLoader.getObjectsByHandle(handle));
37296
+ objects.push(this.gltfLoader.getObjectsByHandle(handle));
37260
37297
  });
37261
- return objects;
37298
+ return objects.flat();
37262
37299
  }
37263
37300
  getHandlesByObjects(objects) {
37264
- const ownObjects = this.getOwnObjects(objects);
37265
- if (ownObjects.length === 0)
37266
- return [];
37301
+ if (!Array.isArray(objects))
37302
+ objects = [objects];
37267
37303
  const handleSet = new Set();
37268
- ownObjects.forEach((object) => {
37269
- const handle = object.userData.handle;
37270
- if (handle)
37271
- handleSet.add(handle);
37304
+ objects
37305
+ .filter((object) => this.gltfLoader.originalObjects.has(object))
37306
+ .forEach((object) => {
37307
+ handleSet.add(object.userData.handle);
37272
37308
  });
37273
37309
  return Array.from(handleSet);
37274
37310
  }
@@ -37291,14 +37327,78 @@ void main() {
37291
37327
  this.gltfLoader.showAllHiddenObjects();
37292
37328
  return this;
37293
37329
  }
37294
- showOriginalObjects(objects) {
37330
+ highlightObjects(objects) {
37295
37331
  this.gltfLoader.showOriginalObjects(objects);
37296
37332
  return this;
37297
37333
  }
37298
- hideOriginalObjects(objects) {
37334
+ unhighlightObjects(objects) {
37299
37335
  this.gltfLoader.hideOriginalObjects(objects);
37300
37336
  return this;
37301
37337
  }
37338
+ explode(scale = 0, coeff = 4) {
37339
+ const centers = new Map();
37340
+ const calcObjectCenter = (object, target) => {
37341
+ const extents = new Box3().setFromObject(object);
37342
+ const handle = object.userData.handle;
37343
+ if (!handle)
37344
+ return extents.getCenter(target);
37345
+ const center = centers.get(handle);
37346
+ if (center)
37347
+ return target.copy(center);
37348
+ const objects = this.getObjectsByHandles(handle);
37349
+ objects.forEach((x) => extents.expandByObject(x));
37350
+ extents.getCenter(target);
37351
+ centers.set(handle, target.clone());
37352
+ return target;
37353
+ };
37354
+ function calcExplodeDepth(object, depth) {
37355
+ let result = depth;
37356
+ object.children
37357
+ .filter((x) => !x.userData.isOptimized)
37358
+ .forEach((x) => {
37359
+ const objectDepth = calcExplodeDepth(x, depth + 1);
37360
+ if (result < objectDepth)
37361
+ result = objectDepth;
37362
+ });
37363
+ object.userData.originalPosition = object.position.clone();
37364
+ object.userData.originalCenter = calcObjectCenter(object, new Vector3());
37365
+ return result;
37366
+ }
37367
+ const explodeScale = scale / 100;
37368
+ const explodeRoot = this.scene.children[0];
37369
+ if (!explodeRoot.userData.explodeDepth)
37370
+ explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
37371
+ const maxDepth = explodeRoot.userData.explodeDepth;
37372
+ const scaledExplodeDepth = explodeScale * maxDepth + 1;
37373
+ const explodeDepth = 0 | scaledExplodeDepth;
37374
+ const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
37375
+ const transformMap = new Map();
37376
+ function explodeObject(object, depth) {
37377
+ if (object.isCamera)
37378
+ return;
37379
+ if (object.userData.isHighlightWireframe)
37380
+ return;
37381
+ object.position.copy(object.userData.originalPosition);
37382
+ if (depth > 0 && depth <= explodeDepth && !object.userData.isExplodeLocked) {
37383
+ let objectScale = explodeScale * coeff;
37384
+ if (depth === explodeDepth)
37385
+ objectScale *= currentSegmentFraction;
37386
+ const parentCenter = object.parent.userData.originalCenter;
37387
+ const objectCenter = object.userData.originalCenter;
37388
+ const objectOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
37389
+ object.position.add(objectOffset);
37390
+ const matrix = new Matrix4().makeTranslation(objectOffset.x, objectOffset.y, objectOffset.z);
37391
+ transformMap.set(object, matrix);
37392
+ }
37393
+ object.children
37394
+ .filter((x) => !x.userData.isOptimized)
37395
+ .forEach((x) => explodeObject(x, depth + 1));
37396
+ }
37397
+ explodeObject(explodeRoot, 0);
37398
+ this.scene.updateMatrixWorld();
37399
+ this.gltfLoader.applyObjectTransforms(transformMap);
37400
+ return this;
37401
+ }
37302
37402
  }
37303
37403
 
37304
37404
  const GL_COMPONENT_TYPES = {
@@ -37347,7 +37447,7 @@ void main() {
37347
37447
  this.textureCache = new Map();
37348
37448
  this.materialCache = new Map();
37349
37449
  this.uri = "";
37350
- this._nextObjectId = 0;
37450
+ this._nextObjectId = 1;
37351
37451
  this.loadingAborted = false;
37352
37452
  this.criticalError = null;
37353
37453
  }
@@ -38015,6 +38115,8 @@ void main() {
38015
38115
  this.hiddenHandles = new Set();
38016
38116
  this.newOptimizedObjects = new Set();
38017
38117
  this.oldOptimizeObjects = new Set();
38118
+ this.objectTransforms = new Map();
38119
+ this.transformedGeometries = new Map();
38018
38120
  this.activeChunkLoads = 0;
38019
38121
  this.chunkQueue = [];
38020
38122
  this.objectIdToIndex = new Map();
@@ -38776,14 +38878,32 @@ void main() {
38776
38878
  if (!node.geometryExtents) continue;
38777
38879
  if (node.object && this.hiddenHandles.has(node.object.userData.handle)) continue;
38778
38880
  const transformedBox = node.geometryExtents.clone();
38779
- if (node.group && node.group.matrix) {
38780
- transformedBox.applyMatrix4(node.group.matrix);
38781
- if (node.group.parent && node.group.parent.matrix) {
38782
- transformedBox.applyMatrix4(node.group.parent.matrix);
38881
+ const structureRoot = node.structure ? this.structureRoots.get(node.structure.id) : null;
38882
+ if (node.group) {
38883
+ const matrices = [];
38884
+ let currentGroup = node.group;
38885
+ while (currentGroup && currentGroup !== structureRoot) {
38886
+ if (currentGroup.matrix && currentGroup.matrixAutoUpdate === false) {
38887
+ matrices.unshift(currentGroup.matrix);
38888
+ }
38889
+ currentGroup = currentGroup.parent;
38783
38890
  }
38891
+ for (const matrix of matrices) {
38892
+ transformedBox.applyMatrix4(matrix);
38893
+ }
38894
+ }
38895
+ if (structureRoot && structureRoot.matrix) {
38896
+ transformedBox.applyMatrix4(structureRoot.matrix);
38897
+ }
38898
+ const transform = this.objectTransforms.get(node.object);
38899
+ if (transform) {
38900
+ transformedBox.applyMatrix4(transform);
38784
38901
  }
38785
38902
  totalExtent.union(transformedBox);
38786
38903
  }
38904
+ if (this.scene && this.scene.matrix && !totalExtent.isEmpty()) {
38905
+ totalExtent.applyMatrix4(this.scene.matrix);
38906
+ }
38787
38907
  return totalExtent;
38788
38908
  }
38789
38909
  loadCamera(structure, cameraIndex, nodeDef) {
@@ -38859,7 +38979,6 @@ void main() {
38859
38979
  for (let i = 0; i < this.maxObjectId; i++) {
38860
38980
  this.objectVisibility[i] = 1.0;
38861
38981
  }
38862
- console.log(`Initialized object visibility array: ${this.maxObjectId} objects`);
38863
38982
  }
38864
38983
  }
38865
38984
  createVisibilityMaterial(material) {
@@ -38996,6 +39115,8 @@ void main() {
38996
39115
  this.newOptimizedObjects.clear();
38997
39116
  this.oldOptimizeObjects.clear();
38998
39117
  this.isolatedObjects = [];
39118
+ this.objectTransforms.clear();
39119
+ this.transformedGeometries.clear();
38999
39120
  this.totalLoadedObjects = 0;
39000
39121
  this.lastUpdateTime = 0;
39001
39122
  this.currentMemoryUsage = 0;
@@ -39693,6 +39814,171 @@ void main() {
39693
39814
  mergedObject.geometry.attributes.visibility.needsUpdate = true;
39694
39815
  }
39695
39816
  }
39817
+ applyObjectTransforms(objectTransformMap) {
39818
+ if (this.mergedObjectMap.size === 0) {
39819
+ console.warn("No merged objects to transform");
39820
+ return;
39821
+ }
39822
+ this.objectTransforms = new Map(objectTransformMap);
39823
+ for (const mesh of this.mergedMesh) {
39824
+ this._applyTransformToMergedObject(mesh);
39825
+ }
39826
+ for (const line of this.mergedLines) {
39827
+ this._applyTransformToMergedObject(line);
39828
+ }
39829
+ for (const lineSegment of this.mergedLineSegments) {
39830
+ this._applyTransformToMergedObject(lineSegment);
39831
+ }
39832
+ for (const point of this.mergedPoints) {
39833
+ this._applyTransformToMergedObject(point);
39834
+ }
39835
+ }
39836
+ createExplodeTransforms(objects = null, explodeCenter = null, explodeFactor = 1.5) {
39837
+ const transformMap = new Map();
39838
+ if (!explodeCenter) {
39839
+ explodeCenter = new Vector3();
39840
+ const extent = this.getTotalGeometryExtent();
39841
+ if (!extent.isEmpty()) {
39842
+ extent.getCenter(explodeCenter);
39843
+ }
39844
+ }
39845
+ const objectsArray = objects
39846
+ ? Array.isArray(objects)
39847
+ ? objects
39848
+ : Array.from(objects)
39849
+ : Array.from(this.originalObjects);
39850
+ for (const obj of objectsArray) {
39851
+ if (!obj.geometry || !obj.geometry.attributes.position) continue;
39852
+ const boundingBox = new Box3().setFromBufferAttribute(obj.geometry.attributes.position);
39853
+ if (obj.matrixWorld) {
39854
+ boundingBox.applyMatrix4(obj.matrixWorld);
39855
+ }
39856
+ if (boundingBox.isEmpty()) continue;
39857
+ const objectCenter = new Vector3();
39858
+ boundingBox.getCenter(objectCenter);
39859
+ const direction = objectCenter.clone().sub(explodeCenter);
39860
+ const distance = direction.length();
39861
+ if (distance > 0) {
39862
+ direction.normalize();
39863
+ const offset = direction.multiplyScalar(distance * (explodeFactor - 1.0));
39864
+ const matrix = new Matrix4().makeTranslation(offset.x, offset.y, offset.z);
39865
+ transformMap.set(obj, matrix);
39866
+ }
39867
+ }
39868
+ return transformMap;
39869
+ }
39870
+ clearTransforms() {
39871
+ this.objectTransforms.clear();
39872
+ for (const mesh of this.mergedMesh) {
39873
+ this._restoreOriginalGeometry(mesh);
39874
+ }
39875
+ for (const line of this.mergedLines) {
39876
+ this._restoreOriginalGeometry(line);
39877
+ }
39878
+ for (const lineSegment of this.mergedLineSegments) {
39879
+ this._restoreOriginalGeometry(lineSegment);
39880
+ }
39881
+ for (const point of this.mergedPoints) {
39882
+ this._restoreOriginalGeometry(point);
39883
+ }
39884
+ }
39885
+ clearHandleTransforms() {
39886
+ this.clearTransforms();
39887
+ }
39888
+ _applyTransformToMergedObject(mergedObject) {
39889
+ const objectData = this.mergedObjectMap.get(mergedObject.uuid);
39890
+ if (!objectData || !objectData.objectMapping) return;
39891
+ const geometry = mergedObject.geometry;
39892
+ if (!geometry || !geometry.attributes.position) return;
39893
+ const positionAttr = geometry.attributes.position;
39894
+ const positions = positionAttr.array;
39895
+ if (!this.transformedGeometries.has(mergedObject.uuid)) {
39896
+ this.transformedGeometries.set(mergedObject.uuid, new Float32Array(positions));
39897
+ }
39898
+ const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
39899
+ const tempVector = new Vector3();
39900
+ for (const [originalMesh, mappingData] of objectData.objectMapping) {
39901
+ const transform = this.objectTransforms.get(originalMesh);
39902
+ if (!transform) {
39903
+ const startIdx = mappingData.startVertexIndex * 3;
39904
+ const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
39905
+ for (let i = startIdx; i < endIdx; i++) {
39906
+ positions[i] = originalPositions[i];
39907
+ }
39908
+ continue;
39909
+ }
39910
+ const startVertex = mappingData.startVertexIndex;
39911
+ const vertexCount = mappingData.vertexCount;
39912
+ for (let i = 0; i < vertexCount; i++) {
39913
+ const idx = (startVertex + i) * 3;
39914
+ tempVector.set(originalPositions[idx], originalPositions[idx + 1], originalPositions[idx + 2]);
39915
+ tempVector.applyMatrix4(transform);
39916
+ positions[idx] = tempVector.x;
39917
+ positions[idx + 1] = tempVector.y;
39918
+ positions[idx + 2] = tempVector.z;
39919
+ }
39920
+ }
39921
+ if (geometry.attributes.normal) {
39922
+ this._updateNormalsForTransform(geometry, objectData, originalPositions);
39923
+ }
39924
+ positionAttr.needsUpdate = true;
39925
+ geometry.computeBoundingSphere();
39926
+ geometry.computeBoundingBox();
39927
+ }
39928
+ _updateNormalsForTransform(geometry, objectData, originalPositions) {
39929
+ const normalAttr = geometry.attributes.normal;
39930
+ if (!normalAttr) return;
39931
+ const normals = normalAttr.array;
39932
+ const tempVector = new Vector3();
39933
+ const normalMatrix = new Matrix4();
39934
+ const normalsKey = `${geometry.uuid}_normals`;
39935
+ if (!this.transformedGeometries.has(normalsKey)) {
39936
+ this.transformedGeometries.set(normalsKey, new Float32Array(normals));
39937
+ }
39938
+ const originalNormals = this.transformedGeometries.get(normalsKey);
39939
+ for (const [originalMesh, mappingData] of objectData.objectMapping) {
39940
+ const transform = this.objectTransforms.get(originalMesh);
39941
+ if (!transform) {
39942
+ const startIdx = mappingData.startVertexIndex * 3;
39943
+ const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
39944
+ for (let i = startIdx; i < endIdx; i++) {
39945
+ normals[i] = originalNormals[i];
39946
+ }
39947
+ continue;
39948
+ }
39949
+ normalMatrix.copy(transform).invert().transpose();
39950
+ const startVertex = mappingData.startVertexIndex;
39951
+ const vertexCount = mappingData.vertexCount;
39952
+ for (let i = 0; i < vertexCount; i++) {
39953
+ const idx = (startVertex + i) * 3;
39954
+ tempVector.set(originalNormals[idx], originalNormals[idx + 1], originalNormals[idx + 2]);
39955
+ tempVector.applyMatrix4(normalMatrix).normalize();
39956
+ normals[idx] = tempVector.x;
39957
+ normals[idx + 1] = tempVector.y;
39958
+ normals[idx + 2] = tempVector.z;
39959
+ }
39960
+ }
39961
+ normalAttr.needsUpdate = true;
39962
+ }
39963
+ _restoreOriginalGeometry(mergedObject) {
39964
+ const geometry = mergedObject.geometry;
39965
+ if (!geometry || !geometry.attributes.position) return;
39966
+ const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
39967
+ if (originalPositions) {
39968
+ const positions = geometry.attributes.position.array;
39969
+ positions.set(originalPositions);
39970
+ geometry.attributes.position.needsUpdate = true;
39971
+ }
39972
+ const normalsKey = `${geometry.uuid}_normals`;
39973
+ const originalNormals = this.transformedGeometries.get(normalsKey);
39974
+ if (originalNormals && geometry.attributes.normal) {
39975
+ const normals = geometry.attributes.normal.array;
39976
+ normals.set(originalNormals);
39977
+ geometry.attributes.normal.needsUpdate = true;
39978
+ }
39979
+ geometry.computeBoundingSphere();
39980
+ geometry.computeBoundingBox();
39981
+ }
39696
39982
  syncHiddenObjects() {
39697
39983
  if (this.mergedObjectMap.size === 0) {
39698
39984
  console.log("No merged objects to sync");
@@ -39724,19 +40010,33 @@ void main() {
39724
40010
  }
39725
40011
  getStructureGeometryExtent(structureId) {
39726
40012
  const extent = new Box3();
40013
+ const structureRoot = this.structureRoots.get(structureId);
39727
40014
  for (const [nodeId, node] of this.nodes.entries()) {
39728
40015
  if (!node.geometryExtents) continue;
39729
40016
  if (!nodeId.startsWith(structureId + "_")) continue;
39730
40017
  if (node.object && this.hiddenHandles && this.hiddenHandles.has(node.object.userData.handle)) continue;
39731
40018
  const transformedBox = node.geometryExtents.clone();
39732
- if (node.group && node.group.matrix) {
39733
- transformedBox.applyMatrix4(node.group.matrix);
39734
- if (node.group.parent && node.group.parent.matrix) {
39735
- transformedBox.applyMatrix4(node.group.parent.matrix);
40019
+ if (node.group) {
40020
+ const matrices = [];
40021
+ let currentGroup = node.group;
40022
+ while (currentGroup && currentGroup !== structureRoot) {
40023
+ if (currentGroup.matrix && currentGroup.matrixAutoUpdate === false) {
40024
+ matrices.unshift(currentGroup.matrix);
40025
+ }
40026
+ currentGroup = currentGroup.parent;
39736
40027
  }
40028
+ for (const matrix of matrices) {
40029
+ transformedBox.applyMatrix4(matrix);
40030
+ }
40031
+ }
40032
+ if (structureRoot && structureRoot.matrix) {
40033
+ transformedBox.applyMatrix4(structureRoot.matrix);
39737
40034
  }
39738
40035
  extent.union(transformedBox);
39739
40036
  }
40037
+ if (this.scene && this.scene.matrix && !extent.isEmpty()) {
40038
+ extent.applyMatrix4(this.scene.matrix);
40039
+ }
39740
40040
  return extent;
39741
40041
  }
39742
40042
  setMaxConcurrentChunks(maxChunks) {
@@ -54402,7 +54702,7 @@ js: import "konva/skia-backend";
54402
54702
  }
54403
54703
  getViewpoint(viewpoint) {
54404
54704
  if (!viewpoint)
54405
- viewpoint = {};
54705
+ viewpoint = { custom_fields: {} };
54406
54706
  viewpoint.lines = this.getMarkupLines();
54407
54707
  viewpoint.texts = this.getMarkupTexts();
54408
54708
  viewpoint.arrows = this.getMarkupArrows();
@@ -54410,8 +54710,8 @@ js: import "konva/skia-backend";
54410
54710
  viewpoint.ellipses = this.getMarkupEllipses();
54411
54711
  viewpoint.images = this.getMarkupImages();
54412
54712
  viewpoint.rectangles = this.getMarkupRectangles();
54413
- viewpoint.custom_fields = { markup_color: this.getMarkupColor() };
54414
54713
  viewpoint.snapshot = { data: this.combineMarkupWithDrawing() };
54714
+ viewpoint.custom_fields.markup_color = this.getMarkupColor();
54415
54715
  return viewpoint;
54416
54716
  }
54417
54717
  enableEditMode(mode) {
@@ -55122,8 +55422,8 @@ js: import "konva/skia-backend";
55122
55422
  const rect = canvas.parentElement.getBoundingClientRect();
55123
55423
  const width = rect.width || 1;
55124
55424
  const height = rect.height || 1;
55125
- const aspect = width / height;
55126
- this.camera = new PerspectiveCamera(45, aspect, 0.001, 1000);
55425
+ const aspectRatio = width / height;
55426
+ this.camera = new PerspectiveCamera(45, aspectRatio, 0.001, 1000);
55127
55427
  this.camera.up.set(0, 1, 0);
55128
55428
  this.camera.position.set(0, 0, 1);
55129
55429
  this.camera.lookAt(this.target);
@@ -55220,14 +55520,14 @@ js: import "konva/skia-backend";
55220
55520
  if (!this.renderer)
55221
55521
  return;
55222
55522
  const camera = this.camera;
55223
- const aspect = width / height;
55523
+ const aspectRatio = width / height;
55224
55524
  if (camera.isPerspectiveCamera) {
55225
- camera.aspect = aspect;
55525
+ camera.aspect = aspectRatio;
55226
55526
  camera.updateProjectionMatrix();
55227
55527
  }
55228
55528
  if (camera.isOrthographicCamera) {
55229
- camera.left = camera.bottom * aspect;
55230
- camera.right = camera.top * aspect;
55529
+ camera.left = camera.bottom * aspectRatio;
55530
+ camera.right = camera.top * aspectRatio;
55231
55531
  camera.updateProjectionMatrix();
55232
55532
  }
55233
55533
  this.renderer.setSize(width, height, updateStyle);
@@ -55454,12 +55754,12 @@ js: import "konva/skia-backend";
55454
55754
  if (orthogonal_camera) {
55455
55755
  const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
55456
55756
  const rendererSize = this.renderer.getSize(new Vector2());
55457
- const aspect = rendererSize.x / rendererSize.y;
55757
+ const aspectRatio = rendererSize.x / rendererSize.y;
55458
55758
  const camera = new OrthographicCamera();
55459
55759
  camera.top = orthogonal_camera.field_height / 2;
55460
55760
  camera.bottom = -orthogonal_camera.field_height / 2;
55461
- camera.left = camera.bottom * aspect;
55462
- camera.right = camera.top * aspect;
55761
+ camera.left = camera.bottom * aspectRatio;
55762
+ camera.right = camera.top * aspectRatio;
55463
55763
  camera.near = 0;
55464
55764
  camera.far = extentsSize * 1000;
55465
55765
  camera.zoom = orthogonal_camera.view_to_world_scale;
@@ -55472,6 +55772,7 @@ js: import "konva/skia-backend";
55472
55772
  this.renderPass.camera = camera;
55473
55773
  this.helpersPass.camera = camera;
55474
55774
  this.ssaaRenderPass.camera = camera;
55775
+ this.options.cameraMode = "orthographic";
55475
55776
  this.emitEvent({ type: "changecameramode", mode: "orthographic" });
55476
55777
  }
55477
55778
  };
@@ -55479,10 +55780,10 @@ js: import "konva/skia-backend";
55479
55780
  if (perspective_camera) {
55480
55781
  const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
55481
55782
  const rendererSize = this.renderer.getSize(new Vector2());
55482
- const aspect = rendererSize.x / rendererSize.y;
55783
+ const aspectRatio = rendererSize.x / rendererSize.y;
55483
55784
  const camera = new PerspectiveCamera();
55484
55785
  camera.fov = perspective_camera.field_of_view;
55485
- camera.aspect = aspect;
55786
+ camera.aspect = aspectRatio;
55486
55787
  camera.near = extentsSize / 1000;
55487
55788
  camera.far = extentsSize * 1000;
55488
55789
  camera.updateProjectionMatrix();
@@ -55494,6 +55795,7 @@ js: import "konva/skia-backend";
55494
55795
  this.renderPass.camera = camera;
55495
55796
  this.helpersPass.camera = camera;
55496
55797
  this.ssaaRenderPass.camera = camera;
55798
+ this.options.cameraMode = "perspective";
55497
55799
  this.emitEvent({ type: "changecameramode", mode: "perspective" });
55498
55800
  }
55499
55801
  };
@@ -55523,6 +55825,7 @@ js: import "konva/skia-backend";
55523
55825
  setSelection(((_b = viewpoint.custom_fields) === null || _b === void 0 ? void 0 : _b.selection2) || viewpoint.selection);
55524
55826
  this._markup.setViewpoint(viewpoint);
55525
55827
  this.target.copy(getVector3FromPoint3d((_d = (_c = viewpoint.custom_fields) === null || _c === void 0 ? void 0 : _c.camera_target) !== null && _d !== void 0 ? _d : this.target));
55828
+ this.syncOverlay();
55526
55829
  this.setActiveDragger(draggerName);
55527
55830
  this.emitEvent({ type: "drawviewpoint", data: viewpoint });
55528
55831
  this.update();