@inweb/viewer-three 26.12.6 → 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 (42) 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 +457 -155
  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 +455 -153
  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/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +3 -3
  21. package/lib/Viewer/measurement/Snapper.d.ts +1 -0
  22. package/lib/Viewer/measurement/UnitConverter.d.ts +20 -13
  23. package/lib/Viewer/models/IModelImpl.d.ts +2 -6
  24. package/lib/Viewer/models/ModelImpl.d.ts +4 -6
  25. package/package.json +5 -5
  26. package/src/Viewer/Viewer.ts +15 -11
  27. package/src/Viewer/commands/GetSelected2.ts +2 -2
  28. package/src/Viewer/commands/ZoomTo.ts +3 -3
  29. package/src/Viewer/components/CameraComponent.ts +4 -4
  30. package/src/Viewer/components/ExtentsComponent.ts +3 -3
  31. package/src/Viewer/components/HighlighterComponent.ts +11 -17
  32. package/src/Viewer/components/SelectionComponent.ts +14 -13
  33. package/src/Viewer/draggers/MeasureLineDragger.ts +1 -0
  34. package/src/Viewer/draggers/OrbitDragger.ts +2 -0
  35. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +285 -10
  36. package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +94 -18
  37. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +1 -1
  38. package/src/Viewer/measurement/Snapper.ts +6 -3
  39. package/src/Viewer/measurement/UnitConverter.ts +19 -12
  40. package/src/Viewer/measurement/UnitFormatter.ts +2 -2
  41. package/src/Viewer/models/IModelImpl.ts +2 -10
  42. package/src/Viewer/models/ModelImpl.ts +111 -61
