2017-09-12 4 views
2

Je peux obtenir le modèle à rendre, je peux faire pivoter, et zoomer et tout est bon JUSQU'A, j'essaie d'effacer la scène. Je veux effacer la scène en cliquant sur le button#clear.Comment puis-je effacer la mémoire correctement dans TROIS.js

Je m'attends à ce que la scène soit traversée et que ses enfants soient ajoutés à un tableau. Je m'attends alors à parcourir sur le tableau et pour chaque élément dans le tableau l'efface en appelant dispose() s'il s'agit d'une géométrie ou d'un matériau, puis supprime le maillage de la scène.

<html> 
    <head> 
    <title>Three.js</title> 
    <link rel="stylesheet" href="css/main.css" /> 
    </head> 
    <body> 
    <button id="clear">Clear Three Out</button> 
    <script src="js/three.js"></script> 
    <script src="js/OrbitControls.js"></script> 
    <script src="js/ObjectLoader.js"></script> 
    <script> 
    <script> 
     (function(){var script=document.createElement('script');script.onload=function(){var stats=new Stats();document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);})(); 
     var scene = new THREE.Scene(); 

     var width = window.innerWidth; 
     var height = window.innerHeight; 
     var camera = new THREE.OrthographicCamera(width/- 2, width/2, height/2, height/- 2, -1000, 1000); // new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); 

     var blackReflectiveMaterial = new THREE.MeshBasicMaterial();  
     var renderer = new THREE.WebGLRenderer(); 
     renderer.setSize(window.innerWidth, window.innerHeight); 
     document.body.appendChild(renderer.domElement); 

     // handle resize event 
     window.addEventListener('resize', function() { 
     var width = window.innerWidth; 
     var height = window.innerHeight; 

     renderer.setSize(width, height); 
     camera.aspect = width/height; 
     camera.updateProjectionMatrix(); 
     }); 

     // controls 
     controls = new THREE.OrbitControls(camera, renderer.domElement); 
     camera.position.z = 3; 

     // model loader 
     var loader = new THREE.ObjectLoader(); 

     loader.load(
     'models/revol-uv.json', // model of a compound bow 
     function(object) { 
      console.log('object: ', object); 
      object.scale.x = object.scale.y = object.scale.z = 200; 

      object.traverse(function(child) { 
      child.material = blackReflectiveMaterial; 
      }); 

      scene.add(object); 
     } 
    ); 

     scene.translateY(-345); 

     // array to hold Scene's children 
     var holder = []; 

     // when click the #clear button, call this function 
     document.getElementById('clear').onclick = function() { 
     scene.traverse(function (child) { 
      if (child.type === "Mesh") { 
      holder.push(child); 
      } 

     }); 
     console.log('holder before clean: ', holder); 
     for (var i = 0; i < holder.length; i++) { 
      if (holder[i].geometry) { 
      holder[i].geometry.dispose(); 
      } 

      console.log('holder[i].material: ', holder[i].material); 
      if (holder[i].material) { 
      if (holder[i].map) { 
       holder[i].material.map.dispose(); 
      } 
      holder[i].material.dispose(); 
      } 

      console.log('holder[i]: ', holder[i]); 
      scene.remove(holder[i]); 
     } 
     console.log('holder after clean: ', holder); // all the objects are still there 
     } 

     // logic 
     var update = function() { 

     // any code to rotate ... blah blah not important 
     }; 

     // draw Scene 
     var render = function() { 
     renderer.render(scene, camera); 
     }; 

     // run loop (update, render, repeat) 
     var bowLoop = function() { 
     requestAnimationFrame(bowLoop); 

     update(); 
     render(); 
     }; 
     bowLoop(); 
    </script> 
    </body> 
</html> 

est ici les journaux de la console:

Les enfants de la scène

