Harman052
Estoy usando ThreeJS para desarrollar una aplicación web que muestra una lista de entidades, cada una con el botón correspondiente “Ver” y “Ocultar”; p.ej nombre de la entidad Ver Ocultar. Cuando el usuario hace clic Vista botón, se llama a la siguiente función y la entidad se dibuja en la pantalla con éxito.
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);
}
Y al hacer clic Esconder botón, se llama a la siguiente función:
function removeEntity(object){
scene.remove(object.name);
}
El problema es que la entidad no se elimina de la pantalla una vez cargada cuando Esconder se hace clic en el botón. ¿Qué puedo hacer para hacer Esconder botón para trabajar?
Hice un pequeño experimento. yo añadí scene.remove(object.name);
justo después de scene.add(object);
dentro addEntity
función y como resultado, cuando se hace clic en el botón “Ver”, no se dibuja ninguna entidad (como se esperaba), lo que significa que scene.remove(object.name);
funcionó bien dentro addEntity
. Pero aún no puedo descubrir cómo usarlo en removeEntity (objeto).
Además, verifiqué el contenido de scene.children y muestra: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Código completo: http://devplace.in/~harman/model_display1.php.html
Por favor pregunte, si necesita más detalles. Probé con rev-59-dev y rev-60 de ThreeJS.
Gracias. 🙂
Darryl_Lehmann
Creo que ver su uso para el código addEntity y removeEntity sería útil, pero mi primer pensamiento es ¿realmente está configurando object.name? Pruebe en su cargador justo antes de scene.add(object); algo como esto:
object.name = "test_name";
scene.add(object);
Lo que podría estar sucediendo es que el “nombre” predeterminado para un Object3D es “”, por lo que cuando llama a su función removeEntity falla debido a que el nombre de los objetos de la escena es “”
Además, me doy cuenta de que pasas object.name a tu cargador. ¿Es aquí donde está almacenando la URL del recurso? Si es así, recomendaría usar el método .userData incorporado de Object3D para almacenar esa información y mantener el campo de nombre para identificar la escena.
Editar: respuesta al código recién agregado
Lo primero que debe tener en cuenta es que no es una gran idea tener “/” en el nombre de su objeto, parece funcionar bien, pero nunca se sabe si algún algoritmo decidirá escapar de esa cadena y romper su proyecto.
El segundo elemento es ahora que he visto su código, es realmente sencillo lo que está pasando. Su función de eliminación está intentando eliminar por nombre, necesita un Object3D para eliminar. Prueba esto:
function removeEntity(object) {
var selectedObject = scene.getObjectByName(object.name);
scene.remove( selectedObject );
animate();
}
Aquí ves que busco tu Object3D
en los Tres.js Scene
pasando la etiqueta de su objeto name
atributo.
-
En realidad, el argumento “objeto” pasado a
addEntity
yremoveEntity
es una palabra clave predeterminada de JavaScript que elige el “nombre” de la entidad en cuyo botón “Ver” correspondiente se hizo clic (addEntity y removeEntity son funciones de llamada al hacer clic), por lo queobject.name
contiene en realidad el nombre de la entidad. scene.add(object) funciona bien ya que puedo ver los objetos dibujados en la pantalla. El problema es solo con scene.remove(object.name) ya que no muestra ningún error ni ningún resultado.– harman052
21 de agosto de 2013 a las 15:51
-
Ya veo, no estoy seguro del problema exacto, pero la función scene.remove en Three.js está buscando un Object3D.name que puede o no ser equivalente. Por desgracia, creo que, para mayor claridad, es posible que se necesite un poco más de código para ver la construcción del objeto y el uso de su código de agregar eliminar objeto. De lo contrario, haría console.log the Mesh.name en su función de agregar y quitar la función y ver qué resultados obtiene.
– Darryl_Lehmann
21 de agosto de 2013 a las 16:20
-
Acabo de editar la pregunta agregando más detalles y mencioné el enlace para completar el código. Por favor, compruebe. Gracias.
– harman052
22 de agosto de 2013 a las 5:42
-
Lo intenté como me sugeriste, no pasó nada. También comprobé poniendo
scene.remove( scene.getObjectByName(object.name) );
en alerta () y obtuvo “indefinido”. Como no sé mucho sobre ThreeJS, descubrí que los objetos tienen una historia en scene.children. Cada objeto que agregamos a la escena se agrega al final de scene.children. Entonces escribí el siguiente código:var lastIndex = scene.children.length - 1; endElement = scene.children[lastIndex]; scene.remove(endElement);
Esto elimina el último elemento que dibujé. Ahora, ¿pueden ayudarme a obtener la ID del elemento de scene.children con referencia al nombre del objeto?– harman052
22 de agosto de 2013 a las 16:28
-
+1 para las sugerencias y la información sobre el atributo de nombre, lo que es importante es que debe asegurarse de que cada objeto en la escena tenga un nombre único al usar este método.
– kon psicología
27/03/2014 a las 21:43
MJB
clearScene: function() {
var objsToRemove = _.rest(scene.children, 1);
_.each(objsToRemove, function( object ) {
scene.remove(object);
});
},
esto usa undescore.js para iterar sobre todos los niños (excepto el primero) en una escena (es parte del código que uso para borrar una escena). solo asegúrate de que prestar la escena al menos una vez después borrando, porque de lo contrario el lienzo no cambia! No hay necesidad de una bandera obj “especial” ni nada como esto.
Además, no elimina el objeto por su nombre, solo por el objeto en sí, por lo que llamar
scene.remove(object);
en lugar de scene.remove(object.name);
puede ser suficiente
PD: _.each
es una función de guión bajo.js
-
¿Qué tiene de malo un for normal (let x of foo)? o un bucle for regular?
– Shinzou
21 de febrero de 2017 a las 12:53
-
por supuesto, puede usar un bucle for simple, no hay nada de malo en eso, simplemente he usado _.each, eso es todo.
– MJB
21 de febrero de 2017 a las 22:09
-
Solución perfectamente válida, pero el guión bajo es una dependencia adicional que abarrota el código base a menos que ya lo esté usando.
– DOOMDUDEMX
15 de julio de 2019 a las 8:55
-
Oh, estos tipos adictos a la biblioteca… Parecen olvidar que todas las bibliotecas JS no hacen nada más que usar… ¡JS simple, antiguo y nativo! 😉
– Pedro Ferreira
16 mayo 2020 a las 17:35
-
¿Sabes que el estado de javascript era completamente diferente en 2013? Además de eso, las bibliotecas resuelven muchos problemas que ocurren regularmente y, por ejemplo, lodash, están bien probadas. No hay razón para implementar la lógica usted mismo. Además, si ya tiene una biblioteca incluida por la razón X, no hay razón para no reutilizar los módulos existentes para resolver otros problemas. Sin embargo, si importa jquery para acceder a un nodo dom usando una identificación, lo está haciendo mal.
– MJB
20 de mayo de 2020 a las 9:43
Ibrahim W.
Llegué tarde, pero después de leer las respuestas, es necesario aclarar más.
La función de eliminación que escribiste
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
}
Una buena práctica para eliminar objetos 3D de las escenas de Three.js
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;
}
-
por favor reemplace “objeto” a “objeto3D”
– Andrej
15 de diciembre de 2021 a las 2:58
-
Consulte también Atravesar a todos los elementos secundarios y llame a disponer en su geometría, material y textura.
– Andrej
15 de diciembre de 2021 a las 3:12
Si su elemento no está directamente en su escena, vuelva a Padre para eliminarlo
function removeEntity(object) {
var selectedObject = scene.getObjectByName(object.name);
selectedObject.parent.remove( selectedObject );
}
Роман Зыков
ESTO FUNCIONA MUY BIEN. Lo probé, así que, ESTABLEZCA EL NOMBRE para cada objeto.
dar el nombre al objeto en el momento de la creación
mesh.name="nameMeshObject";
y use esto si tiene que eliminar un objeto
delete3DOBJ('nameMeshObject');
function delete3DOBJ(objName){
var selectedObject = scene.getObjectByName(objName);
scene.remove( selectedObject );
animate();
}
Alex Melluzzo
Empecé a guardar esto como una función y lo llamé según sea necesario para cualquier reacción que lo requiera:
function Remove(){
while(scene.children.length > 0){
scene.remove(scene.children[0]);
}
}
Ahora puede llamar a Remove(); función cuando corresponda.
Sylvain Luguez
Cuando usas: scene.remove(objeto); ¡El objeto se elimina de la escena, pero la colisión con él todavía está habilitada!
Para eliminar también la colisión con el objeto, puede usar eso (para una matriz): objectsArray.splice(i, 1);
Ejemplo :
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);
}
¿Quizás olvidaste actualizar la escena (renderizarla)? ¿Existe una actualización de procesamiento (requestAnimationFrame loop o renderer.render(…))?
– Antón Krutikov
21 de agosto de 2013 a las 12:46
Lo intenté llamando a animate() (update() y render() se llaman dentro de animate()) después
scene.remove(object.name);
enremoveEntity(object)
, pero sin cambios. 🙁– harman052
21 de agosto de 2013 a las 15:39