@inweb/viewer-three 26.8.1 → 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 (49) 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 +169 -19
  13. package/dist/plugins/loaders/IFCXLoader.js.map +1 -1
  14. package/dist/plugins/loaders/IFCXLoader.min.js +1 -1
  15. package/dist/viewer-three.js +31141 -5500
  16. package/dist/viewer-three.js.map +1 -1
  17. package/dist/viewer-three.min.js +3 -3
  18. package/dist/viewer-three.module.js +402 -295
  19. package/dist/viewer-three.module.js.map +1 -1
  20. package/lib/Viewer/Viewer.d.ts +17 -3
  21. package/lib/Viewer/commands/SetDefaultViewPosition.d.ts +6 -6
  22. package/lib/Viewer/components/HighlighterComponent.d.ts +5 -4
  23. package/lib/Viewer/components/SelectionComponent.d.ts +1 -1
  24. package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +3 -1
  25. package/lib/Viewer/models/IModelImpl.d.ts +27 -0
  26. package/lib/Viewer/models/ModelImpl.d.ts +27 -0
  27. package/lib/Viewer/scenes/Helpers.d.ts +7 -0
  28. package/lib/index.d.ts +2 -1
  29. package/package.json +9 -9
  30. package/plugins/components/StatsPanelComponent.ts +1 -1
  31. package/src/Viewer/Viewer.ts +124 -48
  32. package/src/Viewer/commands/SetDefaultViewPosition.ts +8 -8
  33. package/src/Viewer/components/CameraComponent.ts +20 -16
  34. package/src/Viewer/components/ExtentsComponent.ts +1 -0
  35. package/src/Viewer/components/HighlighterComponent.ts +78 -80
  36. package/src/Viewer/components/LightComponent.ts +1 -1
  37. package/src/Viewer/components/ResizeCanvasComponent.ts +1 -0
  38. package/src/Viewer/components/SelectionComponent.ts +1 -1
  39. package/src/Viewer/helpers/WCSHelper.ts +8 -5
  40. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +33 -16
  41. package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +12 -5
  42. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +100 -20
  43. package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +4 -2
  44. package/src/Viewer/loaders/GLTFFileLoader.ts +1 -1
  45. package/src/Viewer/models/IModelImpl.ts +67 -0
  46. package/src/Viewer/models/ModelImpl.ts +214 -0
  47. package/src/Viewer/postprocessing/SSAARenderPass.js +245 -0
  48. package/src/Viewer/scenes/Helpers.ts +42 -0
  49. package/src/index.ts +2 -1
