es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Three.js: cómo agregar una URL personalizada a un modelo GLTF cargado

Tengo una galaxia compuesta por 3 planetas y una nave espacial, y quiero hacer que todos ellos sean clicables para cargar otra página. Logré hacerlo con los 3 planetas agregando planet.userData = {URL: "my.html"}; pero no con la nave espacial, que es un modelo cargado GLTF.

Así es como cargué la nave espacial:

const loader = new GLTFLoader();
            loader.load('models/spaceship.glb', function(gltf) {

            const spaceship = gltf.scene;

            spaceship.scale.set(0.08, 0.08, 0.08);
            spaceship.userData = {URL: "my.html"}; //Agregando la URL aquí
            objects.push(spaceship); //Esto es para el raycasting
            scene.add(spaceship);


        }, undefined, function(error){
            console.error(error);
        });

Y esta es la función para el evento Mouse Down:

function onDocumentMouseDown(){

            mouse.x = (event.clientX/window.innerWidth)*2-1;
            mouse.y = -(event.clientY/window.innerHeight)*2+1; 

            const raycaster = new THREE.Raycaster();
            raycaster.setFromCamera(mouse, camera);
            const intersects = raycaster.intersectObjects(objects, true);

            if ( intersects.length > 0 ) {
                window.open(intersects[0].object.userData.URL); // <-- No funciona
            }

        }

Cuando hago clic en la nave espacial, el valor de la URL es “undefined”. Estoy seguro de que hay otra forma de hacerlo, pero no puedo encontrar ninguna solución. ¡Muchas gracias de antemano a cualquiera que ayude!

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Parece que el modelo GLTF cargado para la nave espacial no tiene asignada la propiedad userData. Según el código proporcionado, parece que esta línea spaceship.userData = {URL: "my.html"}; se está ejecutando correctamente. Sin embargo, cuando se revisa el array intersects en busca de objetos clicables, la propiedad userData del objeto de la nave espacial devuelve undefined.

    Una posible solución podría ser verificar si el array intersects está vacío y, en ese caso, intentar buscar la propiedad userData en alguno de los padres del objeto. Esto se puede lograr recorriendo la jerarquía de padres del objeto hasta que se encuentre la propiedad userData o se alcance el objeto raíz.

    Aquí tienes un ejemplo de cómo se podría implementar esto:

    function onDocumentMouseDown() {
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    
      const raycaster = new THREE.Raycaster();
      raycaster.setFromCamera(mouse, camera);
      const intersects = raycaster.intersectObjects(objects, true);
    
      if (intersects.length > 0) {
        // Comprobar si el objeto clicado tiene userData
        if (intersects[0].object.userData && intersects[0].object.userData.URL) {
          window.open(intersects[0].object.userData.URL);
        } else {
          // Si no se encuentra userData en el objeto clicado, intentar encontrarlo en sus padres
          let currentObject = intersects[0].object.parent;
          while (currentObject !== scene) {
            if (currentObject.userData && currentObject.userData.URL) {
              window.open(currentObject.userData.URL);
              break;
            }
            currentObject = currentObject.parent;
          }
        }
      }
    }
    

    En este ejemplo, si el objeto clicado no tiene userData, el bucle recorrerá los objetos padre hasta que encuentre el primer objeto con userData. Si no se encuentra ningún objeto con userData, el bucle finalizará cuando llegue al objeto raíz scene.

    ¡Espero que esto ayude!

Comments are closed.