@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
@@ -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);
@@ -1911,18 +1931,19 @@ class LightComponent {
1911
1931
  if (this.viewer.extents.isEmpty()) return;
1912
1932
  const extentsCenter = this.viewer.extents.getCenter(new Vector3);
1913
1933
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere).radius;
1914
- this.directionalLight.position.set(.5, .866, 0).multiplyScalar(extentsSize * 2).add(extentsCenter);
1934
+ const front = (new Vector3).copy(this.viewer.camera.up).cross(new Vector3(1, 0, 0)).negate();
1935
+ this.directionalLight.position.copy(this.viewer.camera.up).applyAxisAngle(front, -Math.PI * 30 / 180).multiplyScalar(extentsSize * 2).add(extentsCenter);
1915
1936
  this.directionalLight.target.position.copy(extentsCenter);
1916
- this.frontLight.position.set(0, 0, 1).multiplyScalar(extentsSize * 2).add(extentsCenter);
1937
+ this.frontLight.position.copy(front).multiplyScalar(extentsSize * 2).add(extentsCenter);
1917
1938
  this.frontLight.target.position.copy(extentsCenter);
1918
- this.hemisphereLight.position.set(0, 0, 1).multiplyScalar(extentsSize * 3).add(extentsCenter);
1939
+ this.hemisphereLight.position.copy(front).multiplyScalar(extentsSize * 3).add(extentsCenter);
1919
1940
  this.viewer.scene.add(this.ambientLight);
1920
1941
  this.viewer.scene.add(this.directionalLight);
1921
1942
  this.viewer.scene.add(this.frontLight);
1922
1943
  this.viewer.scene.add(this.hemisphereLight);
1923
1944
  };
1924
1945
  this.viewer = viewer;
1925
- this.ambientLight = new AmbientLight(16777215, 1);
1946
+ this.ambientLight = new AmbientLight(16777215, 1.5);
1926
1947
  this.directionalLight = new DirectionalLight(16777215, 1);
1927
1948
  this.frontLight = new DirectionalLight(16777215, 1.25);
1928
1949
  this.hemisphereLight = new HemisphereLight(16777215, 4473924, 1.25);
@@ -1978,6 +1999,7 @@ class ResizeCanvasComponent {
1978
1999
  camera.updateProjectionMatrix();
1979
2000
  }
1980
2001
  this.viewer.renderer.setSize(width, height, true);
2002
+ this.viewer.composer.setSize(width, height);
1981
2003
  this.viewer.update(true);
