ThreeJS:从场景中移除物体

我正在使用ThreeJS开发一个Web应用程序,显示实体列表,每个实体都有相应的“查看”和“隐藏”button。 例如entityName 查看隐藏 。 当用户点击查看button时,下面的函数被调用,实体在屏幕上绘制成功。

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); } 

并点击隐藏button,下面的函数被调用:

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

问题是,点击“ 隐藏”button后,实体不会从屏幕上移除。 我能做些什么来隐藏button的工作?

我做了小实验。 我添加了scene.remove(object.name);scene.add(object);后面 在addEntity函数中作为结果,当“View”button被点击时,没有实体绘制(如预期的)意思是scene.remove(object.name);addEntity工作得很好。 但是我仍然无法弄清楚如何在removeEntity(object)中使用它。

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

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

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

谢谢。 🙂

我认为看到你的使用addEntity和removeEntity代码将是有益的,但我的第一个想法是你实际设置object.name? 在scene.add(object)之前试试你的loader。 像这样的东西:

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

可能发生的情况是Object3D的默认“名称”是“”,所以当您调用removeEntity函数时,由于场景对象名称为“”

另外,我注意到你传入的object.name到你的loader? 这是你的URL存储资源? 如果是这样的话,我会build议使用Object3D内置的.userData方法来存储这些信息,并保留名称字段进行场景识别。

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

首先要注意的是,在对象名中使用“/”并不是一个好主意,它似乎可以正常工作,但是您永远不知道某些algorithm是否会决定转义该string并破坏您的项目。

第二项是现在我已经看到你的代码,它实际上是直接发生了什么事情。 你的删除function试图按名称删除,你需要一个Object3D来删除。 尝试这个:

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

在这里你看到我在Three.js Scene通过传入你的object标签的name属性来查找你的Object3D 。 希望有所帮助

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

这个使用了unrecore.js来让场景中的所有孩子(除了第一个孩子)(这是我用来清除场景的代码的一部分)。 只要确保删除后至less 渲染 一次场景,否则canvas不会改变! 不需要“特殊”obj国旗或任何类似的东西。

你也不要删除名字的对象,只是由对象本身,所以调用

 scene.remove(object); 

而不是scene.remove(object.name); 可以够了

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

我有像你一样的问题。 我尝试这个代码,它工作得很好:当你创build你的对象把这个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); } } } 

尝试一下,告诉我是否有效,看来三个jsjoin到场景后不会识别这个对象。 但有了这个技巧,它的作品。

如果您的元素不是直接在您的场景上,请回到“家长”以将其删除

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

这个伟大的工作 – 我testing它,请为每个对象设置名称

在创build时将名称提供给对象

  mesh.name = 'nameMeshObject'; 

并使用这个如果你有删除对象

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

打开新的场景,添加对象 打开新的场景,添加对象

删除对象并创build新的 删除对象并创建新的

你可以使用这个

 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 }