Realidad Aumentada: Manipula Modelos 3D con Zoom y Rotación

Componente de Gestos Personalizado para A-Frame y MindAR: Cómo Añadir Interactividad Táctil a tus Modelos 3D

 

Ingcarlosreina enseña como crear una aplicacion de realidad aumentada WebAR
Manipula Modelos 3D con Zoom y Rotación WebAR

Vivimos en un mundo táctil, y por eso asumimos que la interacción con nuestros dispositivos siempre ha sido así. Sin embargo, hace solo unos años, cuando la realidad aumentada (AR) comenzaba a desarrollarse en dispositivos móviles y de escritorio, crear una aplicación con funciones tan básicas como rotar o hacer zoom en un modelo 3D era un proceso complejo.

Los gestos que usamos hoy en día, como pellizcar la pantalla para hacer zoom o deslizar el dedo para rotar, no existían en la tecnología AR de esos primeros días. Ahora, estos gestos son algo que tenemos interiorizado; los hacemos de forma automática cada vez que interactuamos con nuestro móvil, sin siquiera pensarlo.

En este tutorial, vamos a explorar una de las funcionalidades más simples, pero a menudo olvidadas de las aplicaciones de realidad aumentada (AR): cómo hacer zoom y rotar modelos 3D. Damos por sentado que todas las aplicaciones tienen estas funciones, pero la realidad es que no es así. Para implementarlas, debemos programarlas nosotros mismos, especialmente cuando desarrollamos experiencias de WebAR, es decir, realidad aumentada directamente en la web.

Si eres nuevo en esto del mundo de la realidad aumentada y no sabes por donde comenzar te recomiendo este post: Aprende Realidad Aumentada Desde Cero: Guia para empezar |

Comencemos con el tutorial

Quieres aprender a hacer aplicaciones de realidad aumentada en minutos de forma fácil y sencilla. Sigue nuestra comunidad en: 

Para este tutorial utilice un modelo 3D en formato .glb que descargue en Sketchfab.

vamos directamente al código JavaScript que es el encargado de permitir los gestos táctiles.


<script>
AFRAME.registerComponent("gestos", {
init: function() {
this.initialDistance = null;
this.isRotating = false;
this.isScaling = false;
this.lastClientX = 0;
this.lastClientY = 0;
this.el.sceneEl.addEventListener("touchstart", this.onTouchStart.bind(this));
this.el.sceneEl.addEventListener("touchmove", this.onTouchMove.bind(this));
this.el.sceneEl.addEventListener("touchend", this.onTouchEnd.bind(this));
},
onTouchStart: function(evt) {
if (evt.touches.length === 2) {
this.isScaling = true;
this.isRotating = false;
this.initialDistance = this.getDistance(evt.touches[0], evt.touches[1]);
} else if (evt.touches.length === 1) {
this.isRotating = true;
this.isScaling = false;
this.lastClientX = evt.touches[0].clientX;
this.lastClientY = evt.touches[0].clientY;
}
},
onTouchMove: function(evt) {
if (this.isScaling && evt.touches.length === 2) {
let currentDistance = this.getDistance(evt.touches[0], evt.touches[1]);
let scaleFactor = currentDistance / this.initialDistance;
let currentScale = this.el.object3D.scale;
this.el.setAttribute("scale", {
x: currentScale.x * scaleFactor,
y: currentScale.y * scaleFactor,
z: currentScale.z * scaleFactor,
});
this.initialDistance = currentDistance;
} else if (this.isRotating && evt.touches.length === 1) {
const sensitivity = 0.005; // Ajuste para una rotación más fluida
let deltaX = evt.touches[0].clientX - this.lastClientX;
let deltaY = evt.touches[0].clientY - this.lastClientY;

let currentRotation = this.el.object3D.rotation;
currentRotation.y += deltaX * sensitivity;
currentRotation.x += deltaY * sensitivity;

this.lastClientX = evt.touches[0].clientX;
this.lastClientY = evt.touches[0].clientY;
}
},
onTouchEnd: function(evt) {
this.isScaling = false;
this.isRotating = false;
this.initialDistance = null;
},
getDistance: function(touch1, touch2) {
return Math.sqrt(
Math.pow(touch2.clientX - touch1.clientX, 2) +
Math.pow(touch2.clientY - touch1.clientY, 2)
);
},
});
</script>

