@inweb/viewer-three 26.9.1 → 26.9.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 (32) hide show
  1. package/dist/plugins/components/AxesHelperComponent.js +8 -6
  2. package/dist/plugins/components/AxesHelperComponent.js.map +1 -1
  3. package/dist/plugins/components/AxesHelperComponent.min.js +1 -1
  4. package/dist/plugins/components/AxesHelperComponent.module.js +7 -5
  5. package/dist/plugins/components/AxesHelperComponent.module.js.map +1 -1
  6. package/dist/plugins/loaders/IFCXLoader.js.map +1 -1
  7. package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -1
  8. package/dist/plugins/loaders/PotreeLoader.js +160 -0
  9. package/dist/plugins/loaders/PotreeLoader.js.map +1 -0
  10. package/dist/plugins/loaders/PotreeLoader.min.js +1 -0
  11. package/dist/plugins/loaders/PotreeLoader.module.js +68 -0
  12. package/dist/plugins/loaders/PotreeLoader.module.js.map +1 -0
  13. package/dist/viewer-three.js +41 -27
  14. package/dist/viewer-three.js.map +1 -1
  15. package/dist/viewer-three.min.js +2 -2
  16. package/dist/viewer-three.module.js +49 -31
  17. package/dist/viewer-three.module.js.map +1 -1
  18. package/lib/Viewer/Viewer.d.ts +3 -2
  19. package/package.json +6 -5
  20. package/plugins/components/AxesHelperComponent.ts +10 -6
  21. package/plugins/loaders/{IFCXCloudLoader.ts → IFCX/IFCXCloudLoader.ts} +1 -1
  22. package/plugins/loaders/{IFCXFileLoader.ts → IFCX/IFCXFileLoader.ts} +1 -1
  23. package/plugins/loaders/Potree/PotreeFileLoader.ts +106 -0
  24. package/plugins/loaders/Potree/PotreeModelImpl.ts +36 -0
  25. package/plugins/loaders/Potree/index.ts +28 -0
  26. package/src/Viewer/Viewer.ts +34 -10
  27. package/src/Viewer/components/ExtentsComponent.ts +1 -1
  28. package/src/Viewer/components/ResizeCanvasComponent.ts +1 -18
  29. package/src/Viewer/draggers/OrbitDragger.ts +9 -0
  30. package/src/Viewer/draggers/WalkDragger.ts +1 -0
  31. package/src/Viewer/helpers/WCSHelper.ts +3 -3
  32. /package/plugins/loaders/{IFCXLoader.ts → IFCX/index.ts} +0 -0
@@ -38,8 +38,8 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
38
38
  target: Vector3;
39
39
  private _activeDragger;
40
40
  private _components;
41
- private renderNeeded;
42
- private renderTime;
41
+ private _renderNeeded;
42
+ private _renderTime;
43
43
  private _markup;
