简体   繁体   English

如何清除 THREE.JS 场景

[英]How do I clear THREE.JS Scene

I am trying to find ways of clearing all the objects in a scene without destroying the scene itself.我试图找到在不破坏场景本身的情况下清除场景中所有对象的方法。 I know that naming the object is one way and then when we want to delete the object, we just "get" it by its name.我知道命名 object 是一种方法,然后当我们想删除 object 时,我们只需按其名称“获取”它。 However, I want to find a quick way to clear a scene of all the objects in it, regardless of their names.但是,我想找到一种快速清除场景中所有对象的方法,无论它们的名称如何。 Is there a easy way to do it?有简单的方法吗? Thanks!谢谢!

You can traverse the child objects of the scene and remove them one by one.您可以遍历场景的子对象并一一移除它们。

As suggested in the comments, this should be done in reverse order to not modify the elements that you're iterating over.正如评论中所建议的,这应该以相反的顺序完成,以免修改您正在迭代的元素。

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

Note: This is just a quick and dirty clearing of the object hierarchy.注意:这只是对对象层次结构的快速清除。 If you plan on doing this a lot you risk running in to memory leaks with the code above because the renderer has references to the objects materials, textures and geometries.如果您计划大量执行此操作,则可能会因上述代码而导致内存泄漏,因为渲染器引用了对象材质、纹理和几何图形。 A complete clean of the scene is more complicated and there are plenty other questions that goes in to more detail:完全清理场景更复杂,还有很多其他问题需要详细说明:

I have a more concise way of doing this.我有一个更简洁的方法来做到这一点。 I noticed that the remove method of Object3D accepts more than one parameter for object removal.我注意到 Object3D 的remove方法接受多个用于对象删除的参数。 This allows us to use the entire children array by modifying the call to use each element as individual parameters by taking advantage of the built-in apply method for functions.这允许我们通过利用函数的内置apply方法修改调用以使用每个元素作为单独的参数来使用整个children数组。 This works like so:这像这样工作:

scene.remove.apply(scene, scene.children);

Traversing all children and call dispose on their geometry, material and texture.遍历所有子元素并调用它们的几何、材质和纹理的 dispose。 The code below is my solution.下面的代码是我的解决方案。

function clearThree(obj){
  while(obj.children.length > 0){ 
    clearThree(obj.children[0]);
    obj.remove(obj.children[0]);
  }
  if(obj.geometry) obj.geometry.dispose();

  if(obj.material){ 
    //in case of map, bumpMap, normalMap, envMap ...
    Object.keys(obj.material).forEach(prop => {
      if(!obj.material[prop])
        return;
      if(obj.material[prop] !== null && typeof obj.material[prop].dispose === 'function')                                  
        obj.material[prop].dispose();                                                      
    })
    obj.material.dispose();
  }
}   

clearThree(scene);

Also the next method of clearing the scene worked to me:清除场景的下一种方法也对我有用:

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

Iterating the items in the reversed order, it will not get the issue with the current array index.以相反的顺序迭代项目,它不会遇到当前数组索引的问题。

Kind regards, Adrian B.亲切的问候,阿德里安 B.

Be sure to remove all things, especially texture maps.一定要删除所有东西,尤其是纹理贴图。

    function removeObjectsWithChildren(obj){

        if(obj.children.length > 0){
            for (var x = obj.children.length - 1; x>=0; x--){
                removeObjectsWithChildren( obj.children[x]);
            }
        }

        if (obj.geometry) {
            obj.geometry.dispose();
        }

        if (obj.material) {
            if (obj.material.length) {
                for (let i = 0; i < obj.material.length; ++i) {

    
                    if (obj.material[i].map) obj.material[i].map.dispose();
                    if (obj.material[i].lightMap) obj.material[i].lightMap.dispose();
                    if (obj.material[i].bumpMap) obj.material[i].bumpMap.dispose();
                    if (obj.material[i].normalMap) obj.material[i].normalMap.dispose();
                    if (obj.material[i].specularMap) obj.material[i].specularMap.dispose();
                    if (obj.material[i].envMap) obj.material[i].envMap.dispose();

                    obj.material[i].dispose()
                }
            }
            else {
                if (obj.material.map) obj.material.map.dispose();
                if (obj.material.lightMap) obj.material.lightMap.dispose();
                if (obj.material.bumpMap) obj.material.bumpMap.dispose();
                if (obj.material.normalMap) obj.material.normalMap.dispose();
                if (obj.material.specularMap) obj.material.specularMap.dispose();
                if (obj.material.envMap) obj.material.envMap.dispose();

                obj.material.dispose();
            }
        }

        obj.removeFromParent();

        return true;
    }

scene.clear() is what you need. scene.clear() 是您所需要的。 Here is example code, make it become a function first, then call the function every time you want to change object.这是示例代码,首先将其变为 function,然后每次要更改 object 时调用 function。

function loadscene(path)
{
    scene.clear();
    loader.load(path,function(gltf)
    {
        const model = gltf.scene;
        model.position.set(0,0,0);
        model.rotation.set(0,0,0);
        model.scale.set(1,1,1);
        scene.add(model);
        animate();
    }, 
    undefined, function(e)
    {
        console.error(e);
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM