@inweb/viewer-three 27.1.0 → 27.1.2

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 (85) 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/InfoPanelComponent.js +7 -9
  12. package/dist/extensions/components/InfoPanelComponent.js.map +1 -1
  13. package/dist/extensions/components/InfoPanelComponent.min.js +1 -1
  14. package/dist/extensions/components/InfoPanelComponent.module.js +7 -9
  15. package/dist/extensions/components/InfoPanelComponent.module.js.map +1 -1
  16. package/dist/extensions/components/LightHelperComponent.js +5 -5
  17. package/dist/extensions/components/LightHelperComponent.js.map +1 -1
  18. package/dist/extensions/components/LightHelperComponent.min.js +1 -1
  19. package/dist/extensions/components/LightHelperComponent.module.js +6 -6
  20. package/dist/extensions/components/LightHelperComponent.module.js.map +1 -1
  21. package/dist/extensions/loaders/GLTFCloudLoader.js +1 -1
  22. package/dist/extensions/loaders/GLTFCloudLoader.js.map +1 -1
  23. package/dist/extensions/loaders/GLTFCloudLoader.min.js +1 -1
  24. package/dist/extensions/loaders/GLTFCloudLoader.module.js +1 -1
  25. package/dist/extensions/loaders/GLTFCloudLoader.module.js.map +1 -1
  26. package/dist/extensions/loaders/GLTFFileLoader.js +1 -1
  27. package/dist/extensions/loaders/GLTFFileLoader.js.map +1 -1
  28. package/dist/extensions/loaders/GLTFFileLoader.min.js +1 -1
  29. package/dist/extensions/loaders/GLTFFileLoader.module.js +1 -1
  30. package/dist/extensions/loaders/GLTFFileLoader.module.js.map +1 -1
  31. package/dist/extensions/loaders/IFCXLoader.js +2 -2
  32. package/dist/extensions/loaders/IFCXLoader.js.map +1 -1
  33. package/dist/extensions/loaders/IFCXLoader.min.js +1 -1
  34. package/dist/extensions/loaders/IFCXLoader.module.js +2 -2
  35. package/dist/extensions/loaders/IFCXLoader.module.js.map +1 -1
  36. package/dist/extensions/loaders/PotreeLoader.js +1 -1
  37. package/dist/extensions/loaders/PotreeLoader.js.map +1 -1
  38. package/dist/extensions/loaders/PotreeLoader.min.js +1 -1
  39. package/dist/extensions/loaders/PotreeLoader.module.js +1 -1
  40. package/dist/extensions/loaders/PotreeLoader.module.js.map +1 -1
  41. package/dist/viewer-three.js +1379 -104
  42. package/dist/viewer-three.js.map +1 -1
  43. package/dist/viewer-three.min.js +4 -4
  44. package/dist/viewer-three.module.js +133 -105
  45. package/dist/viewer-three.module.js.map +1 -1
  46. package/extensions/components/AxesHelperComponent.ts +13 -12
  47. package/extensions/components/GridHelperComponent.ts +4 -6
  48. package/extensions/components/InfoPanelComponent.ts +8 -11
  49. package/extensions/components/LightHelperComponent.ts +6 -6
  50. package/extensions/loaders/GLTFCloudLoader.ts +1 -1
  51. package/extensions/loaders/GLTFFileLoader.ts +1 -1
  52. package/extensions/loaders/IFCX/IFCXCloudLoader.ts +1 -1
  53. package/extensions/loaders/IFCX/IFCXFileLoader.ts +1 -1
  54. package/extensions/loaders/Potree/PotreeFileLoader.ts +1 -1
  55. package/lib/Viewer/Viewer.d.ts +1 -1
  56. package/lib/Viewer/commands/CreatePreview.d.ts +1 -1
  57. package/lib/Viewer/commands/SetDefaultViewPosition.d.ts +1 -1
  58. package/lib/Viewer/components/RenderLoopComponent.d.ts +1 -1
  59. package/lib/Viewer/draggers/FlyDragger.d.ts +1 -0
  60. package/lib/Viewer/draggers/WalkDragger.d.ts +1 -0
  61. package/lib/Viewer/loaders/GLTFBinaryParser.d.ts +11 -0
  62. package/lib/Viewer/loaders/GLTFFileDynamicLoader.d.ts +0 -1
  63. package/lib/Viewer/loaders/JSONStreamParser.d.ts +5 -0
  64. package/lib/Viewer/loaders/index.d.ts +2 -1
  65. package/package.json +7 -5
  66. package/src/Viewer/Viewer.ts +32 -32
  67. package/src/Viewer/commands/CreatePreview.ts +2 -2
  68. package/src/Viewer/commands/SetDefaultViewPosition.ts +3 -3
  69. package/src/Viewer/commands/ZoomTo.ts +6 -6
  70. package/src/Viewer/components/CameraComponent.ts +3 -3
  71. package/src/Viewer/components/InfoComponent.ts +4 -4
  72. package/src/Viewer/components/LightComponent.ts +5 -8
  73. package/src/Viewer/components/RenderLoopComponent.ts +2 -2
  74. package/src/Viewer/components/SelectionComponent.ts +3 -1
  75. package/src/Viewer/draggers/CuttingPlaneDragger.ts +6 -6
  76. package/src/Viewer/draggers/FlyDragger.ts +9 -2
  77. package/src/Viewer/draggers/MeasureLineDragger.ts +10 -7
  78. package/src/Viewer/draggers/WalkDragger.ts +9 -2
  79. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +7 -1
  80. package/src/Viewer/loaders/{GLTFBinaryExtension.ts → GLTFBinaryParser.ts} +34 -29
  81. package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +12 -11
  82. package/src/Viewer/loaders/GLTFFileDynamicLoader.ts +11 -10
  83. package/src/Viewer/loaders/JSONStreamParser.ts +38 -0
  84. package/src/Viewer/loaders/index.ts +2 -1
  85. package/lib/Viewer/loaders/GLTFBinaryExtension.d.ts +0 -5
