@inweb/viewer-three 27.1.1 → 27.1.3

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 (51) hide show
  1. package/dist/extensions/components/AxesHelperComponent.js +12 -11
  2. package/dist/extensions/components/AxesHelperComponent.js.map +1 -1
  3. package/dist/extensions/components/AxesHelperComponent.min.js +1 -1
  4. package/dist/extensions/components/AxesHelperComponent.module.js +12 -11
  5. package/dist/extensions/components/AxesHelperComponent.module.js.map +1 -1
  6. package/dist/extensions/components/GridHelperComponent.js +4 -6
  7. package/dist/extensions/components/GridHelperComponent.js.map +1 -1
  8. package/dist/extensions/components/GridHelperComponent.min.js +1 -1
  9. package/dist/extensions/components/GridHelperComponent.module.js +4 -6
  10. package/dist/extensions/components/GridHelperComponent.module.js.map +1 -1
  11. package/dist/extensions/components/LightHelperComponent.js +5 -5
  12. package/dist/extensions/components/LightHelperComponent.js.map +1 -1
  13. package/dist/extensions/components/LightHelperComponent.min.js +1 -1
  14. package/dist/extensions/components/LightHelperComponent.module.js +6 -6
  15. package/dist/extensions/components/LightHelperComponent.module.js.map +1 -1
  16. package/dist/extensions/components/RoomEnvironmentComponent.js +1 -0
  17. package/dist/extensions/components/RoomEnvironmentComponent.js.map +1 -1
  18. package/dist/extensions/components/RoomEnvironmentComponent.min.js +1 -1
  19. package/dist/extensions/loaders/GLTFCloudLoader.js.map +1 -1
  20. package/dist/extensions/loaders/GLTFFileLoader.js.map +1 -1
  21. package/dist/extensions/loaders/IFCXLoader.js.map +1 -1
  22. package/dist/viewer-three.js +2630 -751
  23. package/dist/viewer-three.js.map +1 -1
  24. package/dist/viewer-three.min.js +4 -4
  25. package/dist/viewer-three.module.js +143 -89
  26. package/dist/viewer-three.module.js.map +1 -1
  27. package/extensions/components/AxesHelperComponent.ts +13 -12
  28. package/extensions/components/GridHelperComponent.ts +4 -6
  29. package/extensions/components/LightHelperComponent.ts +6 -6
  30. package/lib/Viewer/commands/SetDefaultViewPosition.d.ts +1 -1
  31. package/lib/Viewer/loaders/GLTFBinaryParser.d.ts +11 -0
  32. package/lib/Viewer/loaders/GLTFFileDynamicLoader.d.ts +0 -1
  33. package/lib/Viewer/loaders/JSONStreamParser.d.ts +5 -0
  34. package/package.json +11 -9
  35. package/src/Viewer/Viewer.ts +4 -7
  36. package/src/Viewer/commands/SetDefaultViewPosition.ts +3 -3
  37. package/src/Viewer/commands/ZoomTo.ts +6 -6
  38. package/src/Viewer/components/CameraComponent.ts +3 -3
  39. package/src/Viewer/components/LightComponent.ts +5 -8
  40. package/src/Viewer/components/SelectionComponent.ts +3 -1
  41. package/src/Viewer/draggers/CuttingPlaneDragger.ts +6 -6
  42. package/src/Viewer/draggers/FlyDragger.ts +1 -1
  43. package/src/Viewer/draggers/MeasureLineDragger.ts +10 -7
  44. package/src/Viewer/draggers/WalkDragger.ts +1 -1
  45. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +63 -10
  46. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +7 -1
  47. package/src/Viewer/loaders/{GLTFBinaryExtension.ts → GLTFBinaryParser.ts} +34 -29
  48. package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +10 -9
  49. package/src/Viewer/loaders/GLTFFileDynamicLoader.ts +9 -8
  50. package/src/Viewer/loaders/JSONStreamParser.ts +38 -0
  51. package/lib/Viewer/loaders/GLTFBinaryExtension.d.ts +0 -5
@@ -23,12 +23,13 @@
23
23
 
