【问题标题】:load obj and mtl file by three.js OBJMTLLoader.js causes memory leak after multi-times load通过three.js加载obj和mtl文件 OBJMTLLoader.js在多次加载后导致内存泄漏
【发布时间】:2015-06-27 10:13:45
【问题描述】:

当通过three.js加载多个带有mtl文件的obj网格时出现内存泄漏,这是我的步骤:

首先,打开这个页面:http://idazhenhan.github.io/threejs/loader/index.html,数据加载完毕点击“加载”,鼠标轻轻移动,屏幕上会出现一些黄色网格;

然后,如果你用的是windows,就打开你的任务管理器,看看浏览器标签占用多少内存,记录一下。

最后,点击'reload'重新点击页面左上角的'load'或'clear',再次在任务管理器中查看内存消耗,你会看到,内存正在增长和/或似乎永远不会释放。

我在index.js的最后写了一些发布代码,这里是:

function reload() {
    var indexes = [];
    for (var index in scene.children) {
        if(scene.children[index].name.indexOf('test') !== -1){
            indexes.push(scene.children[index]);
        }
    }
    for(var index in indexes){
        scene.remove(indexes[index]);
    }
    load();
};

我改变了两个主要功能:

function load() {
    clear();
    var paths = [];
    for(var i=1;i<=4;i++){
        paths.push({obj: i + '/model_1v.obj', mtl: i + '/model_1v.mtl'});
    }

    var onProgress = function(xhr) {
        if (xhr.lengthComputable) {
            var percentComplete = xhr.loaded / xhr.total * 100;
        }
    };

    var onError = function(xhr) {};

    THREE.Loader.Handlers.add(/\.dds$/i, new THREE.DDSLoader());
    for(var i=0;i<paths.length;i++){
        var path = paths[i];
        var loader = new THREE.OBJMTLLoader();
        loader.load(path.obj, path.mtl, function(model) {
            model.name='test-' + i;
            scene.add(model);
        }, onProgress, onError);
    }
}

function clear() {
    THREE.Cache.clear();
    var models = [];
    for (var i in scene.children) {
        if(scene.children[i].name.indexOf('test') !== -1){
            models.push(scene.children[i]);
        }
    }
    for(var i in models){
        scene.remove(models[i]);
        models[i].traverse(
           function(obj){
                if (obj instanceof THREE.Mesh) {
                    obj.geometry.dispose();
                    obj.material.dispose();
                }
            }, true
        );
    }
    models.length = 0;
};

但还是无效,如果你有兴趣,可以在https://github.com/idazhenhan/idazhenhan.github.io.git处克隆代码,然后在你的本地服务器上运行代码,你就会清楚地看到问题了。

有没有人可以帮我解决?

【问题讨论】:

  • Geometry 有一个 dispose() 方法。
  • 上面的main函数改了,还是无效。
  • 是的,我几天前看了答案,我尝试了这个方法,现在我发现 Three.js 中有一个全局缓存,THREE.Cache,我在它的“文件”中找到了一些缓存数据' 属性,所以,在执行 load() 之前,我调用了 THREE.Cache.clear(),新代码上传,我看到问题仍然在这里:(
  • 你还在使用reload()函数吗?因为顶部的链接仍然使用 reload()。

标签: javascript memory-leaks three.js


【解决方案1】:

对于 javascript 垃圾收集器 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management),所有对对象的引用必须为零。告诉 javascript 您已完成对象的一种方法是将其设置为 undefined。另外你需要dispose()下面的所有对象组。这是我处理层次结构的版本。

在您致电scene.remove(models[i]);之后

使用它:disposeHierarchy (object, disposeNode); 或 disposeNode (node);

var debugging = false;
var indent = "", indent_level = 0;

function disposeNode (node)
{
    if (debugging) console.log (indent_level + " " + indent + "\"" + node.name + "\"");

         if (node instanceof THREE.Camera)
    {
        if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Camera");

        node = undefined;
    }
    else if (node instanceof THREE.Light)
    {
        if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Light");

        node.dispose ();
        node = undefined;
    }
    else if (node instanceof THREE.Mesh)
    {
        if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Mesh");

        if (node.geometry)
        {
            if (debugging) console.log (indent + indent + "I have Geometry");

            node.geometry.dispose ();
            node.geometry = undefined;
        }

        if (node.material)
        {
            if (node.material instanceof THREE.MeshFaceMaterial)
            {
                if (debugging) console.log (indent + indent + "I have many Materials");

                $.each (node.material.materials, function (idx, mtrl)
                {
                    if (mtrl.map)           mtrl.map.dispose ();
                    if (mtrl.lightMap)      mtrl.lightMap.dispose ();
                    if (mtrl.bumpMap)       mtrl.bumpMap.dispose ();
                    if (mtrl.normalMap)     mtrl.normalMap.dispose ();
                    if (mtrl.specularMap)   mtrl.specularMap.dispose ();
                    if (mtrl.envMap)        mtrl.envMap.dispose ();

                    mtrl.dispose ();    // disposes any programs associated with the material
                    mtrl = undefined;
                });
            }
            else
            {
                if (debugging) console.log (indent + indent + "I have Material");

                if (node.material.map)          node.material.map.dispose ();
                if (node.material.lightMap)     node.material.lightMap.dispose ();
                if (node.material.bumpMap)      node.material.bumpMap.dispose ();
                if (node.material.normalMap)    node.material.normalMap.dispose ();
                if (node.material.specularMap)  node.material.specularMap.dispose ();
                if (node.material.envMap)       node.material.envMap.dispose ();

                node.material.dispose ();   // disposes any programs associated with the material
                node.material = undefined;
            }
        }

        node = undefined;
    }
    else if (node instanceof THREE.Object3D)
    {
        if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Object3D");

        node = undefined;
    }
    else
    {
        if (debugging) console.log (indent + "UNKNOWN " + "\"" + node.name + "\"" + " " + "\"" + typeof node + "\"");
    }
}

function disposeHierarchy (node, callback)
{
    indent += "    ";
    indent_level++;

    for (var i = node.children.length - 1; i >= 0; i--)
    {
        var child = node.children[i];
        disposeHierarchy (child, callback);
        callback (child);
    }

    indent = indent.substr (4); // remove 4 spaces from indent
    indent_level--;
}

【讨论】:

  • 太棒了!内存占用减少了很多,非常感谢!
猜你喜欢
  • 1970-01-01
  • 2014-10-03
  • 1970-01-01
  • 1970-01-01
  • 2017-06-13
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
  • 2018-10-15
相关资源
最近更新 更多