2015-10-15 10 views
6

Ich habe erfolgreich eine .dae-Szene über ColladaLoader importiert.Three.js Collada - Was ist die richtige Methode zum Entsorgen() und Freigeben von Speicher (Garbage Collection)?

Das Problem ist, ich muss zwischen mehreren .dae Dateien wechseln.

Ich kann nicht scheinen, die dispose-Methode richtig zu implementieren.

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

Was könnte ich möglicherweise falsch machen?

Vielen Dank im Voraus!


EDIT:

Hier ist der gesamte 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(); 

    } 

Antwort

17

Dies sollte die Arbeit machen:

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

und verwenden Sie es

disposeHierarchy (YOUR_OBJECT3D, disposeNode); 
+0

Wow! Das ist ziemlich umfassend! Ich werde es gleich überprüfen. Danke, dass du dir die Zeit genommen hast zu antworten! –

+0

Ich möchte auch wissen, ob die Antwort auf Ihrer eigenen Forschung basiert oder wenn Sie irgendwelche Quellen haben. Danke noch einmal! –

+0

Super Antwort! Ich konnte 700MB + mit der Funktion disposeHierarchy() freigeben! Einfach toller Mann. Danke vielmals. Ich hoffe, diese Antwort hilft auch anderen. –

6

ich gaitat ist schon genial Antwort gezwickt nur die jetzt in Szene Traverse Funktion eingebaut verwenden, zu entfernen $ und auch MultiMaterial handhaben. Warum, oh, warum gibt es keine integrierte Speicherbereinigung in DREI !!? Sicher sollte es das tun, wenn du scene.dispose() machst. Ich bin immer noch ein paar mehr Texturen auf die Spur zu versuchen, ich verwende aber nicht zu entsorgen zu bekommen scheinen() ed nach 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

Deshalb wird es nicht _automatisch_ entfernt. [Heap-Objekte werden verschoben ...] (https://github.com/mrdoob/three.js/issues/5175). Der Programmierer ** muss involviert sein, weil es nicht so einfach ist, wie du denkst. In großen Projekten wird die Sache kompliziert und du wirst Materialien, Geometrien und sogar Meshes zwischen den Szenen wiederverwenden (kein Witz, du könntest am Ende all das machen). Also Dinge so glücklich zu löschen bringt nur Schmerz und Leid. Eine Lernkurve zu haben und sich als Programmierer zu engagieren, hält dich davon ab, dumme Fehler zu machen. – tfrascaroli

1

die Antworten hier Gebäude aus dieser Code behandelt Arrays von Materialien.

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