【问题标题】:Threejs remove all together object from sceneThreejs从场景中删除所有对象
【发布时间】:2015-06-07 16:03:35
【问题描述】:

我试图创建一个函数来在一次拍摄中从场景中删除所有对象,但它只删除了一个用于调用的对象。

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

我尝试过的另一个解决方案是这样的:

scene.children={};

但我不确定它是否正确。

【问题讨论】:

标签: javascript three.js


【解决方案1】:

你必须做相反的事情:

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

因为在每次迭代中,一旦您从一开始就执行 .remove() 并且该数组的索引发生变化,.children 数组就会发生变化。

如果你想更好地理解它,展开 for 循环并按照数组中的索引是什么。

【讨论】:

  • 这不是解决方案,它会导致 HEAP 内存泄漏,请参阅我的问题stackoverflow.com/questions/37762961/…
  • 不是while循环更容易。
  • @Martin 作为另一个 SO 答案说这主要是垃圾收集的问题。
【解决方案2】:

您可以使用 while 来实现:

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

说明:

object.children.length 如果object.children.length 不为0,则返回true,如果等于0,则返回false

因此,只要对象有子元素,您只需删除第一个子元素。

【讨论】:

  • 区别在哪里?
  • 有时,特别是在大量的情况下,对象不会在第一次 .remove() 迭代中被移除(我认为移除材料的速度较慢。)那么这对这种情况很有好处。问题将是当对象由于某种原因无法删除时。
【解决方案3】:

首选方法是使用场景的traverse 函数。所有对象都具有此功能,并将通过父对象的子对象进行深度优先搜索。

Here's a snippet from Mr. Doob himself.

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

        ...

    }
});

这里有一点来自 r82 的来源:

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

你也可以在你的情况下使用traverseVisible

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

【讨论】:

    【解决方案4】:

    现有的答案很好,我只想为遇到同样问题的人提供更全面的回应。当我通过 Three.js 使用热模块重新加载时,我经常想要重新创建除平面和相机之外的所有对象。为此,我执行以下操作:

    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.')
    }
    

    【讨论】:

    猜你喜欢
    • 2013-08-23
    • 2022-01-10
    • 1970-01-01
    • 2017-10-13
    • 2015-04-28
    • 1970-01-01
    • 2013-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多