Threejs 从场景中删除所有对象
Threejs remove all together object from scene
我试图制作一个函数,在一次拍摄中从场景中移除所有对象,但它只移除了一个对象以供调用。
GeometryModel.prototype.clearScene = function(scene) {
var i;
for(i=0; i < scene.children.length; i++){
obj = scene.children[i];
scene.remove(obj);
}
}
我尝试过的另一个解决方案是:
scene.children={};
但我不确定是否正确。
你必须做相反的事情:
for( var i = scene.children.length - 1; i >= 0; i--) {
obj = scene.children[i];
scene.remove(obj);
}
因为在每次迭代中,一旦您从头开始执行 .remove()
并且该数组的索引发生变化,.children
数组就会发生变化。
如果您想更好地理解它,请展开 for 循环并查看数组中的索引。
现有答案很好,我只是想为那些运行同样问题的人提供更全面的回应。当我通过 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.')
}
首选方法是使用场景的 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);
}
});
您可以使用 while :
while (object.children.length)
{
object.remove(object.children[0]);
}
解释:
object.children.length return true 如果 object.children.length 不是 0, 如果等于0 它 return false.
因此只要对象有子元素,您只需删除第一个子元素即可。
我试图制作一个函数,在一次拍摄中从场景中移除所有对象,但它只移除了一个对象以供调用。
GeometryModel.prototype.clearScene = function(scene) {
var i;
for(i=0; i < scene.children.length; i++){
obj = scene.children[i];
scene.remove(obj);
}
}
我尝试过的另一个解决方案是:
scene.children={};
但我不确定是否正确。
你必须做相反的事情:
for( var i = scene.children.length - 1; i >= 0; i--) {
obj = scene.children[i];
scene.remove(obj);
}
因为在每次迭代中,一旦您从头开始执行 .remove()
并且该数组的索引发生变化,.children
数组就会发生变化。
如果您想更好地理解它,请展开 for 循环并查看数组中的索引。
现有答案很好,我只是想为那些运行同样问题的人提供更全面的回应。当我通过 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.')
}
首选方法是使用场景的 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);
}
});
您可以使用 while :
while (object.children.length)
{
object.remove(object.children[0]);
}
解释:
object.children.length return true 如果 object.children.length 不是 0, 如果等于0 它 return false.
因此只要对象有子元素,您只需删除第一个子元素即可。