2015-10-15 3 views
6

J'ai réussi à importer une scène .dae via ColladaLoader.Three.js Collada - Quelle est la bonne façon de disposer() et libérer de la mémoire (garbage collection)?

Le problème est, j'ai besoin de basculer entre plusieurs fichiers .dae.

Je n'arrive pas à implémenter correctement la méthode d'élimination.

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

Que pourrais-je faire de mal?

Merci beaucoup d'avance!


EDIT:

est ici tout le code.

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

    } 

Répondre

17

Cela devrait faire le travail:

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

et vous l'utiliser

disposeHierarchy (YOUR_OBJECT3D, disposeNode); 
+0

Wow! C'est assez complet! Je vais vérifier dans un peu. Merci d'avoir pris le temps de répondre! –

+0

Je veux aussi savoir si la réponse est basée sur votre propre recherche ou si vous avez des sources. Merci encore! –

+0

Super réponse! J'ai été capable de libérer 700 Mo + en utilisant la fonction disposeHierarchy()! Juste un homme génial. Merci beaucoup. J'espère que cette réponse aide les autres aussi. –

6

Je peaufiné gaitat est déjà impressionnante réponse à simplement utiliser le maintenant construit en scène fonction transversale, pour enlever $ et gère également MultiMaterial. Pourquoi, oh pourquoi n'y a-t-il pas un nettoyage de mémoire intégré dans TROIS !!? Il devrait sûrement le faire quand vous faites scene.dispose(). Je suis encore en train de retrouver un couple plus de textures que je utilise, mais ne semble pas se débarrasser() uré selon 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

C'est pourquoi il n'est pas _automagically_ supprimé. [Délocaliser des objets tas ...] (https://github.com/mrdoob/three.js/issues/5175). Le programmeur ** a ** à être impliqué, parce que ce n'est pas aussi simple que vous le pensez. Dans les projets suffisamment grands, les choses se compliquent et vous finissez par réutiliser des matériaux, des géométries et même des maillages entre les scènes (sans blague, vous pourriez finir par faire tout ce qui précède). Donc, supprimer des choses si heureusement ne va apporter que de la souffrance et du chagrin. Avoir une courbe d'apprentissage et d'être impliqué en tant que programmeur vous empêche de faire des erreurs stupides. – tfrascaroli

1

Construire les réponses proposées ici, ce code gère des réseaux de matériaux.

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