Fíjate en el componente, llamado «gestos», este encapsula toda la lógica necesaria para interpretar los toques en la pantalla y traducirlos en acciones sobre un modelo tridimensional. Al ser un componente de A-Frame, se puede adjuntar a cualquier entidad 3D con una simple línea de código <a-gltf-model … gestos></a-gltf-model>.

Hablemos de…

  • La Estructura del Componente «gestos»

El script se define con AFRAME.registerComponent(«gestos», { … });. A-Frame utiliza este método para crear componentes reutilizables. El componente tiene una función principal, init, que se ejecuta una vez cuando el componente se adjunta a una entidad.

Dentro de init, se inicializan varias variables para llevar el registro del estado de los gestos, como si el usuario está rotando (isRotating) o escalando (isScaling). Lo más importante es que se agregan escuchadores de eventos a la escena completa (this.el.sceneEl) para detectar los toques del usuario: touchstart, touchmove y touchend.

  • Detección de Gestos: onTouchStart

La función onTouchStart es la primera en ejecutarse cuando el usuario toca la pantalla. Su objetivo es determinar qué tipo de gesto se está intentando:

Si evt.touches.length === 2: Esto significa que el usuario ha tocado la pantalla con dos dedos. El script interpreta esto como un gesto de escalado (zoom). Se calcula la distancia inicial entre los dos dedos y se almacena en this.initialDistance para usarla como referencia.

Si evt.touches.length === 1: Si hay un solo dedo en la pantalla, se considera un gesto de rotación. Se guarda la posición inicial del dedo (clientX, clientY) para poder calcular el movimiento en la siguiente fase.

  • Ejecución de los Gestos: onTouchMove

Esta es la función que realmente anima el modelo. Se activa continuamente mientras el usuario mueve sus dedos sobre la pantalla.

Para el escalado: Si this.isScaling es verdadero, el script calcula la distancia actual entre los dos dedos. Luego, compara esta distancia con la distancia inicial para obtener un scaleFactor (factor de escalado). Este factor se usa para multiplicar la escala actual del modelo, haciéndolo más grande o más pequeño de manera proporcional.

Para la rotación: Si this.isRotating es verdadero, el script calcula la diferencia de posición del dedo (deltaX, deltaY) desde el último fotograma. Esta diferencia se usa para modificar las propiedades de rotación (rotation.y y rotation.x) del modelo 3D. Se utiliza una sensitivity para ajustar la velocidad de la rotación y hacerla más fluida.

  • Finalización del Gesto: onTouchEnd

Cuando el usuario levanta los dedos de la pantalla, la función onTouchEnd se activa. Su propósito es restablecer el estado del componente, estableciendo this.isScaling e this.isRotating a false. Esto asegura que el modelo deje de cambiar cuando el usuario ya no está interactuando con él, preparándolo para el siguiente gesto.

¿Qué podemos concluir?

El componente aquí llamado «gestos» es un ejemplo robusto de cómo se pueden utilizar los eventos del navegador para crear interacciones avanzadas y multitáctiles en experiencias de AR. Al encapsular esta lógica en un componente de A-Frame, el desarrollador puede añadir esta funcionalidad a cualquier modelo 3D con una sola palabra, haciendo el código limpio y fácil de mantener. Esto demuestra el poder de combinar librerías como MindAR y A-Frame para ir más allá de la simple visualización y ofrecer experiencias de usuario ricas e intuitivas.


¿Quieres tener este script junto a su HTML y los otros archivos?

  • Visita y haz parte de la comunidad de WhatsApp de Realidad Aumentada Empezando Desde Cero
  • Si ya eres miembro podrás ver todos los tutoriales que subo junto a sus archivos de descarga.
  • Si eres usuario nuevo y quieres estos archivos deja un mensaje y con gusto te los comparto.

 

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Scroll al inicio
0
Would love your thoughts, please comment.x
()
x