44
44
  /**
45
45
  * @param client - The `Client` instance that is used to load model reference files from the Open Cloud
@@ -59,6 +59,7 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
59
59
  initialize(canvas: HTMLCanvasElement, onProgress?: (event: ProgressEvent<EventTarget>) => void): Promise<this>;
60
60
  dispose(): this;
61
61
  isInitialized(): boolean;
62
+ setSize(width: number, height: number, updateStyle?: boolean): void;
62
63
  update(force?: boolean): void;
63
64
  render(time?: DOMHighResTimeStamp, force?: boolean): void;
64
65
  loadReferences(model: Model | File | Assembly): Promise<this>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inweb/viewer-three",
3
- "version": "26.9.1",
3
+ "version": "26.9.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,13 +35,14 @@
35
35
  "docs": "typedoc"
36
36
  },
37
37
  "dependencies": {
38
- "@inweb/client": "~26.9.1",
39
- "@inweb/eventemitter2": "~26.9.1",
40
- "@inweb/markup": "~26.9.1",
41
- "@inweb/viewer-core": "~26.9.1"
38
+ "@inweb/client": "~26.9.2",
39
+ "@inweb/eventemitter2": "~26.9.2",
40
+ "@inweb/markup": "~26.9.2",
41
+ "@inweb/viewer-core": "~26.9.2"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/three": "^0.179.0",
45
+ "potree-core": "^2.0.11",
45
46
  "three": "^0.179.1"
46
47
  },
47
48
  "peerDependencies": {
@@ -32,7 +32,9 @@ class AxesHelperComponent implements IComponent {
32
32
  constructor(viewer: Viewer) {
33
33
  this.axesHelper1 = new AxesHelper();
34
34
  this.axesHelper2 = new AxesHelper();
35
+
35
36
  this.viewer = viewer;
37
+ this.viewer.addEventListener("initialize", this.syncHelper);
36
38
  this.viewer.addEventListener("geometryend", this.syncHelper);
37
39
  this.viewer.addEventListener("clear", this.syncHelper);
38
40
  }
@@ -44,6 +46,7 @@ class AxesHelperComponent implements IComponent {
44
46
  this.axesHelper2.removeFromParent();
45
47
  this.axesHelper2.dispose();
46
48
 
49
+ this.viewer.removeEventListener("initialize", this.syncHelper);
47
50
  this.viewer.removeEventListener("geometryend", this.syncHelper);
48
51
  this.viewer.removeEventListener("clear", this.syncHelper);
49
52
  }
@@ -55,17 +58,18 @@ class AxesHelperComponent implements IComponent {
55
58
  this.axesHelper2.removeFromParent();
56
59
  this.axesHelper2.dispose();
57
60
 
58
- if (this.viewer.extents.isEmpty()) return;
59
-
60
61
  const size = this.viewer.extents.getSize(new Vector3()).length();
61
62
  const center = this.viewer.extents.getCenter(new Vector3());
62
63
 
63
- this.axesHelper1 = new AxesHelper(size);
64
- this.axesHelper1.position.copy(center);
64
+ this.axesHelper1 = new AxesHelper(size || 1);
65
+ this.axesHelper2 = new AxesHelper(size);
66
+
67
+ this.axesHelper1.position.set(0, 0, 0);
65
68
  this.viewer.helpers.add(this.axesHelper1);
66
69
 
67
- this.axesHelper2 = new AxesHelper(size);
68
- this.axesHelper2.position.set(0, 0, 0);
70
+ if (this.viewer.extents.isEmpty()) return;
71
+
72
+ this.axesHelper2.position.copy(center);
69
73
  this.viewer.helpers.add(this.axesHelper2);
70
74
  };
71
75
  }
@@ -22,7 +22,7 @@
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
24
  import { Loader, ModelImpl, Viewer } from "@inweb/viewer-three";
25
- import { parse, clear } from "./IFCX/render.js";
25
+ import { parse, clear } from "./render.js";
26
26
 
27
27
  export class IFCXCloudLoader extends Loader {
28
28
  public viewer: Viewer;
@@ -22,7 +22,7 @@
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
24
  import { GLTFLoadingManager, GLTFLoadParams, Loader, ModelImpl, Viewer } from "@inweb/viewer-three";
25
- import { IFCXLoader } from "./IFCX/IFCXLoader";
25
+ import { IFCXLoader } from "./IFCXLoader";
26
26
 
27
27
  export class IFCXFileLoader extends Loader {
28
28
  public viewer: Viewer;
@@ -0,0 +1,106 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
24
+ import { Euler, Vector3 } from "three";
25
+ import { PointColorType, PointCloudOctree, PointSizeType, PointShape, Potree } from "potree-core";
26
+ import { Loader, Viewer } from "@inweb/viewer-three";
27
+
28
+ import { PotreeModelImpl } from "./PotreeModelImpl";
29
+
30
+ export type PotreeLoadParams = {
31
+ path?: string;
32
+ position?: Vector3;
33
+ rotation?: Euler;
34
+ scale?: Vector3;
35
+ };
36
+
37
+ export class PotreeFileLoader extends Loader {
38
+ public viewer: Viewer;
39
+ public potree: Potree;
40
+ public pointClouds: PointCloudOctree[];
41
+
42
+ constructor(viewer: Viewer) {
43
+ super();
44
+ this.viewer = viewer;
45
+
46
+ this.potree = new Potree();
47
+ this.pointClouds = [];
48
+
49
+ this.viewer.addEventListener("render", this.updatePointClouds);
50
+ this.viewer.addEventListener("changecamera", this.updatePointClouds);
51
+ }
52
+
53
+ override dispose() {
54
+ this.pointClouds.forEach((pco) => pco.dispose());
55
+
56
+ this.viewer.removeEventListener("render", this.updatePointClouds);
57
+ this.viewer.removeEventListener("changecamera", this.updatePointClouds);
58
+ }
59
+
60
+ override isSupport(file: any, format?: string): boolean {
61
+ return typeof file === "string" && /(cloud.js|metadata.json)$/i.test(file);
62
+ }
63
+
64
+ override async load(file: any, format?: string, params: PotreeLoadParams = {}): Promise<this> {
65
+ const path = (params.path || "") + file;
66
+ const index = path.lastIndexOf("/");
67
+ const baseUrl = path.slice(0, index + 1);
68
+ const url = path.slice(index + 1);
69
+
70
+ const pco = await this.potree.loadPointCloud(url, baseUrl);
71
+ pco.material.size = 1.0;
72
+ pco.material.shape = 2;
73
+ pco.material.inputColorEncoding = 1;
74
+ pco.material.outputColorEncoding = 1;
75
+ pco.material.pointColorType = PointColorType.RGB; // RGB | DEPTH | HEIGHT | POINT_INDEX | LOD | CLASSIFICATION
76
+ pco.material.pointSizeType = PointSizeType.ADAPTIVE; // ADAPTIVE | FIXED
77
+ pco.material.shape = PointShape.CIRCLE; // CIRCLE | SQUARE
78
+
79
+ if (params.position) pco.position.copy(params.position);
80
+ if (params.rotation) pco.rotation.copy(params.rotation);
81
+ if (params.scale) pco.scale.copy(params.scale);
82
+
83
+ this.pointClouds.push(pco);
84
+
85
+ const modelImpl = new PotreeModelImpl(pco);
86
+ modelImpl.loader = this;
87
+ modelImpl.viewer = this.viewer;
88
+ modelImpl.pco = pco;
89
+
90
+ this.viewer.scene.add(pco);
91
+ this.viewer.models.push(modelImpl);
92
+
93
+ this.viewer.syncOptions();
94
+ this.viewer.syncOverlay();
95
+ this.viewer.update();
96
+
97
+ this.viewer.emitEvent({ type: "databasechunk", data: pco, file });
98
+
99
+ return this;
100
+ }
101
+
102
+ updatePointClouds = () => {
103
+ const result = this.potree.updatePointClouds(this.pointClouds, this.viewer.camera, this.viewer.renderer);
104
+ if (result.exceededMaxLoadsToGPU || result.nodeLoadPromises.length > 0) this.viewer.update();
105
+ };
106
+ }
@@ -0,0 +1,36 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
24
+ import { Box3 } from "three";
25
+ import { PointCloudOctree } from "potree-core";
26
+ import { ModelImpl } from "@inweb/viewer-three";
27
+
28
+ // Potree model implementation.
29
+
30
+ export class PotreeModelImpl extends ModelImpl {
31
+ public pco: PointCloudOctree;
32
+
33
+ override getExtents(target: Box3): Box3 {
34
+ return target.union(this.pco.pcoGeometry.boundingBox);
35
+ }
36
+ }
@@ -0,0 +1,28 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
24
+ import { loaders } from "@inweb/viewer-three";
25
+
26
+ import { PotreeFileLoader } from "./PotreeFileLoader";
27
+
28
+ loaders.registerLoader("potree-file", (viewer: any) => new PotreeFileLoader(viewer));
@@ -108,8 +108,8 @@ export class Viewer
108
108
  private _activeDragger: IDragger | null;
109
109
  private _components: IComponent[];
110
110
 
111
- private renderNeeded: boolean;
112
- private renderTime: DOMHighResTimeStamp;
111
+ private _renderNeeded: boolean;
112
+ private _renderTime: DOMHighResTimeStamp;
113
113
 
114
114
  private _markup: IMarkup;
115
115
 
@@ -136,7 +136,7 @@ export class Viewer
136
136
  this._activeDragger = null;
137
137
  this._components = [];
138
138
 
139
- this.renderTime = 0;
139
+ this._renderTime = 0;
140
140
 
141
141
  this.render = this.render.bind(this);
142
142
  this.update = this.update.bind(this);
@@ -217,6 +217,7 @@ export class Viewer
217
217
  this.composer.addPass(this.fxaaPass);
218
218
  this.composer.addPass(this.ssaaRenderPass);
219
219
  this.composer.addPass(this.outputPass);
220
+ this.composer.setSize(width, height);
220
221
 
221
222
  this.canvas = canvas;
222
223
  this.canvasEvents.forEach((x) => canvas.addEventListener(x, this.canvaseventlistener));
@@ -230,8 +231,8 @@ export class Viewer
230
231
  this.syncOptions();
231
232
  this.syncOverlay();
232
233
 
233
- this.renderTime = performance.now();
234
- this.render(this.renderTime);
234
+ this._renderTime = performance.now();
235
+ this.render(this._renderTime);
235
236
 
236
237
  if (typeof onProgress === "function")
237
238
  onProgress(new ProgressEvent("progress", { lengthComputable: true, loaded: 1, total: 1 }));
@@ -289,21 +290,44 @@ export class Viewer
289
290
  return !!this.renderer;
290
291
  }
291
292
 
293
+ setSize(width: number, height: number, updateStyle = true) {
294
+ if (!this.renderer) return;
295
+
296
+ const camera = this.camera as any;
297
+ const aspect = width / height;
298
+
299
+ if (camera.isPerspectiveCamera) {
300
+ camera.aspect = aspect;
301
+ camera.updateProjectionMatrix();
302
+ }
303
+ if (camera.isOrthographicCamera) {
304
+ camera.left = camera.bottom * aspect;
305
+ camera.right = camera.top * aspect;
306
+ camera.updateProjectionMatrix();
307
+ }
308
+
309
+ this.renderer.setSize(width, height, updateStyle);
310
+ this.composer.setSize(width, height);
311
+
312
+ this.update(true);
313
+ this.emitEvent({ type: "resize", width, height });
314
+ }
315
+
292
316
  update(force = false): void {
293
- this.renderNeeded = true;
317
+ this._renderNeeded = true;
294
318
  if (force) this.render();
295
319
  this.emitEvent({ type: "update", data: force });
296
320
  }
297
321
 
298
322
  render(time?: DOMHighResTimeStamp, force = false): void {
299
323
  if (!this.renderer) return;
300
- if (!(this.renderNeeded || force)) return;
324
+ if (!this._renderNeeded && !force) return;
301
325
 
302
326
  if (!time) time = performance.now();
303
- const deltaTime = (time - this.renderTime) / 1000;
327
+ const deltaTime = (time - this._renderTime) / 1000;
304
328
 
305
- this.renderTime = time;
306
- this.renderNeeded = false;
329
+ this._renderTime = time;
330
+ this._renderNeeded = false;
307
331
 
308
332
  if (this.options.antialiasing === true || this.options.antialiasing === "msaa") {
309
333
  this.renderer.render(this.scene, this.camera);
@@ -55,6 +55,6 @@ export class ExtentsComponent implements IComponent {
55
55
  this.viewer.models.forEach((model) => model.getExtents(extents));
56
56
 
57
57
  this.viewer.extents.copy(extents);
58
- extents.getCenter(this.viewer.target);
58
+ this.viewer.extents.getCenter(this.viewer.target);
59
59
  };
60
60
  }
@@ -43,23 +43,6 @@ export class ResizeCanvasComponent implements IComponent {
43
43
 
44
44
  if (!width || !height) return; // <- invisible viewer, or viewer with parent removed
45
45
 
46
- const camera = this.viewer.camera as any;
47
- const aspect = width / height;
48
-
49
- if (camera.isPerspectiveCamera) {
50
- camera.aspect = aspect;
51
- camera.updateProjectionMatrix();
52
- }
53
- if (camera.isOrthographicCamera) {
54
- camera.left = camera.bottom * aspect;
55
- camera.right = camera.top * aspect;
56
- camera.updateProjectionMatrix();
57
- }
58
-
59
- this.viewer.renderer.setSize(width, height, true);
60
- this.viewer.composer.setSize(width, height);
61
-
62
- this.viewer.update(true);
63
- this.viewer.emitEvent({ type: "resize", width, height });
46
+ this.viewer.setSize(width, height);
64
47
  };
65
48
  }
@@ -81,6 +81,13 @@ export class OrbitDragger implements IDragger {
81
81
  this.viewer.update();
82
82
 
83
83
  switch (this.orbit.state) {
84
+ case STATE.ROTATE:
85
+ case STATE.TOUCH_ROTATE:
86
+ this.viewer.emitEvent({
87
+ type: "orbit",
88
+ });
89
+ break;
90
+
84
91
  case STATE.PAN:
85
92
  case STATE.TOUCH_PAN:
86
93
  this.viewer.emitEvent({
@@ -102,6 +109,8 @@ export class OrbitDragger implements IDragger {
102
109
  break;
103
110
  }
104
111
 
112
+ this.viewer.emitEvent({ type: "changecamera" });
113
+
105
114
  this.changed = true;
106
115
  };
107
116
 
@@ -56,6 +56,7 @@ export class WalkDragger implements IDragger {
56
56
 
57
57
  controlsChange = () => {
58
58
  this.viewer.update();
59
+ this.viewer.emitEvent({ type: "changecamera" });
59
60
  };
60
61
 
61
62
  walkspeedChange = (event: any) => {
@@ -28,9 +28,9 @@ export class WCSHelper extends Object3D {
28
28
  this.orthoCamera = new OrthographicCamera(-2, 2, 2, -2, 0, 4);
29
29
  this.orthoCamera.position.set(0, 0, 2);
30
30
 
31
- const matRed = new MeshBasicMaterial({ toneMapped: false, color: "#aa0000" });
32
- const matGreen = new MeshBasicMaterial({ toneMapped: false, color: "#00aa00" });
33
- const matBlue = new MeshBasicMaterial({ toneMapped: false, color: "#0000aa" });
31
+ const matRed = new MeshBasicMaterial({ toneMapped: false, color: "#dd0000" });
32
+ const matGreen = new MeshBasicMaterial({ toneMapped: false, color: "#00dd00" });
33
+ const matBlue = new MeshBasicMaterial({ toneMapped: false, color: "#0000dd" });
34
34
 
35
35
  const spriteRed = this.getSpriteMaterial(matRed.color, "X");
36
36
  const spriteGreen = this.getSpriteMaterial(matGreen.color, "Y");