Three.js Collada – ¿Cuál es la forma correcta de deshacerse () y liberar memoria (recolección de basura)?

He importado con éxito una escena .dae a través de ColladaLoader.

El problema es que necesito cambiar entre varios archivos .dae.

Parece que no puedo implementar el método de eliminación correctamente.

dae.traverse(function(obj) { console.log('unloading ' + obj.id); scene.remove(obj); if(obj.geometry) obj.geometry.dispose(); if(obj.material) obj.material.dispose(); if(obj.mesh) obj.mesh.dispose(); if(obj.texture) obj.texture.dispose(); }); scene.remove(dae); 

¿Qué podría estar haciendo mal?

Muchas gracias de antemano!


EDITAR:

Aquí está el código completo.

  var renderer = null; var scene = null; var camera = null; var controls = null; var dae = null; //var loader = null; function init() { renderer = new THREE.WebGLRenderer( { alpha: 1, antialias: true, clearColor: 0xffffff } ); renderer.setSize( 800, 600 ); var elem = $('.main3d')[0]; elem.appendChild( renderer.domElement ); scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera( 20, 800/600, 1, 1000 ); camera.position.set( 0, -100, 50 ); //camera.lookAt( scene.position ); controls = new THREE.TrackballControls( camera, renderer.domElement ); var light = new THREE.AmbientLight( 0xffffff ); // soft white light scene.add( light ); threeAnimate(); } function load(url) { loader = new THREE.ColladaLoader(); loader.load(url, function (collada) { dae = collada.scene; scene.add(dae); }); } function unload() { dae.traverse(function(obj) { console.log('unloading ' + obj.id); scene.remove(obj); if(obj.geometry) obj.geometry.dispose(); if(obj.material) obj.material.dispose(); if(obj.mesh) obj.mesh.dispose(); if(obj.texture) obj.texture.dispose(); }); scene.remove(dae); } var animFrame = null; function animate() { animFrame = requestAnimationFrame( threeAnimate ); renderer.render( scene, camera ); controls.update(); } 

Esto debería hacer el trabajo:

 function disposeNode (node) { if (node instanceof THREE.Mesh) { if (node.geometry) { node.geometry.dispose (); } if (node.material) { if (node.material instanceof THREE.MeshFaceMaterial) { $.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 }); } else { 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 } } } } // disposeNode function disposeHierarchy (node, callback) { for (var i = node.children.length - 1; i >= 0; i--) { var child = node.children[i]; disposeHierarchy (child, callback); callback (child); } } 

y lo usas

 disposeHierarchy (YOUR_OBJECT3D, disposeNode); 

Modifiqué la ya impresionante respuesta de gaitat para simplemente usar la función transversal de escena ahora incorporada, para eliminar $ y también manejar MultiMaterial. ¿Por qué? ¿Por qué no hay una limpieza de memoria integrada en TRES? Seguramente debería hacerlo cuando haces scene.dispose (). Todavía estoy tratando de encontrar un par de texturas más que estoy usando, pero parece que no se eliminan () según renderer.info.memory.textures

 this.disposeNode = function (parentObject) { parentObject.traverse(function (node) { if (node instanceof THREE.Mesh) { if (node.geometry) { node.geometry.dispose(); } if (node.material) { if (node.material instanceof THREE.MeshFaceMaterial || node.material instanceof THREE.MultiMaterial) { node.material.materials.forEach(function (mtrl, idx) { 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 }); } else { 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 } } } }); } 

Construyendo las respuestas aquí, este código maneja matrices de materiales.

 function disposeNode(parentObject) { parentObject.traverse(function (node) { if (node instanceof THREE.Mesh) { if (node.geometry) { node.geometry.dispose(); } if (node.material) { var materialArray; if (node.material instanceof THREE.MeshFaceMaterial || node.material instanceof THREE.MultiMaterial) { materialArray = node.material.materials; } else if(node.material instanceof Array) { materialArray = node.material; } if(materialArray) { materialArray.forEach(function (mtrl, idx) { 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(); }); } else { 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(); } } } }); }