ThreeJS:从场景中删除对象

har*_*052 45 javascript three.js

我正在使用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);
}
Run Code Online (Sandbox Code Playgroud)

在单击" 隐藏"按钮时,将调用以下函数:

function removeEntity(object){
    scene.remove(object.name);
}
Run Code Online (Sandbox Code Playgroud)

问题是,单击" 隐藏"按钮后,一旦加载,实体就不会从屏幕中删除.如何使" 隐藏"按钮起作用?

我做了小实验.我在函数内部scene.remove(object.name);之后添加,结果,当点击"查看"按钮时,没有实体绘制(如预期的那样)意味着内部工作正常.但我仍然无法弄清楚如何在removeEntity(object)中使用它.scene.add(object);addEntityscene.remove(object.name);addEntity

另外,我检查了scene.children的内容,它显示:[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

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

如果需要更多细节,请询问.我用revJ-59-dev和rev-60测试了ThreeJS.

谢谢.:)

Dar*_*ann 42

我认为看到你对addEntity和removeEntity代码的使用会有所帮助,但我首先想到的是你实际上是在设置object.name吗?在scene.add(object)之前尝试加载你的加载器; 这样的事情:

object.name = "test_name";
scene.add(object);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

现在第二项是我见过你的代码,它实际上是直截了当的.您的删除功能正在尝试按名称删除,您需要删除一个Object3D.试试这个:

function removeEntity(object) {
    var selectedObject = scene.getObjectByName(object.name);
    scene.remove( selectedObject );
    animate();
}
Run Code Online (Sandbox Code Playgroud)

在这里,您可以看到我通过传入对象标签的属性来查找Object3DThree.js .希望有所帮助Scenename


Ibr*_* W. 12

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

你写的删除函数

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
}
Run Code Online (Sandbox Code Playgroud)

从 Three.js 场景中删除 3D 对象的好习惯

function removeObject3D(object3D) {
    if (!(object3D instanceof THREE.Object3D)) return false;

    // for better memory management and performance
    if (object3D.geometry) object3D.geometry.dispose();

    if (object3D.material) {
        if (object3D.material instanceof Array) {
            // for better memory management and performance
            object3D.material.forEach(material => material.dispose());
        } else {
            // for better memory management and performance
            object3D.material.dispose();
        }
    }
    object3D.removeFromParent(); // the parent might be the scene or another Object3D, but it is sure to be removed this way
    return true;
}
Run Code Online (Sandbox Code Playgroud)

  • 请将“object”替换为“object3D” (2认同)

MJB*_*MJB 10

clearScene: function() {
    var objsToRemove = _.rest(scene.children, 1);
    _.each(objsToRemove, function( object ) {
          scene.remove(object);
    });
},
Run Code Online (Sandbox Code Playgroud)

这使用了unexcore.js来对场景中的所有子节点(除了第一个)进行迭代(它是我用来清除场景的代码的一部分).只需确保删除后至少渲染一次场景,否则画布不会改变!不需要"特殊"obj标志或类似的东西.

此外,您不会通过名称删除对象,只是通过对象本身,所以调用

scene.remove(object); 
Run Code Online (Sandbox Code Playgroud)

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

PS:_.eachunderscore.js的函数

  • 常规for(let x of foo)有什么问题?或定期循环? (4认同)
  • 哦,这些对库上瘾的家伙...他们似乎忘记了所有 JS 库只不过是使用...普通的、旧的、原生的 JS!;-) (3认同)
  • 完全有效的解决方案,但下划线是一个额外的依赖项,它会使代码库变得混乱,除非您已经在使用它。 (2认同)