24
24
  import { draggersRegistry, commandsRegistry, Options, componentsRegistry, Info, Loader, loadersRegistry, CANVAS_EVENTS } from '@inweb/viewer-core';
25
25
  export * from '@inweb/viewer-core';
26
- import { Line, Vector3, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Line3, Raycaster, MathUtils, EdgesGeometry, Matrix4, Vector4, Controls, Clock, Sphere, Box3, Color, PerspectiveCamera, OrthographicCamera, AmbientLight, DirectionalLight, HemisphereLight, REVISION, MeshPhongMaterial, WebGLRenderTarget, UnsignedByteType, RGBAFormat, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, TextureLoader, BufferAttribute, PointsMaterial, Points, TriangleStripDrawMode, TriangleFanDrawMode, LineSegments, LineLoop, Group, NormalBlending, LoadingManager, LoaderUtils, FileLoader, UniformsUtils, ShaderMaterial, AdditiveBlending, HalfFloatType, Scene, WebGLRenderer, LinearSRGBColorSpace } from 'three';
26
+ import { Line, Vector3, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Line3, Raycaster, MathUtils, EdgesGeometry, Matrix4, Vector4, Controls, Clock, Box3, Color, PerspectiveCamera, OrthographicCamera, AmbientLight, DirectionalLight, HemisphereLight, REVISION, MeshPhongMaterial, WebGLRenderTarget, UnsignedByteType, RGBAFormat, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, TextureLoader, BufferAttribute, PointsMaterial, Points, TriangleStripDrawMode, TriangleFanDrawMode, LineSegments, LineLoop, Group, NormalBlending, LoadingManager, LoaderUtils, FileLoader, UniformsUtils, ShaderMaterial, AdditiveBlending, HalfFloatType, Scene, WebGLRenderer, LinearSRGBColorSpace } from 'three';
27
27
  import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';
28
28
  import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry.js';
29
29
  import { Wireframe } from 'three/examples/jsm/lines/Wireframe.js';
30
30
  import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js';
31
31
  import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
32
+ import { JSONParser } from '@streamparser/json';
32
33
  import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
33
34
  import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
34
35
  import { FXAAPass } from 'three/examples/jsm/postprocessing/FXAAPass.js';
@@ -841,7 +842,7 @@ class CuttingPlaneDragger extends OrbitDragger {
841
842
  this.orbit.enabled = !event.value;
842
843
  };
843
844
  this.updatePlaneSize = () => {
844
- this.planeHelper.size = this.viewer.extents.getSize(new Vector3()).length();
845
+ this.planeHelper.size = this.viewer.extents.getSize(new Vector3()).length() || 1;
845
846
  this.viewer.update();
846
847
  };
