5
votes

-Three.js Version 66

-Running in Chrome v33 (latest)

-WebGL Renderer

I have a scene in which I draw objects (nodes). The objects are all children of a "root" object which I add to the scene. The user has the ability to press a button and toggle a subset of nodes to be added/removed (without changing/destroying the camera).

After each toggle the animation (camera movement) becomes slower and slower indicating to me there is a leak. I've looked everywhere inside the objects and a little bit of WebGL buffers but I can't find the leak.

Is there something I could be missing to dispose of the scene??

I do the following:

  1. Create WebGL Renderer and a Scene object
  2. Create a camera and lighting and add them to scene
  3. Create a 'root' object3d, add it to the scene
  4. For every node, create a BoxGeometry, mesh, object3d and add it to the root object

When the user presses a button:

  1. Remove all children of root from the scene
  2. For a subset of nodes, create BoxGeometry, mesh, object3d and add it to the root object

When the user presses the button again:

  1. Remove all children of root from the scene
  2. For every node, create BoxGeometry, mesh, object3d and add it to the root object

Appreciate any help!!!


EDIT

I actually just found the problem. My redraw method was calling my animate hook again so each type it was adding another additional pointless animation.

If anyone else has this problem MAKE SURE YOU ONLY CALL YOUR ANIMATE METHOD ONCE

And to help anyone looking for generic cleanup this is what I'm doing:

    function doDispose(obj)
    {
        if (obj !== null)
        {
            for (var i = 0; i < obj.children.length; i++)
            {
                doDispose(obj.children[i]);
            }
            if (obj.geometry)
            {
                obj.geometry.dispose();
                obj.geometry = undefined;
            }
            if (obj.material)
            {
                if (obj.material.materials)
                {
                    for (i = 0; i < obj.material.materials.length; i++)
                    {
                        obj.material.materials[i].dispose();
                    }
                }
                else
                {
                    obj.material.dispose();
                }
                obj.material = undefined;
            }
            if (obj.texture)
            {
                obj.texture.dispose();
                obj.texture = undefined;
            }
        }
        obj = undefined;
    }
1
You also need to remove the else condition around obj.material.dispose();.WestLangley
I had the same problem and was doing the exact same thing! So thanks for that.Ian Devlin
I found this post when searching for whether animations are cleaned up when geometry/objects are disposed. Hopefully it will be helpful for others to know that animations are not deleted, so it may be helpful for your dispose function to include cleanup code. function deleteAnimations(obj){ var globAnims = THREE.AnimationHandler.animations; var id = obj.id; for (var i=0, l=globAnims.length; i<l; i++){ if (globAnims[i].root.id === id){ globAnims[i].stop(); } } }Richard
May I know show you prevent animate function to run multiple times? I have been struggling for that issue for a long time. Thank you so much!MMzztx
@Richard Do you have any idea about how to clean animation in new version r94MMzztx

1 Answers

4
votes

This worked brilliantly for me, thank you!

I modified it a for Three.js Version 72

function doDispose(obj)
{
    if (obj !== null)
    {
        for (var i = 0; i < obj.children.length; i++)
        {
            doDispose(obj.children[i]);
        }
        if (obj.geometry)
        {
            obj.geometry.dispose();
            obj.geometry = undefined;
        }
        if (obj.material)
        {
            if (obj.material.map)
            {
                obj.material.map.dispose();
                obj.material.map = undefined;
            }
            obj.material.dispose();
            obj.material = undefined;
        }
    }
    obj = undefined;
}