ThreeJS:从场景中移除对象

内容来源于 Stack Overflow,遵循 CC BY-SA 4.0 许可协议进行翻译与使用。IT领域专用引擎提供翻译支持

腾讯云小微IT领域专用引擎提供翻译支持

原文
Stack Overflow用户 修改于2015-09-22
  • 该问题已被编辑
  • 提问者: Stack Overflow用户
  • 提问时间: 2013-08-21 20:32

我正在使用ThreeJS开发一个web应用程序,它显示一个实体列表,每个实体都有相应的“查看”和“隐藏”按钮;例如,entityName 视图隐藏 。当用户单击 查看 按钮时,将调用以下函数并将实体成功绘制到屏幕上。

function loadOBJFile(objFile){            
    /* material of OBJ model */                                          
    var OBJMaterial = new THREE.MeshPhongMaterial({color: 0x8888ff});
    var loader = new THREE.OBJLoader();
    loader.load(objFile, function (object){
        object.traverse (function (child){
            if (child instanceof THREE.Mesh) {
                child.material = OBJMaterial;
        object.position.y = 0.1;
        scene.add(object);
function addEntity(object) {
    loadOBJFile(object.name);
}

在单击 Hide 按钮时,将调用以下函数:

function removeEntity(object){
    scene.remove(object.name);
}

问题是,当 Hide 按钮被点击时,实体一旦加载就不会从屏幕中删除。要让 隐藏 按钮工作,我该怎么做?

我做了个小实验。我在 addEntity 函数中的 scene.add(object); 后面添加了 scene.remove(object.name); ,因此,当单击“查看”按钮时,没有绘制任何实体(正如预期的那样),这意味着 scene.remove(object.name); addEntity 中工作得很好。但是我仍然不知道如何在removeEntity(object)中使用它。

另外,我检查了scene.children的内容,结果显示: object Object,object object

完整代码: http://devplace.in/~harman/model_display1.php.html

如果需要更多细节,请询问。我使用ThreeJS的rev-59-dev和rev-60进行测试。

谢谢。:)

浏览 769 关注 0 得票数 58
  • 得票数为Stack Overflow原文数据
原文
修改于2013-08-23
  • 该回答已被编辑
  • 回答者: Stack Overflow用户
  • 回答时间: 2013-08-21 23:12
得票数 55

我认为看到你对addEntity和removeEntity代码的使用会很有帮助,但我的第一个想法是,你实际上是在设置object.name吗?在scene.add(Object)之前尝试一下您的加载器;如下所示:

object.name = "test_name";
scene.add(object);

可能发生的情况是,Object3D的默认“名称”为"",因此,当您随后调用removeEntity函数时,由于场景对象名称为"“,因此调用失败。

另外,我注意到你把object.name传给了你的加载器?这是您存储资源的URL的地方吗?如果是这样的话,我建议使用Object3D内置的.userData方法来存储该信息,并保留name字段以用于场景识别。

编辑:对新添加的代码的响应

首先要注意的是,在你的对象名中包含"/“不是一个好主意,它似乎工作得很好,但你永远不知道是否有一些算法会决定转义该字符串并破坏你的项目。

第二件事就是我已经看过你的代码了,它实际上是直接的。您的删除函数正在尝试按名称删除,您需要一个Object3D才能删除。试试这个:

function removeEntity(object) {
    var selectedObject = scene.getObjectByName(object.name);
    scene.remove( selectedObject );
    animate();
}

在这里,您可以看到我通过传入 Object3D 标记的 name 属性在Three.js Scene 中查找您的对象。希望这能有所帮助

回答于2013-09-09
得票数 0

我和你有同样的问题。我尝试了这段代码,它工作得很好:当您创建对象时,将这个object.is_ob = true

function loadOBJFile(objFile){            
    /* material of OBJ model */                                          
    var OBJMaterial = new THREE.MeshPhongMaterial({color: 0x8888ff});
    var loader = new THREE.OBJLoader();
    loader.load(objFile, function (object){
        object.traverse (function (child){
            if (child instanceof THREE.Mesh) {
                child.material = OBJMaterial;
        object.position.y = 0.1;
      // add this code
        object.is_ob = true;
        scene.add(object);
function addEntity(object) {
    loadOBJFile(object.name);
}

然后删除你的对象,试试下面的代码:

function removeEntity(object){
    var obj, i;
            for ( i = scene.children.length - 1; i >= 0 ; i -- ) {
                obj = scene.children[ i ];
                if ( obj.is_ob) {
                    scene.remove(obj);
}

试一试,告诉我这是否有效,似乎三个js在添加到场景中后无法识别对象。但是通过这个技巧,它起作用了。

原文
修改于2013-09-21
  • 该回答已被编辑
  • 回答者: Stack Overflow用户
  • 回答时间: 2013-09-21 17:04
得票数 -9

你可以使用这个

function removeEntity(object) {
    var scene = document.querySelectorAll("scene");                               //clear the objects from the scene
    for (var i = 0; i < scene.length; i++) {                                    //loop through to get all object in the scene
    var scene =document.getElementById("scene");                                  
    scene.removeChild(scene.childNodes[0]);                                        //remove all specified objects
  }   
评论 0
0
修改于2014-01-10
  • 该回答已被编辑
  • 回答者: Stack Overflow用户
  • 回答时间: 2013-12-24 09:34
得票数 10
clearScene: function() {
    var objsToRemove = _.rest(scene.children, 1);
    _.each(objsToRemove, function( object ) {
          scene.remove(object);
},

它使用undescore.js遍历场景中的所有子对象(第一个除外)(这是我用来清除场景的代码的一部分)。只需确保在删除 后至少渲染一次场景,否则画布不会更改!不需要“特殊的”obj标志或类似的东西。

此外,您不能按名称删除对象,而只能按对象本身删除,因此调用

scene.remove(object); 

而不是 scene.remove(object.name); 就足够了

PS: _.each underscore.js 的一个函数

回答于2017-05-15
得票数 4

如果您的元素不直接位于场景中,请返回父级将其移除

  function removeEntity(object) {
        var selectedObject = scene.getObjectByName(object.name);
        selectedObject.parent.remove( selectedObject );
    }
Stack Overflow用户
修改于2019-03-06
  • 该回答已被编辑
  • 回答者: Stack Overflow用户
  • 回答时间: 2017-05-17 20:42
得票数 4

这工作得很好-我测试过了,请为每个对象设置名称

在创建时为对象命名

    mesh.name = 'nameMeshObject';

如果您必须删除对象,请使用此选项

    delete3DOBJ('nameMeshObject');
    function delete3DOBJ(objName){
        var selectedObject = scene.getObjectByName(objName);
        scene.remove( selectedObject );
        animate();
    }

打开新场景,添加对象

删除对象并创建新对象

原文
回答于2019-02-20
得票数 2

我开始将它保存为一个函数,并根据需要调用它,以满足任何反应的需要:

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

现在,您可以在适当的地方调用Remove();函数。

操作
回答于2020-03-09
得票数 2

使用:scene.remove( object )时,对象将从场景中移除,但与其的碰撞仍处于启用状态!

要删除与对象的拼接,您可以使用它(对于数组):objectsArray.splice(i,1);

示例:

for (var i = 0; i < objectsArray.length; i++) {
//::: each object ::://
var object = objectsArray[i]; 
//::: remove all objects from the scene ::://
scene.remove(object); 
//::: remove all objects from the array ::://
objectsArray.splice(i, 1); 

}

Stack Overflow用户
回答于2021-03-30
得票数 1

this 示例可能会给您一种不同的方法。我也在尝试用 scene.remove(mesh) 在我的项目中实现类似的功能。然而,网格的几何和材质属性的处理对我来说是有效的! source

原文
回答于2021-06-16
得票数 2

我来晚了,但在看了答案后,需要说更多的澄清。

您编写的remove函数

function removeEntity(object) {
    // scene.remove(); it expects as a parameter a THREE.Object3D and not a string
    scene.remove(object.name); // you are giving it a string => it will not remove the object
}

从Three.js场景中删除3D对象的好做法

function removeObject3D(object3D) {
    if (!(object3D instanceof THREE.Object3D)) return false;
    // for better memory management and performance
    object.geometry.dispose();
    if (object.material instanceof Array) {
        // for better memory management and performance
        object.material.forEach(material => material.dispose());
    } else {
        // for better memory management and performance
        object.material.dispose();
    object.removeFromParent(); // the parent might be the scene or another Object3D, but it is sure to be removed this way
    return true;
}
回答于2021-07-14
得票数 1

我改进了removeObject3D的易卜拉欣代码,添加了一些几何或材质检查

removeObject3D(object) {
    if (!(object instanceof THREE.Object3D)) return false;
    // for better memory management and performance
    if (object.geometry) {
        object.geometry.dispose();
    if (object.material) {
        if (object.material instanceof Array) {
            // for better memory management and performance
            object.material.forEach(material => material.dispose());
        } else {
            // for better memory management and performance
            object.material.dispose();