2015-10-15 21 views
6

Pomyślnie zaimportowałem scenę .dae przez ColladaLoader.Three.js Collada - Jaki jest właściwy sposób na pozbycie się() i zwolnienie pamięci (odśmiecanie)?

Problem polega na tym, że muszę przełączać się między kilkoma plikami .dae.

Nie mogę poprawnie wdrożyć metody usuwania.

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

Co mógłbym robić źle?

Dziękuję bardzo z góry!


EDIT:

Oto cały kod.

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

    } 

Odpowiedz

17

To powinno załatwić sprawę:

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

i go używać

disposeHierarchy (YOUR_OBJECT3D, disposeNode); 
+0

Wow! To całkiem wyczerpujące! Sprawdzę to trochę. Dziękujemy za poświęcenie czasu na odpowiedź! –

+0

Chcę również wiedzieć, czy odpowiedź jest oparta na własnych badaniach, czy też masz jakieś źródła. Dzięki jeszcze raz! –

+0

Niesamowita odpowiedź! Udało mi się uwolnić 700 MB + przy użyciu funkcji disposeHierarchy()! Po prostu niesamowity człowiek. Wielkie dzięki. Mam nadzieję, że ta odpowiedź pomoże także innym. –

6

I manipulowane gaitat już niesamowite odpowiedź po prostu użyć teraz wbudowany sceny kierunkowej funkcji, aby usunąć $, a także obsługuje MultiMaterial. Dlaczego, och dlaczego nie ma wbudowanego czyszczenia pamięci w TRZECH !!? Na pewno powinien to zrobić, gdy robisz scene.dispose(). Ja wciąż próbuje wyśledzić jeszcze kilka tekstur używam, ale nie wydaje się, aby wyrzucać() ed według 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

Dlatego nie jest automatycznie usuwany. [Delokalizacja obiektów sterty ...] (https://github.com/mrdoob/three.js/issues/5175). Programista ** musi się zaangażować, ponieważ nie jest tak prosty, jak ci się wydaje. W przypadku wystarczająco dużych projektów, rzeczy stają się skomplikowane, a na końcu ponownie wykorzystujesz materiały, geometrie, a nawet siatki pomiędzy scenami (nie żartuję, możesz skończyć, wykonując wszystkie powyższe czynności). Tak więc szczęśliwie usuwanie rzeczy przyniesie tylko ból i smutek. Posiadanie krzywej uczenia się i bycie zaangażowanym jako programista powstrzymuje cię od robienia głupich błędów. – tfrascaroli

1

Opierając się odpowiedź tutaj, kod ten obsługuje macierze materiałów.

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