1
votes

As the basis for my scene objects, I have a single root Object3D. My data is loaded as a tree structure of Object3Ds from this root. Meshes are added to the leaf Object3Ds, using BufferGeometry/MeshPhongMaterial. I clear the existing tree by passing the root Object3D into this method:

clearScene:
    function (obj) {
        if (obj instanceof THREE.Mesh)
        {
            obj.geometry.dispose();
            obj.geometry = undefined;
            obj.material.dispose();
            obj.material = undefined;
            obj = undefined;
        }
        else
        {
            if (obj.children !== undefined) {
                while (obj.children.length > 0) {
                    this.clearScene(obj.children[0]); // removing children changes the length of the array.
                    obj.remove(obj.children[0]);
                }
            }
        }
    }

Consider the following simple tree:

  • Scene (Scene)
    • Root (Object3D)
      • Branch (Object3D)
        • Leaf (Mesh)

Once this structure is in the scene, I observe the heap (using Chrome's dev tools). I can see 3 Object3Ds objects, and 2 Mesh objects (the extras are the prototypes).

When I call clearScene(Root), I see it step through the tree, removing the Object3Ds, and cleaning up the meshes. But when I observe the heap, I see that although the Object3Ds have been removed, the 2 Mesh objects (and their associated BufferGoemetry and Material objects) remain. If I load the data a second time after clearing, I see 3 Object3Ds (okay), and 4 Meshes (not okay).

I believe this means that a reference isn't getting cleared correctly, but I didn't see any retainers in the heap that would do this.

I must be missing something else which is causing these objects to hang around.

r69dev (I was seeing the same in r68), testing in Chrome 36.0.1985.125

1
Can you create a jsfiddle for this?mrdoob
You can see my jsfiddle for it here (jsfiddle.net/TheJim01/mw9Df/51), but that demo is working mostly as expected--it does completely remove the Mesh and Material objects, so my code must be hanging onto the Mesh object somewhere else. That said, the above fiddle doesn't fully remove the BufferGeometry object, but that may be because of how I defined it.TheJim01
I was doing more testing today, and I must have jumbled my versions. r68 does clear memory correctly, but r69dev does not. I'll try to trace it back to a root cause, and submit a bug, if it hasn't already been addressed/fixed.TheJim01
Oh! It'll be great if you can find the culprit :)mrdoob

1 Answers

2
votes

Issue (concern) submitted on github: https://github.com/mrdoob/three.js/issues/5175

r69dev requires an explicit call to the dispose method for meshes to properly remove references held by the renderer.

Working code:

clearScene:
function (obj) {
    if (obj instanceof THREE.Mesh)
    {
        obj.geometry.dispose();
        obj.geometry = null;
        obj.material.dispose();
        obj.material = null;
        obj.dispose(); // required in r69dev to remove references from the renderer.
        obj = null;
    }
    else
    {
        if (obj.children !== undefined) {
            while (obj.children.length > 0) {
                this.clearScene(obj.children[0]);
                obj.remove(obj.children[0]);
            }
        }
    }
}