2015-10-15 13 views
6

Ho importato con successo una scena .dae tramite ColladaLoader.Three.js Collada - Qual è il modo corretto di disporre() e rilasciare memoria (garbage collection)?

Il problema è che ho bisogno di passare tra diversi file .dae.

Non riesco a implementare correttamente il metodo di smaltimento.

 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); 

Cosa potrei fare eventualmente storto?

Grazie mille in anticipo!


EDIT:

Ecco l'intero codice.

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(); 

    } 

risposta

17

Questo dovrebbe fare il lavoro:

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); 
    } 
} 

e usarlo

disposeHierarchy (YOUR_OBJECT3D, disposeNode); 
+0

Wow! È abbastanza completo! Lo controllerò tra un po '. Grazie per aver trovato il tempo di rispondere! –

+0

Voglio anche sapere se la risposta è basata sulla tua ricerca o se hai qualche fonte. Grazie ancora! –

+0

Risposta stupenda! Sono stato in grado di rilasciare 700 MB + usando la funzione disposeHierarchy()! Semplicemente fantastico. Molte grazie. Spero che questa risposta aiuti anche gli altri. –

6

ho ottimizzato gaitat risposta è già impressionante basta usare l'ormai costruito in scena la funzione di traslazione, per rimuovere $ e gestisce anche MultiMaterial. Perché, oh, perché non c'è una pulizia della memoria incorporata in TRE !!? Sicuramente dovrebbe farlo quando fai scena.dispose(). Sto ancora cercando di rintracciare un altro paio di texture che sto usando, ma non sembrano avere smaltire() cati secondo 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 
       } 
      } 
     } 
    }); 
} 
+1

Questo è il motivo per cui non viene rimosso _automagicamente. [Delocating heap objects ...] (https://github.com/mrdoob/three.js/issues/5175). Il programmatore ** ha ** di essere coinvolto, perché non è così semplice come pensi che sia. Nei progetti abbastanza grandi, le cose si complicano e si finisce per riutilizzare materiali, geometrie e persino mesh tra le scene (non scherzando, si potrebbe finire per fare tutto quanto sopra). Quindi cancellare le cose così felicemente porterà solo dolore e dolore. Avere una curva di apprendimento e dover essere coinvolto come programmatore ti impedisce di fare errori stupidi. – tfrascaroli

1

Partendo le risposte qui, questo codice gestisce matrici di materiali.

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(); 
       } 
      } 
     } 
    }); 
}