web-dev-qa-db-fra.com

Threejs supprime tous les objets de la scène

J'ai essayé de créer une fonction pour supprimer tous les objets de la scène en une seule prise de vue, mais cela ne supprime qu'un seul objet à invoquer.

GeometryModel.prototype.clearScene = function(scene) {
var i;
for(i=0; i < scene.children.length; i++){
     obj = scene.children[i];
     scene.remove(obj);
  }
}

une autre solution que j'ai essayée et qui fonctionne est la suivante:

scene.children={};

mais je ne suis pas sûr si c'est correct.

13
Stefano Maglione

Vous devez faire le contraire:

for( var i = scene.children.length - 1; i >= 0; i--) { }

parce que dans chaque itération, le tableau .children change une fois que vous effectuez un .remove() à partir du début et que l'indexation de ce tableau change.

Si vous voulez mieux le comprendre, déroulez la boucle for et suivez l'index dans le tableau. 

19
gaitat

Vous pouvez accomplir cela avec while :

while (object.children.length)
{
    object.children.remove(object.children[0]);
}

Explications:

object.children.length return true si object.children.length n'est pas 0 , s'il est égal à 0 il retourne false .

Il suffit donc de supprimer le premier élément enfant tant que l'objet a des enfants.

8
csblo

La réponse existante est bonne, je souhaite simplement fournir une réponse plus complète à ceux qui se heurtent au même problème. Lorsque j'utilise le rechargement de module à chaud avec Three.js, je souhaite souvent recréer tous les objets autres que l'avion et la caméra. Pour ce faire, je fais ce qui suit:

export const reload = (/* updatedDependencies */) => {
  console.info('Canceling the run loop...')
  cancelAnimationFrame(runLoopIdentifier) // the return value of `requestAnimationFrame`, stored earlier

  console.info('Removing all children...')
  for (let i = scene.children.length - 1; i >= 0 ; i--) {
    let child = scene.children[ i ];

    if ( child !== plane && child !== camera ) { // plane & camera are stored earlier
      scene.remove(child);
    }
  }

  while (renderer.domElement.lastChild) // `renderer` is stored earlier
    renderer.domElement.removeChild(renderer.domElement.lastChild)

  document.removeEventListener( 'DOMContentLoaded', onDOMLoad )
  conicalDendriteTreeSegments = require('./plantae/conical-dendrite-trees').default

  initializeScene() // re-add all your objects
  runLoopIdentifier = startRenderRunLoop() // render on each animation frame

  console.info('Reload complete.')
}
2
james_womack

Une méthode préférée consiste à utiliser la fonction traverse de la scène. Tous les objets ont cette fonction et effectueront une recherche approfondie dans les enfants du parent.

Voici un extrait de M. Doob lui-même .

scene.traverse( function ( object ) {
    if ( object instanceof THREE.Mesh ) {
        var geometry = object.geometry;
        var matrixWorld = object.matrixWorld;

        ...

    }
});

Et voici un peu de la source de r82:

traverse: function ( callback ) {
    callback( this );
    var children = this.children;
    for ( var i = 0, l = children.length; i < l; i ++ ) {
        children[ i ].traverse( callback );
    }
}

Vous pouvez également utiliser traverseVisible dans votre cas:

scene.traverseVisible(function(child) {
   if (child.type !== 'Scene') {
      scene.remove(child);
   }
});
1
austince