three.js内存泄漏.dispose()无法正常工作/错误使用

时间:2016-02-10 15:18:21

标签: javascript d3.js memory-leaks three.js

美好的一天!

存在内存处理问题。我阅读了很多论坛,但仍然无法找到我的代码的错误。

我正在研究项目,我将d3.js与three.js结合起来,可视化节点,如空间轨道上的行星。 我有很多数据 - 比如8个轨道上的8K行星。但是当我尝试加载新数据时 - 我无法在没有内存泄漏的情况下销毁当前树。

我将不胜感激任何帮助!以下是我创建行星的代码的一部分,以及我试图销毁它们的地方:

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;

}

所以我将球体添加到父Object3D,然后将其添加到场景中。

这是破坏功能:

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 = [];

}

1 个答案:

答案 0 :(得分:1)

不会遍历场景也能找到球体吗?在该循环中,您可以直接进行处理,而无需使用to_delete数组。如果所有的spere都不是场景的孩子,那么可能会重新考虑何时创建它们?这些只是优化而且可能做的很少,然后澄清可能泄漏的地方。

然后再次尝试持有纹理数组并直接释放它们?

在这里等一下,这个链接也表示要从渲染器中删除对象和纹理。

Memory leak in Three.js

renderer.deallocateObject renderer.deallocateTexture