From c244562ed0e388c076e25a9962ff1975fe030dd0 Mon Sep 17 00:00:00 2001 From: kovacsv Date: Fri, 16 Dec 2022 13:24:31 +0100 Subject: [PATCH] Context and Closure Memory Leaks #321 --- sandbox/embed_selfhost_memory_test.html | 87 +++++++++++++++++++++++ source/engine/main.js | 3 +- source/engine/threejs/threemodelloader.js | 6 ++ source/engine/threejs/threeutils.js | 20 ++++++ source/engine/viewer/embeddedviewer.js | 7 ++ source/engine/viewer/viewer.js | 6 ++ source/engine/viewer/viewergeometry.js | 19 ++--- 7 files changed, 132 insertions(+), 16 deletions(-) create mode 100644 sandbox/embed_selfhost_memory_test.html diff --git a/sandbox/embed_selfhost_memory_test.html b/sandbox/embed_selfhost_memory_test.html new file mode 100644 index 0000000..7a986bf --- /dev/null +++ b/sandbox/embed_selfhost_memory_test.html @@ -0,0 +1,87 @@ + + + + + + + + Online 3D Viewer + + + + + + + + + + + + diff --git a/source/engine/main.js b/source/engine/main.js index 321d2c6..e00c0ad 100644 --- a/source/engine/main.js +++ b/source/engine/main.js @@ -63,7 +63,7 @@ import { Triangle } from './model/triangle.js'; import { ParameterListBuilder, ParameterListParser, CreateUrlBuilder, CreateUrlParser, CreateModelUrlParameters, ParameterConverter } from './parameters/parameterlist.js'; import { ModelToThreeConversionParams, ModelToThreeConversionOutput, ThreeConversionStateHandler, ThreeNodeTree, ConvertModelToThreeObject } from './threejs/threeconverter.js'; import { ThreeModelLoader } from './threejs/threemodelloader.js'; -import { HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, ShadingType } from './threejs/threeutils.js'; +import { HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, DisposeThreeObjects, ShadingType } from './threejs/threeutils.js'; import { Camera, CameraIsEqual3D } from './viewer/camera.js'; import { GetIntegerFromStyle, GetDomElementExternalWidth, GetDomElementExternalHeight, GetDomElementInnerDimensions, GetDomElementClientCoordinates, CreateDomElement, AddDomElement, AddDiv, ClearDomElement, InsertDomElementBefore, InsertDomElementAfter, ShowDomElement, IsDomElementVisible, SetDomElementWidth, SetDomElementHeight, GetDomElementOuterWidth, GetDomElementOuterHeight, SetDomElementOuterWidth, SetDomElementOuterHeight, CreateDiv } from './viewer/domutils.js'; import { EmbeddedViewer, Init3DViewerElement, Init3DViewerElements } from './viewer/embeddedviewer.js'; @@ -285,6 +285,7 @@ export { ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, + DisposeThreeObjects, ShadingType, Camera, CameraIsEqual3D, diff --git a/source/engine/threejs/threemodelloader.js b/source/engine/threejs/threemodelloader.js index fc8c20b..73037a6 100644 --- a/source/engine/threejs/threemodelloader.js +++ b/source/engine/threejs/threemodelloader.js @@ -108,4 +108,10 @@ export class ThreeModelLoader } this.objectUrls = null; } + + Destroy () + { + this.RevokeObjectUrls (); + this.importer = null; + } } diff --git a/source/engine/threejs/threeutils.js b/source/engine/threejs/threeutils.js index ec91713..016d05d 100644 --- a/source/engine/threejs/threeutils.js +++ b/source/engine/threejs/threeutils.js @@ -181,3 +181,23 @@ export function ConvertThreeGeometryToMesh (threeGeometry, materialIndex) return mesh; } + +export function DisposeThreeObjects (mainObject) +{ + if (mainObject === null) { + return; + } + + mainObject.traverse ((obj) => { + if (obj.isMesh || obj.isLineSegments) { + obj.geometry.dispose (); + if (Array.isArray (obj.material)) { + for (let material of obj.material) { + material.dispose (); + } + } else { + obj.material.dispose (); + } + } + }); +} diff --git a/source/engine/viewer/embeddedviewer.js b/source/engine/viewer/embeddedviewer.js index 4385f1d..59b74ec 100644 --- a/source/engine/viewer/embeddedviewer.js +++ b/source/engine/viewer/embeddedviewer.js @@ -157,6 +157,13 @@ export class EmbeddedViewer let height = this.parentElement.clientHeight; this.viewer.Resize (width, height); } + + Destroy () + { + this.modelLoader.Destroy (); + this.viewer.Destroy (); + this.model = null; + } } export function Init3DViewerElement (parentElement, modelUrls, parameters) diff --git a/source/engine/viewer/viewer.js b/source/engine/viewer/viewer.js index 3d0b89e..99a34f8 100644 --- a/source/engine/viewer/viewer.js +++ b/source/engine/viewer/viewer.js @@ -686,4 +686,10 @@ export class Viewer this.ResizeRenderer (originalSize.width, originalSize.height); return url; } + + Destroy () + { + this.Clear (); + this.renderer.dispose (); + } } diff --git a/source/engine/viewer/viewergeometry.js b/source/engine/viewer/viewergeometry.js index c04d0f6..399a9b6 100644 --- a/source/engine/viewer/viewergeometry.js +++ b/source/engine/viewer/viewergeometry.js @@ -1,5 +1,5 @@ import { RGBColor } from '../model/color.js'; -import { ConvertColorToThreeColor } from '../threejs/threeutils.js'; +import { ConvertColorToThreeColor, DisposeThreeObjects } from '../threejs/threeutils.js'; import * as THREE from 'three'; @@ -143,9 +143,7 @@ export class ViewerGeometry return; } - this.EnumerateMeshes ((mesh) => { - mesh.geometry.dispose (); - }); + DisposeThreeObjects (this.mainObject); this.scene.remove (this.mainObject); this.mainObject = null; } @@ -159,9 +157,7 @@ export class ViewerGeometry this.EnumerateMeshes ((mesh) => { SetThreeMeshPolygonOffset (mesh, false); }); - this.EnumerateEdges ((edge) => { - edge.geometry.dispose (); - }); + DisposeThreeObjects (this.mainEdgeObject); this.scene.remove (this.mainEdgeObject); this.mainEdgeObject = null; } @@ -236,14 +232,7 @@ export class ViewerExtraGeometry Clear () { - if (this.mainObject === null) { - return; - } - this.mainObject.traverse ((obj) => { - if (obj.isMesh || obj.isLineSegments) { - obj.geometry.dispose (); - } - }); + DisposeThreeObjects (this.mainObject); this.scene.remove (this.mainObject); this.mainObject = null; }