mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.19k stars 35.34k forks source link

three.js memory leak .dispose() not working #8102

Closed Kaniber closed 8 years ago

Kaniber commented 8 years ago

Good day!

Have issue with memory handling. I read lots of forums but still can't find whats wrong with my code.

I'm working on project where I combine d3.js with three.js to visualize nodes like planets on orbits in space. I have a lot of data - like 8K planets in 8+ orbits. But when I try to load new data - I can't destroy current tree without memory leak.

I would be grateful for any help! Here is part of code where I create planets and where I try to destroy them:

function initTree(root) {
        var start, end;

        var nodes = tree.nodes(root); //this is d3.js tree init
        var depth = getDepth(root);

        var first_x_offset = nodes[0].x;
        if (isNaN(first_x_offset)) {first_x_offset = 0}

        //create orbits
        var orbitTexture = new THREE.ImageUtils.loadTexture('img/orbit_texture.png');
        var orbitMaterial = new THREE.MeshBasicMaterial({map: orbitTexture, transparent:true, side: THREE.DoubleSide, alphaTest: 0.05, opacity:0.3});
        var sphereGeometry = new THREE.SphereGeometry(1, 6, 6);

        var orbitSize = 30;
        for (var k=1; k<depth; k++) {
            var orbit = new THREE.Mesh(new THREE.CircleGeometry(orbitSize*k, 64), orbitMaterial);
            orbit.rotation.x = -90*Math.PI/180;
            orbit.name = 'orbit';
            scene.add(orbit);
        }
        //end orbits

        //camera position
        camera.position.x = 0;
        camera.position.y = 70;
        camera.position.z = -orbitSize*depth-100;

        controls.target.x = 0;
        controls.target.y = 0;
        controls.target.z = 0;

        camera.up.x = 0;
        camera.up.y = 1;
        camera.up.z = 0;

        //this is parent object to place in center
        var parent = new THREE.Object3D();
        parent.name = 'parent';
        scene.add(parent);

        y=0;

        spheres = {};
        objects = [];

        nodes.forEach(function(d) {
            if (d.type == 'BLANK') {return}
            d.x = d.x - first_x_offset;
            if (isNaN(d.x)) {d.x = 0}

            var sphereMaterial = new THREE.MeshLambertMaterial({color: 0xdddddd, wireframe: false, opacity: 0.7, transparent: true});
            var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial );
            sphere.material.color.setHex(color_type[d.type]);

            sphere.castShadow = false; //maybe change to true
            sphere.id2 = y;
            d.id2 = y;
            sphere.d = d;

            sphere.scale.x = radius_type[d.type];
            sphere.scale.y = radius_type[d.type];
            sphere.scale.z = radius_type[d.type];

            sphere.name = 'sphere';

            spheres[y] = sphere;
            //count items of each type
            count_type[d.type]++;
            //how many nodes in tree
            y++;

            //create pivot
            var pivot = new THREE.Object3D;
            //rotate it
            pivot.rotation.y = d.x*Math.PI/180-90;
            //append to parent
            pivot.name = 'pivot';
            parent.add(pivot);
            //add mesh to pivot
            var default_distance = size/(depth-1);
                if (d.y > 0) {
                    d.y = (Math.round(d.y/default_distance)) * (orbitSize-8.8);
                }

            sphere.position.x = d.y;
            sphere.position.y = 0; //should be 0!
            sphere.position.z = d.y;

            objects.push(sphere);

            pivot.add(sphere);
        });
        nodesLength = y;

        render();

        $('.loading').fadeOut(500);
        if (!animationId) {
            animate();
        }
        temp = null;
        nodes = null;

    }

So I'm adding spheres to parent Object3D and then add it to scene.

And here is destroy function:

function destroyTree() {
        //spheres
        //console.log(renderer.info);
        var to_delete = [];

        for (var i=0; i<spheres.length; i++) {
            scene.remove(spheres[i]);
            spheres[i].material.dispose();
            spheres[i].geometry.dispose();
        }
        for (var i=0; i<spheres.length; i++) {
            spheres[i] = undefined;
        }
        spheres = {};
        for (var i=0; i<objects.length; i++) {
            scene.remove(objects[i]);
        }
        for (var i=0; i<objects.length; i++) {
            objects[i] = undefined;
        }
        objects = [];

        var parent = scene.getObjectByName('parent');
        scene.remove(parent);

        if (links.length) {
            for (var i=0; i<links.length; i++) {
                scene.remove(links[i]);
            }
        }
        links = [];

        scene.traverse(function (child) {
            if (child instanceof THREE.Mesh) {
                if (child.name.length) {
                    to_delete.push(child);
                }
            }

        });

        for (var i=0; i<to_delete.length; i++) {
            scene.remove(to_delete[i]);

                to_delete[i].geometry.dispose();
                to_delete[i].material.dispose();
            to_delete[i] = undefined;
        }

        to_delete = [];

    }
WestLangley commented 8 years ago

As stated in the guidelines, help requests should be directed to stackoverflow.

Kaniber commented 8 years ago

http://stackoverflow.com/questions/35318988/three-js-memory-leak-dispose-not-working-wrong-usage