@@ -805,6 +805,7 @@ class OrbitDragger {
805
805
  this.changed = false;
806
806
  this.viewer = viewer;
807
807
  this.viewer.addEventListener("databasechunk", this.updateControls);
808
+ this.viewer.addEventListener("clear", this.updateControls);
808
809
  this.viewer.on("viewposition", this.updateControls);
809
810
  this.viewer.addEventListener("zoom", this.updateControls);
810
811
  this.viewer.addEventListener("drawviewpoint", this.updateControls);
@@ -816,6 +817,7 @@ class OrbitDragger {
816
817
  initialize() { }
817
818
  dispose() {
818
819
  this.viewer.removeEventListener("databasechunk", this.updateControls);
820
+ this.viewer.removeEventListener("clear", this.updateControls);
819
821
  this.viewer.off("viewposition", this.updateControls);
820
822
  this.viewer.removeEventListener("zoom", this.updateControls);
821
823
  this.viewer.removeEventListener("drawviewpoint", this.updateControls);
@@ -913,20 +915,25 @@ class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
913
915
  }
914
916
  }
915
917
 
918
+ const DisplayUnits = {
919
+ Meters: { name: "Meters", symbol: "m", scale: 1.0 },
920
+ Centimeters: { name: "Centimeters", symbol: "cm", scale: 0.01 },
921
+ Millimeters: { name: "Millimeters", symbol: "mm", scale: 0.001 },
922
+ Feet: { name: "Feet", symbol: "ft", scale: 0.3048 },
923
+ Inches: { name: "Inches", symbol: "in", scale: 0.0254 },
924
+ Yards: { name: "Yards", symbol: "yd", scale: 0.9144 },
925
+ Kilometers: { name: "Kilometers", symbol: "km", scale: 1000.0 },
926
+ Miles: { name: "Miles", symbol: "mi", scale: 1609.344 },
927
+ Micrometers: { name: "Micrometers", symbol: "µm", scale: 0.000001 },
928
+ Mils: { name: "Mils", symbol: "mil", scale: 0.0000254 },
929
+ MicroInches: { name: "Micro-inches", symbol: "µin", scale: 0.0000000254 },
930
+ Default: { name: "File units", symbol: "", scale: 1.0 },
931
+ };
916
932
  const ModelUnits = {
917
- Meters: { name: "Meters", type: "m", scale: 1.0 },
918
- Centimeters: { name: "Centimeters", type: "cm", scale: 0.01 },
919
- Millimeters: { name: "Millimeters", type: "mm", scale: 0.001 },
920
- Feet: { name: "Feet", type: "ft", scale: 0.3048 },
921
- Inches: { name: "Inches", type: "in", scale: 0.0254 },
922
- Yards: { name: "Yards", type: "yd", scale: 0.9144 },
923
- Kilometers: { name: "Kilometers", type: "km", scale: 1000.0 },
924
- Miles: { name: "Miles", type: "mi", scale: 1609.344 },
925
- Micrometers: { name: "Micrometers", type: "µm", scale: 0.000001 },
926
- Mils: { name: "Mils", type: "mil", scale: 0.0000254 },
927
- MicroInches: { name: "Micro-inches", type: "µin", scale: 0.0000000254 },
928
- Default: { name: "File units", type: "unit", scale: 1.0 },
933
+ Default: { name: "", symbol: "", scale: 1.0 },
929
934
  };
935
+ Object.keys(DisplayUnits).forEach((key) => (ModelUnits[key] = DisplayUnits[key]));
936
+ Object.keys(DisplayUnits).forEach((key) => (ModelUnits[DisplayUnits[key].symbol] = DisplayUnits[key]));
930
937
  function convertUnits(fromUnits, toUnits, distance) {
931
938
  const fromFactor = 1 / (ModelUnits[fromUnits] || ModelUnits.Default).scale;
932
939
  const toFactor = (ModelUnits[toUnits] || ModelUnits.Default).scale || 1;
@@ -934,7 +941,7 @@ function convertUnits(fromUnits, toUnits, distance) {
934
941
  }
935
942
 
936
943
  function getDisplayUnit(units) {
937
- return (ModelUnits[units] || ModelUnits.Default).type;
944
+ return (ModelUnits[units] || ModelUnits.Default).symbol;
938
945
  }
939
946
  function calculatePrecision(value) {
940
947
  const distance = Math.abs(value);
@@ -971,7 +978,7 @@ function formatDistance(distance, units, precision = 2) {
971
978
  else if (digits > 10)
972
979
  digits = 10;
973
980
  if (ModelUnits[units]) {
974
- return formatNumber(distance, digits, precision) + " " + ModelUnits[units].type;
981
+ return formatNumber(distance, digits, precision) + " " + ModelUnits[units].symbol;
975
982
  }
976
983
  else if (units) {
977
984
  return formatNumber(distance, digits, precision) + " " + units;
@@ -994,6 +1001,7 @@ class Snapper {
994
1001
  this.camera = camera;
995
1002
  this.renderer = renderer;
996
1003
  this.canvas = canvas;
1004
+ this.threshold = 0.0001;
997
1005
  this.raycaster = new Raycaster();
998
1006
  this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
999
1007
  this.edgesCache = new WeakMap();
@@ -1014,10 +1022,10 @@ class Snapper {
1014
1022
  this.raycaster.setFromCamera(coords, this.camera);
1015
1023
  this.raycaster.params = {
1016
1024
  Mesh: {},
1017
- Line: { threshold: 0.05 },
1018
- Line2: { threshold: 0.05 },
1025
+ Line: { threshold: this.threshold },
1026
+ Line2: { threshold: this.threshold },
1019
1027
  LOD: {},
1020
- Points: { threshold: 0.01 },
1028
+ Points: { threshold: this.threshold },
1021
1029
  Sprite: {},
1022
1030
  };
1023
1031
  let intersects = this.raycaster.intersectObjects(objects, false);
@@ -1186,6 +1194,7 @@ class MeasureLineDragger extends OrbitDragger {
1186
1194
  this.line = new MeasureLine(this.overlay, this.scale, this.units, this.precision);
1187
1195
  this.overlay.addLine(this.line);
1188
1196
  this.snapper = new Snapper(viewer.camera, viewer.renderer, viewer.canvas);
1197
+ this.snapper.threshold = viewer.extents.getSize(new Vector3()).length() / 10000;
1189
1198
  this.objects = [];
1190
1199
  this.updateObjects();
1191
1200
  this.updateUnits();
@@ -2189,7 +2198,7 @@ function zoomTo(viewer, box) {
2189
2198
  const boxCenter = box.getCenter(new Vector3());
2190
2199
  const boxSize = box.getBoundingSphere(new Sphere()).radius;
2191
2200
  const rendererSize = viewer.renderer.getSize(new Vector2());
2192
- const aspect = rendererSize.x / rendererSize.y;
2201
+ const aspectRatio = rendererSize.x / rendererSize.y;
2193
2202
  const camera = viewer.camera;
2194
2203
  if (camera.isPerspectiveCamera) {
2195
2204
  const offset = new Vector3(0, 0, 1)
@@ -2201,8 +2210,8 @@ function zoomTo(viewer, box) {
2201
2210
  if (camera.isOrthographicCamera) {
2202
2211
  camera.top = boxSize;
2203
2212
  camera.bottom = -boxSize;
2204
- camera.left = camera.bottom * aspect;
2205
- camera.right = camera.top * aspect;
2213
+ camera.left = camera.bottom * aspectRatio;
2214
+ camera.right = camera.top * aspectRatio;
2206
2215
  camera.zoom = 1;
2207
2216
  camera.updateProjectionMatrix();
2208
2217
  const offset = new Vector3(0, 0, 1)
@@ -2263,9 +2272,9 @@ function getSelected(viewer) {
2263
2272
  function getSelected2(viewer) {
2264
2273
  const handles2 = [];
2265
2274
  viewer.models.forEach((model) => {
2266
- handles2.push(...model.getHandlesByObjects(viewer.selected));
2275
+ handles2.push(model.getHandlesByObjects(viewer.selected));
2267
2276
  });
2268
- return handles2;
2277
+ return handles2.flat();
2269
2278
  }
2270
2279
 
2271
2280
  function hideSelected(viewer) {
@@ -2489,15 +2498,15 @@ class CameraComponent {
2489
2498
  switchCamera(camera) {
2490
2499
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius * 2 || 1;
2491
2500
  const rendererSize = this.viewer.renderer.getSize(new Vector2());
2492
- const aspect = rendererSize.x / rendererSize.y;
2501
+ const aspectRatio = rendererSize.x / rendererSize.y;
2493
2502
  if (camera.isPerspectiveCamera) {
2494
- camera.aspect = aspect;
2503
+ camera.aspect = aspectRatio;
2495
2504
  camera.near = extentsSize / 1000;
2496
2505
  camera.far = extentsSize * 1000;
2497
2506
  }
2498
2507
  if (camera.isOrthographicCamera) {
2499
- camera.left = camera.bottom * aspect;
2500
- camera.right = camera.top * aspect;
2508
+ camera.left = camera.bottom * aspectRatio;
2509
+ camera.right = camera.top * aspectRatio;
2501
2510
  camera.near = 0;
2502
2511
  camera.far = extentsSize * 1000;
2503
2512
  }
@@ -2545,10 +2554,12 @@ class CameraComponent {
2545
2554
 
2546
2555
  class ExtentsComponent {
2547
2556
  constructor(viewer) {
2548
- this.syncExtents = () => {
2557
+ this.syncExtents = (event) => {
2549
2558
  const extents = new Box3();
2550
2559
  this.viewer.models.forEach((model) => model.getExtents(extents));
2551
2560
  this.viewer.extents.copy(extents);
2561
+ if (event.type !== "databasechunk" && event.target !== "clear")
2562
+ return;
2552
2563
  if (this.viewer.models.length > 1)
2553
2564
  return;
2554
2565
  this.viewer.extents.getCenter(this.viewer.target);
@@ -2915,12 +2926,12 @@ class HighlighterComponent {
2915
2926
  const { edgesVisibility } = this.viewer.options;
2916
2927
  if (!Array.isArray(objects))
2917
2928
  objects = [objects];
2918
- if (!objects.length)
2929
+ if (objects.length === 0)
2919
2930
  return;
2920
2931
  objects
2921
2932
  .filter((object) => !object.userData.isEdge)
2922
2933
  .forEach((object) => {
2923
- if (object.isHighlighted)
2934
+ if (object.userData.isHighlighted)
2924
2935
  return;
2925
2936
  if (object.isLine || object.isLineSegments) {
2926
2937
  const positions = object.geometry.attributes.position.array;
@@ -2929,43 +2940,39 @@ class HighlighterComponent {
2929
2940
  ? HighlighterUtils.fromIndexedLine(positions, indices)
2930
2941
  : HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
2931
2942
  const wireframe = new Wireframe(lineGeometry, this.lineGlowMaterial);
2932
- wireframe.position.copy(object.position);
2933
- wireframe.rotation.copy(object.rotation);
2934
- wireframe.scale.copy(object.scale);
2935
2943
  wireframe.visible = edgesVisibility;
2936
- object.parent.add(wireframe);
2944
+ wireframe.userData.isHighlightWireframe = true;
2945
+ object.add(wireframe);
2937
2946
  object.userData.highlightWireframe = wireframe;
2938
2947
  object.userData.originalMaterial = object.material;
2939
2948
  object.material = this.lineMaterial;
2940
- object.isHighlighted = true;
2949
+ object.userData.isHighlighted = true;
2941
2950
  }
2942
2951
  else if (object.isMesh) {
2943
2952
  const edgesGeometry = new EdgesGeometry(object.geometry, 89);
2944
2953
  const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
2945
2954
  const wireframe = new Wireframe(lineGeometry, this.edgesMaterial);
2946
- wireframe.position.copy(object.position);
2947
- wireframe.rotation.copy(object.rotation);
2948
- wireframe.scale.copy(object.scale);
2949
2955
  wireframe.visible = edgesVisibility;
2950
- object.parent.add(wireframe);
2956
+ wireframe.userData.isHighlightWireframe = true;
2957
+ object.add(wireframe);
2951
2958
  object.userData.highlightWireframe = wireframe;
2952
2959
  object.userData.originalMaterial = object.material;
2953
2960
  object.material = this.facesMaterial;
2954
- object.isHighlighted = true;
2961
+ object.userData.isHighlighted = true;
2955
2962
  }
2956
2963
  });
2957
2964
  }
2958
2965
  unhighlight(objects) {
2959
2966
  if (!Array.isArray(objects))
2960
2967
  objects = [objects];
2961
- if (!objects.length)
2968
+ if (objects.length === 0)
2962
2969
  return;
2963
2970
  objects.forEach((object) => {
2964
- if (!object.isHighlighted)
2971
+ if (!object.userData.isHighlighted)
2965
2972
  return;
2966
- object.isHighlighted = false;
2967
2973
  object.material = object.userData.originalMaterial;
2968
2974
  object.userData.highlightWireframe.removeFromParent();
2975
+ delete object.userData.isHighlighted;
2969
2976
  delete object.userData.originalMaterial;
2970
2977
  delete object.userData.highlightWireframe;
2971
2978
  });
@@ -3013,6 +3020,7 @@ class SelectionComponent {
3013
3020
  if (upPosition.distanceTo(this.downPosition) !== 0)
3014
3021
  return;
3015
3022
  const snapper = new Snapper(this.viewer.camera, this.viewer.renderer, this.viewer.canvas);
3023
+ snapper.threshold = this.viewer.extents.getSize(new Vector3()).length() / 10000;
3016
3024
  let intersections = [];
3017
3025
  this.viewer.models.forEach((model) => {
3018
3026
  const objects = model.getVisibleObjects();
@@ -3067,12 +3075,12 @@ class SelectionComponent {
3067
3075
  }
3068
3076
  if (!Array.isArray(objects))
3069
3077
  objects = [objects];
3070
- if (!objects.length)
3078
+ if (objects.length === 0)
3071
3079
  return;
3072
- model.showOriginalObjects(objects);
3080
+ model.highlightObjects(objects);
3073
3081
  this.highlighter.highlight(objects);
3074
3082
  objects.forEach((object) => this.viewer.selected.push(object));
3075
- objects.forEach((object) => (object.isSelected = true));
3083
+ objects.forEach((object) => (object.userData.isSelected = true));
3076
3084
  }
3077
3085
  deselect(objects, model) {
3078
3086
  if (!model) {
@@ -3081,29 +3089,29 @@ class SelectionComponent {
3081
3089
  }
3082
3090
  if (!Array.isArray(objects))
3083
3091
  objects = [objects];
3084
- if (!objects.length)
3092
+ if (objects.length === 0)
3085
3093
  return;
3094
+ model.unhighlightObjects(objects);
3086
3095
  this.highlighter.unhighlight(objects);
3087
- model.hideOriginalObjects(objects);
3088
3096
  this.viewer.selected = this.viewer.selected.filter((x) => !objects.includes(x));
3089
- objects.forEach((object) => (object.isSelected = false));
3097
+ objects.forEach((object) => (object.userData.isSelected = false));
3090
3098
  }
3091
3099
  toggleSelection(objects, model) {
3092
3100
  if (!Array.isArray(objects))
3093
3101
  objects = [objects];
3094
- if (!objects.length)
3102
+ if (objects.length === 0)
3095
3103
  return;
3096
- if (objects[0].isSelected)
3104
+ if (objects[0].userData.isSelected)
3097
3105
  this.deselect(objects, model);
3098
3106
  else
3099
3107
  this.select(objects, model);
3100
3108
  }
3101
3109
  clearSelection() {
3102
- if (!this.viewer.selected.length)
3110
+ if (this.viewer.selected.length === 0)
3103
3111
  return;
3112
+ this.viewer.models.forEach((model) => model.unhighlightObjects(this.viewer.selected));
3104
3113
  this.highlighter.unhighlight(this.viewer.selected);
3105
- this.viewer.models.forEach((model) => model.hideOriginalObjects(this.viewer.selected));
3106
- this.viewer.selected.forEach((object) => (object.isSelected = false));
3114
+ this.viewer.selected.forEach((object) => (object.userData.isSelected = false));
3107
3115
  this.viewer.selected.length = 0;
3108
3116
  }
3109
3117
  }
@@ -3265,6 +3273,20 @@ components.registerComponent("ResetComponent", (viewer) => new ResetComponent(vi
3265
3273
  class ModelImpl {
3266
3274
  constructor(scene) {
3267
3275
  this.scene = scene;
3276
+ this.handleToObjects = new Map();
3277
+ this.originalObjects = new Set();
3278
+ this.scene.traverse((object) => {
3279
+ this.originalObjects.add(object);
3280
+ const handle = object.userData.handle;
3281
+ if (!handle)
3282
+ return;
3283
+ let objects = this.handleToObjects.get(handle);
3284
+ if (!objects) {
3285
+ objects = new Set();
3286
+ this.handleToObjects.set(handle, objects);
3287
+ }
3288
+ objects.add(object);
3289
+ });
3268
3290
  }
3269
3291
  dispose() {
3270
3292
  function disposeMaterial(material) {
@@ -3280,6 +3302,8 @@ class ModelImpl {
3280
3302
  if (object.material)
3281
3303
  disposeMaterials(object.material);
3282
3304
  }
3305
+ this.handleToObjects = undefined;
3306
+ this.originalObjects = undefined;
3283
3307
  this.scene.traverse(disposeObject);
3284
3308
  this.scene.clear();
3285
3309
  }
@@ -3422,67 +3446,56 @@ class ModelImpl {
3422
3446
  return info;
3423
3447
  }
3424
3448
  getExtents(target) {
3425
- this.scene.traverseVisible((object) => !object.children.length && target.expandByObject(object));
3449
+ this.scene.traverseVisible((object) => target.expandByObject(object));
3426
3450
  return target;
3427
3451
  }
3428
3452
  getObjects() {
3429
- const objects = [];
3430
- this.scene.traverse((object) => objects.push(object));
3431
- return objects;
3453
+ return Array.from(this.originalObjects);
3432
3454
  }
3433
3455
  getVisibleObjects() {
3434
3456
  const objects = [];
3435
3457
  this.scene.traverseVisible((object) => objects.push(object));
3436
- return objects;
3437
- }
3438
- hasObject(object) {
3439
- while (object) {
3440
- if (object === this.scene)
3441
- return true;
3442
- object = object.parent;
3443
- }
3444
- return false;
3445
- }
3446
- hasHandle(handle) {
3447
- return !handle.includes(":") || handle.split(":", 1)[0] === this.id + "";
3458
+ return objects.filter((object) => object.userData.handle);
3448
3459
  }
3449
- getOwnObjects(objects) {
3450
- if (!Array.isArray(objects))
3451
- objects = [objects];
3452
- return objects.filter((object) => this.hasObject(object));
3453
- }
3454
- getOwnHandles(handles) {
3460
+ getObjectsByHandles(handles) {
3455
3461
  if (!Array.isArray(handles))
3456
3462
  handles = [handles];
3457
- return handles.filter((handle) => this.hasHandle(handle));
3458
- }
3459
- getObjectsByHandles(handles) {
3460
- const ownHandles = this.getOwnHandles(handles);
3461
- if (ownHandles.length === 0)
3462
- return [];
3463
- const handleSet = new Set(ownHandles.map((handle) => handle.slice(handle.indexOf(":") + 1)));
3463
+ const ownHandles = [];
3464
+ handles.forEach((handle) => {
3465
+ const index = handle.indexOf(":");
3466
+ if (index !== -1) {
3467
+ if (handle.slice(0, index) !== this.id)
3468
+ return;
3469
+ handle = handle.slice(index + 1);
3470
+ }
3471
+ ownHandles.push(handle);
3472
+ });
3473
+ const handlesSet = new Set(ownHandles);
3464
3474
  const objects = [];
3465
- this.scene.traverse((object) => {
3466
- const handle = object.userData.handle;
3467
- if (handle && handleSet.has(handle))
3468
- objects.push(object);
3475
+ handlesSet.forEach((handle) => {
3476
+ objects.push(Array.from(this.handleToObjects.get(handle) || []));
3469
3477
  });
3470
- return objects;
3478
+ return objects.flat();
3471
3479
  }
3472
3480
  getHandlesByObjects(objects) {
3473
- const ownObjects = this.getOwnObjects(objects);
3474
- if (ownObjects.length === 0)
3475
- return [];
3481
+ if (!Array.isArray(objects))
3482
+ objects = [objects];
3476
3483
  const handleSet = new Set();
3477
- ownObjects.forEach((object) => {
3478
- const handle = object.userData.handle;
3479
- if (handle)
3480
- handleSet.add(`${this.id}:${handle}`);
3484
+ objects
3485
+ .filter((object) => this.originalObjects.has(object))
3486
+ .forEach((object) => {
3487
+ handleSet.add(`${this.id}:${object.userData.handle}`);
3481
3488
  });
3482
3489
  return Array.from(handleSet);
3483
3490
  }
3484
3491
  hideObjects(objects) {
3485
- this.getOwnObjects(objects).forEach((object) => (object.visible = false));
3492
+ if (!Array.isArray(objects))
3493
+ objects = [objects];
3494
+ objects
3495
+ .filter((object) => this.originalObjects.has(object))
3496
+ .forEach((object) => {
3497
+ object.visible = false;
3498
+ });
3486
3499
  return this;
3487
3500
  }
3488
3501
  hideAllObjects() {
@@ -3492,12 +3505,20 @@ class ModelImpl {
3492
3505
  if (!Array.isArray(objects))
3493
3506
  objects = [objects];
3494
3507
  const visibleSet = new Set(objects);
3495
- this.getOwnObjects(objects).forEach((object) => object.traverseAncestors((parent) => visibleSet.add(parent)));
3508
+ objects
3509
+ .filter((object) => this.originalObjects.has(object))
3510
+ .forEach((object) => {
3511
+ object.traverseAncestors((parent) => visibleSet.add(parent));
3512
+ });
3496
3513
  this.scene.traverse((object) => (object.visible = visibleSet.has(object)));
3497
3514
  return this;
3498
3515
  }
3499
3516
  showObjects(objects) {
3500
- this.getOwnObjects(objects).forEach((object) => {
3517
+ if (!Array.isArray(objects))
3518
+ objects = [objects];
3519
+ objects
3520
+ .filter((object) => this.originalObjects.has(object))
3521
+ .forEach((object) => {
3501
3522
  object.visible = true;
3502
3523
  object.traverseAncestors((parent) => (parent.visible = true));
3503
3524
  });
@@ -3507,36 +3528,55 @@ class ModelImpl {
3507
3528
  this.scene.traverse((object) => (object.visible = true));
3508
3529
  return this;
3509
3530
  }
3510
- showOriginalObjects(objects) {
3531
+ highlightObjects(objects) {
3511
3532
  return this;
3512
3533
  }
3513
- hideOriginalObjects(objects) {
3534
+ unhighlightObjects(objects) {
3514
3535
  return this;
3515
3536
  }
3516
3537
  explode(scale = 0, coeff = 4) {
3538
+ const centers = new Map();
3539
+ const getObjectCenter = (object, target) => {
3540
+ const extents = new Box3().setFromObject(object);
3541
+ const handle = object.userData.handle;
3542
+ if (!handle)
3543
+ return extents.getCenter(target);
3544
+ const center = centers.get(handle);
3545
+ if (center)
3546
+ return target.copy(center);
3547
+ const objects = this.getObjectsByHandles(handle);
3548
+ objects.forEach((x) => extents.expandByObject(x));
3549
+ extents.getCenter(target);
3550
+ centers.set(handle, target.clone());
3551
+ return target;
3552
+ };
3517
3553
  function calcExplodeDepth(object, depth) {
3518
- let res = depth;
3554
+ let result = depth;
3519
3555
  object.children.forEach((x) => {
3520
3556
  const objectDepth = calcExplodeDepth(x, depth + 1);
3521
- if (res < objectDepth)
3522
- res = objectDepth;
3557
+ if (result < objectDepth)
3558
+ result = objectDepth;
3523
3559
  });
3524
3560
  object.userData.originalPosition = object.position.clone();
3525
- object.userData.originalCenter = new Box3().setFromObject(object).getCenter(new Vector3());
3526
- object.userData.isExplodeLocked = depth > 2 && object.children.length === 0;
3527
- return res;
3528
- }
3529
- scale /= 100;
3530
- if (!this.scene.userData.explodeDepth)
3531
- this.scene.userData.explodeDepth = calcExplodeDepth(this.scene, 1);
3532
- const maxDepth = this.scene.userData.explodeDepth;
3533
- const scaledExplodeDepth = scale * maxDepth + 1;
3561
+ object.userData.originalCenter = getObjectCenter(object, new Vector3());
3562
+ return result;
3563
+ }
3564
+ const explodeScale = scale / 100;
3565
+ const explodeRoot = this.scene;
3566
+ if (!explodeRoot.userData.explodeDepth)
3567
+ explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
3568
+ const maxDepth = explodeRoot.userData.explodeDepth;
3569
+ const scaledExplodeDepth = explodeScale * maxDepth + 1;
3534
3570
  const explodeDepth = 0 | scaledExplodeDepth;
3535
3571
  const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
3536
3572
  function explodeObject(object, depth) {
3573
+ if (object.isCamera)
3574
+ return;
3575
+ if (object.userData.isHighlightWireframe)
3576
+ return;
3537
3577
  object.position.copy(object.userData.originalPosition);
3538
- if (depth > 0 && depth <= explodeDepth && !object.userData.isExplodeLocked) {
3539
- let objectScale = scale * coeff;
3578
+ if (depth > 0 && depth <= explodeDepth) {
3579
+ let objectScale = explodeScale * coeff;
3540
3580
  if (depth === explodeDepth)
3541
3581
  objectScale *= currentSegmentFraction;
3542
3582
  const parentCenter = object.parent.userData.originalCenter;
@@ -3546,7 +3586,7 @@ class ModelImpl {
3546
3586
  }
3547
3587
  object.children.forEach((x) => explodeObject(x, depth + 1));
3548
3588
  }
3549
- explodeObject(this.scene, 0);
3589
+ explodeObject(explodeRoot, 0);
3550
3590
  this.scene.updateMatrixWorld();
3551
3591
  return this;
3552
3592
  }
@@ -3584,29 +3624,24 @@ class DynamicModelImpl extends ModelImpl {
3584
3624
  getVisibleObjects() {
3585
3625
  return this.gltfLoader.getOriginalObjectForSelect();
3586
3626
  }
3587
- hasObject(object) {
3588
- return this.gltfLoader.originalObjects.has(object);
3589
- }
3590
3627
  getObjectsByHandles(handles) {
3591
- const ownHandles = this.getOwnHandles(handles);
3592
- if (ownHandles.length === 0)
3593
- return [];
3594
- const handlesSet = new Set(ownHandles);
3628
+ if (!Array.isArray(handles))
3629
+ handles = [handles];
3630
+ const handlesSet = new Set(handles);
3595
3631
  const objects = [];
3596
3632
  handlesSet.forEach((handle) => {
3597
- objects.push(...this.gltfLoader.getObjectsByHandle(handle));
3633
+ objects.push(this.gltfLoader.getObjectsByHandle(handle));
3598
3634
  });
3599
- return objects;
3635
+ return objects.flat();
3600
3636
  }
3601
3637
  getHandlesByObjects(objects) {
3602
- const ownObjects = this.getOwnObjects(objects);
3603
- if (ownObjects.length === 0)
3604
- return [];
3638
+ if (!Array.isArray(objects))
3639
+ objects = [objects];
3605
3640
  const handleSet = new Set();
3606
- ownObjects.forEach((object) => {
3607
- const handle = object.userData.handle;
3608
- if (handle)
3609
- handleSet.add(handle);
3641
+ objects
3642
+ .filter((object) => this.gltfLoader.originalObjects.has(object))
3643
+ .forEach((object) => {
3644
+ handleSet.add(object.userData.handle);
3610
3645
  });
3611
3646
  return Array.from(handleSet);
3612
3647
  }
@@ -3629,14 +3664,78 @@ class DynamicModelImpl extends ModelImpl {
3629
3664
  this.gltfLoader.showAllHiddenObjects();
3630
3665
  return this;
3631
3666
  }
3632
- showOriginalObjects(objects) {
3667
+ highlightObjects(objects) {
3633
3668
  this.gltfLoader.showOriginalObjects(objects);
3634
3669
  return this;
3635
3670
  }
3636
- hideOriginalObjects(objects) {
3671
+ unhighlightObjects(objects) {
3637
3672
  this.gltfLoader.hideOriginalObjects(objects);
3638
3673
  return this;
3639
3674
  }
3675
+ explode(scale = 0, coeff = 4) {
3676
+ const centers = new Map();
3677
+ const calcObjectCenter = (object, target) => {
3678
+ const extents = new Box3().setFromObject(object);
3679
+ const handle = object.userData.handle;
3680
+ if (!handle)
3681
+ return extents.getCenter(target);
3682
+ const center = centers.get(handle);
3683
+ if (center)
3684
+ return target.copy(center);
3685
+ const objects = this.getObjectsByHandles(handle);
3686
+ objects.forEach((x) => extents.expandByObject(x));
3687
+ extents.getCenter(target);
3688
+ centers.set(handle, target.clone());
3689
+ return target;
3690
+ };
3691
+ function calcExplodeDepth(object, depth) {
3692
+ let result = depth;
3693
+ object.children
3694
+ .filter((x) => !x.userData.isOptimized)
3695
+ .forEach((x) => {
3696
+ const objectDepth = calcExplodeDepth(x, depth + 1);
3697
+ if (result < objectDepth)
3698
+ result = objectDepth;
3699
+ });
3700
+ object.userData.originalPosition = object.position.clone();
3701
+ object.userData.originalCenter = calcObjectCenter(object, new Vector3());
3702
+ return result;
3703
+ }
3704
+ const explodeScale = scale / 100;
3705
+ const explodeRoot = this.scene.children[0];
3706
+ if (!explodeRoot.userData.explodeDepth)
3707
+ explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
3708
+ const maxDepth = explodeRoot.userData.explodeDepth;
3709
+ const scaledExplodeDepth = explodeScale * maxDepth + 1;
3710
+ const explodeDepth = 0 | scaledExplodeDepth;
3711
+ const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
3712
+ const transformMap = new Map();
3713
+ function explodeObject(object, depth) {
3714
+ if (object.isCamera)
3715
+ return;
3716
+ if (object.userData.isHighlightWireframe)
3717
+ return;
3718
+ object.position.copy(object.userData.originalPosition);
3719
+ if (depth > 0 && depth <= explodeDepth && !object.userData.isExplodeLocked) {
3720
+ let objectScale = explodeScale * coeff;
3721
+ if (depth === explodeDepth)
3722
+ objectScale *= currentSegmentFraction;
3723
+ const parentCenter = object.parent.userData.originalCenter;
3724
+ const objectCenter = object.userData.originalCenter;
3725
+ const objectOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
3726
+ object.position.add(objectOffset);
3727
+ const matrix = new Matrix4().makeTranslation(objectOffset.x, objectOffset.y, objectOffset.z);
3728
+ transformMap.set(object, matrix);
3729
+ }
3730
+ object.children
3731
+ .filter((x) => !x.userData.isOptimized)
3732
+ .forEach((x) => explodeObject(x, depth + 1));
3733
+ }
3734
+ explodeObject(explodeRoot, 0);
3735
+ this.scene.updateMatrixWorld();
3736
+ this.gltfLoader.applyObjectTransforms(transformMap);
3737
+ return this;
3738
+ }
3640
3739
  }
3641
3740
 
3642
3741
  const GL_COMPONENT_TYPES = {
@@ -3685,7 +3784,7 @@ class GltfStructure {
3685
3784
  this.textureCache = new Map();
3686
3785
  this.materialCache = new Map();
3687
3786
  this.uri = "";
3688
- this._nextObjectId = 0;
3787
+ this._nextObjectId = 1;
3689
3788
  this.loadingAborted = false;
3690
3789
  this.criticalError = null;
3691
3790
  }
@@ -4204,6 +4303,8 @@ class DynamicGltfLoader {
4204
4303
  this.hiddenHandles = new Set();
4205
4304
  this.newOptimizedObjects = new Set();
4206
4305
  this.oldOptimizeObjects = new Set();
4306
+ this.objectTransforms = new Map();
4307
+ this.transformedGeometries = new Map();
4207
4308
  this.activeChunkLoads = 0;
4208
4309
  this.chunkQueue = [];
4209
4310
  this.objectIdToIndex = new Map();
@@ -4965,14 +5066,32 @@ class DynamicGltfLoader {
4965
5066
  if (!node.geometryExtents) continue;
4966
5067
  if (node.object && this.hiddenHandles.has(node.object.userData.handle)) continue;
4967
5068
  const transformedBox = node.geometryExtents.clone();
4968
- if (node.group && node.group.matrix) {
4969
- transformedBox.applyMatrix4(node.group.matrix);
4970
- if (node.group.parent && node.group.parent.matrix) {
4971
- transformedBox.applyMatrix4(node.group.parent.matrix);
5069
+ const structureRoot = node.structure ? this.structureRoots.get(node.structure.id) : null;
5070
+ if (node.group) {
5071
+ const matrices = [];
5072
+ let currentGroup = node.group;
5073
+ while (currentGroup && currentGroup !== structureRoot) {
5074
+ if (currentGroup.matrix && currentGroup.matrixAutoUpdate === false) {
5075
+ matrices.unshift(currentGroup.matrix);
5076
+ }
5077
+ currentGroup = currentGroup.parent;
4972
5078
  }
5079
+ for (const matrix of matrices) {
5080
+ transformedBox.applyMatrix4(matrix);
5081
+ }
5082
+ }
5083
+ if (structureRoot && structureRoot.matrix) {
5084
+ transformedBox.applyMatrix4(structureRoot.matrix);
5085
+ }
5086
+ const transform = this.objectTransforms.get(node.object);
5087
+ if (transform) {
5088
+ transformedBox.applyMatrix4(transform);
4973
5089
  }
4974
5090
  totalExtent.union(transformedBox);
4975
5091
  }
5092
+ if (this.scene && this.scene.matrix && !totalExtent.isEmpty()) {
5093
+ totalExtent.applyMatrix4(this.scene.matrix);
5094
+ }
4976
5095
  return totalExtent;
4977
5096
  }
4978
5097
  loadCamera(structure, cameraIndex, nodeDef) {
@@ -5048,7 +5167,6 @@ class DynamicGltfLoader {
5048
5167
  for (let i = 0; i < this.maxObjectId; i++) {
5049
5168
  this.objectVisibility[i] = 1.0;
5050
5169
  }
5051
- console.log(`Initialized object visibility array: ${this.maxObjectId} objects`);
5052
5170
  }
5053
5171
  }
5054
5172
  createVisibilityMaterial(material) {
@@ -5185,6 +5303,8 @@ class DynamicGltfLoader {
5185
5303
  this.newOptimizedObjects.clear();
5186
5304
  this.oldOptimizeObjects.clear();
5187
5305
  this.isolatedObjects = [];
5306
+ this.objectTransforms.clear();
5307
+ this.transformedGeometries.clear();
5188
5308
  this.totalLoadedObjects = 0;
5189
5309
  this.lastUpdateTime = 0;
5190
5310
  this.currentMemoryUsage = 0;
@@ -5882,6 +6002,171 @@ class DynamicGltfLoader {
5882
6002
  mergedObject.geometry.attributes.visibility.needsUpdate = true;
5883
6003
  }
5884
6004
  }
6005
+ applyObjectTransforms(objectTransformMap) {
6006
+ if (this.mergedObjectMap.size === 0) {
6007
+ console.warn("No merged objects to transform");
6008
+ return;
6009
+ }
6010
+ this.objectTransforms = new Map(objectTransformMap);
6011
+ for (const mesh of this.mergedMesh) {
6012
+ this._applyTransformToMergedObject(mesh);
6013
+ }
6014
+ for (const line of this.mergedLines) {
6015
+ this._applyTransformToMergedObject(line);
6016
+ }
6017
+ for (const lineSegment of this.mergedLineSegments) {
6018
+ this._applyTransformToMergedObject(lineSegment);
6019
+ }
6020
+ for (const point of this.mergedPoints) {
6021
+ this._applyTransformToMergedObject(point);
6022
+ }
6023
+ }
6024
+ createExplodeTransforms(objects = null, explodeCenter = null, explodeFactor = 1.5) {
6025
+ const transformMap = new Map();
6026
+ if (!explodeCenter) {
6027
+ explodeCenter = new Vector3();
6028
+ const extent = this.getTotalGeometryExtent();
6029
+ if (!extent.isEmpty()) {
6030
+ extent.getCenter(explodeCenter);
6031
+ }
6032
+ }
6033
+ const objectsArray = objects
6034
+ ? Array.isArray(objects)
6035
+ ? objects
6036
+ : Array.from(objects)
6037
+ : Array.from(this.originalObjects);
6038
+ for (const obj of objectsArray) {
6039
+ if (!obj.geometry || !obj.geometry.attributes.position) continue;
6040
+ const boundingBox = new Box3().setFromBufferAttribute(obj.geometry.attributes.position);
6041
+ if (obj.matrixWorld) {
6042
+ boundingBox.applyMatrix4(obj.matrixWorld);
6043
+ }
6044
+ if (boundingBox.isEmpty()) continue;
6045
+ const objectCenter = new Vector3();
6046
+ boundingBox.getCenter(objectCenter);
6047
+ const direction = objectCenter.clone().sub(explodeCenter);
6048
+ const distance = direction.length();
6049
+ if (distance > 0) {
6050
+ direction.normalize();
6051
+ const offset = direction.multiplyScalar(distance * (explodeFactor - 1.0));
6052
+ const matrix = new Matrix4().makeTranslation(offset.x, offset.y, offset.z);
6053
+ transformMap.set(obj, matrix);
6054
+ }
6055
+ }
6056
+ return transformMap;
6057
+ }
6058
+ clearTransforms() {
6059
+ this.objectTransforms.clear();
6060
+ for (const mesh of this.mergedMesh) {
6061
+ this._restoreOriginalGeometry(mesh);
6062
+ }
6063
+ for (const line of this.mergedLines) {
6064
+ this._restoreOriginalGeometry(line);
6065
+ }
6066
+ for (const lineSegment of this.mergedLineSegments) {
6067
+ this._restoreOriginalGeometry(lineSegment);
6068
+ }
6069
+ for (const point of this.mergedPoints) {
6070
+ this._restoreOriginalGeometry(point);
6071
+ }
6072
+ }
6073
+ clearHandleTransforms() {
6074
+ this.clearTransforms();
6075
+ }
6076
+ _applyTransformToMergedObject(mergedObject) {
6077
+ const objectData = this.mergedObjectMap.get(mergedObject.uuid);
6078
+ if (!objectData || !objectData.objectMapping) return;
6079
+ const geometry = mergedObject.geometry;
6080
+ if (!geometry || !geometry.attributes.position) return;
6081
+ const positionAttr = geometry.attributes.position;
6082
+ const positions = positionAttr.array;
6083
+ if (!this.transformedGeometries.has(mergedObject.uuid)) {
6084
+ this.transformedGeometries.set(mergedObject.uuid, new Float32Array(positions));
6085
+ }
6086
+ const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
6087
+ const tempVector = new Vector3();
6088
+ for (const [originalMesh, mappingData] of objectData.objectMapping) {
6089
+ const transform = this.objectTransforms.get(originalMesh);
6090
+ if (!transform) {
6091
+ const startIdx = mappingData.startVertexIndex * 3;
6092
+ const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
6093
+ for (let i = startIdx; i < endIdx; i++) {
6094
+ positions[i] = originalPositions[i];
6095
+ }
6096
+ continue;
6097
+ }
6098
+ const startVertex = mappingData.startVertexIndex;
6099
+ const vertexCount = mappingData.vertexCount;
6100
+ for (let i = 0; i < vertexCount; i++) {
6101
+ const idx = (startVertex + i) * 3;
6102
+ tempVector.set(originalPositions[idx], originalPositions[idx + 1], originalPositions[idx + 2]);
6103
+ tempVector.applyMatrix4(transform);
6104
+ positions[idx] = tempVector.x;
6105
+ positions[idx + 1] = tempVector.y;
6106
+ positions[idx + 2] = tempVector.z;
6107
+ }
6108
+ }
6109
+ if (geometry.attributes.normal) {
6110
+ this._updateNormalsForTransform(geometry, objectData, originalPositions);
6111
+ }
6112
+ positionAttr.needsUpdate = true;
6113
+ geometry.computeBoundingSphere();
6114
+ geometry.computeBoundingBox();
6115
+ }
6116
+ _updateNormalsForTransform(geometry, objectData, originalPositions) {
6117
+ const normalAttr = geometry.attributes.normal;
6118
+ if (!normalAttr) return;
6119
+ const normals = normalAttr.array;
6120
+ const tempVector = new Vector3();
6121
+ const normalMatrix = new Matrix4();
6122
+ const normalsKey = `${geometry.uuid}_normals`;
6123
+ if (!this.transformedGeometries.has(normalsKey)) {
6124
+ this.transformedGeometries.set(normalsKey, new Float32Array(normals));
6125
+ }
6126
+ const originalNormals = this.transformedGeometries.get(normalsKey);
6127
+ for (const [originalMesh, mappingData] of objectData.objectMapping) {
6128
+ const transform = this.objectTransforms.get(originalMesh);
6129
+ if (!transform) {
6130
+ const startIdx = mappingData.startVertexIndex * 3;
6131
+ const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
6132
+ for (let i = startIdx; i < endIdx; i++) {
6133
+ normals[i] = originalNormals[i];
6134
+ }
6135
+ continue;
6136
+ }
6137
+ normalMatrix.copy(transform).invert().transpose();
6138
+ const startVertex = mappingData.startVertexIndex;
6139
+ const vertexCount = mappingData.vertexCount;
6140
+ for (let i = 0; i < vertexCount; i++) {
6141
+ const idx = (startVertex + i) * 3;
6142
+ tempVector.set(originalNormals[idx], originalNormals[idx + 1], originalNormals[idx + 2]);
6143
+ tempVector.applyMatrix4(normalMatrix).normalize();
6144
+ normals[idx] = tempVector.x;
6145
+ normals[idx + 1] = tempVector.y;
6146
+ normals[idx + 2] = tempVector.z;
6147
+ }
6148
+ }
6149
+ normalAttr.needsUpdate = true;
6150
+ }
6151
+ _restoreOriginalGeometry(mergedObject) {
6152
+ const geometry = mergedObject.geometry;
6153
+ if (!geometry || !geometry.attributes.position) return;
6154
+ const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
6155
+ if (originalPositions) {
6156
+ const positions = geometry.attributes.position.array;
6157
+ positions.set(originalPositions);
6158
+ geometry.attributes.position.needsUpdate = true;
6159
+ }
6160
+ const normalsKey = `${geometry.uuid}_normals`;
6161
+ const originalNormals = this.transformedGeometries.get(normalsKey);
6162
+ if (originalNormals && geometry.attributes.normal) {
6163
+ const normals = geometry.attributes.normal.array;
6164
+ normals.set(originalNormals);
6165
+ geometry.attributes.normal.needsUpdate = true;
6166
+ }
6167
+ geometry.computeBoundingSphere();
6168
+ geometry.computeBoundingBox();
6169
+ }
5885
6170
  syncHiddenObjects() {
5886
6171
  if (this.mergedObjectMap.size === 0) {
5887
6172
  console.log("No merged objects to sync");
@@ -5913,19 +6198,33 @@ class DynamicGltfLoader {
5913
6198
  }
5914
6199
  getStructureGeometryExtent(structureId) {
5915
6200
  const extent = new Box3();
6201
+ const structureRoot = this.structureRoots.get(structureId);
5916
6202
  for (const [nodeId, node] of this.nodes.entries()) {
5917
6203
  if (!node.geometryExtents) continue;
5918
6204
  if (!nodeId.startsWith(structureId + "_")) continue;
5919
6205
  if (node.object && this.hiddenHandles && this.hiddenHandles.has(node.object.userData.handle)) continue;
5920
6206
  const transformedBox = node.geometryExtents.clone();
5921
- if (node.group && node.group.matrix) {
5922
- transformedBox.applyMatrix4(node.group.matrix);
5923
- if (node.group.parent && node.group.parent.matrix) {
5924
- transformedBox.applyMatrix4(node.group.parent.matrix);
6207
+ if (node.group) {
6208
+ const matrices = [];
6209
+ let currentGroup = node.group;
6210
+ while (currentGroup && currentGroup !== structureRoot) {
6211
+ if (currentGroup.matrix && currentGroup.matrixAutoUpdate === false) {
6212
+ matrices.unshift(currentGroup.matrix);
6213
+ }
6214
+ currentGroup = currentGroup.parent;
5925
6215
  }
6216
+ for (const matrix of matrices) {
6217
+ transformedBox.applyMatrix4(matrix);
6218
+ }
6219
+ }
6220
+ if (structureRoot && structureRoot.matrix) {
6221
+ transformedBox.applyMatrix4(structureRoot.matrix);
5926
6222
  }
5927
6223
  extent.union(transformedBox);
5928
6224
  }
6225
+ if (this.scene && this.scene.matrix && !extent.isEmpty()) {
6226
+ extent.applyMatrix4(this.scene.matrix);
6227
+ }
5929
6228
  return extent;
5930
6229
  }
5931
6230
  setMaxConcurrentChunks(maxChunks) {
@@ -6498,8 +6797,8 @@ class Viewer extends EventEmitter2 {
6498
6797
  const rect = canvas.parentElement.getBoundingClientRect();
6499
6798
  const width = rect.width || 1;
6500
6799
  const height = rect.height || 1;
6501
- const aspect = width / height;
6502
- this.camera = new PerspectiveCamera(45, aspect, 0.001, 1000);
6800
+ const aspectRatio = width / height;
6801
+ this.camera = new PerspectiveCamera(45, aspectRatio, 0.001, 1000);
6503
6802
  this.camera.up.set(0, 1, 0);
6504
6803
  this.camera.position.set(0, 0, 1);
6505
6804
  this.camera.lookAt(this.target);
@@ -6596,14 +6895,14 @@ class Viewer extends EventEmitter2 {
6596
6895
  if (!this.renderer)
6597
6896
  return;
6598
6897
  const camera = this.camera;
6599
- const aspect = width / height;
6898
+ const aspectRatio = width / height;
6600
6899
  if (camera.isPerspectiveCamera) {
6601
- camera.aspect = aspect;
6900
+ camera.aspect = aspectRatio;
6602
6901
  camera.updateProjectionMatrix();
6603
6902
  }
6604
6903
  if (camera.isOrthographicCamera) {
6605
- camera.left = camera.bottom * aspect;
6606
- camera.right = camera.top * aspect;
6904
+ camera.left = camera.bottom * aspectRatio;
6905
+ camera.right = camera.top * aspectRatio;
6607
6906
  camera.updateProjectionMatrix();
6608
6907
  }
6609
6908
  this.renderer.setSize(width, height, updateStyle);
@@ -6830,12 +7129,12 @@ class Viewer extends EventEmitter2 {
6830
7129
  if (orthogonal_camera) {
6831
7130
  const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
6832
7131
  const rendererSize = this.renderer.getSize(new Vector2());
6833
- const aspect = rendererSize.x / rendererSize.y;
7132
+ const aspectRatio = rendererSize.x / rendererSize.y;
6834
7133
  const camera = new OrthographicCamera();
6835
7134
  camera.top = orthogonal_camera.field_height / 2;
6836
7135
  camera.bottom = -orthogonal_camera.field_height / 2;
6837
- camera.left = camera.bottom * aspect;
6838
- camera.right = camera.top * aspect;
7136
+ camera.left = camera.bottom * aspectRatio;
7137
+ camera.right = camera.top * aspectRatio;
6839
7138
  camera.near = 0;
6840
7139
  camera.far = extentsSize * 1000;
6841
7140
  camera.zoom = orthogonal_camera.view_to_world_scale;
@@ -6848,6 +7147,7 @@ class Viewer extends EventEmitter2 {
6848
7147
  this.renderPass.camera = camera;
6849
7148
  this.helpersPass.camera = camera;
6850
7149
  this.ssaaRenderPass.camera = camera;
7150
+ this.options.cameraMode = "orthographic";
6851
7151
  this.emitEvent({ type: "changecameramode", mode: "orthographic" });
6852
7152
  }
6853
7153
  };
@@ -6855,10 +7155,10 @@ class Viewer extends EventEmitter2 {
6855
7155
  if (perspective_camera) {
6856
7156
  const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
6857
7157
  const rendererSize = this.renderer.getSize(new Vector2());
6858
- const aspect = rendererSize.x / rendererSize.y;
7158
+ const aspectRatio = rendererSize.x / rendererSize.y;
6859
7159
  const camera = new PerspectiveCamera();
6860
7160
  camera.fov = perspective_camera.field_of_view;
6861
- camera.aspect = aspect;
7161
+ camera.aspect = aspectRatio;
6862
7162
  camera.near = extentsSize / 1000;
6863
7163
  camera.far = extentsSize * 1000;
6864
7164
  camera.updateProjectionMatrix();
@@ -6870,6 +7170,7 @@ class Viewer extends EventEmitter2 {
6870
7170
  this.renderPass.camera = camera;
6871
7171
  this.helpersPass.camera = camera;
6872
7172
  this.ssaaRenderPass.camera = camera;
7173
+ this.options.cameraMode = "perspective";
6873
7174
  this.emitEvent({ type: "changecameramode", mode: "perspective" });
6874
7175
  }
6875
7176
  };
@@ -6899,6 +7200,7 @@ class Viewer extends EventEmitter2 {
6899
7200
  setSelection(((_b = viewpoint.custom_fields) === null || _b === void 0 ? void 0 : _b.selection2) || viewpoint.selection);
6900
7201
  this._markup.setViewpoint(viewpoint);
6901
7202
  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));
7203
+ this.syncOverlay();
6902
7204
  this.setActiveDragger(draggerName);
6903
7205
  this.emitEvent({ type: "drawviewpoint", data: viewpoint });
6904
7206
  this.update();