@inweb/viewer-three 26.8.0 → 26.8.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 (54) hide show
  1. package/dist/plugins/components/RoomEnvironmentComponent.js +75 -40
  2. package/dist/plugins/components/RoomEnvironmentComponent.js.map +1 -1
  3. package/dist/plugins/components/RoomEnvironmentComponent.min.js +1 -1
  4. package/dist/plugins/components/StatsPanelComponent.js +1 -1
  5. package/dist/plugins/components/StatsPanelComponent.js.map +1 -1
  6. package/dist/plugins/components/StatsPanelComponent.min.js +1 -1
  7. package/dist/plugins/components/StatsPanelComponent.module.js +1 -1
  8. package/dist/plugins/components/StatsPanelComponent.module.js.map +1 -1
  9. package/dist/plugins/loaders/GLTFCloudLoader.js +225 -94
  10. package/dist/plugins/loaders/GLTFCloudLoader.js.map +1 -1
  11. package/dist/plugins/loaders/GLTFCloudLoader.min.js +1 -1
  12. package/dist/plugins/loaders/IFCXLoader.js +1977 -881
  13. package/dist/plugins/loaders/IFCXLoader.js.map +1 -1
  14. package/dist/plugins/loaders/IFCXLoader.min.js +1 -1
  15. package/dist/plugins/loaders/IFCXLoader.module.js +477 -154
  16. package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -1
  17. package/dist/viewer-three.js +31149 -5503
  18. package/dist/viewer-three.js.map +1 -1
  19. package/dist/viewer-three.min.js +3 -3
  20. package/dist/viewer-three.module.js +406 -298
  21. package/dist/viewer-three.module.js.map +1 -1
  22. package/lib/Viewer/Viewer.d.ts +17 -3
  23. package/lib/Viewer/commands/SetDefaultViewPosition.d.ts +6 -6
  24. package/lib/Viewer/components/HighlighterComponent.d.ts +5 -4
  25. package/lib/Viewer/components/SelectionComponent.d.ts +1 -1
  26. package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +3 -1
  27. package/lib/Viewer/models/IModelImpl.d.ts +27 -0
  28. package/lib/Viewer/models/ModelImpl.d.ts +27 -0
  29. package/lib/Viewer/scenes/Helpers.d.ts +7 -0
  30. package/lib/index.d.ts +2 -1
  31. package/package.json +9 -9
  32. package/plugins/components/StatsPanelComponent.ts +1 -1
  33. package/plugins/loaders/IFCX/IFCXLoader.ts +4 -7
  34. package/plugins/loaders/IFCX/render.js +686 -181
  35. package/plugins/loaders/IFCXCloudLoader.ts +1 -1
  36. package/src/Viewer/Viewer.ts +124 -48
  37. package/src/Viewer/commands/SetDefaultViewPosition.ts +8 -8
  38. package/src/Viewer/components/CameraComponent.ts +20 -16
  39. package/src/Viewer/components/ExtentsComponent.ts +1 -0
  40. package/src/Viewer/components/HighlighterComponent.ts +78 -80
  41. package/src/Viewer/components/LightComponent.ts +10 -4
  42. package/src/Viewer/components/ResizeCanvasComponent.ts +1 -0
  43. package/src/Viewer/components/SelectionComponent.ts +1 -1
  44. package/src/Viewer/helpers/WCSHelper.ts +8 -5
  45. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +33 -16
  46. package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +12 -5
  47. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +100 -20
  48. package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +4 -2
  49. package/src/Viewer/loaders/GLTFFileLoader.ts +1 -1
  50. package/src/Viewer/models/IModelImpl.ts +67 -0
  51. package/src/Viewer/models/ModelImpl.ts +214 -0
  52. package/src/Viewer/postprocessing/SSAARenderPass.js +245 -0
  53. package/src/Viewer/scenes/Helpers.ts +42 -0
  54. package/src/index.ts +2 -1