@@ -35,7 +35,7 @@ class AxesHelperComponent implements IComponent {
35
35
  this.axesHelper2 = new AxesHelper(1);
36
36
  this.modelHelpers = [];
37
37
 
38
- this.axesHelper1.setColors("#ccc", "#ccc", "#ccc");
38
+ // this.axesHelper1.setColors("#ccc", "#ccc", "#ccc");
39
39
 
40
40
  this.viewer = viewer;
41
41
  this.viewer.addEventListener("initialize", this.syncHelper);
@@ -70,27 +70,28 @@ class AxesHelperComponent implements IComponent {
70
70
  this.axesHelper1.removeFromParent();
71
71
  this.axesHelper2.removeFromParent();
72
72
 
73
- const size = this.viewer.extents.getSize(new Vector3()).length();
74
- const center = this.viewer.extents.getCenter(new Vector3());
73
+ const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
74
+ const extentsCenter = this.viewer.extents.getCenter(new Vector3());
75
75
 
76
76
  this.axesHelper1.position.set(0, 0, 0);
77
- this.axesHelper1.scale.setScalar(size * 1.25);
77
+ this.axesHelper1.scale.setScalar(extentsSize * 1.5);
78
+ this.viewer.helpers.add(this.axesHelper1);
78
79
 
79
- this.axesHelper2.position.copy(center);
80
- this.axesHelper2.scale.setScalar(size);
80
+ if (this.viewer.models.length < 1) return;
81
81
 
82
- this.viewer.helpers.add(this.axesHelper1);
82
+ this.axesHelper2.position.copy(extentsCenter);
83
+ this.axesHelper2.scale.setScalar(extentsSize);
83
84
  this.viewer.helpers.add(this.axesHelper2);
84
85
 
85
86
  if (this.viewer.models.length < 2) return;
86
87
 
87
88
  this.viewer.models.forEach((model) => {
88
- const extents = model.getExtents(new Box3());
89
- const size = extents.getSize(new Vector3()).length();
90
- const center = extents.getCenter(new Vector3());
89
+ const modelExtents = model.getExtents(new Box3());
90
+ const modelSize = modelExtents.getSize(new Vector3()).length() || 1;
91
+ const modelCenter = modelExtents.getCenter(new Vector3());
91
92
 
92
- const helper = new AxesHelper(size);
93
- helper.position.copy(center);
93
+ const helper = new AxesHelper(modelSize);
94
+ helper.position.copy(modelCenter);
94
95
 
95
96
  this.modelHelpers.push(helper);
96
97
  this.viewer.helpers.add(helper);
@@ -48,16 +48,14 @@ class GridHelperComponent implements IComponent {
48
48
  syncHelper = () => {
49
49
  this.gridHelper.removeFromParent();
50
50
 
51
- if (this.viewer.extents.isEmpty()) return;
52
-
53
- const size = this.viewer.extents.getSize(new Vector3()).multiply(this.viewer.camera.up).length();
54
- const center = this.viewer.extents.getCenter(new Vector3());
51
+ const extentsSizeUp = this.viewer.extents.getSize(new Vector3()).multiply(this.viewer.camera.up).length() || 1;
52
+ const extentsCenter = this.viewer.extents.getCenter(new Vector3());
55
53
 
56
54
  const upY = new Vector3(0, 1, 0);
57
55
  const up = new Vector3().copy(this.viewer.camera.up);
58
56
 
59
- this.gridHelper.scale.setScalar(size);
60
- this.gridHelper.position.copy(center);
57
+ this.gridHelper.scale.setScalar(extentsSizeUp);
58
+ this.gridHelper.position.copy(extentsCenter);
61
59
  this.gridHelper.quaternion.setFromUnitVectors(upY, up);
62
60
 
63
61
  this.viewer.helpers.add(this.gridHelper);
@@ -107,9 +107,8 @@ class InfoPanelComponent implements IComponent {
107
107
  this.viewer.addEventListener("clear", this.updateSceneInfo);
108
108
  this.viewer.addEventListener("geometryend", this.updateSceneInfo);
109
109
  this.viewer.addEventListener("render", this.updateRenderInfo);
110
- this.viewer.addEventListener("animate", this.updatePreformanceInfo);
110
+ this.viewer.addEventListener("animate", this.updateViewer);
111
111
 
112
- this.updatePreformanceInfo();
113
112
  this.updateRenderInfo();
114
113
  this.updateSceneInfo();
115
114
  }
@@ -118,7 +117,7 @@ class InfoPanelComponent implements IComponent {
118
117
  this.viewer.removeEventListener("clear", this.updateSceneInfo);
119
118
  this.viewer.removeEventListener("geometryend", this.updateSceneInfo);
120
119
  this.viewer.removeEventListener("render", this.updateRenderInfo);
121
- this.viewer.removeEventListener("animate", this.updatePreformanceInfo);
120
+ this.viewer.removeEventListener("animate", this.updateViewer);
122
121
 
123
122
  this.performancePanel = undefined;
124
123
  this.renderPanel = undefined;
@@ -141,7 +140,7 @@ class InfoPanelComponent implements IComponent {
141
140
  }
142
141
  }
143
142
 
144
- updatePreformanceInfo = () => {
143
+ updateRenderInfo = () => {
145
144
  const info = this.viewer.info;
146
145
 
147
146
  const text = [];
@@ -149,13 +148,7 @@ class InfoPanelComponent implements IComponent {
149
148
  text.push(`Frame Time: ${info.performance.frameTime} ms`);
150
149
  this.performancePanel.update(text.join("\n"));
151
150
 
152
- this.viewer.update();
153
- };
154
-
155
- updateRenderInfo = () => {
156
- const info = this.viewer.info;
157
-
158
- const text = [];
151
+ text.length = 0;
159
152
  text.push(`Viewport: ${info.render.viewport.width} x ${info.render.viewport.height}`);
160
153
  text.push(`Antialiasing: ${info.render.antialiasing}`);
161
154
  text.push(`Draw Calls: ${info.render.drawCalls}`);
@@ -192,6 +185,10 @@ class InfoPanelComponent implements IComponent {
192
185
  text.push(`JS Heap Used: ${formatBytes(info.memory.usedJSHeapSize)}`);
193
186
  this.memoryPanel.update(text.join("\n"));
194
187
  };
188
+
189
+ updateViewer = () => {
190
+ this.viewer.update();
191
+ };
195
192
  }
196
193
 
197
194
  components.registerComponent("InfoPanelComponent", (viewer) => new InfoPanelComponent(viewer));
@@ -21,7 +21,7 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import { DirectionalLightHelper, HemisphereLightHelper, PointLightHelper, Sphere } from "three";
24
+ import { DirectionalLightHelper, HemisphereLightHelper, PointLightHelper, Vector3 } from "three";
25
25
  import { IComponent, components, Viewer } from "@inweb/viewer-three";
26
26
 
27
27
  class LightHelperComponent implements IComponent {
@@ -53,15 +53,15 @@ class LightHelperComponent implements IComponent {
53
53
  });
54
54
  this.lightHelpers.length = 0;
55
55
 
56
- const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius * 2;
57
- const size = extentsSize / 20;
56
+ const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
57
+ const helperSize = extentsSize / 20;
58
58
 
59
59
  this.viewer.scene.traverse((object: any) => {
60
60
  let helper: DirectionalLightHelper | HemisphereLightHelper | PointLightHelper;
61
61
 
62
- if (object.isDirectionalLight) helper = new DirectionalLightHelper(object, size, "#aa0000");
63
- else if (object.isHemisphereLight) helper = new HemisphereLightHelper(object, size, "#ff9800");
64
- else if (object.isPointLight) helper = new PointLightHelper(object, size, "#ff9800");
62
+ if (object.isDirectionalLight) helper = new DirectionalLightHelper(object, helperSize, "#aa0000");
63
+ else if (object.isHemisphereLight) helper = new HemisphereLightHelper(object, helperSize, "#ff9800");
64
+ else if (object.isPointLight) helper = new PointLightHelper(object, helperSize, "#ff9800");
65
65
 
66
66
  if (helper) {
67
67
  this.lightHelpers.push(helper);
@@ -65,9 +65,9 @@ class GLTFCloudLoader extends Loader {
65
65
 
66
66
  this.viewer.syncOptions();
67
67
  this.viewer.syncOverlay();
68
- this.viewer.update();
69
68
 
70
69
  this.viewer.emitEvent({ type: "databasechunk", data: gltf.scene, file: model.file, model });
70
+ this.viewer.update(true);
71
71
 
72
72
  return this;
73
73
  }
@@ -76,9 +76,9 @@ export class GLTFFileLoader extends Loader {
76
76
 
77
77
  this.viewer.syncOptions();
78
78
  this.viewer.syncOverlay();
79
- this.viewer.update();
80
79
 
81
80
  this.viewer.emitEvent({ type: "databasechunk", data: gltf.scene, file });
81
+ this.viewer.update(true);
82
82
 
83
83
  return this;
84
84
  }
@@ -70,9 +70,9 @@ export class IFCXCloudLoader extends Loader {
70
70
 
71
71
  this.viewer.syncOptions();
72
72
  this.viewer.syncOverlay();
73
- this.viewer.update();
74
73
 
75
74
  this.viewer.emitEvent({ type: "databasechunk", data: scene, file });
75
+ this.viewer.update(true);
76
76
 
77
77
  return this;
78
78
  }
@@ -70,9 +70,9 @@ export class IFCXFileLoader extends Loader {
70
70
 
71
71
  this.viewer.syncOptions();
72
72
  this.viewer.syncOverlay();
73
- this.viewer.update();
74
73
 
75
74
  this.viewer.emitEvent({ type: "databasechunk", data: scene, file });
75
+ this.viewer.update(true);
76
76
 
77
77
  return this;
78
78
  }
@@ -91,9 +91,9 @@ export class PotreeFileLoader extends Loader {
91
91
 
92
92
  this.viewer.syncOptions();
93
93
  this.viewer.syncOverlay();
94
- this.viewer.update();
95
94
 
96
95
  this.viewer.emitEvent({ type: "databasechunk", data: pco, file });
96
+ this.viewer.update(true);
97
97
 
98
98
  return this;
99
99
  }
@@ -62,7 +62,7 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
62
62
  isInitialized(): boolean;
63
63
  setSize(width: number, height: number, updateStyle?: boolean): void;
64
64
  update(force?: boolean): void;
65
- render(time?: DOMHighResTimeStamp): void;
65
+ render(time?: DOMHighResTimeStamp, force?: boolean): void;
66
66
  loadReferences(model: Model | File | Assembly): Promise<this>;
67
67
  /**
68
68
  * Loads a file into the viewer.
@@ -1,2 +1,2 @@
1
1
  import type { Viewer } from "../Viewer";
2
- export declare function createPreview(viewer: Viewer, type?: string, encoderOptions?: number): string;
2
+ export declare function createPreview(viewer: Viewer, type?: string, quality?: number): string;
@@ -12,4 +12,4 @@ export declare const defaultViewPositions: {
12
12
  ne: Vector3;
13
13
  nw: Vector3;
14
14
  };
15
- export declare function setDefaultViewPosition(viewer: Viewer, position: string): void;
15
+ export declare function setDefaultViewPosition(viewer: Viewer, position?: string): void;
@@ -5,5 +5,5 @@ export declare class RenderLoopComponent implements IComponent {
5
5
  protected requestId: number;
6
6
  constructor(viewer: Viewer);
7
7
  dispose(): void;
8
- animate: (time?: number) => void;
8
+ animate: (time: number) => void;
9
9
  }
@@ -13,4 +13,5 @@ export declare class FlyDragger implements IDragger {
13
13
  flyspeedChange: (event: any) => void;
14
14
  viewerRender: () => void;
15
15
  viewerZoom: () => void;
16
+ animate: () => void;
16
17
  }
@@ -13,4 +13,5 @@ export declare class WalkDragger implements IDragger {
13
13
  walkspeedChange: (event: any) => void;
14
14
  viewerRender: () => void;
15
15
  viewerZoom: () => void;
16
+ animate: () => void;
16
17
  }
@@ -0,0 +1,11 @@
1
+ export interface GLTFBinaryHeader {
2
+ magic: string;
3
+ version: number;
4
+ length: number;
5
+ }
6
+ export declare class GLTFBinaryParser {
7
+ header: GLTFBinaryHeader;
8
+ content: Uint8Array;
9
+ body: ArrayBuffer;
10
+ constructor(data: ArrayBuffer);
11
+ }
@@ -5,7 +5,6 @@ export declare class GLTFFileDynamicLoader extends Loader {
5
5
  viewer: Viewer;
6
6
  private gltfLoader;
7
7
  private manager;
8
- private gltf;
9
8
  private glb;
10
9
  constructor(viewer: Viewer);
11
10
  dispose(): void;
@@ -0,0 +1,5 @@
1
+ import { JSONParser } from "@streamparser/json";
2
+ export declare class JSONStreamParser extends JSONParser {
3
+ json: any;
4
+ constructor(data?: Uint8Array);
5
+ }
@@ -59,11 +59,12 @@ import { ILoadersRegistry } from "@inweb/viewer-core";
59
59
  *
60
60
  * this.viewer.syncOptions();
61
61
  * this.viewer.syncOverlay();
62
- * this.viewer.update();
63
62
  *
64
63
  * this.viewer.emitEvent({ type: "geometryprogress", data: 1, file });
65
64
  * this.viewer.emitEvent({ type: "databasechunk", data: scene, file });
66
65
  *
66
+ * this.viewer.update(true);
67
+ *
67
68
  * return Promise.resove(this);
68
69
  * };
69
70
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inweb/viewer-three",
3
- "version": "27.1.0",
3
+ "version": "27.1.2",
4
4
  "description": "JavaScript library for rendering CAD and BIM files in a browser using Three.js",
5
5
  "homepage": "https://cloud.opendesign.com/docs/index.html",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -35,17 +35,19 @@
35
35
  "docs": "typedoc"
36
36
  },
37
37
  "dependencies": {
38
- "@inweb/client": "~27.1.0",
39
- "@inweb/eventemitter2": "~27.1.0",
40
- "@inweb/markup": "~27.1.0",
41
- "@inweb/viewer-core": "~27.1.0"
38
+ "@inweb/client": "~27.1.2",
39
+ "@inweb/eventemitter2": "~27.1.2",
40
+ "@inweb/markup": "~27.1.2",
41
+ "@inweb/viewer-core": "~27.1.2"
42
42
  },
43
43
  "devDependencies": {
44
+ "@streamparser/json": "^0.0.22",
44
45
  "@types/three": "^0.180.0",
45
46
  "potree-core": "^2.0.11",
46
47
  "three": "^0.180.0"
47
48
  },
48
49
  "peerDependencies": {
50
+ "@streamparser/json": "^0.0.22",
49
51
  "@types/three": "^0.180.0",
50
52
  "three": "^0.180.0"
51
53
  }
@@ -24,13 +24,13 @@
24
24
  import {
25
25
  Box3,
26
26
  LinearSRGBColorSpace,
27
+ // LinearToneMapping,
27
28
  Object3D,
28
29
  OrthographicCamera,
29
30
  PerspectiveCamera,
30
31
  Plane,
31
32
  Raycaster,
32
33
  Scene,
33
- Sphere,
34
34
  Vector2,
35
35
  Vector3,
36
36
  WebGLRenderer,
@@ -195,20 +195,16 @@ export class Viewer
195
195
  });
196
196
  this.renderer.setPixelRatio(pixelRatio);
197
197
  this.renderer.setSize(width, height);
198
- // this.renderer.toneMapping = LinearToneMapping;
199
198
  this.renderer.outputColorSpace = LinearSRGBColorSpace;
199
+ // this.renderer.toneMapping = LinearToneMapping;
200
200
 
201
201
  this.renderPass = new RenderPass(this.scene, this.camera);
202
-
203
202
  this.helpersPass = new RenderPass(this.helpers, this.camera);
204
203
  this.helpersPass.clear = false;
205
-
206
204
  this.fxaaPass = new FXAAPass();
207
205
  this.smaaPass = new SMAAPass();
208
-
209
206
  this.ssaaRenderPass = new SSAARenderPass([this.scene, this.helpers], this.camera);
210
207
  this.ssaaRenderPass.unbiased = true;
211
-
212
208
  this.outputPass = new OutputPass();
213
209
 
214
210
  this.composer = new EffectComposer(this.renderer);
@@ -233,13 +229,15 @@ export class Viewer
233
229
  this.syncOverlay();
234
230
 
235
231
  this._renderTime = performance.now();
236
- this.render(this._renderTime);
237
232
 
238
- if (typeof onProgress === "function")
239
- onProgress(new ProgressEvent("progress", { lengthComputable: true, loaded: 1, total: 1 }));
233
+ if (typeof onProgress === "function") {
234
+ const event = new ProgressEvent("progress", { lengthComputable: true, loaded: 1, total: 1 });
235
+ onProgress(event);
236
+ }
240
237
 
241
238
  this.emitEvent({ type: "initializeprogress", data: 1, loaded: 1, total: 1 });
242
239
  this.emitEvent({ type: "initialize" });
240
+ this.update(true);
243
241
 
244
242
  return Promise.resolve(this);
245
243
  }
@@ -310,8 +308,8 @@ export class Viewer
310
308
  this.renderer.setSize(width, height, updateStyle);
311
309
  this.composer.setSize(width, height);
312
310
 
313
- this.update(true);
314
311
  this.emitEvent({ type: "resize", width, height });
312
+ this.update(true);
315
313
  }
316
314
 
317
315
  update(force = false): void {
@@ -326,9 +324,9 @@ export class Viewer
326
324
 
327
325
  // Internal render routines
328
326
 
329
- render(time?: DOMHighResTimeStamp): void {
327
+ render(time?: DOMHighResTimeStamp, force = false): void {
330
328
  if (!this.renderer) return;
331
- if (!this._renderNeeded) return;
329
+ if (!this._renderNeeded && !force) return;
332
330
 
333
331
  if (!time) time = performance.now();
334
332
  const deltaTime = (time - this._renderTime) / 1000;
@@ -459,15 +457,14 @@ export class Viewer
459
457
  if (model && typeof model.database === "string") {
460
458
  file = model.file;
461
459
  }
462
- if (!model) throw new Error(`Format not supported`);
463
460
 
464
461
  let format = params.format;
465
- if (!format && typeof file["type"] === "string") format = file["type"].split(".").pop();
462
+ if (!format && file && typeof file["type"] === "string") format = file["type"].split(".").pop();
466
463
  if (!format && typeof file === "string") format = file.split(".").pop();
467
464
  if (!format && file instanceof globalThis.File) format = file.name.split(".").pop();
468
465
 
469
466
  const loader: ILoader = loaders.createLoader(this, model, format);
470
- if (!loader) throw new Error(`Format not supported`);
467
+ if (!loader) throw new Error(`Format not supported (${format})`);
471
468
  this.loaders.push(loader);
472
469
 
473
470
  this.emitEvent({ type: "geometrystart", file, model });
@@ -479,6 +476,7 @@ export class Viewer
479
476
  throw error;
480
477
  }
481
478
  this.emitEvent({ type: "geometryend", file, model });
479
+ this.update(true);
482
480
 
483
481
  return this;
484
482
  }
@@ -534,13 +532,12 @@ export class Viewer
534
532
  this.helpers.clear();
535
533
 
536
534
  this.extents.makeEmpty();
537
- this.target.set(0, 0, 0);
538
535
 
539
536
  this.syncOptions();
540
537
  this.syncOverlay();
541
- this.update(true);
542
538
 
543
539
  this.emitEvent({ type: "clear" });
540
+ this.update(true);
544
541
 
545
542
  return this;
546
543
  }
@@ -675,7 +672,7 @@ export class Viewer
675
672
 
676
673
  const setOrthogonalCamera = (orthogonal_camera: IOrthogonalCamera) => {
677
674
  if (orthogonal_camera) {
678
- const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
675
+ const extentsSize = this.extents.getSize(new Vector3()).length() || 1;
679
676
  const rendererSize = this.renderer.getSize(new Vector2());
680
677
  const aspectRatio = rendererSize.x / rendererSize.y;
681
678
 
@@ -706,7 +703,7 @@ export class Viewer
706
703
 
707
704
  const setPerspectiveCamera = (perspective_camera: IPerspectiveCamera) => {
708
705
  if (perspective_camera) {
709
- const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
706
+ const extentsSize = this.extents.getSize(new Vector3()).length() || 1;
710
707
  const rendererSize = this.renderer.getSize(new Vector2());
711
708
  const aspectRatio = rendererSize.x / rendererSize.y;
712
709
 
@@ -769,10 +766,10 @@ export class Viewer
769
766
  this.target.copy(getVector3FromPoint3d(viewpoint.custom_fields?.camera_target ?? this.target));
770
767
 
771
768
  this.syncOverlay();
772
-
773
769
  this.setActiveDragger(draggerName);
770
+
774
771
  this.emitEvent({ type: "drawviewpoint", data: viewpoint });
775
- this.update();
772
+ this.update(true);
776
773
  }
777
774
 
778
775
  createViewpoint(): IViewpoint {
@@ -842,11 +839,7 @@ export class Viewer
842
839
  }
843
840
 
844
841
  // IWorldTransform
845
- // ===================== AI-CODE-START ======================
846
- // Source: Claude Sonnet 4.5
847
- // Date: 2025-11-25
848
- // Reviewer: vitaly.ivanov@opendesign.com
849
- // Issue: CLOUD-5990
842
+
850
843
  screenToWorld(position: { x: number; y: number }): { x: number; y: number; z: number } {
851
844
  if (!this.renderer) return { x: position.x, y: position.y, z: 0 };
852
845
 
@@ -854,6 +847,12 @@ export class Viewer
854
847
  const x = position.x / (rect.width / 2) - 1;
855
848
  const y = -position.y / (rect.height / 2) + 1;
856
849
 
850
+ // ===================== AI-CODE-START ======================
851
+ // Source: Claude Sonnet 4.5
852
+ // Date: 2025-11-25
853
+ // Reviewer: vitaly.ivanov@opendesign.com
854
+ // Issue: CLOUD-5990
855
+
857
856
  if (this.camera["isPerspectiveCamera"]) {
858
857
  // Create a raycaster from the screen position
859
858
  const raycaster = new Raycaster();
@@ -876,14 +875,15 @@ export class Viewer
876
875
  return { x: point.x, y: point.y, z: point.z };
877
876
  }
878
877
  return { x: intersectionPoint.x, y: intersectionPoint.y, z: intersectionPoint.z };
879
- } else {
880
- const point = new Vector3(x, y, -1);
881
- point.unproject(this.camera);
882
-
883
- return { x: point.x, y: point.y, z: point.z };
884
878
  }
879
+
880
+ // ===================== AI-CODE-END ======================
881
+
882
+ const point = new Vector3(x, y, -1);
883
+ point.unproject(this.camera);
884
+
885
+ return { x: point.x, y: point.y, z: point.z };
885
886
  }
886
- // ===================== AI-CODE-END ======================
887
887
 
888
888
  worldToScreen(position: { x: number; y: number; z: number }): { x: number; y: number } {
889
889
  if (!this.renderer) return { x: position.x, y: position.y };
@@ -23,7 +23,7 @@
23
23
 
24
24
  import type { Viewer } from "../Viewer";
25
25
 
26
- export function createPreview(viewer: Viewer, type = "image/jpeg", encoderOptions = 0.25): string {
26
+ export function createPreview(viewer: Viewer, type = "image/jpeg", quality = 0.25): string {
27
27
  viewer.update(true);
28
- return viewer.canvas.toDataURL(type, encoderOptions);
28
+ return viewer.canvas.toDataURL(type, quality);
29
29
  }
@@ -21,7 +21,7 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import { Quaternion, Sphere, Vector3 } from "three";
24
+ import { Quaternion, Vector3 } from "three";
25
25
  import type { Viewer } from "../Viewer";
26
26
  import { zoomTo } from "./ZoomTo";
27
27
 
@@ -38,9 +38,9 @@ export const defaultViewPositions = {
38
38
  nw: new Vector3(1, 1, 1).normalize(),
39
39
  };
40
40
 
41
- export function setDefaultViewPosition(viewer: Viewer, position: string): void {
41
+ export function setDefaultViewPosition(viewer: Viewer, position = "sw"): void {
42
42
  const extentsCenter = viewer.extents.getCenter(new Vector3());
43
- const extentsSize = viewer.extents.getBoundingSphere(new Sphere()).radius * 2;
43
+ const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
44
44
 
45
45
  const upY = new Vector3(0, 1, 0);
46
46
  const offsetY = defaultViewPositions[position] || defaultViewPositions["sw"];
@@ -21,14 +21,14 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import { Box3, MathUtils, Sphere, Vector2, Vector3 } from "three";
24
+ import { Box3, MathUtils, Vector2, Vector3 } from "three";
25
25
  import type { Viewer } from "../Viewer";
26
26
 
27
27
  export function zoomTo(viewer: Viewer, box: Box3): void {
28
28
  if (box.isEmpty()) return;
29
29
 
30
30
  const boxCenter = box.getCenter(new Vector3());
31
- const boxSize = box.getBoundingSphere(new Sphere()).radius;
31
+ const boxSize = box.getSize(new Vector3()).length() || 1;
32
32
 
33
33
  const rendererSize = viewer.renderer.getSize(new Vector2());
34
34
  const aspectRatio = rendererSize.x / rendererSize.y;
@@ -38,14 +38,14 @@ export function zoomTo(viewer: Viewer, box: Box3): void {
38
38
  if (camera.isPerspectiveCamera) {
39
39
  const offset = new Vector3(0, 0, 1)
40
40
  .applyQuaternion(camera.quaternion)
41
- .multiplyScalar(boxSize / Math.tan(MathUtils.degToRad(camera.fov * 0.5)));
41
+ .multiplyScalar(boxSize / (2 * Math.tan(MathUtils.degToRad(camera.fov * 0.5))));
42
42
 
43
43
  camera.position.copy(offset).add(boxCenter);
44
44
  camera.updateMatrixWorld();
45
45
  }
46
46
  if (camera.isOrthographicCamera) {
47
- camera.top = boxSize;
48
- camera.bottom = -boxSize;
47
+ camera.top = boxSize / 2;
48
+ camera.bottom = -boxSize / 2;
49
49
  camera.left = camera.bottom * aspectRatio;
50
50
  camera.right = camera.top * aspectRatio;
51
51
  camera.zoom = 1;
@@ -53,7 +53,7 @@ export function zoomTo(viewer: Viewer, box: Box3): void {
53
53
 
54
54
  const offset = new Vector3(0, 0, 1)
55
55
  .applyQuaternion(camera.quaternion)
56
- .multiplyScalar(viewer.extents.getBoundingSphere(new Sphere()).radius * 3);
56
+ .multiplyScalar(viewer.extents.getSize(new Vector3()).length() || 1);
57
57
 
58
58
  camera.position.copy(offset).add(boxCenter);
59
59
  camera.updateMatrixWorld();
@@ -21,7 +21,7 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import { MathUtils, OrthographicCamera, PerspectiveCamera, Sphere, Vector2, Vector3 } from "three";
24
+ import { MathUtils, OrthographicCamera, PerspectiveCamera, Vector2, Vector3 } from "three";
25
25
 
26
26
  import { CameraMode, IComponent } from "@inweb/viewer-core";
27
27
  import type { Viewer } from "../Viewer";
@@ -47,7 +47,7 @@ export class CameraComponent implements IComponent {
47
47
  }
48
48
 
49
49
  switchCamera(camera: any) {
50
- const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius * 2 || 1;
50
+ const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
51
51
  const rendererSize = this.viewer.renderer.getSize(new Vector2());
52
52
  const aspectRatio = rendererSize.x / rendererSize.y;
53
53
 
@@ -95,7 +95,7 @@ export class CameraComponent implements IComponent {
95
95
  if (currentCamera.isPerspectiveCamera) {
96
96
  const fov = currentCamera.fov;
97
97
  const distance = currentCamera.position.distanceTo(target);
98
- const fieldHeight = 2 * Math.tan(MathUtils.degToRad(fov) / 2) * distance;
98
+ const fieldHeight = 2 * Math.tan(MathUtils.degToRad(fov * 0.5)) * distance;
99
99
 
100
100
  camera = new OrthographicCamera();
101
101
  camera.top = fieldHeight / 2;