847
848
  this.updateTransformCamera = () => {
@@ -852,17 +853,17 @@ class CuttingPlaneDragger extends OrbitDragger {
852
853
  this.plane.negate();
853
854
  this.viewer.update();
854
855
  };
855
- const size = viewer.extents.getSize(new Vector3()).length();
856
- const center = viewer.extents.getCenter(new Vector3());
857
- const constant = -center.dot(normal);
856
+ const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
857
+ const extentsCenter = viewer.extents.getCenter(new Vector3());
858
+ const constant = -extentsCenter.dot(normal);
858
859
  this.plane = new Plane(normal, constant);
859
860
  if (!viewer.renderer.clippingPlanes)
860
861
  viewer.renderer.clippingPlanes = [];
861
862
  viewer.renderer.clippingPlanes.push(this.plane);
862
- this.planeHelper = new PlaneHelper(this.plane, size, color, center);
863
+ this.planeHelper = new PlaneHelper(this.plane, extentsSize, color, extentsCenter);
863
864
  this.viewer.helpers.add(this.planeHelper);
864
865
  this.planeCenter = new Object3D();
865
- this.planeCenter.position.copy(viewer.extents.getCenter(new Vector3()));
866
+ this.planeCenter.position.copy(extentsCenter);
866
867
  this.viewer.helpers.add(this.planeCenter);
867
868
  this.transform = new TransformControls(viewer.camera, viewer.canvas);
868
869
  this.transform.showX = !!normal.x;
@@ -1173,7 +1174,11 @@ class MeasureLineDragger extends OrbitDragger {
1173
1174
  const model = this.viewer.models[0];
1174
1175
  const units = (_a = this.viewer.options.rulerUnit) !== null && _a !== void 0 ? _a : "Default";
1175
1176
  const precision = (_b = this.viewer.options.rulerPrecision) !== null && _b !== void 0 ? _b : "Default";
1176
- if (units === "Default") {
1177
+ if (!model) {
1178
+ this.scale = 1;
1179
+ this.units = "";
1180
+ }
1181
+ else if (units === "Default") {
1177
1182
  this.scale = model.getUnitScale();
1178
1183
  this.units = model.getUnitString();
1179
1184
  }
@@ -1181,20 +1186,21 @@ class MeasureLineDragger extends OrbitDragger {
1181
1186
  this.scale = convertUnits(model.getUnits(), units, 1);
1182
1187
  this.units = units;
1183
1188
  }
1184
- if (precision === "Default") {
1189
+ if (!model)
1190
+ this.precision = 2;
1191
+ else if (precision === "Default")
1185
1192
  this.precision = model.getPrecision();
1186
- }
1187
- else {
1193
+ else
1188
1194
  this.precision = precision;
1189
- }
1190
1195
  this.overlay.updateLineUnits(this.scale, this.units, this.precision);
1191
1196
  };
1192
1197
  this.overlay = new MeasureOverlay(viewer.camera, viewer.canvas);
1193
1198
  this.overlay.attach();
1194
1199
  this.line = new MeasureLine(this.overlay, this.scale, this.units, this.precision);
1195
1200
  this.overlay.addLine(this.line);
1201
+ const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
1196
1202
  this.snapper = new Snapper(viewer.camera, viewer.renderer, viewer.canvas);
1197
- this.snapper.threshold = viewer.extents.getSize(new Vector3()).length() / 10000;
1203
+ this.snapper.threshold = extentsSize / 10000;
1198
1204
  this.objects = [];
1199
1205
  this.updateObjects();
1200
1206
  this.updateUnits();
@@ -1893,7 +1899,7 @@ class WalkDragger {
1893
1899
  constructor(viewer) {
1894
1900
  this.updateControls = () => {
1895
1901
  const size = this.viewer.extents.getSize(new Vector3());
1896
- this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2;
1902
+ this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2 || 1;
1897
1903
  this.joyStickControls.movementSpeed = this.controls.movementSpeed;
1898
1904
  this.joyStickControls.multiplier = this.controls.multiplier;
1899
1905
  };
@@ -2099,7 +2105,7 @@ class FlyDragger {
2099
2105
  constructor(viewer) {
2100
2106
  this.updateControls = () => {
2101
2107
  const size = this.viewer.extents.getSize(new Vector3());
2102
- this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2;
2108
+ this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2 || 1;
2103
2109
  this.joyStickControls.movementSpeed = this.controls.movementSpeed;
2104
2110
  this.joyStickControls.multiplier = this.controls.multiplier;
2105
2111
  };
@@ -2204,27 +2210,27 @@ function zoomTo(viewer, box) {
2204
2210
  if (box.isEmpty())
2205
2211
  return;
2206
2212
  const boxCenter = box.getCenter(new Vector3());
2207
- const boxSize = box.getBoundingSphere(new Sphere()).radius;
2213
+ const boxSize = box.getSize(new Vector3()).length() || 1;
2208
2214
  const rendererSize = viewer.renderer.getSize(new Vector2());
2209
2215
  const aspectRatio = rendererSize.x / rendererSize.y;
2210
2216
  const camera = viewer.camera;
2211
2217
  if (camera.isPerspectiveCamera) {
2212
2218
  const offset = new Vector3(0, 0, 1)
2213
2219
  .applyQuaternion(camera.quaternion)
2214
- .multiplyScalar(boxSize / Math.tan(MathUtils.degToRad(camera.fov * 0.5)));
2220
+ .multiplyScalar(boxSize / (2 * Math.tan(MathUtils.degToRad(camera.fov * 0.5))));
2215
2221
  camera.position.copy(offset).add(boxCenter);
2216
2222
  camera.updateMatrixWorld();
2217
2223
  }
2218
2224
  if (camera.isOrthographicCamera) {
2219
- camera.top = boxSize;
2220
- camera.bottom = -boxSize;
2225
+ camera.top = boxSize / 2;
2226
+ camera.bottom = -boxSize / 2;
2221
2227
  camera.left = camera.bottom * aspectRatio;
2222
2228
  camera.right = camera.top * aspectRatio;
2223
2229
  camera.zoom = 1;
2224
2230
  camera.updateProjectionMatrix();
2225
2231
  const offset = new Vector3(0, 0, 1)
2226
2232
  .applyQuaternion(camera.quaternion)
2227
- .multiplyScalar(viewer.extents.getBoundingSphere(new Sphere()).radius * 3);
2233
+ .multiplyScalar(viewer.extents.getSize(new Vector3()).length() || 1);
2228
2234
  camera.position.copy(offset).add(boxCenter);
2229
2235
  camera.updateMatrixWorld();
2230
2236
  }
@@ -2245,9 +2251,9 @@ const defaultViewPositions = {
2245
2251
  ne: new Vector3(-1, 1, 1).normalize(),
2246
2252
  nw: new Vector3(1, 1, 1).normalize(),
2247
2253
  };
2248
- function setDefaultViewPosition(viewer, position) {
2254
+ function setDefaultViewPosition(viewer, position = "sw") {
2249
2255
  const extentsCenter = viewer.extents.getCenter(new Vector3());
2250
- const extentsSize = viewer.extents.getBoundingSphere(new Sphere()).radius * 2;
2256
+ const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
2251
2257
  const upY = new Vector3(0, 1, 0);
2252
2258
  const offsetY = defaultViewPositions[position] || defaultViewPositions["sw"];
2253
2259
  const up = new Vector3().copy(viewer.camera.up);
@@ -2504,7 +2510,7 @@ class CameraComponent {
2504
2510
  return camera.isOrthographicCamera ? "orthographic" : "perspective";
2505
2511
  }
2506
2512
  switchCamera(camera) {
2507
- const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius * 2 || 1;
2513
+ const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
2508
2514
  const rendererSize = this.viewer.renderer.getSize(new Vector2());
2509
2515
  const aspectRatio = rendererSize.x / rendererSize.y;
2510
2516
  if (camera.isPerspectiveCamera) {
@@ -2544,7 +2550,7 @@ class CameraComponent {
2544
2550
  if (currentCamera.isPerspectiveCamera) {
2545
2551
  const fov = currentCamera.fov;
2546
2552
  const distance = currentCamera.position.distanceTo(target);
2547
- const fieldHeight = 2 * Math.tan(MathUtils.degToRad(fov) / 2) * distance;
2553
+ const fieldHeight = 2 * Math.tan(MathUtils.degToRad(fov * 0.5)) * distance;
2548
2554
  camera = new OrthographicCamera();
2549
2555
  camera.top = fieldHeight / 2;
2550
2556
  camera.bottom = -fieldHeight / 2;
@@ -2602,7 +2608,7 @@ class LightComponent {
2602
2608
  if (this.viewer.extents.isEmpty())
2603
2609
  return;
2604
2610
  const extentsCenter = this.viewer.extents.getCenter(new Vector3());
2605
- const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius;
2611
+ const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
2606
2612
  const upY = new Vector3(0, 1, 0);
2607
2613
  const frontY = new Vector3(0, 0, -1);
2608
2614
  const up = new Vector3().copy(this.viewer.camera.up);
@@ -2611,17 +2617,14 @@ class LightComponent {
2611
2617
  this.directionalLight.position
2612
2618
  .copy(up)
2613
2619
  .applyAxisAngle(front, (-Math.PI * 30) / 180)
2614
- .multiplyScalar(extentsSize * 2)
2620
+ .multiplyScalar(extentsSize)
2615
2621
  .add(extentsCenter);
2616
2622
  this.directionalLight.target.position.copy(extentsCenter);
2617
- this.frontLight.position
2618
- .copy(front)
2619
- .multiplyScalar(extentsSize * 2)
2620
- .add(extentsCenter);
2623
+ this.frontLight.position.copy(front).multiplyScalar(extentsSize).add(extentsCenter);
2621
2624
  this.frontLight.target.position.copy(extentsCenter);
2622
2625
  this.hemisphereLight.position
2623
2626
  .copy(front)
2624
- .multiplyScalar(extentsSize * 3)
2627
+ .multiplyScalar(extentsSize * 1.5)
2625
2628
  .add(extentsCenter);
2626
2629
  this.viewer.scene.add(this.ambientLight);
2627
2630
  this.viewer.scene.add(this.directionalLight);
@@ -3027,8 +3030,9 @@ class SelectionComponent {
3027
3030
  const upPosition = this.getMousePosition(event, new Vector2());
3028
3031
  if (upPosition.distanceTo(this.downPosition) !== 0)
3029
3032
  return;
3033
+ const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
3030
3034
  const snapper = new Snapper(this.viewer.camera, this.viewer.renderer, this.viewer.canvas);
3031
- snapper.threshold = this.viewer.extents.getSize(new Vector3()).length() / 10000;
3035
+ snapper.threshold = extentsSize / 10000;
3032
3036
  let intersections = [];
3033
3037
  this.viewer.models.forEach((model) => {
3034
3038
  const objects = model.getVisibleObjects();
@@ -3797,7 +3801,11 @@ class GltfStructure {
3797
3801
  this.criticalError = null;
3798
3802
  }
3799
3803
  async initialize(loader) {
3800
- this.json = await this.loadController.loadJson();
3804
+ const json = await this.loadController.loadJson();
3805
+ if (json.asset === undefined || json.asset.version[0] < 2) {
3806
+ throw new Error("GltfStructure: Unsupported asset. glTF versions >=2.0 are supported.");
3807
+ }
3808
+ this.json = json;
3801
3809
  this.loader = loader;
3802
3810
  this.uri = this.json.buffers[0].uri || "";
3803
3811
  }
@@ -5070,16 +5078,14 @@ class DynamicGltfLoader {
5070
5078
  const transformedBox = node.geometryExtents.clone();
5071
5079
  const structureRoot = node.structure ? this.structureRoots.get(node.structure.id) : null;
5072
5080
  if (node.group) {
5073
- const matrices = [];
5074
- let currentGroup = node.group;
5075
- while (currentGroup && currentGroup !== structureRoot) {
5076
- if (currentGroup.matrix && currentGroup.matrixAutoUpdate === false) {
5077
- matrices.unshift(currentGroup.matrix);
5078
- }
5079
- currentGroup = currentGroup.parent;
5081
+ const relativeMatrix = new Matrix4();
5082
+ let currentObject = node.group;
5083
+ while (currentObject && currentObject !== structureRoot) {
5084
+ relativeMatrix.premultiply(currentObject.matrix);
5085
+ currentObject = currentObject.parent;
5080
5086
  }
5081
- for (const matrix of matrices) {
5082
- transformedBox.applyMatrix4(matrix);
5087
+ if (!relativeMatrix.equals(new Matrix4())) {
5088
+ transformedBox.applyMatrix4(relativeMatrix);
5083
5089
  }
5084
5090
  }
5085
5091
  if (structureRoot && structureRoot.matrix) {
@@ -5532,6 +5538,15 @@ class DynamicGltfLoader {
5532
5538
  let currentVertexOffset = 0;
5533
5539
  for (const mesh of group.objects) {
5534
5540
  const geometry = mesh.geometry.clone();
5541
+ const relativeMatrix = new Matrix4();
5542
+ let currentObject = mesh;
5543
+ while (currentObject && currentObject !== rootGroup) {
5544
+ relativeMatrix.premultiply(currentObject.matrix);
5545
+ currentObject = currentObject.parent;
5546
+ }
5547
+ if (!relativeMatrix.equals(new Matrix4())) {
5548
+ geometry.applyMatrix4(relativeMatrix);
5549
+ }
5535
5550
  const handle = mesh.userData.handle;
5536
5551
  if (!this.objectIdToIndex.has(handle)) {
5537
5552
  this.objectIdToIndex.set(handle, this.maxObjectId++);
@@ -5626,7 +5641,16 @@ class DynamicGltfLoader {
5626
5641
  let isEdge = false;
5627
5642
  group.objects.forEach((line) => {
5628
5643
  isEdge = line.userData.isEdge;
5629
- const geometry = line.geometry;
5644
+ const geometry = line.geometry.clone();
5645
+ const relativeMatrix = new Matrix4();
5646
+ let currentObject = line;
5647
+ while (currentObject && currentObject !== rootGroup) {
5648
+ relativeMatrix.premultiply(currentObject.matrix);
5649
+ currentObject = currentObject.parent;
5650
+ }
5651
+ if (!relativeMatrix.equals(new Matrix4())) {
5652
+ geometry.applyMatrix4(relativeMatrix);
5653
+ }
5630
5654
  const positionAttr = geometry.attributes.position;
5631
5655
  const vertexCount = positionAttr.count;
5632
5656
  const handle = line.userData.handle;
@@ -5649,6 +5673,7 @@ class DynamicGltfLoader {
5649
5673
  indices.push(vertexOffset + i, vertexOffset + i + 1);
5650
5674
  }
5651
5675
  vertexOffset += vertexCount;
5676
+ geometry.dispose();
5652
5677
  });
5653
5678
  const geometry = new BufferGeometry();
5654
5679
  geometry.setAttribute("position", new BufferAttribute(positions, 3));
@@ -5720,6 +5745,15 @@ class DynamicGltfLoader {
5720
5745
  for (const line of group.objects) {
5721
5746
  isEdge = line.userData.isEdge;
5722
5747
  const geometry = line.geometry.clone();
5748
+ const relativeMatrix = new Matrix4();
5749
+ let currentObject = line;
5750
+ while (currentObject && currentObject !== rootGroup) {
5751
+ relativeMatrix.premultiply(currentObject.matrix);
5752
+ currentObject = currentObject.parent;
5753
+ }
5754
+ if (!relativeMatrix.equals(new Matrix4())) {
5755
+ geometry.applyMatrix4(relativeMatrix);
5756
+ }
5723
5757
  const handle = line.userData.handle;
5724
5758
  if (!this.objectIdToIndex.has(handle)) {
5725
5759
  this.objectIdToIndex.set(handle, this.maxObjectId++);
@@ -5805,6 +5839,15 @@ class DynamicGltfLoader {
5805
5839
  const handles = new Set();
5806
5840
  for (const points of group.objects) {
5807
5841
  const geometry = points.geometry.clone();
5842
+ const relativeMatrix = new Matrix4();
5843
+ let currentObject = points;
5844
+ while (currentObject && currentObject !== rootGroup) {
5845
+ relativeMatrix.premultiply(currentObject.matrix);
5846
+ currentObject = currentObject.parent;
5847
+ }
5848
+ if (!relativeMatrix.equals(new Matrix4())) {
5849
+ geometry.applyMatrix4(relativeMatrix);
5850
+ }
5808
5851
  geometries.push(geometry);
5809
5852
  optimizedObjects.push(points);
5810
5853
  handles.add(points.userData.handle);
@@ -6293,48 +6336,59 @@ class GLTFLoadingManager extends LoadingManager {
6293
6336
 
6294
6337
  const BINARY_EXTENSION_HEADER_MAGIC = "glTF";
6295
6338
  const BINARY_EXTENSION_HEADER_LENGTH = 12;
6296
- const BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4e4f534a, BIN: 0x004e4042 };
6297
- class GLTFBinaryExtension {
6339
+ const BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4e4f534a, BIN: 0x004e4942 };
6340
+ class GLTFBinaryParser {
6298
6341
  constructor(data) {
6299
- const headerView = new DataView(data, 0, BINARY_EXTENSION_HEADER_LENGTH);
6342
+ const dataView = new DataView(data, 0);
6300
6343
  const textDecoder = new TextDecoder();
6301
- const magic = textDecoder.decode(new Uint8Array(data.slice(0, 4)));
6344
+ const magic = textDecoder.decode(new Uint8Array(data, 0, Math.min(4, data.byteLength)));
6302
6345
  if (magic !== BINARY_EXTENSION_HEADER_MAGIC) {
6303
- this.content = textDecoder.decode(data);
6346
+ this.content = new Uint8Array(data);
6304
6347
  return;
6305
6348
  }
6306
- const header = {
6349
+ this.header = {
6307
6350
  magic,
6308
- version: headerView.getUint32(4, true),
6309
- length: headerView.getUint32(8, true),
6351
+ version: dataView.getUint32(4, true),
6352
+ length: dataView.getUint32(8, true),
6310
6353
  };
6311
- if (header.magic !== BINARY_EXTENSION_HEADER_MAGIC) {
6312
- throw new Error("Unsupported glTF-Binary header.");
6313
- }
6314
- if (header.version < 2.0) {
6315
- throw new Error("Legacy binary file detected.");
6316
- }
6317
- const chunkContentsLength = header.length - BINARY_EXTENSION_HEADER_LENGTH;
6318
- const chunkView = new DataView(data, BINARY_EXTENSION_HEADER_LENGTH);
6319
- let chunkIndex = 0;
6320
- while (chunkIndex < chunkContentsLength) {
6321
- const chunkLength = chunkView.getUint32(chunkIndex, true);
6322
- chunkIndex += 4;
6323
- const chunkType = chunkView.getUint32(chunkIndex, true);
6324
- chunkIndex += 4;
6354
+ if (this.header.length !== data.byteLength) {
6355
+ throw new Error("GLTFBinaryParser: Invalid binary file header.");
6356
+ }
6357
+ if (this.header.version < 2.0) {
6358
+ throw new Error("GLTFBinaryParser: Legacy binary file detected.");
6359
+ }
6360
+ let offset = BINARY_EXTENSION_HEADER_LENGTH;
6361
+ while (offset < this.header.length) {
6362
+ const chunkLength = dataView.getUint32(offset, true);
6363
+ offset += 4;
6364
+ const chunkType = dataView.getUint32(offset, true);
6365
+ offset += 4;
6325
6366
  if (chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON) {
6326
- const contentArray = new Uint8Array(data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength);
6327
- this.content = textDecoder.decode(contentArray);
6367
+ this.content = new Uint8Array(data, offset, chunkLength);
6328
6368
  }
6329
6369
  else if (chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN) {
6330
- const byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;
6331
- this.body = data.slice(byteOffset, byteOffset + chunkLength);
6370
+ this.body = data.slice(offset, offset + chunkLength);
6332
6371
  }
6333
- chunkIndex += chunkLength;
6372
+ offset += chunkLength;
6334
6373
  }
6335
6374
  if (typeof this.content === "undefined") {
6336
- throw new Error("JSON content not found.");
6375
+ throw new Error("GLTFBinaryParser: JSON content not found.");
6337
6376
  }
6377
+ if (typeof this.body === "undefined") {
6378
+ throw new Error("GLTFBinaryParser: Binary buffer chunk not found or type not supported.");
6379
+ }
6380
+ }
6381
+ }
6382
+
6383
+ class JSONStreamParser extends JSONParser {
6384
+ constructor(data) {
6385
+ super();
6386
+ this.onValue = ({ value, stack }) => {
6387
+ if (stack.length === 0)
6388
+ this.json = value;
6389
+ };
6390
+ if (data)
6391
+ this.write(data);
6338
6392
  }
6339
6393
  }
6340
6394
 
@@ -6443,13 +6497,13 @@ class GLTFFileDynamicLoader extends Loader {
6443
6497
  this.viewer.emitEvent({ type: "geometryprogress", data: progress, file });
6444
6498
  };
6445
6499
  const data = await loader.loadAsync(this.manager.fileURL, progress);
6446
- const extension = new GLTFBinaryExtension(data);
6447
- this.gltf = JSON.parse(extension.content);
6448
- this.glb = extension.body;
6449
- if (/\.glb$/i.test(this.manager.fileURL) && !this.glb) {
6450
- throw new Error("GLTFFileDynamicLoader: Binary buffer chunk not found or type not supported.");
6500
+ const binaryParser = new GLTFBinaryParser(data);
6501
+ const jsonParser = new JSONStreamParser(binaryParser.content);
6502
+ if (!jsonParser.json) {
6503
+ throw new Error("GLTFFileDynamicLoader: JSON content not found or invalid.");
6451
6504
  }
6452
- return this.gltf;
6505
+ this.glb = binaryParser.body;
6506
+ return jsonParser.json;
6453
6507
  },
6454
6508
  loadBinaryData: (ranges, uri = "") => {
6455
6509
  const loader = new RangesLoader();
@@ -6520,13 +6574,16 @@ class GLTFCloudDynamicLoader extends Loader {
6520
6574
  });
6521
6575
  const loadController = {
6522
6576
  loadJson: async () => {
6523
- const progress = (progress) => {
6577
+ const jsonParser = new JSONStreamParser();
6578
+ const progress = (progress, chunk) => {
6579
+ jsonParser.write(chunk);
6524
6580
  this.viewer.emitEvent({ type: "geometryprogress", data: progress, file: model.file, model });
6525
6581
  };
6526
- const arrayBuffer = await model.downloadResource(model.database, progress, this.gltfLoader.getAbortController().signal);
6527
- const text = new TextDecoder().decode(arrayBuffer);
6528
- const json = JSON.parse(text);
6529
- return json;
6582
+ await model.downloadResource(model.database, progress, this.gltfLoader.getAbortController().signal);
6583
+ if (!jsonParser.json) {
6584
+ throw new Error("GLTFCloudDynamicLoader: JSON content not found or invalid.");
6585
+ }
6586
+ return jsonParser.json;
6530
6587
  },
6531
6588
  loadBinaryData: (requests) => {
6532
6589
  const ranges = requests.map((request) => ({
@@ -6963,10 +7020,8 @@ class Viewer extends EventEmitter2 {
6963
7020
  if (model && typeof model.database === "string") {
6964
7021
  file = model.file;
6965
7022
  }
6966
- if (!model)
6967
- throw new Error(`Format not supported`);
6968
7023
  let format = params.format;
6969
- if (!format && typeof file["type"] === "string")
7024
+ if (!format && file && typeof file["type"] === "string")
6970
7025
  format = file["type"].split(".").pop();
6971
7026
  if (!format && typeof file === "string")
6972
7027
  format = file.split(".").pop();
@@ -6974,7 +7029,7 @@ class Viewer extends EventEmitter2 {
6974
7029
  format = file.name.split(".").pop();
6975
7030
  const loader = loaders.createLoader(this, model, format);
6976
7031
  if (!loader)
6977
- throw new Error(`Format not supported`);
7032
+ throw new Error(`Format not supported (${format})`);
6978
7033
  this.loaders.push(loader);
6979
7034
  this.emitEvent({ type: "geometrystart", file, model });
6980
7035
  try {
@@ -7016,7 +7071,6 @@ class Viewer extends EventEmitter2 {
7016
7071
  this.scene.clear();
7017
7072
  this.helpers.clear();
7018
7073
  this.extents.makeEmpty();
7019
- this.target.set(0, 0, 0);
7020
7074
  this.syncOptions();
7021
7075
  this.syncOverlay();
7022
7076
  this.emitEvent({ type: "clear" });
@@ -7132,7 +7186,7 @@ class Viewer extends EventEmitter2 {
7132
7186
  const getVector3FromPoint3d = ({ x, y, z }) => new Vector3(x, y, z);
7133
7187
  const setOrthogonalCamera = (orthogonal_camera) => {
7134
7188
  if (orthogonal_camera) {
7135
- const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
7189
+ const extentsSize = this.extents.getSize(new Vector3()).length() || 1;
7136
7190
  const rendererSize = this.renderer.getSize(new Vector2());
7137
7191
  const aspectRatio = rendererSize.x / rendererSize.y;
7138
7192
  const camera = new OrthographicCamera();
@@ -7158,7 +7212,7 @@ class Viewer extends EventEmitter2 {
7158
7212
  };
7159
7213
  const setPerspectiveCamera = (perspective_camera) => {
7160
7214
  if (perspective_camera) {
7161
- const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
7215
+ const extentsSize = this.extents.getSize(new Vector3()).length() || 1;
7162
7216
  const rendererSize = this.renderer.getSize(new Vector2());
7163
7217
  const aspectRatio = rendererSize.x / rendererSize.y;
7164
7218
  const camera = new PerspectiveCamera();