@@ -2,7 +2,7 @@ import { draggersRegistry, commandsRegistry, componentsRegistry, Loader, loaders
2
2
 
3
3
  export * from "@inweb/viewer-core";
4
4
 
5
- import { Line, Vector3, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Matrix4, Vector4, Raycaster, Controls, Clock, Sphere, MathUtils, Box3, Color, AmbientLight, DirectionalLight, HemisphereLight, MeshPhongMaterial, WebGLRenderTarget, UnsignedByteType, RGBAFormat, EdgesGeometry, OrthographicCamera, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, LoadingManager, LoaderUtils, TextureLoader, BufferAttribute, PointsMaterial, Material, Points, TriangleStripDrawMode, TriangleFanDrawMode, LineSegments, LineLoop, Group, NormalBlending, MeshStandardMaterial, PerspectiveCamera, Scene, WebGLRenderer, LinearToneMapping } from "three";
5
+ import { Line, Vector3, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Matrix4, Vector4, Raycaster, Controls, Clock, Sphere, MathUtils, Box3, Color, AmbientLight, DirectionalLight, HemisphereLight, MeshPhongMaterial, WebGLRenderTarget, UnsignedByteType, RGBAFormat, EdgesGeometry, OrthographicCamera, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, LoadingManager, LoaderUtils, TextureLoader, BufferAttribute, PointsMaterial, Points, TriangleStripDrawMode, TriangleFanDrawMode, LineSegments, LineLoop, Group, NormalBlending, PerspectiveCamera, UniformsUtils, ShaderMaterial, AdditiveBlending, HalfFloatType, Scene, WebGLRenderer, LinearSRGBColorSpace } from "three";
6
6
 
7
7
  import { TransformControls } from "three/examples/jsm/controls/TransformControls.js";
8
8
 
@@ -14,6 +14,22 @@ import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
14
14
 
15
15
  import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
16
16
 
17
+ import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
18
+
19
+ import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
20
+
21
+ import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
22
+
23
+ import { FXAAPass } from "three/examples/jsm/postprocessing/FXAAPass.js";
24
+
25
+ import { SMAAPass } from "three/examples/jsm/postprocessing/SMAAPass.js";
26
+
27
+ import { Pass, FullScreenQuad } from "three/examples/jsm/postprocessing/Pass.js";
28
+
29
+ import { CopyShader } from "three/examples/jsm/shaders/CopyShader.js";
30
+
31
+ import { OutputPass } from "three/examples/jsm/postprocessing/OutputPass.js";
32
+
17
33
  import { EventEmitter2 } from "@inweb/eventemitter2";
18
34
 
19
35
  import { Markup } from "@inweb/markup";
@@ -1564,16 +1580,16 @@ function zoomTo(viewer, box) {
1564
1580
  }
1565
1581
 
1566
1582
  const defaultViewPositions = {
1567
- top: new Vector3(0, 0, 1),
1568
- bottom: new Vector3(0, 0, -1),
1583
+ front: new Vector3(0, 0, 1),
1584
+ back: new Vector3(0, 0, -1),
1569
1585
  left: new Vector3(-1, 0, 0),
1570
1586
  right: new Vector3(1, 0, 0),
1571
- front: new Vector3(0, -1, 0),
1572
- back: new Vector3(0, 1, 0),
1573
- sw: new Vector3(-.5, -.5, 1).normalize(),
1574
- se: new Vector3(.5, -.5, 1).normalize(),
1575
- ne: new Vector3(.5, .5, 1).normalize(),
1576
- nw: new Vector3(-.5, .5, 1).normalize()
1587
+ bottom: new Vector3(0, -1, 0),
1588
+ top: new Vector3(0, 1, 0),
1589
+ ns: new Vector3(-.5, 1, -.5).normalize(),
1590
+ sw: new Vector3(.5, 1, -.5).normalize(),
1591
+ nw: new Vector3(.5, 1, .5).normalize(),
1592
+ se: new Vector3(-.5, 1, .5).normalize()
1577
1593
  };
1578
1594
 
1579
1595
  function setDefaultViewPosition(viewer, position) {
@@ -1835,34 +1851,37 @@ class BackgroundComponent {
1835
1851
  class CameraComponent {
1836
1852
  constructor(viewer) {
1837
1853
  this.geometryEnd = () => {
1838
- const extentsCenter = this.viewer.extents.getCenter(new Vector3);
1839
1854
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere).radius * 2;
1840
1855
  const rendererSize = this.viewer.renderer.getSize(new Vector2);
1841
1856
  const aspect = rendererSize.x / rendererSize.y;
1842
- let sceneCamera;
1857
+ let camera;
1843
1858
  this.viewer.scene.traverse((object => {
1844
- if (object.isCamera) if (!sceneCamera) sceneCamera = object; else if (object.isPerspectiveCamera && sceneCamera.isOrthographicCamera) sceneCamera = object;
1859
+ if (object.isCamera) if (!camera) camera = object; else if (object.isPerspectiveCamera && camera.isOrthographicCamera) camera = object;
1845
1860
  }));
1846
- if (sceneCamera) {
1847
- this.viewer.camera = sceneCamera.clone();
1848
- this.viewer.camera.scale.set(1, 1, 1);
1861
+ if (camera) {
1862
+ camera.isDefaultCamera = true;
1863
+ camera.scale.set(1, 1, 1);
1864
+ this.viewer.camera = camera;
1865
+ this.viewer.renderPass.camera = camera;
1866
+ this.viewer.helpersPass.camera = camera;
1867
+ this.viewer.ssaaRenderPass.camera = camera;
1868
+ } else {
1869
+ camera = this.viewer.camera;
1849
1870
  }
1850
- const camera = this.viewer.camera;
1851
1871
  if (camera.isPerspectiveCamera) {
1852
1872
  camera.aspect = aspect;
1853
- camera.near = extentsSize / 100;
1854
- camera.far = extentsSize * 100;
1873
+ camera.near = extentsSize / 1e3;
1874
+ camera.far = extentsSize * 1e3;
1855
1875
  camera.updateProjectionMatrix();
1856
1876
  }
1857
1877
  if (camera.isOrthographicCamera) {
1858
1878
  camera.left = camera.bottom * aspect;
1859
1879
  camera.right = camera.top * aspect;
1860
1880
  camera.near = 0;
1861
- camera.far = extentsSize * 100;
1881
+ camera.far = extentsSize * 1e3;
1862
1882
  camera.updateProjectionMatrix();
1863
1883
  }
1864
- this.viewer.target.copy(extentsCenter);
1865
- if (!sceneCamera) {
1884
+ if (!camera.isDefaultCamera) {
1866
1885
  this.viewer.executeCommand("setDefaultViewPosition");
1867
1886
  }
1868
1887
  };
@@ -1880,6 +1899,7 @@ class ExtentsComponent {
1880
1899
  const extents = new Box3;
1881
1900
  this.viewer.models.forEach((model => model.getExtents(extents)));
1882
1901
  this.viewer.extents.copy(extents);
1902
+ extents.getCenter(this.viewer.target);
1883
1903
  };
1884
1904
  this.viewer = viewer;
1885
1905
  this.viewer.addEventListener("databasechunk", this.syncExtents);
@@ -1923,7 +1943,7 @@ class LightComponent {
1923
1943
  this.viewer.scene.add(this.hemisphereLight);
1924
1944
  };
1925
1945
  this.viewer = viewer;
1926
- this.ambientLight = new AmbientLight(16777215, 1);
1946
+ this.ambientLight = new AmbientLight(16777215, 1.5);
1927
1947
  this.directionalLight = new DirectionalLight(16777215, 1);
1928
1948
  this.frontLight = new DirectionalLight(16777215, 1.25);
1929
1949
  this.hemisphereLight = new HemisphereLight(16777215, 4473924, 1.25);
@@ -1979,6 +1999,7 @@ class ResizeCanvasComponent {
1979
1999
  camera.updateProjectionMatrix();
1980
2000
  }
1981
2001
  this.viewer.renderer.setSize(width, height, true);
2002
+ this.viewer.composer.setSize(width, height);
1982
2003
  this.viewer.update(true);
1983
2004
  this.viewer.emitEvent({
1984
2005
  type: "resize",
@@ -2045,13 +2066,8 @@ class HighlighterUtils {
2045
2066
  class HighlighterComponent {
2046
2067
  constructor(viewer) {
2047
2068
  this.geometryEnd = () => {
2048
- const {facesColor: facesColor, facesTransparancy: facesTransparancy, edgesColor: edgesColor, edgesOverlap: edgesOverlap, facesOverlap: facesOverlap} = this.viewer.options;
2049
- this.highlightMaterial = new MeshPhongMaterial({
2050
- color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
2069
+ this.facesMaterial = new MeshPhongMaterial({
2051
2070
  transparent: true,
2052
- opacity: (255 - facesTransparancy) / 255,
2053
- depthTest: !facesOverlap,
2054
- depthWrite: !facesOverlap,
2055
2071
  specular: 2236962,
2056
2072
  shininess: 10,
2057
2073
  reflectivity: .05,
@@ -2059,43 +2075,25 @@ class HighlighterComponent {
2059
2075
  polygonOffsetFactor: 1,
2060
2076
  polygonOffsetUnits: 1
2061
2077
  });
2062
- this.outlineMaterial = new LineMaterial({
2063
- color: new Color(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255),
2078
+ this.edgesMaterial = new LineMaterial({
2064
2079
  linewidth: 1.5,
2065
- depthTest: !edgesOverlap,
2066
- depthWrite: !edgesOverlap,
2067
2080
  resolution: new Vector2(window.innerWidth, window.innerHeight)
2068
2081
  });
2069
- this.highlightLineMaterial = new LineBasicMaterial({
2070
- color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
2071
- depthTest: false,
2072
- depthWrite: false
2082
+ this.lineMaterial = new LineBasicMaterial({
2083
+ transparent: true,
2084
+ depthTest: true,
2085
+ depthWrite: true
2073
2086
  });
2074
- this.highlightLineGlowMaterial = new LineMaterial({
2075
- color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
2076
- linewidth: 5,
2087
+ this.lineGlowMaterial = new LineMaterial({
2088
+ linewidth: 1.5,
2077
2089
  transparent: true,
2078
2090
  opacity: .8,
2079
- depthTest: !edgesOverlap,
2080
- depthWrite: !edgesOverlap,
2081
2091
  resolution: new Vector2(window.innerWidth, window.innerHeight)
2082
2092
  });
2093
+ this.syncHighlightColors();
2083
2094
  };
2084
2095
  this.optionsChange = () => {
2085
- const {facesColor: facesColor, facesTransparancy: facesTransparancy, edgesColor: edgesColor, edgesVisibility: edgesVisibility, edgesOverlap: edgesOverlap, facesOverlap: facesOverlap} = this.viewer.options;
2086
- this.highlightMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
2087
- this.highlightMaterial.opacity = (255 - facesTransparancy) / 255;
2088
- this.highlightMaterial.depthTest = !facesOverlap;
2089
- this.highlightMaterial.depthWrite = !facesOverlap;
2090
- this.outlineMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
2091
- this.outlineMaterial.depthTest = !edgesOverlap;
2092
- this.outlineMaterial.depthWrite = !edgesOverlap;
2093
- this.highlightLineMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
2094
- this.highlightLineGlowMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
2095
- this.viewer.selected.forEach((selected => {
2096
- const wireframe = selected.userData.highlightWireframe;
2097
- if (wireframe) wireframe.visible = edgesVisibility;
2098
- }));
2096
+ this.syncHighlightColors();
2099
2097
  this.viewer.update();
2100
2098
  };
2101
2099
  this.viewer = viewer;
@@ -2123,13 +2121,13 @@ class HighlighterComponent {
2123
2121
  const {edgesVisibility: edgesVisibility} = this.viewer.options;
2124
2122
  if (!Array.isArray(objects)) objects = [ objects ];
2125
2123
  if (!objects.length) return;
2126
- objects.forEach((object => {
2124
+ objects.filter((object => !object.userData.isEdge)).forEach((object => {
2127
2125
  if (object.isHighlighted) return;
2128
2126
  if (object.isLine || object.isLineSegments) {
2129
2127
  const positions = object.geometry.attributes.position.array;
2130
2128
  const indices = object.geometry.index ? object.geometry.index.array : null;
2131
2129
  const lineGeometry = indices ? HighlighterUtils.fromIndexedLine(positions, indices) : HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
2132
- const wireframe = new Wireframe(lineGeometry, this.highlightLineGlowMaterial);
2130
+ const wireframe = new Wireframe(lineGeometry, this.lineGlowMaterial);
2133
2131
  wireframe.position.copy(object.position);
2134
2132
  wireframe.rotation.copy(object.rotation);
2135
2133
  wireframe.scale.copy(object.scale);
@@ -2137,12 +2135,12 @@ class HighlighterComponent {
2137
2135
  object.parent.add(wireframe);
2138
2136
  object.userData.highlightWireframe = wireframe;
2139
2137
  object.userData.originalMaterial = object.material;
2140
- object.material = this.highlightLineMaterial;
2138
+ object.material = this.lineMaterial;
2141
2139
  object.isHighlighted = true;
2142
2140
  } else if (object.isMesh) {
2143
- const edgesGeometry = new EdgesGeometry(object.geometry, 60);
2141
+ const edgesGeometry = new EdgesGeometry(object.geometry, 89);
2144
2142
  const lineGeometry = (new LineSegmentsGeometry).fromEdgesGeometry(edgesGeometry);
2145
- const wireframe = new Wireframe(lineGeometry, this.outlineMaterial);
2143
+ const wireframe = new Wireframe(lineGeometry, this.edgesMaterial);
2146
2144
  wireframe.position.copy(object.position);
2147
2145
  wireframe.rotation.copy(object.rotation);
2148
2146
  wireframe.scale.copy(object.scale);
@@ -2150,7 +2148,7 @@ class HighlighterComponent {
2150
2148
  object.parent.add(wireframe);
2151
2149
  object.userData.highlightWireframe = wireframe;
2152
2150
  object.userData.originalMaterial = object.material;
2153
- object.material = this.highlightMaterial;
2151
+ object.material = this.facesMaterial;
2154
2152
  object.isHighlighted = true;
2155
2153
  }
2156
2154
  }));
@@ -2167,10 +2165,30 @@ class HighlighterComponent {
2167
2165
  delete object.userData.highlightWireframe;
2168
2166
  }));
2169
2167
  }
2168
+ syncHighlightColors() {
2169
+ const {facesColor: facesColor, facesTransparancy: facesTransparancy, facesOverlap: facesOverlap} = this.viewer.options;
2170
+ const {edgesColor: edgesColor, edgesVisibility: edgesVisibility, edgesOverlap: edgesOverlap} = this.viewer.options;
2171
+ this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
2172
+ this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
2173
+ this.facesMaterial.depthTest = !facesOverlap;
2174
+ this.facesMaterial.depthWrite = !facesOverlap;
2175
+ this.edgesMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
2176
+ this.edgesMaterial.depthTest = !edgesOverlap;
2177
+ this.edgesMaterial.depthWrite = !edgesOverlap;
2178
+ this.lineMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
2179
+ this.lineGlowMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
2180
+ this.lineGlowMaterial.depthTest = !edgesOverlap;
2181
+ this.lineGlowMaterial.depthWrite = !edgesOverlap;
2182
+ this.viewer.selected.forEach((selected => {
2183
+ const wireframe = selected.userData.highlightWireframe;
2184
+ if (wireframe) wireframe.visible = edgesVisibility;
2185
+ }));
2186
+ }
2170
2187
  viewerResize(event) {
2171
- var _a, _b;
2188
+ var _a, _b, _c;
2172
2189
  (_a = this.renderTarget) === null || _a === undefined ? undefined : _a.setSize(event.width, event.height);
2173
- (_b = this.outlineMaterial) === null || _b === undefined ? undefined : _b.resolution.set(event.width, event.height);
2190
+ (_b = this.edgesMaterial) === null || _b === undefined ? undefined : _b.resolution.set(event.width, event.height);
2191
+ (_c = this.lineGlowMaterial) === null || _c === undefined ? undefined : _c.resolution.set(event.width, event.height);
2174
2192
  }
2175
2193
  }
2176
2194
 
@@ -2362,14 +2380,17 @@ class WCSHelper extends Object3D {
2362
2380
  render(renderer) {
2363
2381
  this.quaternion.copy(this.camera.quaternion).invert();
2364
2382
  this.updateMatrixWorld();
2365
- const clippingPlanes = renderer.clippingPlanes;
2366
- const viewport = renderer.getViewport(new Vector4);
2367
- renderer.setViewport(this.position.x, this.position.y, this.size, this.size);
2383
+ const oldAutoClear = renderer.autoClear;
2384
+ const oldClippingPlanes = renderer.clippingPlanes;
2385
+ const oldViewport = renderer.getViewport(new Vector4);
2386
+ renderer.autoClear = false;
2368
2387
  renderer.clippingPlanes = [];
2388
+ renderer.setViewport(this.position.x, this.position.y, this.size, this.size);
2369
2389
  renderer.clearDepth();
2370
2390
  renderer.render(this, this.orthoCamera);
2371
- renderer.setViewport(viewport);
2372
- renderer.clippingPlanes = clippingPlanes;
2391
+ renderer.setViewport(oldViewport);
2392
+ renderer.clippingPlanes = oldClippingPlanes;
2393
+ renderer.autoClear = oldAutoClear;
2373
2394
  }
2374
2395
  }
2375
2396
 
@@ -2638,23 +2659,28 @@ class DynamicModelImpl extends ModelImpl {
2638
2659
  const handlesSet = new Set(handles);
2639
2660
  const objects = [];
2640
2661
  handlesSet.forEach((handle => {
2641
- const handles = this.gltfLoader.handleToObjects.get(handle) || [];
2662
+ const handle2 = `${this.modelId}_${handle}`;
2663
+ const handles = this.gltfLoader.handleToObjects.get(handle2) || [];
2642
2664
  objects.push(...Array.from(handles));
2643
2665
  }));
2644
2666
  return objects;
2645
2667
  }
2668
+ getHandlesByObjects(objects) {
2669
+ const handles = super.getHandlesByObjects(objects);
2670
+ return handles.map((x => x.split("_").pop()));
2671
+ }
2646
2672
  hideObjects(objects) {
2647
- const handles = this.getHandlesByObjects(objects);
2673
+ const handles = super.getHandlesByObjects(objects);
2648
2674
  this.gltfLoader.hideObjects(handles);
2649
2675
  return this;
2650
2676
  }
2651
2677
  isolateObjects(objects) {
2652
- const handles = this.getHandlesByObjects(objects);
2678
+ const handles = super.getHandlesByObjects(objects);
2653
2679
  this.gltfLoader.isolateObjects(new Set(handles));
2654
2680
  return this;
2655
2681
  }
2656
2682
  showObjects(objects) {
2657
- const handles = this.getHandlesByObjects(objects);
2683
+ const handles = super.getHandlesByObjects(objects);
2658
2684
  this.gltfLoader.showObjects(handles);
2659
2685
  return this;
2660
2686
  }
@@ -2709,6 +2735,7 @@ class GltfStructure {
2709
2735
  this.textureLoader = new TextureLoader;
2710
2736
  this.materials = new Map;
2711
2737
  this.textureCache = new Map;
2738
+ this.materialCache = new Map;
2712
2739
  }
2713
2740
  async initialize(loadController) {
2714
2741
  this.json = await loadController.loadJson();
@@ -2983,17 +3010,24 @@ class GltfStructure {
2983
3010
  }
2984
3011
  await Promise.all(texturePromises);
2985
3012
  }
2986
- async loadMaterials() {
3013
+ loadMaterials() {
2987
3014
  if (!this.json.materials) return this.materials;
2988
3015
  for (let i = 0; i < this.json.materials.length; i++) {
2989
3016
  const materialDef = this.json.materials[i];
2990
- const material = await this.createMaterial(materialDef);
2991
- material.name = materialDef.name;
2992
- this.materials.set(i, material);
3017
+ const materialCacheKey = `material_${i}`;
3018
+ this.materialCache.set(materialCacheKey, {
3019
+ mesh: this.createMaterial(materialDef, GL_CONSTANTS.TRIANGLES),
3020
+ points: this.createMaterial(materialDef, GL_CONSTANTS.POINTS),
3021
+ lines: this.createMaterial(materialDef, GL_CONSTANTS.LINES)
3022
+ });
3023
+ this.materialCache.get(materialCacheKey).mesh.name = materialDef.name;
3024
+ this.materialCache.get(materialCacheKey).points.name = materialDef.name;
3025
+ this.materialCache.get(materialCacheKey).lines.name = materialDef.name;
3026
+ this.materials.set(i, this.materialCache.get(materialCacheKey).mesh);
2993
3027
  }
2994
3028
  return this.materials;
2995
3029
  }
2996
- createMaterial(materialDef) {
3030
+ createMaterial(materialDef, primitiveMode = undefined) {
2997
3031
  const params = {};
2998
3032
  if (materialDef.pbrMetallicRoughness) {
2999
3033
  const pbr = materialDef.pbrMetallicRoughness;
@@ -3006,27 +3040,50 @@ class GltfStructure {
3006
3040
  params.map = this.textureCache.get(pbr.baseColorTexture.index);
3007
3041
  }
3008
3042
  }
3009
- params.specular = 2236962;
3010
- params.shininess = 10;
3011
- params.reflectivity = .05;
3012
- params.polygonOffset = true;
3013
- params.polygonOffsetFactor = 1;
3014
- params.polygonOffsetUnits = 1;
3015
3043
  if (materialDef.emissiveFactor) {
3016
3044
  params.emissive = (new Color).fromArray(materialDef.emissiveFactor);
3017
3045
  }
3018
- if (materialDef.normalTexture) {
3019
- params.normalMap = this.textureCache.get(materialDef.normalTexture.index);
3020
- }
3021
3046
  if (materialDef.alphaMode === "BLEND") {
3022
3047
  params.transparent = true;
3023
3048
  }
3024
3049
  if (materialDef.doubleSided) {
3025
3050
  params.side = DoubleSide;
3026
3051
  }
3027
- const material = new MeshPhongMaterial(params);
3052
+ let material;
3053
+ if (primitiveMode === GL_CONSTANTS.POINTS) {
3054
+ params.sizeAttenuation = false;
3055
+ material = new PointsMaterial(params);
3056
+ material.sizeAttenuation = false;
3057
+ } else if (primitiveMode === GL_CONSTANTS.LINES || primitiveMode === GL_CONSTANTS.LINE_STRIP || primitiveMode === GL_CONSTANTS.LINE_LOOP) {
3058
+ material = new LineBasicMaterial(params);
3059
+ } else {
3060
+ params.specular = 2236962;
3061
+ params.shininess = 10;
3062
+ params.reflectivity = .05;
3063
+ params.polygonOffset = true;
3064
+ params.polygonOffsetFactor = 1;
3065
+ params.polygonOffsetUnits = 1;
3066
+ if (materialDef.normalTexture) {
3067
+ params.normalMap = this.textureCache.get(materialDef.normalTexture.index);
3068
+ }
3069
+ material = new MeshPhongMaterial(params);
3070
+ }
3028
3071
  return material;
3029
3072
  }
3073
+ getCachedMaterial(materialIndex, primitiveMode) {
3074
+ const materialCacheKey = `material_${materialIndex}`;
3075
+ const materialCache = this.materialCache.get(materialCacheKey);
3076
+ if (materialCache) {
3077
+ if (primitiveMode === GL_CONSTANTS.POINTS) {
3078
+ return materialCache.points;
3079
+ } else if (primitiveMode === GL_CONSTANTS.LINES || primitiveMode === GL_CONSTANTS.LINE_STRIP || primitiveMode === GL_CONSTANTS.LINE_LOOP) {
3080
+ return materialCache.lines;
3081
+ } else {
3082
+ return materialCache.mesh;
3083
+ }
3084
+ }
3085
+ return null;
3086
+ }
3030
3087
  disposeMaterials() {
3031
3088
  this.textureCache.forEach((texture => texture.dispose()));
3032
3089
  this.textureCache.clear();
@@ -3044,6 +3101,30 @@ class GltfStructure {
3044
3101
  material.dispose();
3045
3102
  }));
3046
3103
  this.materials.clear();
3104
+ this.materialCache.forEach((materialCache => {
3105
+ if (materialCache.mesh) {
3106
+ if (materialCache.mesh.map) materialCache.mesh.map.dispose();
3107
+ if (materialCache.mesh.lightMap) materialCache.mesh.lightMap.dispose();
3108
+ if (materialCache.mesh.bumpMap) materialCache.mesh.bumpMap.dispose();
3109
+ if (materialCache.mesh.normalMap) materialCache.mesh.normalMap.dispose();
3110
+ if (materialCache.mesh.specularMap) materialCache.mesh.specularMap.dispose();
3111
+ if (materialCache.mesh.envMap) materialCache.mesh.envMap.dispose();
3112
+ if (materialCache.mesh.aoMap) materialCache.mesh.aoMap.dispose();
3113
+ if (materialCache.mesh.metalnessMap) materialCache.mesh.metalnessMap.dispose();
3114
+ if (materialCache.mesh.roughnessMap) materialCache.mesh.roughnessMap.dispose();
3115
+ if (materialCache.mesh.emissiveMap) materialCache.mesh.emissiveMap.dispose();
3116
+ materialCache.mesh.dispose();
3117
+ }
3118
+ if (materialCache.points) {
3119
+ if (materialCache.points.map) materialCache.points.map.dispose();
3120
+ materialCache.points.dispose();
3121
+ }
3122
+ if (materialCache.lines) {
3123
+ if (materialCache.lines.map) materialCache.lines.map.dispose();
3124
+ materialCache.lines.dispose();
3125
+ }
3126
+ }));
3127
+ this.materialCache.clear();
3047
3128
  }
3048
3129
  estimateNodeSize(meshIndex) {
3049
3130
  if (!this.json.meshes) return 0;
@@ -3073,156 +3154,6 @@ class GltfStructure {
3073
3154
  }
3074
3155
  }
3075
3156
 
3076
- function mergeGeometries(geometries, useGroups = false) {
3077
- const isIndexed = geometries[0].index !== null;
3078
- const attributesUsed = new Set(Object.keys(geometries[0].attributes));
3079
- const morphAttributesUsed = new Set(Object.keys(geometries[0].morphAttributes));
3080
- const attributes = {};
3081
- const morphAttributes = {};
3082
- const morphTargetsRelative = geometries[0].morphTargetsRelative;
3083
- const mergedGeometry = new BufferGeometry;
3084
- let offset = 0;
3085
- for (let i = 0; i < geometries.length; ++i) {
3086
- const geometry = geometries[i];
3087
- let attributesCount = 0;
3088
- if (isIndexed !== (geometry.index !== null)) {
3089
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + ". All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them.");
3090
- return null;
3091
- }
3092
- for (const name in geometry.attributes) {
3093
- if (!attributesUsed.has(name)) {
3094
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + '. All geometries must have compatible attributes; make sure "' + name + '" attribute exists among all geometries, or in none of them.');
3095
- return null;
3096
- }
3097
- if (attributes[name] === undefined) attributes[name] = [];
3098
- attributes[name].push(geometry.attributes[name]);
3099
- attributesCount++;
3100
- }
3101
- if (attributesCount !== attributesUsed.size) {
3102
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + ". Make sure all geometries have the same number of attributes.");
3103
- return null;
3104
- }
3105
- if (morphTargetsRelative !== geometry.morphTargetsRelative) {
3106
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + ". .morphTargetsRelative must be consistent throughout all geometries.");
3107
- return null;
3108
- }
3109
- for (const name in geometry.morphAttributes) {
3110
- if (!morphAttributesUsed.has(name)) {
3111
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + ". .morphAttributes must be consistent throughout all geometries.");
3112
- return null;
3113
- }
3114
- if (morphAttributes[name] === undefined) morphAttributes[name] = [];
3115
- morphAttributes[name].push(geometry.morphAttributes[name]);
3116
- }
3117
- if (useGroups) {
3118
- let count;
3119
- if (isIndexed) {
3120
- count = geometry.index.count;
3121
- } else if (geometry.attributes.position !== undefined) {
3122
- count = geometry.attributes.position.count;
3123
- } else {
3124
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + ". The geometry must have either an index or a position attribute");
3125
- return null;
3126
- }
3127
- mergedGeometry.addGroup(offset, count, i);
3128
- offset += count;
3129
- }
3130
- }
3131
- if (isIndexed) {
3132
- let indexOffset = 0;
3133
- const mergedIndex = [];
3134
- for (let i = 0; i < geometries.length; ++i) {
3135
- const index = geometries[i].index;
3136
- for (let j = 0; j < index.count; ++j) {
3137
- mergedIndex.push(index.getX(j) + indexOffset);
3138
- }
3139
- indexOffset += geometries[i].attributes.position.count;
3140
- }
3141
- mergedGeometry.setIndex(mergedIndex);
3142
- }
3143
- for (const name in attributes) {
3144
- const mergedAttribute = mergeAttributes(attributes[name]);
3145
- if (!mergedAttribute) {
3146
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the " + name + " attribute.");
3147
- return null;
3148
- }
3149
- mergedGeometry.setAttribute(name, mergedAttribute);
3150
- }
3151
- for (const name in morphAttributes) {
3152
- const numMorphTargets = morphAttributes[name][0].length;
3153
- if (numMorphTargets === 0) break;
3154
- mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};
3155
- mergedGeometry.morphAttributes[name] = [];
3156
- for (let i = 0; i < numMorphTargets; ++i) {
3157
- const morphAttributesToMerge = [];
3158
- for (let j = 0; j < morphAttributes[name].length; ++j) {
3159
- morphAttributesToMerge.push(morphAttributes[name][j][i]);
3160
- }
3161
- const mergedMorphAttribute = mergeAttributes(morphAttributesToMerge);
3162
- if (!mergedMorphAttribute) {
3163
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the " + name + " morphAttribute.");
3164
- return null;
3165
- }
3166
- mergedGeometry.morphAttributes[name].push(mergedMorphAttribute);
3167
- }
3168
- }
3169
- return mergedGeometry;
3170
- }
3171
-
3172
- function mergeAttributes(attributes) {
3173
- let TypedArray;
3174
- let itemSize;
3175
- let normalized;
3176
- let gpuType = -1;
3177
- let arrayLength = 0;
3178
- for (let i = 0; i < attributes.length; ++i) {
3179
- const attribute = attributes[i];
3180
- if (TypedArray === undefined) TypedArray = attribute.array.constructor;
3181
- if (TypedArray !== attribute.array.constructor) {
3182
- console.error("THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes.");
3183
- return null;
3184
- }
3185
- if (itemSize === undefined) itemSize = attribute.itemSize;
3186
- if (itemSize !== attribute.itemSize) {
3187
- console.error("THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes.");
3188
- return null;
3189
- }
3190
- if (normalized === undefined) normalized = attribute.normalized;
3191
- if (normalized !== attribute.normalized) {
3192
- console.error("THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes.");
3193
- return null;
3194
- }
3195
- if (gpuType === -1) gpuType = attribute.gpuType;
3196
- if (gpuType !== attribute.gpuType) {
3197
- console.error("THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.gpuType must be consistent across matching attributes.");
3198
- return null;
3199
- }
3200
- arrayLength += attribute.count * itemSize;
3201
- }
3202
- const array = new TypedArray(arrayLength);
3203
- const result = new BufferAttribute(array, itemSize, normalized);
3204
- let offset = 0;
3205
- for (let i = 0; i < attributes.length; ++i) {
3206
- const attribute = attributes[i];
3207
- if (attribute.isInterleavedBufferAttribute) {
3208
- const tupleOffset = offset / itemSize;
3209
- for (let j = 0, l = attribute.count; j < l; j++) {
3210
- for (let c = 0; c < itemSize; c++) {
3211
- const value = attribute.getComponent(j, c);
3212
- result.setComponent(j + tupleOffset, c, value);
3213
- }
3214
- }
3215
- } else {
3216
- array.set(attribute.array, offset);
3217
- }
3218
- offset += attribute.count * itemSize;
3219
- }
3220
- if (gpuType !== undefined) {
3221
- result.gpuType = gpuType;
3222
- }
3223
- return result;
3224
- }
3225
-
3226
3157
  class DynamicGltfLoader {
3227
3158
  constructor(camera, scene, renderer) {
3228
3159
  this.camera = camera;
@@ -3506,18 +3437,17 @@ class DynamicGltfLoader {
3506
3437
  }
3507
3438
  let material;
3508
3439
  if (primitive.material !== undefined) {
3509
- material = node.structure.materials.get(primitive.material) || this.createDefaultMaterial();
3440
+ material = node.structure.getCachedMaterial(primitive.material, primitive.mode);
3441
+ if (!material) {
3442
+ const materialDef = node.structure.json.materials[primitive.material];
3443
+ material = node.structure.createMaterial(materialDef, primitive.mode);
3444
+ }
3510
3445
  } else {
3511
- material = this.createDefaultMaterial();
3446
+ material = this.createDefaultMaterial(primitive.mode);
3512
3447
  }
3513
3448
  let mesh;
3514
3449
  if (primitive.mode === GL_CONSTANTS.POINTS) {
3515
- const pointsMaterial = new PointsMaterial;
3516
- Material.prototype.copy.call(pointsMaterial, material);
3517
- pointsMaterial.color.copy(material.color);
3518
- pointsMaterial.map = material.map;
3519
- pointsMaterial.sizeAttenuation = false;
3520
- mesh = new Points(geometry, pointsMaterial);
3450
+ mesh = new Points(geometry, material);
3521
3451
  } else if (primitive.mode === GL_CONSTANTS.TRIANGLES || primitive.mode === GL_CONSTANTS.TRIANGLE_STRIP || primitive.mode === GL_CONSTANTS.TRIANGLE_FAN || primitive.mode === undefined) {
3522
3452
  mesh = new Mesh(geometry, material);
3523
3453
  if (primitive.mode === GL_CONSTANTS.TRIANGLE_STRIP) {
@@ -3761,6 +3691,9 @@ class DynamicGltfLoader {
3761
3691
  } else {
3762
3692
  this.edgeNodes.push(uniqueNodeId);
3763
3693
  }
3694
+ if (meshDef.extras && meshDef.extras.handle) {
3695
+ handle = `${structure.id}_${meshDef.extras.handle}`;
3696
+ }
3764
3697
  this.nodes.set(uniqueNodeId, {
3765
3698
  position: nodeGroup ? nodeGroup.position.clone() : (new Vector3).setFromMatrixPosition(nodeMatrix),
3766
3699
  nodeIndex: nodeId,
@@ -3861,12 +3794,12 @@ class DynamicGltfLoader {
3861
3794
  }
3862
3795
  }));
3863
3796
  }
3864
- createDefaultMaterial() {
3865
- if (this.currentPrimitiveMode === GL_CONSTANTS.POINTS) {
3797
+ createDefaultMaterial(primitiveMode = undefined) {
3798
+ if (primitiveMode === GL_CONSTANTS.POINTS) {
3866
3799
  return new PointsMaterial({
3867
3800
  color: new Color(8421504),
3868
3801
  size: .05,
3869
- sizeAttenuation: true,
3802
+ sizeAttenuation: false,
3870
3803
  alphaTest: .5,
3871
3804
  transparent: true,
3872
3805
  vertexColors: false,
@@ -3874,11 +3807,21 @@ class DynamicGltfLoader {
3874
3807
  depthWrite: false,
3875
3808
  depthTest: true
3876
3809
  });
3810
+ } else if (primitiveMode === GL_CONSTANTS.LINES || primitiveMode === GL_CONSTANTS.LINE_STRIP || primitiveMode === GL_CONSTANTS.LINE_LOOP) {
3811
+ return new LineBasicMaterial({
3812
+ color: 8421504,
3813
+ linewidth: 1,
3814
+ alphaTest: .1,
3815
+ depthTest: true,
3816
+ depthWrite: true,
3817
+ transparent: true,
3818
+ opacity: 1
3819
+ });
3877
3820
  } else {
3878
- return new MeshStandardMaterial({
3821
+ return new MeshPhongMaterial({
3879
3822
  color: 8421504,
3880
- metalness: 0,
3881
- roughness: 1,
3823
+ specular: 2236962,
3824
+ shininess: 10,
3882
3825
  side: DoubleSide
3883
3826
  });
3884
3827
  }
@@ -4670,11 +4613,13 @@ class GLTFCloudDynamicLoader {
4670
4613
  const scene = new Group;
4671
4614
  this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, scene, this.viewer.renderer);
4672
4615
  this.gltfLoader.memoryLimit = this.viewer.options.memoryLimit;
4616
+ this.gltfLoader.setVisibleEdges(this.viewer.options.edgeModel);
4673
4617
  this.gltfLoader.addEventListener("databasechunk", (data => {
4674
4618
  const modelImpl = new DynamicModelImpl(scene);
4675
4619
  modelImpl.loader = this;
4676
- modelImpl.gltfLoader = this.gltfLoader;
4677
4620
  modelImpl.viewer = this.viewer;
4621
+ modelImpl.gltfLoader = this.gltfLoader;
4622
+ modelImpl.modelId = model.id;
4678
4623
  this.viewer.scene.add(scene);
4679
4624
  this.viewer.models.push(modelImpl);
4680
4625
  this.viewer.syncOptions();
@@ -4731,7 +4676,7 @@ class GLTFCloudDynamicLoader {
4731
4676
  },
4732
4677
  baseUrl: () => Promise.resolve(`${model.httpClient.serverUrl}${model.path}/`)
4733
4678
  };
4734
- const structure = new GltfStructure(1);
4679
+ const structure = new GltfStructure(model.id);
4735
4680
  await structure.initialize(loadController);
4736
4681
  await this.gltfLoader.loadStructure(structure);
4737
4682
  await this.gltfLoader.loadNodes();
@@ -4748,6 +4693,120 @@ loaders.registerLoader("gltf-file", (viewer => new GLTFFileLoader(viewer)));
4748
4693
 
4749
4694
  loaders.registerLoader("gltf-cloud", (viewer => new GLTFCloudDynamicLoader(viewer)));
4750
4695
 
4696
+ class SSAARenderPass extends Pass {
4697
+ constructor(scenes, camera, clearColor = 0, clearAlpha = 0) {
4698
+ super();
4699
+ this.scenes = Array.isArray(scenes) ? scenes : [ scenes ];
4700
+ this.camera = camera;
4701
+ this.sampleLevel = 2;
4702
+ this.unbiased = true;
4703
+ this.stencilBuffer = false;
4704
+ this.clearColor = clearColor;
4705
+ this.clearAlpha = clearAlpha;
4706
+ this._sampleRenderTarget = null;
4707
+ this._oldClearColor = new Color;
4708
+ this._copyUniforms = UniformsUtils.clone(CopyShader.uniforms);
4709
+ this._copyMaterial = new ShaderMaterial({
4710
+ uniforms: this._copyUniforms,
4711
+ vertexShader: CopyShader.vertexShader,
4712
+ fragmentShader: CopyShader.fragmentShader,
4713
+ transparent: true,
4714
+ depthTest: false,
4715
+ depthWrite: false,
4716
+ premultipliedAlpha: true,
4717
+ blending: AdditiveBlending
4718
+ });
4719
+ this._fsQuad = new FullScreenQuad(this._copyMaterial);
4720
+ }
4721
+ dispose() {
4722
+ if (this._sampleRenderTarget) {
4723
+ this._sampleRenderTarget.dispose();
4724
+ this._sampleRenderTarget = null;
4725
+ }
4726
+ this._copyMaterial.dispose();
4727
+ this._fsQuad.dispose();
4728
+ }
4729
+ setSize(width, height) {
4730
+ if (this._sampleRenderTarget) this._sampleRenderTarget.setSize(width, height);
4731
+ }
4732
+ render(renderer, writeBuffer, readBuffer, deltaTime, maskActive) {
4733
+ if (!this._sampleRenderTarget) {
4734
+ this._sampleRenderTarget = new WebGLRenderTarget(readBuffer.width, readBuffer.height, {
4735
+ type: HalfFloatType,
4736
+ stencilBuffer: this.stencilBuffer
4737
+ });
4738
+ this._sampleRenderTarget.texture.name = "SSAAMultiRenderPass.sample";
4739
+ }
4740
+ const jitterOffsets = _JitterVectors[Math.max(0, Math.min(this.sampleLevel, 5))];
4741
+ const autoClear = renderer.autoClear;
4742
+ renderer.autoClear = false;
4743
+ renderer.getClearColor(this._oldClearColor);
4744
+ const oldClearAlpha = renderer.getClearAlpha();
4745
+ const baseSampleWeight = 1 / jitterOffsets.length;
4746
+ const roundingRange = 1 / 32;
4747
+ this._copyUniforms["tDiffuse"].value = this._sampleRenderTarget.texture;
4748
+ const viewOffset = {
4749
+ fullWidth: readBuffer.width,
4750
+ fullHeight: readBuffer.height,
4751
+ offsetX: 0,
4752
+ offsetY: 0,
4753
+ width: readBuffer.width,
4754
+ height: readBuffer.height
4755
+ };
4756
+ const originalViewOffset = Object.assign({}, this.camera.view);
4757
+ if (originalViewOffset.enabled) Object.assign(viewOffset, originalViewOffset);
4758
+ for (let i = 0; i < jitterOffsets.length; i++) {
4759
+ const jitterOffset = jitterOffsets[i];
4760
+ if (this.camera.setViewOffset) {
4761
+ this.camera.setViewOffset(viewOffset.fullWidth, viewOffset.fullHeight, viewOffset.offsetX + jitterOffset[0] * .0625, viewOffset.offsetY + jitterOffset[1] * .0625, viewOffset.width, viewOffset.height);
4762
+ }
4763
+ let sampleWeight = baseSampleWeight;
4764
+ if (this.unbiased) {
4765
+ const uniformCenteredDistribution = -.5 + (i + .5) / jitterOffsets.length;
4766
+ sampleWeight += roundingRange * uniformCenteredDistribution;
4767
+ }
4768
+ this._copyUniforms["opacity"].value = sampleWeight;
4769
+ renderer.setClearColor(this.clearColor, this.clearAlpha);
4770
+ renderer.setRenderTarget(this._sampleRenderTarget);
4771
+ renderer.clear();
4772
+ this.scenes.forEach((scene => renderer.render(scene, this.camera)));
4773
+ renderer.setRenderTarget(this.renderToScreen ? null : writeBuffer);
4774
+ if (i === 0) {
4775
+ renderer.setClearColor(0, 0);
4776
+ renderer.clear();
4777
+ }
4778
+ this._fsQuad.render(renderer);
4779
+ }
4780
+ if (this.camera.setViewOffset && originalViewOffset.enabled) {
4781
+ this.camera.setViewOffset(originalViewOffset.fullWidth, originalViewOffset.fullHeight, originalViewOffset.offsetX, originalViewOffset.offsetY, originalViewOffset.width, originalViewOffset.height);
4782
+ } else if (this.camera.clearViewOffset) {
4783
+ this.camera.clearViewOffset();
4784
+ }
4785
+ renderer.autoClear = autoClear;
4786
+ renderer.setClearColor(this._oldClearColor, oldClearAlpha);
4787
+ }
4788
+ }
4789
+
4790
+ const _JitterVectors = [ [ [ 0, 0 ] ], [ [ 4, 4 ], [ -4, -4 ] ], [ [ -2, -6 ], [ 6, -2 ], [ -6, 2 ], [ 2, 6 ] ], [ [ 1, -3 ], [ -1, 3 ], [ 5, 1 ], [ -3, -5 ], [ -5, 5 ], [ -7, -1 ], [ 3, 7 ], [ 7, -7 ] ], [ [ 1, 1 ], [ -1, -3 ], [ -3, 2 ], [ 4, -1 ], [ -5, -2 ], [ 2, 5 ], [ 5, 3 ], [ 3, -5 ], [ -2, 6 ], [ 0, -7 ], [ -4, -6 ], [ -6, 4 ], [ -8, 0 ], [ 7, -4 ], [ 6, 7 ], [ -7, -8 ] ], [ [ -4, -7 ], [ -7, -5 ], [ -3, -5 ], [ -5, -4 ], [ -1, -4 ], [ -2, -2 ], [ -6, -1 ], [ -4, 0 ], [ -7, 1 ], [ -1, 2 ], [ -6, 3 ], [ -3, 3 ], [ -7, 6 ], [ -3, 6 ], [ -5, 7 ], [ -1, 7 ], [ 5, -7 ], [ 1, -6 ], [ 6, -5 ], [ 4, -4 ], [ 2, -3 ], [ 7, -2 ], [ 1, -1 ], [ 4, -1 ], [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ], [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ] ] ];
4791
+
4792
+ class Helpers extends Scene {
4793
+ constructor() {
4794
+ super(...arguments);
4795
+ this.oldAutoClear = false;
4796
+ this.oldClippingPlanes = [];
4797
+ }
4798
+ onBeforeRender(renderer) {
4799
+ this.oldAutoClear = renderer.autoClear;
4800
+ this.oldClippingPlanes = renderer.clippingPlanes;
4801
+ renderer.autoClear = false;
4802
+ renderer.clippingPlanes = [];
4803
+ }
4804
+ onAfterRender(renderer) {
4805
+ renderer.clippingPlanes = this.oldClippingPlanes;
4806
+ renderer.autoClear = this.oldAutoClear;
4807
+ }
4808
+ }
4809
+
4751
4810
  class Viewer extends EventEmitter2 {
4752
4811
  constructor(client) {
4753
4812
  super();
@@ -4782,7 +4841,7 @@ class Viewer extends EventEmitter2 {
4782
4841
  initialize(canvas, onProgress) {
4783
4842
  this.addEventListener("optionschange", (event => this.syncOptions(event.data)));
4784
4843
  this.scene = new Scene;
4785
- this.helpers = new Scene;
4844
+ this.helpers = new Helpers;
4786
4845
  this.target = new Vector3;
4787
4846
  const pixelRatio = window.devicePixelRatio;
4788
4847
  const rect = canvas.parentElement.getBoundingClientRect();
@@ -4800,11 +4859,26 @@ class Viewer extends EventEmitter2 {
4800
4859
  alpha: true,
4801
4860
  preserveDrawingBuffer: true,
4802
4861
  powerPreference: "high-performance",
4803
- logarithmicDepthBuffer: false
4862
+ logarithmicDepthBuffer: true
4804
4863
  });
4805
4864
  this.renderer.setPixelRatio(pixelRatio);
4806
4865
  this.renderer.setSize(width, height);
4807
- this.renderer.toneMapping = LinearToneMapping;
4866
+ this.renderer.outputColorSpace = LinearSRGBColorSpace;
4867
+ this.renderPass = new RenderPass(this.scene, this.camera);
4868
+ this.helpersPass = new RenderPass(this.helpers, this.camera);
4869
+ this.helpersPass.clear = false;
4870
+ this.fxaaPass = new FXAAPass;
4871
+ this.smaaPass = new SMAAPass;
4872
+ this.ssaaRenderPass = new SSAARenderPass([ this.scene, this.helpers ], this.camera);
4873
+ this.ssaaRenderPass.unbiased = true;
4874
+ this.outputPass = new OutputPass;
4875
+ this.composer = new EffectComposer(this.renderer);
4876
+ this.composer.addPass(this.renderPass);
4877
+ this.composer.addPass(this.helpersPass);
4878
+ this.composer.addPass(this.smaaPass);
4879
+ this.composer.addPass(this.fxaaPass);
4880
+ this.composer.addPass(this.ssaaRenderPass);
4881
+ this.composer.addPass(this.outputPass);
4808
4882
  this.canvas = canvas;
4809
4883
  this.canvasEvents.forEach((x => canvas.addEventListener(x, this.canvaseventlistener)));
4810
4884
  this._markup.initialize(this.canvas, this.canvasEvents, this, this);
@@ -4846,11 +4920,25 @@ class Viewer extends EventEmitter2 {
4846
4920
  this.canvasEvents.forEach((x => this.canvas.removeEventListener(x, this.canvaseventlistener)));
4847
4921
  this.canvas = undefined;
4848
4922
  }
4923
+ if (this.composer) this.composer.dispose();
4924
+ if (this.renderPass) this.renderPass.dispose();
4925
+ if (this.helpersPass) this.helpersPass.dispose();
4926
+ if (this.fxaaPass) this.fxaaPass.dispose();
4927
+ if (this.smaaPass) this.smaaPass.dispose();
4928
+ if (this.ssaaRenderPass) this.ssaaRenderPass.dispose();
4929
+ if (this.outputPass) this.outputPass.dispose();
4849
4930
  if (this.renderer) this.renderer.dispose();
4850
- this.helpers = undefined;
4851
4931
  this.scene = undefined;
4852
- this.renderer = undefined;
4932
+ this.helpers = undefined;
4853
4933
  this.camera = undefined;
4934
+ this.renderer = undefined;
4935
+ this.renderPass = undefined;
4936
+ this.helpersPass = undefined;
4937
+ this.fxaaPass = undefined;
4938
+ this.smaaPass = undefined;
4939
+ this.ssaaRenderPass = undefined;
4940
+ this.outputPass = undefined;
4941
+ this.composer = undefined;
4854
4942
  return this;
4855
4943
  }
4856
4944
  isInitialized() {
@@ -4858,28 +4946,27 @@ class Viewer extends EventEmitter2 {
4858
4946
  }
4859
4947
  update(force = false) {
4860
4948
  this.renderNeeded = true;
4861
- if (force) this.render(performance.now());
4949
+ if (force) this.render();
4862
4950
  this.emitEvent({
4863
4951
  type: "update",
4864
4952
  data: force
4865
4953
  });
4866
4954
  }
4867
- render(time) {
4955
+ render(time, force = false) {
4868
4956
  var _a, _b;
4869
- if (!this.renderNeeded) return;
4870
4957
  if (!this.renderer) return;
4871
- this.renderNeeded = false;
4872
- this.renderer.setViewport(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
4873
- this.renderer.autoClear = true;
4874
- this.renderer.render(this.scene, this.camera);
4875
- const clippingPlanes = this.renderer.clippingPlanes;
4876
- this.renderer.clippingPlanes = [];
4877
- this.renderer.autoClear = false;
4878
- this.renderer.render(this.helpers, this.camera);
4879
- this.renderer.clippingPlanes = clippingPlanes;
4880
- (_b = (_a = this._activeDragger) === null || _a === undefined ? undefined : _a.updatePreview) === null || _b === undefined ? undefined : _b.call(_a);
4958
+ if (!(this.renderNeeded || force)) return;
4959
+ if (!time) time = performance.now();
4881
4960
  const deltaTime = (time - this.renderTime) / 1e3;
4882
4961
  this.renderTime = time;
4962
+ this.renderNeeded = false;
4963
+ if (this.options.antialiasing === true || this.options.antialiasing === "msaa") {
4964
+ this.renderer.render(this.scene, this.camera);
4965
+ this.renderer.render(this.helpers, this.camera);
4966
+ } else {
4967
+ this.composer.render(deltaTime);
4968
+ }
4969
+ (_b = (_a = this._activeDragger) === null || _a === undefined ? undefined : _a.updatePreview) === null || _b === undefined ? undefined : _b.call(_a);
4883
4970
  this.emitEvent({
4884
4971
  type: "render",
4885
4972
  time: time,
@@ -4970,6 +5057,10 @@ class Viewer extends EventEmitter2 {
4970
5057
  this.loaders = [];
4971
5058
  this.models.forEach((model => model.dispose()));
4972
5059
  this.models = [];
5060
+ this.scene.clear();
5061
+ this.helpers.clear();
5062
+ this.models.forEach((model => model.dispose()));
5063
+ this.models = [];
4973
5064
  this.helpers.clear();
4974
5065
  this.scene.clear();
4975
5066
  this.syncOptions();
@@ -4980,7 +5071,15 @@ class Viewer extends EventEmitter2 {
4980
5071
  });
4981
5072
  return this;
4982
5073
  }
4983
- syncOptions(options = this.options) {}
5074
+ syncOptions(options = this.options) {
5075
+ if (!this.renderer) return;
5076
+ this.fxaaPass.enabled = options.antialiasing === "fxaa";
5077
+ this.smaaPass.enabled = options.antialiasing === "smaa";
5078
+ this.ssaaRenderPass.enabled = options.antialiasing === "ssaa";
5079
+ this.renderPass.enabled = !this.ssaaRenderPass.enabled;
5080
+ this.helpersPass.enabled = !this.ssaaRenderPass.enabled;
5081
+ this.update();
5082
+ }
4984
5083
  syncOverlay() {
4985
5084
  if (!this.renderer) return;
4986
5085
  this._markup.syncOverlay();
@@ -5116,19 +5215,23 @@ class Viewer extends EventEmitter2 {
5116
5215
  const extentsSize = this.extents.getBoundingSphere(new Sphere).radius * 2;
5117
5216
  const rendererSize = this.renderer.getSize(new Vector2);
5118
5217
  const aspect = rendererSize.x / rendererSize.y;
5119
- this.camera = new OrthographicCamera;
5120
- this.camera.top = orthogonal_camera.field_height / 2;
5121
- this.camera.bottom = -orthogonal_camera.field_height / 2;
5122
- this.camera.left = this.camera.bottom * aspect;
5123
- this.camera.right = this.camera.top * aspect;
5124
- this.camera.near = 0;
5125
- this.camera.far = extentsSize * 100;
5126
- this.camera.zoom = orthogonal_camera.view_to_world_scale;
5127
- this.camera.updateProjectionMatrix();
5128
- this.camera.up.copy(getVector3FromPoint3d(orthogonal_camera.up_vector));
5129
- this.camera.position.copy(getVector3FromPoint3d(orthogonal_camera.view_point));
5130
- this.camera.lookAt(getVector3FromPoint3d(orthogonal_camera.direction).add(this.camera.position));
5131
- this.camera.updateMatrixWorld();
5218
+ const camera = new OrthographicCamera;
5219
+ camera.top = orthogonal_camera.field_height / 2;
5220
+ camera.bottom = -orthogonal_camera.field_height / 2;
5221
+ camera.left = camera.bottom * aspect;
5222
+ camera.right = camera.top * aspect;
5223
+ camera.near = 0;
5224
+ camera.far = extentsSize * 100;
5225
+ camera.zoom = orthogonal_camera.view_to_world_scale;
5226
+ camera.updateProjectionMatrix();
5227
+ camera.up.copy(getVector3FromPoint3d(orthogonal_camera.up_vector));
5228
+ camera.position.copy(getVector3FromPoint3d(orthogonal_camera.view_point));
5229
+ camera.lookAt(getVector3FromPoint3d(orthogonal_camera.direction).add(camera.position));
5230
+ camera.updateMatrixWorld();
5231
+ this.camera = camera;
5232
+ this.renderPass.camera = camera;
5233
+ this.helpersPass.camera = camera;
5234
+ this.ssaaRenderPass.camera = camera;
5132
5235
  }
5133
5236
  };
5134
5237
  const setPerspectiveCamera = perspective_camera => {
@@ -5136,16 +5239,20 @@ class Viewer extends EventEmitter2 {
5136
5239
  const extentsSize = this.extents.getBoundingSphere(new Sphere).radius * 2;
5137
5240
  const rendererSize = this.renderer.getSize(new Vector2);
5138
5241
  const aspect = rendererSize.x / rendererSize.y;
5139
- this.camera = new PerspectiveCamera;
5140
- this.camera.fov = perspective_camera.field_of_view;
5141
- this.camera.aspect = aspect;
5142
- this.camera.near = extentsSize / 100;
5143
- this.camera.far = extentsSize * 100;
5144
- this.camera.updateProjectionMatrix();
5145
- this.camera.up.copy(getVector3FromPoint3d(perspective_camera.up_vector));
5146
- this.camera.position.copy(getVector3FromPoint3d(perspective_camera.view_point));
5147
- this.camera.lookAt(getVector3FromPoint3d(perspective_camera.direction).add(this.camera.position));
5148
- this.camera.updateMatrixWorld();
5242
+ const camera = new PerspectiveCamera;
5243
+ camera.fov = perspective_camera.field_of_view;
5244
+ camera.aspect = aspect;
5245
+ camera.near = extentsSize / 100;
5246
+ camera.far = extentsSize * 100;
5247
+ camera.updateProjectionMatrix();
5248
+ camera.up.copy(getVector3FromPoint3d(perspective_camera.up_vector));
5249
+ camera.position.copy(getVector3FromPoint3d(perspective_camera.view_point));
5250
+ camera.lookAt(getVector3FromPoint3d(perspective_camera.direction).add(camera.position));
5251
+ camera.updateMatrixWorld();
5252
+ this.camera = camera;
5253
+ this.renderPass.camera = camera;
5254
+ this.helpersPass.camera = camera;
5255
+ this.ssaaRenderPass.camera = camera;
5149
5256
  }
5150
5257
  };
5151
5258
  const setClippingPlanes = clipping_planes => {