@@ -52,7 +52,7 @@ export class IFCXCloudLoader extends Loader {
52
52
  const textDecoder = new TextDecoder();
53
53
  const json = JSON.parse(textDecoder.decode(arrayBuffer));
54
54
 
55
- const scene = parse(json);
55
+ const scene = await parse(json);
56
56
  clear();
57
57
 
58
58
  let handle = 0;
@@ -23,7 +23,8 @@
23
23
 
24
24
  import {
25
25
  Box3,
26
- LinearToneMapping,
26
+ LinearSRGBColorSpace,
27
+ // LinearToneMapping,
27
28
  Object3D,
28
29
  OrthographicCamera,
29
30
  PerspectiveCamera,
@@ -34,6 +35,12 @@ import {
34
35
  Vector3,
35
36
  WebGLRenderer,
36
37
  } from "three";
38
+ import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
39
+ import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
40
+ import { FXAAPass } from "three/examples/jsm/postprocessing/FXAAPass.js";
41
+ import { SMAAPass } from "three/examples/jsm/postprocessing/SMAAPass.js";
42
+ import { SSAARenderPass } from "./postprocessing/SSAARenderPass.js";
43
+ import { OutputPass } from "three/examples/jsm/postprocessing/OutputPass.js";
37
44
 
38
45
  import { EventEmitter2 } from "@inweb/eventemitter2";
39
46
  import { Assembly, Client, Model, File } from "@inweb/client";
@@ -62,7 +69,8 @@ import { draggers } from "./draggers";
62
69
  import { commands } from "./commands";
63
70
  import { components } from "./components";
64
71
  import { loaders } from "./loaders";
65
- import { IModelImpl } from "./model";
72
+ import { IModelImpl } from "./models/IModelImpl";
73
+ import { Helpers } from "./scenes/Helpers";
66
74
 
67
75
  /**
68
76
  * 3D viewer powered by {@link https://threejs.org/ | Three.js}.
@@ -80,9 +88,17 @@ export class Viewer
80
88
  public canvasEvents: string[];
81
89
 
82
90
  public scene: Scene | undefined;
83
- public helpers: Scene | undefined;
91
+ public helpers: Helpers | undefined;
84
92
  public camera: PerspectiveCamera | OrthographicCamera | undefined;
85
93
  public renderer: WebGLRenderer | undefined;
94
+ public renderPass: RenderPass | undefined;
95
+ public helpersPass: RenderPass | undefined;
96
+ public fxaaPass: FXAAPass | undefined;
97
+ public smaaPass: SMAAPass | undefined;
98
+ public ssaaRenderPass: SSAARenderPass | undefined;
99
+ public outputPass: OutputPass | undefined;
100
+ public composer: EffectComposer | undefined;
101
+
86
102
  public loaders: ILoader[];
87
103
  public models: IModelImpl[];
88
104
  public selected: Object3D[];
@@ -153,7 +169,7 @@ export class Viewer
153
169
  this.addEventListener("optionschange", (event) => this.syncOptions(event.data));
154
170
 
155
171
  this.scene = new Scene();
156
- this.helpers = new Scene();
172
+ this.helpers = new Helpers();
157
173
  this.target = new Vector3();
158
174
 
159
175
  const pixelRatio = window.devicePixelRatio;
@@ -174,11 +190,33 @@ export class Viewer
174
190
  alpha: true,
175
191
  preserveDrawingBuffer: true,
176
192
  powerPreference: "high-performance",
177
- logarithmicDepthBuffer: false,
193
+ logarithmicDepthBuffer: true,
178
194
  });
179
195
  this.renderer.setPixelRatio(pixelRatio);
180
196
  this.renderer.setSize(width, height);
181
- this.renderer.toneMapping = LinearToneMapping;
197
+ // this.renderer.toneMapping = LinearToneMapping;
198
+ this.renderer.outputColorSpace = LinearSRGBColorSpace;
199
+
200
+ this.renderPass = new RenderPass(this.scene, this.camera);
201
+
202
+ this.helpersPass = new RenderPass(this.helpers, this.camera);
203
+ this.helpersPass.clear = false;
204
+
205
+ this.fxaaPass = new FXAAPass();
206
+ this.smaaPass = new SMAAPass();
207
+
208
+ this.ssaaRenderPass = new SSAARenderPass([this.scene, this.helpers], this.camera);
209
+ this.ssaaRenderPass.unbiased = true;
210
+
211
+ this.outputPass = new OutputPass();
212
+
213
+ this.composer = new EffectComposer(this.renderer);
214
+ this.composer.addPass(this.renderPass);
215
+ this.composer.addPass(this.helpersPass);
216
+ this.composer.addPass(this.smaaPass);
217
+ this.composer.addPass(this.fxaaPass);
218
+ this.composer.addPass(this.ssaaRenderPass);
219
+ this.composer.addPass(this.outputPass);
182
220
 
183
221
  this.canvas = canvas;
184
222
  this.canvasEvents.forEach((x) => canvas.addEventListener(x, this.canvaseventlistener));
@@ -223,12 +261,26 @@ export class Viewer
223
261
  this.canvas = undefined;
224
262
  }
225
263
 
264
+ if (this.composer) this.composer.dispose();
265
+ if (this.renderPass) this.renderPass.dispose();
266
+ if (this.helpersPass) this.helpersPass.dispose();
267
+ if (this.fxaaPass) this.fxaaPass.dispose();
268
+ if (this.smaaPass) this.smaaPass.dispose();
269
+ if (this.ssaaRenderPass) this.ssaaRenderPass.dispose();
270
+ if (this.outputPass) this.outputPass.dispose();
226
271
  if (this.renderer) this.renderer.dispose();
227
272
 
228
- this.helpers = undefined;
229
273
  this.scene = undefined;
230
- this.renderer = undefined;
274
+ this.helpers = undefined;
231
275
  this.camera = undefined;
276
+ this.renderer = undefined;
277
+ this.renderPass = undefined;
278
+ this.helpersPass = undefined;
279
+ this.fxaaPass = undefined;
280
+ this.smaaPass = undefined;
281
+ this.ssaaRenderPass = undefined;
282
+ this.outputPass = undefined;
283
+ this.composer = undefined;
232
284
 
233
285
  return this;
234
286
  }
@@ -239,30 +291,29 @@ export class Viewer
239
291
 
240
292
  update(force = false): void {
241
293
  this.renderNeeded = true;
242
- if (force) this.render(performance.now());
294
+ if (force) this.render();
243
295
  this.emitEvent({ type: "update", data: force });
244
296
  }
245
297
 
246
- render(time: DOMHighResTimeStamp): void {
247
- if (!this.renderNeeded) return;
298
+ render(time?: DOMHighResTimeStamp, force = false): void {
248
299
  if (!this.renderer) return;
300
+ if (!(this.renderNeeded || force)) return;
249
301
 
250
- this.renderNeeded = false;
302
+ if (!time) time = performance.now();
303
+ const deltaTime = (time - this.renderTime) / 1000;
251
304
 
252
- this.renderer.setViewport(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
253
- this.renderer.autoClear = true;
254
- this.renderer.render(this.scene, this.camera);
305
+ this.renderTime = time;
306
+ this.renderNeeded = false;
255
307
 
256
- const clippingPlanes = this.renderer.clippingPlanes;
257
- this.renderer.clippingPlanes = [];
258
- this.renderer.autoClear = false;
259
- this.renderer.render(this.helpers, this.camera);
260
- this.renderer.clippingPlanes = clippingPlanes;
308
+ if (this.options.antialiasing === true || this.options.antialiasing === "msaa") {
309
+ this.renderer.render(this.scene, this.camera);
310
+ this.renderer.render(this.helpers, this.camera);
311
+ } else {
312
+ this.composer.render(deltaTime);
313
+ }
261
314
 
262
315
  this._activeDragger?.updatePreview?.();
263
316
 
264
- const deltaTime = (time - this.renderTime) / 1000;
265
- this.renderTime = time;
266
317
  this.emitEvent({ type: "render", time, deltaTime });
267
318
  }
268
319
 
@@ -432,6 +483,12 @@ export class Viewer
432
483
  this.models.forEach((model) => model.dispose());
433
484
  this.models = [];
434
485
 
486
+ this.scene.clear();
487
+ this.helpers.clear();
488
+
489
+ this.models.forEach((model) => model.dispose());
490
+ this.models = [];
491
+
435
492
  this.helpers.clear();
436
493
  this.scene.clear();
437
494
 
@@ -445,7 +502,16 @@ export class Viewer
445
502
  }
446
503
 
447
504
  syncOptions(options: IOptions = this.options): void {
448
- // this.update();
505
+ if (!this.renderer) return;
506
+
507
+ this.fxaaPass.enabled = options.antialiasing === "fxaa";
508
+ this.smaaPass.enabled = options.antialiasing === "smaa";
509
+ this.ssaaRenderPass.enabled = options.antialiasing === "ssaa";
510
+
511
+ this.renderPass.enabled = !this.ssaaRenderPass.enabled;
512
+ this.helpersPass.enabled = !this.ssaaRenderPass.enabled;
513
+
514
+ this.update();
449
515
  }
450
516
 
451
517
  syncOverlay(): void {
@@ -595,20 +661,25 @@ export class Viewer
595
661
  const rendererSize = this.renderer.getSize(new Vector2());
596
662
  const aspect = rendererSize.x / rendererSize.y;
597
663
 
598
- this.camera = new OrthographicCamera();
599
- this.camera.top = orthogonal_camera.field_height / 2;
600
- this.camera.bottom = -orthogonal_camera.field_height / 2;
601
- this.camera.left = this.camera.bottom * aspect;
602
- this.camera.right = this.camera.top * aspect;
603
- this.camera.near = 0;
604
- this.camera.far = extentsSize * 100;
605
- this.camera.zoom = orthogonal_camera.view_to_world_scale;
606
- this.camera.updateProjectionMatrix();
607
-
608
- this.camera.up.copy(getVector3FromPoint3d(orthogonal_camera.up_vector));
609
- this.camera.position.copy(getVector3FromPoint3d(orthogonal_camera.view_point));
610
- this.camera.lookAt(getVector3FromPoint3d(orthogonal_camera.direction).add(this.camera.position));
611
- this.camera.updateMatrixWorld();
664
+ const camera = new OrthographicCamera();
665
+ camera.top = orthogonal_camera.field_height / 2;
666
+ camera.bottom = -orthogonal_camera.field_height / 2;
667
+ camera.left = camera.bottom * aspect;
668
+ camera.right = camera.top * aspect;
669
+ camera.near = 0;
670
+ camera.far = extentsSize * 100;
671
+ camera.zoom = orthogonal_camera.view_to_world_scale;
672
+ camera.updateProjectionMatrix();
673
+
674
+ camera.up.copy(getVector3FromPoint3d(orthogonal_camera.up_vector));
675
+ camera.position.copy(getVector3FromPoint3d(orthogonal_camera.view_point));
676
+ camera.lookAt(getVector3FromPoint3d(orthogonal_camera.direction).add(camera.position));
677
+ camera.updateMatrixWorld();
678
+
679
+ this.camera = camera;
680
+ this.renderPass.camera = camera;
681
+ this.helpersPass.camera = camera;
682
+ this.ssaaRenderPass.camera = camera;
612
683
  }
613
684
  };
614
685
 
@@ -618,17 +689,22 @@ export class Viewer
618
689
  const rendererSize = this.renderer.getSize(new Vector2());
619
690
  const aspect = rendererSize.x / rendererSize.y;
620
691
 
621
- this.camera = new PerspectiveCamera();
622
- this.camera.fov = perspective_camera.field_of_view;
623
- this.camera.aspect = aspect;
624
- this.camera.near = extentsSize / 100;
625
- this.camera.far = extentsSize * 100;
626
- this.camera.updateProjectionMatrix();
627
-
628
- this.camera.up.copy(getVector3FromPoint3d(perspective_camera.up_vector));
629
- this.camera.position.copy(getVector3FromPoint3d(perspective_camera.view_point));
630
- this.camera.lookAt(getVector3FromPoint3d(perspective_camera.direction).add(this.camera.position));
631
- this.camera.updateMatrixWorld();
692
+ const camera = new PerspectiveCamera();
693
+ camera.fov = perspective_camera.field_of_view;
694
+ camera.aspect = aspect;
695
+ camera.near = extentsSize / 100;
696
+ camera.far = extentsSize * 100;
697
+ camera.updateProjectionMatrix();
698
+
699
+ camera.up.copy(getVector3FromPoint3d(perspective_camera.up_vector));
700
+ camera.position.copy(getVector3FromPoint3d(perspective_camera.view_point));
701
+ camera.lookAt(getVector3FromPoint3d(perspective_camera.direction).add(camera.position));
702
+ camera.updateMatrixWorld();
703
+
704
+ this.camera = camera;
705
+ this.renderPass.camera = camera;
706
+ this.helpersPass.camera = camera;
707
+ this.ssaaRenderPass.camera = camera;
632
708
  }
633
709
  };
634
710
 
@@ -26,16 +26,16 @@ import type { Viewer } from "../Viewer";
26
26
  import { zoomTo } from "./ZoomTo";
27
27
 
28
28
  export const defaultViewPositions = {
29
- top: new Vector3(0, 0, 1),
30
- bottom: new Vector3(0, 0, -1),
29
+ front: new Vector3(0, 0, 1),
30
+ back: new Vector3(0, 0, -1),
31
31
  left: new Vector3(-1, 0, 0),
32
32
  right: new Vector3(1, 0, 0),
33
- front: new Vector3(0, -1, 0),
34
- back: new Vector3(0, 1, 0),
35
- sw: new Vector3(-0.5, -0.5, 1.0).normalize(),
36
- se: new Vector3(0.5, -0.5, 1.0).normalize(),
37
- ne: new Vector3(0.5, 0.5, 1.0).normalize(),
38
- nw: new Vector3(-0.5, 0.5, 1.0).normalize(),
33
+ bottom: new Vector3(0, -1, 0),
34
+ top: new Vector3(0, 1, 0),
35
+ ns: new Vector3(-0.5, 1.0, -0.5).normalize(),
36
+ sw: new Vector3(0.5, 1.0, -0.5).normalize(),
37
+ nw: new Vector3(0.5, 1.0, 0.5).normalize(),
38
+ se: new Vector3(-0.5, 1.0, 0.5).normalize(),
39
39
  };
40
40
 
41
41
  export function setDefaultViewPosition(viewer: Viewer, position: string): void {
@@ -21,7 +21,7 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import { Sphere, Vector2, Vector3 } from "three";
24
+ import { Sphere, Vector2 } from "three";
25
25
 
26
26
  import { IComponent } from "@inweb/viewer-core";
27
27
  import type { Viewer } from "../Viewer";
@@ -39,42 +39,46 @@ export class CameraComponent implements IComponent {
39
39
  }
40
40
 
41
41
  geometryEnd = () => {
42
- const extentsCenter = this.viewer.extents.getCenter(new Vector3());
43
42
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius * 2;
44
43
  const rendererSize = this.viewer.renderer.getSize(new Vector2());
45
44
  const aspect = rendererSize.x / rendererSize.y;
46
45
 
46
+ let camera: any;
47
+
47
48
  // TODO: do not change the camera and target after opening the second model in "append" mode
48
- let sceneCamera: any;
49
49
  this.viewer.scene.traverse((object: any) => {
50
50
  if (object.isCamera)
51
- if (!sceneCamera) sceneCamera = object;
52
- else if (object.isPerspectiveCamera && sceneCamera.isOrthographicCamera) sceneCamera = object;
51
+ if (!camera) camera = object;
52
+ else if (object.isPerspectiveCamera && camera.isOrthographicCamera) camera = object;
53
53
  });
54
- if (sceneCamera) {
55
- this.viewer.camera = sceneCamera.clone();
56
- this.viewer.camera.scale.set(1, 1, 1); // <- Visualize fix
57
- }
58
54
 
59
- const camera = this.viewer.camera as any;
55
+ if (camera) {
56
+ camera.isDefaultCamera = true;
57
+ camera.scale.set(1, 1, 1); // <- Visualize fix
58
+
59
+ this.viewer.camera = camera;
60
+ this.viewer.renderPass.camera = camera;
61
+ this.viewer.helpersPass.camera = camera;
62
+ this.viewer.ssaaRenderPass.camera = camera;
63
+ } else {
64
+ camera = this.viewer.camera;
65
+ }
60
66
 
61
67
  if (camera.isPerspectiveCamera) {
62
68
  camera.aspect = aspect;
63
- camera.near = extentsSize / 100;
64
- camera.far = extentsSize * 100;
69
+ camera.near = extentsSize / 1000;
70
+ camera.far = extentsSize * 1000;
65
71
  camera.updateProjectionMatrix();
66
72
  }
67
73
  if (camera.isOrthographicCamera) {
68
74
  camera.left = camera.bottom * aspect;
69
75
  camera.right = camera.top * aspect;
70
76
  camera.near = 0;
71
- camera.far = extentsSize * 100;
77
+ camera.far = extentsSize * 1000;
72
78
  camera.updateProjectionMatrix();
73
79
  }
74
80
 
75
- this.viewer.target.copy(extentsCenter);
76
-
77
- if (!sceneCamera) {
81
+ if (!camera.isDefaultCamera) {
78
82
  this.viewer.executeCommand("setDefaultViewPosition");
79
83
  }
80
84
  };
@@ -55,5 +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
59
  };
59
60
  }
@@ -22,7 +22,6 @@
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
24
  import {
25
- Color,
26
25
  EdgesGeometry,
27
26
  LineBasicMaterial,
28
27
  MeshPhongMaterial,
@@ -43,10 +42,10 @@ import { HighlighterUtils } from "./HighlighterUtils";
43
42
  export class HighlighterComponent implements IComponent {
44
43
  protected viewer: Viewer;
45
44
  public renderTarget: WebGLRenderTarget;
46
- public highlightMaterial: MeshPhongMaterial;
47
- public outlineMaterial: LineMaterial;
48
- public highlightLineMaterial: LineBasicMaterial;
49
- public highlightLineGlowMaterial: LineMaterial;
45
+ public facesMaterial: MeshPhongMaterial;
46
+ public edgesMaterial: LineMaterial;
47
+ public lineMaterial: LineBasicMaterial;
48
+ public lineGlowMaterial: LineMaterial;
50
49
 
51
50
  constructor(viewer: Viewer) {
52
51
  this.viewer = viewer;
@@ -81,46 +80,48 @@ export class HighlighterComponent implements IComponent {
81
80
  if (!Array.isArray(objects)) objects = [objects];
82
81
  if (!objects.length) return;
83
82
 
84
- objects.forEach((object: any) => {
85
- if (object.isHighlighted) return;
86
-
87
- if (object.isLine || object.isLineSegments) {
88
- const positions = object.geometry.attributes.position.array;
89
- const indices = object.geometry.index ? object.geometry.index.array : null;
90
- const lineGeometry = indices
91
- ? HighlighterUtils.fromIndexedLine(positions, indices)
92
- : HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
93
-
94
- const wireframe = new Wireframe(lineGeometry, this.highlightLineGlowMaterial);
95
- wireframe.position.copy(object.position);
96
- wireframe.rotation.copy(object.rotation);
97
- wireframe.scale.copy(object.scale);
98
- wireframe.visible = edgesVisibility;
99
-
100
- object.parent.add(wireframe);
101
- object.userData.highlightWireframe = wireframe;
102
-
103
- object.userData.originalMaterial = object.material;
104
- object.material = this.highlightLineMaterial;
105
- object.isHighlighted = true;
106
- } else if (object.isMesh) {
107
- const edgesGeometry = new EdgesGeometry(object.geometry, 60);
108
- const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
109
-
110
- const wireframe = new Wireframe(lineGeometry, this.outlineMaterial);
111
- wireframe.position.copy(object.position);
112
- wireframe.rotation.copy(object.rotation);
113
- wireframe.scale.copy(object.scale);
114
- wireframe.visible = edgesVisibility;
115
-
116
- object.parent.add(wireframe);
117
- object.userData.highlightWireframe = wireframe;
118
-
119
- object.userData.originalMaterial = object.material;
120
- object.material = this.highlightMaterial;
121
- object.isHighlighted = true;
122
- }
123
- });
83
+ objects
84
+ .filter((object) => !object.userData.isEdge) // <- filtering server generated edges
85
+ .forEach((object: any) => {
86
+ if (object.isHighlighted) return;
87
+
88
+ if (object.isLine || object.isLineSegments) {
89
+ const positions = object.geometry.attributes.position.array;
90
+ const indices = object.geometry.index ? object.geometry.index.array : null;
91
+ const lineGeometry = indices
92
+ ? HighlighterUtils.fromIndexedLine(positions, indices)
93
+ : HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
94
+
95
+ const wireframe = new Wireframe(lineGeometry, this.lineGlowMaterial);
96
+ wireframe.position.copy(object.position);
97
+ wireframe.rotation.copy(object.rotation);
98
+ wireframe.scale.copy(object.scale);
99
+ wireframe.visible = edgesVisibility;
100
+
101
+ object.parent.add(wireframe);
102
+ object.userData.highlightWireframe = wireframe;
103
+
104
+ object.userData.originalMaterial = object.material;
105
+ object.material = this.lineMaterial;
106
+ object.isHighlighted = true;
107
+ } else if (object.isMesh) {
108
+ const edgesGeometry = new EdgesGeometry(object.geometry, 89);
109
+ const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
110
+
111
+ const wireframe = new Wireframe(lineGeometry, this.edgesMaterial);
112
+ wireframe.position.copy(object.position);
113
+ wireframe.rotation.copy(object.rotation);
114
+ wireframe.scale.copy(object.scale);
115
+ wireframe.visible = edgesVisibility;
116
+
117
+ object.parent.add(wireframe);
118
+ object.userData.highlightWireframe = wireframe;
119
+
120
+ object.userData.originalMaterial = object.material;
121
+ object.material = this.facesMaterial;
122
+ object.isHighlighted = true;
123
+ }
124
+ });
124
125
  }
125
126
 
126
127
  unhighlight(objects: Object3D | Object3D[]) {
@@ -140,14 +141,8 @@ export class HighlighterComponent implements IComponent {
140
141
  }
141
142
 
142
143
  geometryEnd = () => {
143
- const { facesColor, facesTransparancy, edgesColor, edgesOverlap, facesOverlap } = this.viewer.options;
144
-
145
- this.highlightMaterial = new MeshPhongMaterial({
146
- color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
144
+ this.facesMaterial = new MeshPhongMaterial({
147
145
  transparent: true,
148
- opacity: (255 - facesTransparancy) / 255,
149
- depthTest: !facesOverlap,
150
- depthWrite: !facesOverlap,
151
146
  specular: 0x222222,
152
147
  shininess: 10,
153
148
  reflectivity: 0.05,
@@ -156,57 +151,60 @@ export class HighlighterComponent implements IComponent {
156
151
  polygonOffsetUnits: 1,
157
152
  });
158
153
 
159
- this.outlineMaterial = new LineMaterial({
160
- color: new Color(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255),
154
+ this.edgesMaterial = new LineMaterial({
161
155
  linewidth: 1.5,
162
- depthTest: !edgesOverlap,
163
- depthWrite: !edgesOverlap,
164
156
  resolution: new Vector2(window.innerWidth, window.innerHeight),
165
157
  });
166
158
 
167
- this.highlightLineMaterial = new LineBasicMaterial({
168
- color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
169
- depthTest: false,
170
- depthWrite: false,
159
+ this.lineMaterial = new LineBasicMaterial({
160
+ transparent: true,
161
+ depthTest: true,
162
+ depthWrite: true,
171
163
  });
172
164
 
173
- this.highlightLineGlowMaterial = new LineMaterial({
174
- color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
175
- linewidth: 5,
165
+ this.lineGlowMaterial = new LineMaterial({
166
+ linewidth: 1.5,
176
167
  transparent: true,
177
168
  opacity: 0.8,
178
- depthTest: !edgesOverlap,
179
- depthWrite: !edgesOverlap,
180
169
  resolution: new Vector2(window.innerWidth, window.innerHeight),
181
170
  });
171
+
172
+ this.syncHighlightColors();
182
173
  };
183
174
 
184
175
  optionsChange = () => {
185
- const { facesColor, facesTransparancy, edgesColor, edgesVisibility, edgesOverlap, facesOverlap } =
186
- this.viewer.options;
176
+ this.syncHighlightColors();
177
+ this.viewer.update();
178
+ };
179
+
180
+ syncHighlightColors() {
181
+ const { facesColor, facesTransparancy, facesOverlap } = this.viewer.options;
182
+ const { edgesColor, edgesVisibility, edgesOverlap } = this.viewer.options;
187
183
 
188
- this.highlightMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
189
- this.highlightMaterial.opacity = (255 - facesTransparancy) / 255;
190
- this.highlightMaterial.depthTest = !facesOverlap;
191
- this.highlightMaterial.depthWrite = !facesOverlap;
184
+ this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
185
+ this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
186
+ this.facesMaterial.depthTest = !facesOverlap;
187
+ this.facesMaterial.depthWrite = !facesOverlap;
192
188
 
193
- this.outlineMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
194
- this.outlineMaterial.depthTest = !edgesOverlap;
195
- this.outlineMaterial.depthWrite = !edgesOverlap;
189
+ this.edgesMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
190
+ this.edgesMaterial.depthTest = !edgesOverlap;
191
+ this.edgesMaterial.depthWrite = !edgesOverlap;
196
192
 
197
- this.highlightLineMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
198
- this.highlightLineGlowMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
193
+ this.lineMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
194
+
195
+ this.lineGlowMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
196
+ this.lineGlowMaterial.depthTest = !edgesOverlap;
197
+ this.lineGlowMaterial.depthWrite = !edgesOverlap;
199
198
 
200
199
  this.viewer.selected.forEach((selected) => {
201
200
  const wireframe = selected.userData.highlightWireframe;
202
201
  if (wireframe) wireframe.visible = edgesVisibility;
203
202
  });
204
-
205
- this.viewer.update();
206
- };
203
+ }
207
204
 
208
205
  viewerResize(event: ResizeEvent) {
209
206
  this.renderTarget?.setSize(event.width, event.height);
210
- this.outlineMaterial?.resolution.set(event.width, event.height);
207
+ this.edgesMaterial?.resolution.set(event.width, event.height);
208
+ this.lineGlowMaterial?.resolution.set(event.width, event.height);
211
209
  }
212
210
  }
@@ -36,7 +36,7 @@ export class LightComponent implements IComponent {
36
36
  constructor(viewer: Viewer) {
37
37
  this.viewer = viewer;
38
38
 
39
- this.ambientLight = new AmbientLight(0xffffff, 1.0);
39
+ this.ambientLight = new AmbientLight(0xffffff, 1.5);
40
40
  this.directionalLight = new DirectionalLight(0xffffff, 1.0);
41
41
  this.frontLight = new DirectionalLight(0xffffff, 1.25);
42
42
  this.hemisphereLight = new HemisphereLight(0xffffff, 0x444444, 1.25);
@@ -73,20 +73,26 @@ export class LightComponent implements IComponent {
73
73
  const extentsCenter = this.viewer.extents.getCenter(new Vector3());
74
74
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius;
75
75
 
76
+ const front = new Vector3()
77
+ .copy(this.viewer.camera.up)
78
+ .cross(new Vector3(1, 0, 0))
79
+ .negate();
80
+
76
81
  this.directionalLight.position
77
- .set(0.5, 0.866, 0) // ~60º
82
+ .copy(this.viewer.camera.up)
83
+ .applyAxisAngle(front, (-Math.PI * 30) / 180)
78
84
  .multiplyScalar(extentsSize * 2)
79
85
  .add(extentsCenter);
80
86
  this.directionalLight.target.position.copy(extentsCenter);
81
87
 
82
88
  this.frontLight.position
83
- .set(0, 0, 1)
89
+ .copy(front)
84
90
  .multiplyScalar(extentsSize * 2)
85
91
  .add(extentsCenter);
86
92
  this.frontLight.target.position.copy(extentsCenter);
87
93
 
88
94
  this.hemisphereLight.position
89
- .set(0, 0, 1)
95
+ .copy(front)
90
96
  .multiplyScalar(extentsSize * 3)
91
97
  .add(extentsCenter);
92
98
 
@@ -57,6 +57,7 @@ export class ResizeCanvasComponent implements IComponent {
57
57
  }
58
58
 
59
59
  this.viewer.renderer.setSize(width, height, true);
60
+ this.viewer.composer.setSize(width, height);
60
61
 
61
62
  this.viewer.update(true);
62
63
  this.viewer.emitEvent({ type: "resize", width, height });
@@ -25,7 +25,7 @@ import { Intersection, Object3D, Raycaster, Vector2 } from "three";
25
25
 
26
26
  import type { IComponent } from "@inweb/viewer-core";
27
27
  import type { Viewer } from "../Viewer";
28
- import type { IModelImpl } from "../model";
28
+ import type { IModelImpl } from "../models/IModelImpl";
29
29
  import type { HighlighterComponent } from "./HighlighterComponent";
30
30
 
31
31
  export class SelectionComponent implements IComponent {