1982
2004
  this.viewer.emitEvent({
1983
2005
  type: "resize",
@@ -2044,13 +2066,8 @@ class HighlighterUtils {
2044
2066
  class HighlighterComponent {
2045
2067
  constructor(viewer) {
2046
2068
  this.geometryEnd = () => {
2047
- const {facesColor: facesColor, facesTransparancy: facesTransparancy, edgesColor: edgesColor, edgesOverlap: edgesOverlap, facesOverlap: facesOverlap} = this.viewer.options;
2048
- this.highlightMaterial = new MeshPhongMaterial({
2049
- color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
2069
+ this.facesMaterial = new MeshPhongMaterial({
2050
2070
  transparent: true,
2051
- opacity: (255 - facesTransparancy) / 255,
2052
- depthTest: !facesOverlap,
2053
- depthWrite: !facesOverlap,
2054
2071
  specular: 2236962,
2055
2072
  shininess: 10,
2056
2073
  reflectivity: .05,
@@ -2058,43 +2075,25 @@ class HighlighterComponent {
2058
2075
  polygonOffsetFactor: 1,
2059
2076
  polygonOffsetUnits: 1
2060
2077
  });
2061
- this.outlineMaterial = new LineMaterial({
2062
- color: new Color(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255),
2078
+ this.edgesMaterial = new LineMaterial({
2063
2079
  linewidth: 1.5,
2064
- depthTest: !edgesOverlap,
2065
- depthWrite: !edgesOverlap,
2066
2080
  resolution: new Vector2(window.innerWidth, window.innerHeight)
2067
2081
  });
2068
- this.highlightLineMaterial = new LineBasicMaterial({
2069
- color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
2070
- depthTest: false,
2071
- depthWrite: false
2082
+ this.lineMaterial = new LineBasicMaterial({
2083
+ transparent: true,
2084
+ depthTest: true,
2085
+ depthWrite: true
2072
2086
  });
2073
- this.highlightLineGlowMaterial = new LineMaterial({
2074
- color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
2075
- linewidth: 5,
2087
+ this.lineGlowMaterial = new LineMaterial({
2088
+ linewidth: 1.5,
2076
2089
  transparent: true,
2077
2090
  opacity: .8,
2078
- depthTest: !edgesOverlap,
2079
- depthWrite: !edgesOverlap,
2080
2091
  resolution: new Vector2(window.innerWidth, window.innerHeight)
2081
2092
  });
2093
+ this.syncHighlightColors();
2082
2094
  };
2083
2095
  this.optionsChange = () => {
2084
- const {facesColor: facesColor, facesTransparancy: facesTransparancy, edgesColor: edgesColor, edgesVisibility: edgesVisibility, edgesOverlap: edgesOverlap, facesOverlap: facesOverlap} = this.viewer.options;
2085
- this.highlightMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
2086
- this.highlightMaterial.opacity = (255 - facesTransparancy) / 255;
2087
- this.highlightMaterial.depthTest = !facesOverlap;
2088
- this.highlightMaterial.depthWrite = !facesOverlap;
2089
- this.outlineMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
2090
- this.outlineMaterial.depthTest = !edgesOverlap;
2091
- this.outlineMaterial.depthWrite = !edgesOverlap;
2092
- this.highlightLineMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
2093
- this.highlightLineGlowMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
2094
- this.viewer.selected.forEach((selected => {
2095
- const wireframe = selected.userData.highlightWireframe;
2096
- if (wireframe) wireframe.visible = edgesVisibility;
2097
- }));
2096
+ this.syncHighlightColors();
2098
2097
  this.viewer.update();
2099
2098
  };
2100
2099
  this.viewer = viewer;
@@ -2122,13 +2121,13 @@ class HighlighterComponent {
2122
2121
  const {edgesVisibility: edgesVisibility} = this.viewer.options;
2123
2122
  if (!Array.isArray(objects)) objects = [ objects ];
2124
2123
  if (!objects.length) return;
2125
- objects.forEach((object => {
2124
+ objects.filter((object => !object.userData.isEdge)).forEach((object => {
2126
2125
  if (object.isHighlighted) return;
2127
2126
  if (object.isLine || object.isLineSegments) {
2128
2127
  const positions = object.geometry.attributes.position.array;
2129
2128
  const indices = object.geometry.index ? object.geometry.index.array : null;
2130
2129
  const lineGeometry = indices ? HighlighterUtils.fromIndexedLine(positions, indices) : HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
2131
- const wireframe = new Wireframe(lineGeometry, this.highlightLineGlowMaterial);
2130
+ const wireframe = new Wireframe(lineGeometry, this.lineGlowMaterial);
2132
2131
  wireframe.position.copy(object.position);
2133
2132
  wireframe.rotation.copy(object.rotation);
2134
2133
  wireframe.scale.copy(object.scale);
@@ -2136,12 +2135,12 @@ class HighlighterComponent {
2136
2135
  object.parent.add(wireframe);
2137
2136
  object.userData.highlightWireframe = wireframe;
2138
2137
  object.userData.originalMaterial = object.material;
2139
- object.material = this.highlightLineMaterial;
2138
+ object.material = this.lineMaterial;
2140
2139
  object.isHighlighted = true;
2141
2140
  } else if (object.isMesh) {
2142
- const edgesGeometry = new EdgesGeometry(object.geometry, 60);
2141
+ const edgesGeometry = new EdgesGeometry(object.geometry, 89);
2143
2142
  const lineGeometry = (new LineSegmentsGeometry).fromEdgesGeometry(edgesGeometry);
2144
- const wireframe = new Wireframe(lineGeometry, this.outlineMaterial);
2143
+ const wireframe = new Wireframe(lineGeometry, this.edgesMaterial);
2145
2144
  wireframe.position.copy(object.position);
2146
2145
  wireframe.rotation.copy(object.rotation);
2147
2146
  wireframe.scale.copy(object.scale);
@@ -2149,7 +2148,7 @@ class HighlighterComponent {
2149
2148
  object.parent.add(wireframe);
2150
2149
  object.userData.highlightWireframe = wireframe;
2151
2150
  object.userData.originalMaterial = object.material;
2152
- object.material = this.highlightMaterial;
2151
+ object.material = this.facesMaterial;
2153
2152
  object.isHighlighted = true;
2154
2153
  }
2155
2154
  }));
@@ -2166,10 +2165,30 @@ class HighlighterComponent {
2166
2165
  delete object.userData.highlightWireframe;
2167
2166
  }));
2168
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
+ }
2169
2187
  viewerResize(event) {
2170
- var _a, _b;
2188
+ var _a, _b, _c;
2171
2189
  (_a = this.renderTarget) === null || _a === undefined ? undefined : _a.setSize(event.width, event.height);
2172
- (_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);
2173
2192
  }
2174
2193
  }
2175
2194
 
@@ -2361,14 +2380,17 @@ class WCSHelper extends Object3D {
2361
2380
  render(renderer) {
2362
2381
  this.quaternion.copy(this.camera.quaternion).invert();
2363
2382
  this.updateMatrixWorld();
2364
- const clippingPlanes = renderer.clippingPlanes;
2365
- const viewport = renderer.getViewport(new Vector4);
2366
- 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;
2367
2387
  renderer.clippingPlanes = [];
2388
+ renderer.setViewport(this.position.x, this.position.y, this.size, this.size);
2368
2389
  renderer.clearDepth();
2369
2390
  renderer.render(this, this.orthoCamera);
2370
- renderer.setViewport(viewport);
2371
- renderer.clippingPlanes = clippingPlanes;
2391
+ renderer.setViewport(oldViewport);
2392
+ renderer.clippingPlanes = oldClippingPlanes;
2393
+ renderer.autoClear = oldAutoClear;
2372
2394
  }
2373
2395
  }
2374
2396
 
@@ -2637,23 +2659,28 @@ class DynamicModelImpl extends ModelImpl {
2637
2659
  const handlesSet = new Set(handles);
2638
2660
  const objects = [];
2639
2661
  handlesSet.forEach((handle => {
2640
- const handles = this.gltfLoader.handleToObjects.get(handle) || [];
2662
+ const handle2 = `${this.modelId}_${handle}`;
2663
+ const handles = this.gltfLoader.handleToObjects.get(handle2) || [];
2641
2664
  objects.push(...Array.from(handles));
2642
2665
  }));
2643
2666
  return objects;
2644
2667
  }
2668
+ getHandlesByObjects(objects) {
2669
+ const handles = super.getHandlesByObjects(objects);
2670
+ return handles.map((x => x.split("_").pop()));
2671
+ }
2645
2672
  hideObjects(objects) {
2646
- const handles = this.getHandlesByObjects(objects);
2673
+ const handles = super.getHandlesByObjects(objects);
2647
2674
  this.gltfLoader.hideObjects(handles);
2648
2675
  return this;
2649
2676
  }
2650
2677
  isolateObjects(objects) {
2651
- const handles = this.getHandlesByObjects(objects);
2678
+ const handles = super.getHandlesByObjects(objects);
2652
2679
  this.gltfLoader.isolateObjects(new Set(handles));
2653
2680
  return this;
2654
2681
  }
2655
2682
  showObjects(objects) {
2656
- const handles = this.getHandlesByObjects(objects);
2683
+ const handles = super.getHandlesByObjects(objects);
2657
2684
  this.gltfLoader.showObjects(handles);
2658
2685
  return this;
2659
2686
  }
@@ -2708,6 +2735,7 @@ class GltfStructure {
2708
2735
  this.textureLoader = new TextureLoader;
2709
2736
  this.materials = new Map;
2710
2737
  this.textureCache = new Map;
2738
+ this.materialCache = new Map;
2711
2739
  }
2712
2740
  async initialize(loadController) {
2713
2741
  this.json = await loadController.loadJson();
@@ -2982,17 +3010,24 @@ class GltfStructure {
2982
3010
  }
2983
3011
  await Promise.all(texturePromises);
2984
3012
  }
2985
- async loadMaterials() {
3013
+ loadMaterials() {
2986
3014
  if (!this.json.materials) return this.materials;
2987
3015
  for (let i = 0; i < this.json.materials.length; i++) {
2988
3016
  const materialDef = this.json.materials[i];
2989
- const material = await this.createMaterial(materialDef);
2990
- material.name = materialDef.name;
2991
- 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);
2992
3027
  }
2993
3028
  return this.materials;
2994
3029
  }
2995
- createMaterial(materialDef) {
3030
+ createMaterial(materialDef, primitiveMode = undefined) {
2996
3031
  const params = {};
2997
3032
  if (materialDef.pbrMetallicRoughness) {
2998
3033
  const pbr = materialDef.pbrMetallicRoughness;
@@ -3005,27 +3040,50 @@ class GltfStructure {
3005
3040
  params.map = this.textureCache.get(pbr.baseColorTexture.index);
3006
3041
  }
3007
3042
  }
3008
- params.specular = 2236962;
3009
- params.shininess = 10;
3010
- params.reflectivity = .05;
3011
- params.polygonOffset = true;
3012
- params.polygonOffsetFactor = 1;
3013
- params.polygonOffsetUnits = 1;
3014
3043
  if (materialDef.emissiveFactor) {
3015
3044
  params.emissive = (new Color).fromArray(materialDef.emissiveFactor);
3016
3045
  }
3017
- if (materialDef.normalTexture) {
3018
- params.normalMap = this.textureCache.get(materialDef.normalTexture.index);
3019
- }
3020
3046
  if (materialDef.alphaMode === "BLEND") {
3021
3047
  params.transparent = true;
3022
3048
  }
3023
3049
  if (materialDef.doubleSided) {
3024
3050
  params.side = DoubleSide;
3025
3051
  }
3026
- 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
+ }
3027
3071
  return material;
3028
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
+ }
3029
3087
  disposeMaterials() {
3030
3088
  this.textureCache.forEach((texture => texture.dispose()));
3031
3089
  this.textureCache.clear();
@@ -3043,6 +3101,30 @@ class GltfStructure {
3043
3101
  material.dispose();
3044
3102
  }));
3045
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();
3046
3128
  }
3047
3129
  estimateNodeSize(meshIndex) {
3048
3130
  if (!this.json.meshes) return 0;
@@ -3072,156 +3154,6 @@ class GltfStructure {
3072
3154
  }
3073
3155
  }
3074
3156
 
3075
- function mergeGeometries(geometries, useGroups = false) {
3076
- const isIndexed = geometries[0].index !== null;
3077
- const attributesUsed = new Set(Object.keys(geometries[0].attributes));
3078
- const morphAttributesUsed = new Set(Object.keys(geometries[0].morphAttributes));
3079
- const attributes = {};
3080
- const morphAttributes = {};
3081
- const morphTargetsRelative = geometries[0].morphTargetsRelative;
3082
- const mergedGeometry = new BufferGeometry;
3083
- let offset = 0;
3084
- for (let i = 0; i < geometries.length; ++i) {
3085
- const geometry = geometries[i];
3086
- let attributesCount = 0;
3087
- if (isIndexed !== (geometry.index !== null)) {
3088
- 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.");
3089
- return null;
3090
- }
3091
- for (const name in geometry.attributes) {
3092
- if (!attributesUsed.has(name)) {
3093
- 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.');
3094
- return null;
3095
- }
3096
- if (attributes[name] === undefined) attributes[name] = [];
3097
- attributes[name].push(geometry.attributes[name]);
3098
- attributesCount++;
3099
- }
3100
- if (attributesCount !== attributesUsed.size) {
3101
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + ". Make sure all geometries have the same number of attributes.");
3102
- return null;
3103
- }
3104
- if (morphTargetsRelative !== geometry.morphTargetsRelative) {
3105
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + ". .morphTargetsRelative must be consistent throughout all geometries.");
3106
- return null;
3107
- }
3108
- for (const name in geometry.morphAttributes) {
3109
- if (!morphAttributesUsed.has(name)) {
3110
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + ". .morphAttributes must be consistent throughout all geometries.");
3111
- return null;
3112
- }
3113
- if (morphAttributes[name] === undefined) morphAttributes[name] = [];
3114
- morphAttributes[name].push(geometry.morphAttributes[name]);
3115
- }
3116
- if (useGroups) {
3117
- let count;
3118
- if (isIndexed) {
3119
- count = geometry.index.count;
3120
- } else if (geometry.attributes.position !== undefined) {
3121
- count = geometry.attributes.position.count;
3122
- } else {
3123
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index " + i + ". The geometry must have either an index or a position attribute");
3124
- return null;
3125
- }
3126
- mergedGeometry.addGroup(offset, count, i);
3127
- offset += count;
3128
- }
3129
- }
3130
- if (isIndexed) {
3131
- let indexOffset = 0;
3132
- const mergedIndex = [];
3133
- for (let i = 0; i < geometries.length; ++i) {
3134
- const index = geometries[i].index;
3135
- for (let j = 0; j < index.count; ++j) {
3136
- mergedIndex.push(index.getX(j) + indexOffset);
3137
- }
3138
- indexOffset += geometries[i].attributes.position.count;
3139
- }
3140
- mergedGeometry.setIndex(mergedIndex);
3141
- }
3142
- for (const name in attributes) {
3143
- const mergedAttribute = mergeAttributes(attributes[name]);
3144
- if (!mergedAttribute) {
3145
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the " + name + " attribute.");
3146
- return null;
3147
- }
3148
- mergedGeometry.setAttribute(name, mergedAttribute);
3149
- }
3150
- for (const name in morphAttributes) {
3151
- const numMorphTargets = morphAttributes[name][0].length;
3152
- if (numMorphTargets === 0) break;
3153
- mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};
3154
- mergedGeometry.morphAttributes[name] = [];
3155
- for (let i = 0; i < numMorphTargets; ++i) {
3156
- const morphAttributesToMerge = [];
3157
- for (let j = 0; j < morphAttributes[name].length; ++j) {
3158
- morphAttributesToMerge.push(morphAttributes[name][j][i]);
3159
- }
3160
- const mergedMorphAttribute = mergeAttributes(morphAttributesToMerge);
3161
- if (!mergedMorphAttribute) {
3162
- console.error("THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the " + name + " morphAttribute.");
3163
- return null;
3164
- }
3165
- mergedGeometry.morphAttributes[name].push(mergedMorphAttribute);
3166
- }
3167
- }
3168
- return mergedGeometry;
3169
- }
3170
-
3171
- function mergeAttributes(attributes) {
3172
- let TypedArray;
3173
- let itemSize;
3174
- let normalized;
3175
- let gpuType = -1;
3176
- let arrayLength = 0;
3177
- for (let i = 0; i < attributes.length; ++i) {
3178
- const attribute = attributes[i];
3179
- if (TypedArray === undefined) TypedArray = attribute.array.constructor;
3180
- if (TypedArray !== attribute.array.constructor) {
3181
- console.error("THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes.");
3182
- return null;
3183
- }
3184
- if (itemSize === undefined) itemSize = attribute.itemSize;
3185
- if (itemSize !== attribute.itemSize) {
3186
- console.error("THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes.");
3187
- return null;
3188
- }
3189
- if (normalized === undefined) normalized = attribute.normalized;
3190
- if (normalized !== attribute.normalized) {
3191
- console.error("THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes.");
3192
- return null;
3193
- }
3194
- if (gpuType === -1) gpuType = attribute.gpuType;
3195
- if (gpuType !== attribute.gpuType) {
3196
- console.error("THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.gpuType must be consistent across matching attributes.");
3197
- return null;
3198
- }
3199
- arrayLength += attribute.count * itemSize;
3200
- }
3201
- const array = new TypedArray(arrayLength);
3202
- const result = new BufferAttribute(array, itemSize, normalized);
3203
- let offset = 0;
3204
- for (let i = 0; i < attributes.length; ++i) {
3205
- const attribute = attributes[i];
3206
- if (attribute.isInterleavedBufferAttribute) {
3207
- const tupleOffset = offset / itemSize;
3208
- for (let j = 0, l = attribute.count; j < l; j++) {
3209
- for (let c = 0; c < itemSize; c++) {
3210
- const value = attribute.getComponent(j, c);
3211
- result.setComponent(j + tupleOffset, c, value);
3212
- }
3213
- }
3214
- } else {
3215
- array.set(attribute.array, offset);
3216
- }
3217
- offset += attribute.count * itemSize;
3218
- }
3219
- if (gpuType !== undefined) {
3220
- result.gpuType = gpuType;
3221
- }
3222
- return result;
3223
- }
3224
-
3225
3157
  class DynamicGltfLoader {
3226
3158
  constructor(camera, scene, renderer) {
3227
3159
  this.camera = camera;
@@ -3505,18 +3437,17 @@ class DynamicGltfLoader {
3505
3437
  }
3506
3438
  let material;
3507
3439
  if (primitive.material !== undefined) {
3508
- 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
+ }
3509
3445
  } else {
3510
- material = this.createDefaultMaterial();
3446
+ material = this.createDefaultMaterial(primitive.mode);
3511
3447
  }
3512
3448
  let mesh;
3513
3449
  if (primitive.mode === GL_CONSTANTS.POINTS) {
3514
- const pointsMaterial = new PointsMaterial;
3515
- Material.prototype.copy.call(pointsMaterial, material);
3516
- pointsMaterial.color.copy(material.color);
3517
- pointsMaterial.map = material.map;
3518
- pointsMaterial.sizeAttenuation = false;
3519
- mesh = new Points(geometry, pointsMaterial);
3450
+ mesh = new Points(geometry, material);
3520
3451
  } else if (primitive.mode === GL_CONSTANTS.TRIANGLES || primitive.mode === GL_CONSTANTS.TRIANGLE_STRIP || primitive.mode === GL_CONSTANTS.TRIANGLE_FAN || primitive.mode === undefined) {
3521
3452
  mesh = new Mesh(geometry, material);
3522
3453
  if (primitive.mode === GL_CONSTANTS.TRIANGLE_STRIP) {
@@ -3760,6 +3691,9 @@ class DynamicGltfLoader {
3760
3691
  } else {
3761
3692
  this.edgeNodes.push(uniqueNodeId);
3762
3693
  }
3694
+ if (meshDef.extras && meshDef.extras.handle) {
3695
+ handle = `${structure.id}_${meshDef.extras.handle}`;
3696
+ }
3763
3697
  this.nodes.set(uniqueNodeId, {
3764
3698
  position: nodeGroup ? nodeGroup.position.clone() : (new Vector3).setFromMatrixPosition(nodeMatrix),
3765
3699
  nodeIndex: nodeId,
@@ -3860,12 +3794,12 @@ class DynamicGltfLoader {
3860
3794
  }
3861
3795
  }));
3862
3796
  }
3863
- createDefaultMaterial() {
3864
- if (this.currentPrimitiveMode === GL_CONSTANTS.POINTS) {
3797
+ createDefaultMaterial(primitiveMode = undefined) {
3798
+ if (primitiveMode === GL_CONSTANTS.POINTS) {
3865
3799
  return new PointsMaterial({
3866
3800
  color: new Color(8421504),
3867
3801
  size: .05,
3868
- sizeAttenuation: true,
3802
+ sizeAttenuation: false,
3869
3803
  alphaTest: .5,
3870
3804
  transparent: true,
3871
3805
  vertexColors: false,
@@ -3873,11 +3807,21 @@ class DynamicGltfLoader {
3873
3807
  depthWrite: false,
3874
3808
  depthTest: true
3875
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
+ });
3876
3820
  } else {
3877
- return new MeshStandardMaterial({
3821
+ return new MeshPhongMaterial({
3878
3822
  color: 8421504,
3879
- metalness: 0,
3880
- roughness: 1,
3823
+ specular: 2236962,
3824
+ shininess: 10,
3881
3825
  side: DoubleSide
3882
3826
  });
3883
3827
  }
@@ -4669,11 +4613,13 @@ class GLTFCloudDynamicLoader {
4669
4613
  const scene = new Group;
4670
4614
  this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, scene, this.viewer.renderer);
4671
4615
  this.gltfLoader.memoryLimit = this.viewer.options.memoryLimit;
4616
+ this.gltfLoader.setVisibleEdges(this.viewer.options.edgeModel);
4672
4617
  this.gltfLoader.addEventListener("databasechunk", (data => {
4673
4618
  const modelImpl = new DynamicModelImpl(scene);
4674
4619
  modelImpl.loader = this;
4675
- modelImpl.gltfLoader = this.gltfLoader;
4676
4620
  modelImpl.viewer = this.viewer;
4621
+ modelImpl.gltfLoader = this.gltfLoader;
4622
+ modelImpl.modelId = model.id;
4677
4623
  this.viewer.scene.add(scene);
4678
4624
  this.viewer.models.push(modelImpl);
4679
4625
  this.viewer.syncOptions();
@@ -4730,7 +4676,7 @@ class GLTFCloudDynamicLoader {
4730
4676
  },
4731
4677
  baseUrl: () => Promise.resolve(`${model.httpClient.serverUrl}${model.path}/`)
4732
4678
  };
4733
- const structure = new GltfStructure(1);
4679
+ const structure = new GltfStructure(model.id);
4734
4680
  await structure.initialize(loadController);
4735
4681
  await this.gltfLoader.loadStructure(structure);
4736
4682
  await this.gltfLoader.loadNodes();
@@ -4747,6 +4693,120 @@ loaders.registerLoader("gltf-file", (viewer => new GLTFFileLoader(viewer)));
4747
4693
 
4748
4694
  loaders.registerLoader("gltf-cloud", (viewer => new GLTFCloudDynamicLoader(viewer)));
4749
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
+
4750
4810
  class Viewer extends EventEmitter2 {
4751
4811
  constructor(client) {
4752
4812
  super();
@@ -4781,7 +4841,7 @@ class Viewer extends EventEmitter2 {
4781
4841
  initialize(canvas, onProgress) {
4782
4842
  this.addEventListener("optionschange", (event => this.syncOptions(event.data)));
4783
4843
  this.scene = new Scene;
4784
- this.helpers = new Scene;
4844
+ this.helpers = new Helpers;
4785
4845
  this.target = new Vector3;
4786
4846
  const pixelRatio = window.devicePixelRatio;
4787
4847
  const rect = canvas.parentElement.getBoundingClientRect();
@@ -4799,11 +4859,26 @@ class Viewer extends EventEmitter2 {
4799
4859
  alpha: true,
4800
4860
  preserveDrawingBuffer: true,
4801
4861
  powerPreference: "high-performance",
4802
- logarithmicDepthBuffer: false
4862
+ logarithmicDepthBuffer: true
4803
4863
  });
4804
4864
  this.renderer.setPixelRatio(pixelRatio);
4805
4865
  this.renderer.setSize(width, height);
4806
- 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);
4807
4882
  this.canvas = canvas;
4808
4883
  this.canvasEvents.forEach((x => canvas.addEventListener(x, this.canvaseventlistener)));
4809
4884
  this._markup.initialize(this.canvas, this.canvasEvents, this, this);
@@ -4845,11 +4920,25 @@ class Viewer extends EventEmitter2 {
4845
4920
  this.canvasEvents.forEach((x => this.canvas.removeEventListener(x, this.canvaseventlistener)));
4846
4921
  this.canvas = undefined;
4847
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();
4848
4930
  if (this.renderer) this.renderer.dispose();
4849
- this.helpers = undefined;
4850
4931
  this.scene = undefined;
4851
- this.renderer = undefined;
4932
+ this.helpers = undefined;
4852
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;
4853
4942
  return this;
4854
4943
  }
4855
4944
  isInitialized() {
@@ -4857,28 +4946,27 @@ class Viewer extends EventEmitter2 {
4857
4946
  }
4858
4947
  update(force = false) {
4859
4948
  this.renderNeeded = true;
4860
- if (force) this.render(performance.now());
4949
+ if (force) this.render();
4861
4950
  this.emitEvent({
4862
4951
  type: "update",
4863
4952
  data: force
4864
4953
  });
4865
4954
  }
4866
- render(time) {
4955
+ render(time, force = false) {
4867
4956
  var _a, _b;
4868
- if (!this.renderNeeded) return;
4869
4957
  if (!this.renderer) return;
4870
- this.renderNeeded = false;
4871
- this.renderer.setViewport(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
4872
- this.renderer.autoClear = true;
4873
- this.renderer.render(this.scene, this.camera);
4874
- const clippingPlanes = this.renderer.clippingPlanes;
4875
- this.renderer.clippingPlanes = [];
4876
- this.renderer.autoClear = false;
4877
- this.renderer.render(this.helpers, this.camera);
4878
- this.renderer.clippingPlanes = clippingPlanes;
4879
- (_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();
4880
4960
  const deltaTime = (time - this.renderTime) / 1e3;
4881
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);
4882
4970
  this.emitEvent({
4883
4971
  type: "render",
4884
4972
  time: time,
@@ -4969,6 +5057,10 @@ class Viewer extends EventEmitter2 {
4969
5057
  this.loaders = [];
4970
5058
  this.models.forEach((model => model.dispose()));
4971
5059
  this.models = [];
5060
+ this.scene.clear();
5061
+ this.helpers.clear();
5062
+ this.models.forEach((model => model.dispose()));
5063
+ this.models = [];
4972
5064
  this.helpers.clear();
4973
5065
  this.scene.clear();
4974
5066
  this.syncOptions();
@@ -4979,7 +5071,15 @@ class Viewer extends EventEmitter2 {
4979
5071
  });
4980
5072
  return this;
4981
5073
  }
4982
- 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
+ }
4983
5083
  syncOverlay() {
4984
5084
  if (!this.renderer) return;
4985
5085
  this._markup.syncOverlay();
@@ -5115,19 +5215,23 @@ class Viewer extends EventEmitter2 {
5115
5215
  const extentsSize = this.extents.getBoundingSphere(new Sphere).radius * 2;
5116
5216
  const rendererSize = this.renderer.getSize(new Vector2);
5117
5217
  const aspect = rendererSize.x / rendererSize.y;
5118
- this.camera = new OrthographicCamera;
5119
- this.camera.top = orthogonal_camera.field_height / 2;
5120
- this.camera.bottom = -orthogonal_camera.field_height / 2;
5121
- this.camera.left = this.camera.bottom * aspect;
5122
- this.camera.right = this.camera.top * aspect;
5123
- this.camera.near = 0;
5124
- this.camera.far = extentsSize * 100;
5125
- this.camera.zoom = orthogonal_camera.view_to_world_scale;
5126
- this.camera.updateProjectionMatrix();
5127
- this.camera.up.copy(getVector3FromPoint3d(orthogonal_camera.up_vector));
5128
- this.camera.position.copy(getVector3FromPoint3d(orthogonal_camera.view_point));
5129
- this.camera.lookAt(getVector3FromPoint3d(orthogonal_camera.direction).add(this.camera.position));
5130
- 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;
5131
5235
  }
5132
5236
  };
5133
5237
  const setPerspectiveCamera = perspective_camera => {
@@ -5135,16 +5239,20 @@ class Viewer extends EventEmitter2 {
5135
5239
  const extentsSize = this.extents.getBoundingSphere(new Sphere).radius * 2;
5136
5240
  const rendererSize = this.renderer.getSize(new Vector2);
5137
5241
  const aspect = rendererSize.x / rendererSize.y;
5138
- this.camera = new PerspectiveCamera;
5139
- this.camera.fov = perspective_camera.field_of_view;
5140
- this.camera.aspect = aspect;
5141
- this.camera.near = extentsSize / 100;
5142
- this.camera.far = extentsSize * 100;
5143
- this.camera.updateProjectionMatrix();
5144
- this.camera.up.copy(getVector3FromPoint3d(perspective_camera.up_vector));
5145
- this.camera.position.copy(getVector3FromPoint3d(perspective_camera.view_point));
5146
- this.camera.lookAt(getVector3FromPoint3d(perspective_camera.direction).add(this.camera.position));
5147
- 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;
5148
5256
  }
5149
5257
  };
5150
5258
  const setClippingPlanes = clipping_planes => {