three.js OBJMTLLoader.js加载obj和mtl文件导致多次加载后内存泄漏
load obj and mtl file by three.js OBJMTLLoader.js causes memory leak after multi-times load
当我通过 three.js 加载多个带有 mtl 文件的 obj 网格时出现内存泄漏,这是我的步骤:
首先,打开这个页面:http://idazhenhan.github.io/threejs/loader/index.html,加载数据后,点击'load',当您移动鼠标时,您会在屏幕上看到一些黄色网格略;
然后,如果你用windows,就打开你的任务管理器,看看浏览器选项卡占用多少内存,记录下来。
最后,点击'reload'再点击'load'或'clear'在上面-在页面左侧,再次查看任务管理器中的内存消耗,您会看到,内存在增长and/or 似乎永远不会释放。
我在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,然后运行本地服务器上的代码,你会看到问题清楚。
有没有人可以帮我解决一下?
要使 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--;
}
当我通过 three.js 加载多个带有 mtl 文件的 obj 网格时出现内存泄漏,这是我的步骤:
首先,打开这个页面:http://idazhenhan.github.io/threejs/loader/index.html,加载数据后,点击'load',当您移动鼠标时,您会在屏幕上看到一些黄色网格略;
然后,如果你用windows,就打开你的任务管理器,看看浏览器选项卡占用多少内存,记录下来。
最后,点击'reload'再点击'load'或'clear'在上面-在页面左侧,再次查看任务管理器中的内存消耗,您会看到,内存在增长and/or 似乎永远不会释放。
我在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,然后运行本地服务器上的代码,你会看到问题清楚。
有没有人可以帮我解决一下?
要使 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--;
}