Array(10) 
0:THREE.Mesh {uuid: "5574129D-7093-4567-8927-4F07BB7A3928", name: "cable-arm", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
1:THREE.Mesh {uuid: "ED867F5C-F6C4-45BC-BBF7-9DD5061A0CF6", name: "cams", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
2:THREE.Mesh {uuid: "D69C58BB-1E03-4D00-8050-6F2F4739DFE9", name: "handles", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
3:THREE.Mesh {uuid: "50A98720-4E8F-4873-B987-0C993D05FE65", name: "hardware", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
4:THREE.Mesh {uuid: "6CE44421-0614-40E9-8013-FE939CFA0191", name: "limb-pockets", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
5:THREE.Mesh {uuid: "60FF4521-B19B-477D-8223-8B4BFA2A0F5A", name: "limbs", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
6:THREE.Mesh {uuid: "D2980C91-0B19-4757-A831-A3B46546E579", name: "limbsavers", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
7:THREE.Mesh {uuid: "D9858B1C-E4F7-40C4-98DD-163230F9A917", name: "riser", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
8:THREE.Mesh {uuid: "BC7C199B-2867-4446-86FE-D244D7A32E07", name: "string-supressor", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
9:THREE.Mesh {uuid: "02A038E9-FB0B-43FF-B3F2-BCCAFD7E10AC", name: "strings", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 

Le tableau de support avant le nettoyage:

Array(10) 
0:THREE.Mesh {uuid: "5574129D-7093-4567-8927-4F07BB7A3928", name: "cable-arm", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
1:THREE.Mesh {uuid: "ED867F5C-F6C4-45BC-BBF7-9DD5061A0CF6", name: "cams", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
2:THREE.Mesh {uuid: "D69C58BB-1E03-4D00-8050-6F2F4739DFE9", name: "handles", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
3:THREE.Mesh {uuid: "50A98720-4E8F-4873-B987-0C993D05FE65", name: "hardware", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
4:THREE.Mesh {uuid: "6CE44421-0614-40E9-8013-FE939CFA0191", name: "limb-pockets", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
5:THREE.Mesh {uuid: "60FF4521-B19B-477D-8223-8B4BFA2A0F5A", name: "limbs", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
6:THREE.Mesh {uuid: "D2980C91-0B19-4757-A831-A3B46546E579", name: "limbsavers", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
7:THREE.Mesh {uuid: "D9858B1C-E4F7-40C4-98DD-163230F9A917", name: "riser", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
8:THREE.Mesh {uuid: "BC7C199B-2867-4446-86FE-D244D7A32E07", name: "string-supressor", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
9:THREE.Mesh {uuid: "02A038E9-FB0B-43FF-B3F2-BCCAFD7E10AC", name: "strings", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 

Le tableau de support après le nettoyage:

Array(10) 
0:THREE.Mesh {uuid: "5574129D-7093-4567-8927-4F07BB7A3928", name: "cable-arm", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
1:THREE.Mesh {uuid: "ED867F5C-F6C4-45BC-BBF7-9DD5061A0CF6", name: "cams", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
2:THREE.Mesh {uuid: "D69C58BB-1E03-4D00-8050-6F2F4739DFE9", name: "handles", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
3:THREE.Mesh {uuid: "50A98720-4E8F-4873-B987-0C993D05FE65", name: "hardware", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
4:THREE.Mesh {uuid: "6CE44421-0614-40E9-8013-FE939CFA0191", name: "limb-pockets", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
5:THREE.Mesh {uuid: "60FF4521-B19B-477D-8223-8B4BFA2A0F5A", name: "limbs", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
6:THREE.Mesh {uuid: "D2980C91-0B19-4757-A831-A3B46546E579", name: "limbsavers", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
7:THREE.Mesh {uuid: "D9858B1C-E4F7-40C4-98DD-163230F9A917", name: "riser", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
8:THREE.Mesh {uuid: "BC7C199B-2867-4446-86FE-D244D7A32E07", name: "string-supressor", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 
9:THREE.Mesh {uuid: "02A038E9-FB0B-43FF-B3F2-BCCAFD7E10AC", name: "strings", type: "Mesh", parent: T…E.Scene, children: Array(0), …} 

Pas de changement dans la mémoire ... objets sont encore en tas.

+1

un coup d'oeil à https://stackoverflow.com/questions/33152132/ – gaitat

+0

sera fais ... merci! –

+1

Vous débarrassez-vous également du tableau dans lequel vous les avez collectés? – pailhead

Répondre

0

@gaitat - merci de fournir une énorme quantité de la solution.

je devais modifier juste quelques lignes pour répondre à mes besoins:

function disposeNode(node) { 
    if (node instanceof THREE.Mesh) { 
     if (node.geometry) { 
     node.geometry.dispose(); 
     node.geometry = undefined; // fixed problem 
     } 

     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(); 
      mrtl = undefined; // fixed problem 
      }); 
     } 
     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(); 
      node.material = undefined; // fixed problem 
     } 
     } 
    } 
    console.log('node before removal: ', node); 
    scene.remove(node); 
    renderer.dispose(); // ***EDIT*** improved even memory more original scene heap is 12.4 MB; add objects increases to 116 MB or 250 MB (different models), clearing always brings down to 13.3 MB ... there still might be some artifacts. 
    node = undefined; // unnecessary 
    } 

    function disposeHierchy(node, callback) { 
    for (var i = node.children.length - 1; i >= 0; i--) { 
     var child = node.children[i]; 

     disposeHierchy(child, callback); 
     callback(child); 
    } 
    } 

Appelez-le:

document.getElementById('clear').onclick = function() { 
    disposeHierchy(scene, disposeNode); 
    console.log('renderer.info.memory after: ', renderer.info); 
    } 
+0

Comme je ne pense pas que cette Q/A est très utile aux autres. Il y a beaucoup de code à travers, peut-être vous devriez décrire - mettre dans un bloc séparé, ou commenter, les lignes qui ont fait le correctif. 'node = undefined' ne semble pas devoir faire quoi que ce soit. Si vous tenez une référence à cette chose ailleurs, elle sera toujours là. – pailhead

+0

@pailhead. Terminé. –

+0

Je pense que vous pouvez toujours rencontrer le même problème avec ceci. Tout ce qu'il faut, c'est avoir 'var foo = someNode.geometry' et cet objet restera. La façon dont vous traversez semble logique, mais je ne suis pas sûr de savoir quel genre de conseil vous pouvez donner ou quelle serait la meilleure pratique pour vous assurer de ne pas laisser une référence dans un endroit où vous ne le souhaitez pas. . – pailhead

1

Deux choses viennent à l'esprit:

  • il ressemble holder tient toujours des références à tous les objets après la fonction d'effacement a été appelé (h/t @pailhead). Vous devriez ajouter quelque chose comme holder = []; à la fin de la fonction pour se débarrasser d'eux aussi. Assurez-vous également qu'il n'y a pas d'autres variables accessibles contenant des références à l'un des objets. Sachez que les objets ne disparaîtront pas automatiquement de la mémoire, mais seulement après que le garbage-collector a fait son travail. Selon ce qui se passe, cela pourrait prendre un moment.