Ejercicio 3: Interacción sencilla en WebGL
La idea de este ejercicio es tomar el ejemplo creado en el Ejercicio 2, y agregar un aspecto interactivo sencillo. En este caso, decidí hacer que la figura siguiera el Mouse, de forma que en cualquier instante el Mouse este siempre en el centro de la figura. Para esto se requieren dos cosas: Transformar las coordenadas del canvas a las coordenadas de WebGL y hacer la translación de la figura.
Transformación de coordenadas
La escena de WebGL se preparo de forma que el borde derecho del canvas corresponde a la posición 6 y el borde izquierdo corresponde a -6 de las coordenadas de WebGL. Por lo tanto necesitamos que cuando el Mouse se mueva a los bordes del canvas, el centro de la figura tome estos valores.
Primero, obtenemos la posición del Mouse sobre el canvas por medio de la siguiente función:
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
Sabemos que las coordenadas del canvas están dadas de tal forma que la esquina superior izquierda representa la posición (0,0), mientras que la esquina inferior derecha representa la posición (ancho, altura). Por lo tanto, las coordenadas del canvas aumentan hacia la derecha y hacia abajo en los ejes X y Y respectivamente. Para este ejercicio vamos a suponer que el canvas es cuadrado, por lo que el ancho y la altura son iguales. Dado que queremos que el tamaño del canvas no importe en la ejecución, vamos a tomar este valor como una constante desconocida w.
Necesitamos transformar una coordenada (x, y), donde sabemos que x y y se encuentran en un rango de 0 a w, a un rango de -6 a 6. Para esto vamos a realizar un mapeo simple. Primero, cambiamos el rango de 0 a w, a uno de -w/2 a w/2:
x' = x - w/2
y' = y - w/2
Posteriormente, necesitamos pasar del rango de -w/2 a w/2 al de -6 a 6, para esto se debe multiplicar por un factor de 12/w:
x' = (x - w/2) * 12/w = 12x/w - 6
y' = (y - w/2) * 12/w = 12y/w - 6
Por ultimo, necesitamos considerar que mientras en la coordenadas del canvas y aumenta hacia abajo, en WebGL aumenta hacia arriba. Por lo que vamos a multiplicar el valor de y' por -1. De esta forma obtenemos nuestra formula final:
x' = 12x/w - 6
y' = - (12y/w - 6)
También vamos a limitar los valores de x' y y' para que nos e salgan del rango de -6 a 6. En código, esto se vería de la siguiente forma:
//Calculamos posicion en WebGL
var glPos = {
x: + ((12 * pos.x) / canvas.width - 6),
y: - ((12 * pos.y) / canvas.height - 6)
}
//Rectificamos valores
glPos = {
x: Math.min(Math.max(glPos.x, -6.0), 6.0),
y: Math.min(Math.max(glPos.y, -6.0), 6.0)
}
Implementación
Para que el ejemplo funcione, crearemos una variable que contenga la posición actual del Mouse:
var mousePosition = {
x: 0,
y: 0
};
Vamos a crear una función que se encargue de refrescar esta variable:
function refresh(e) {
var pos = getMousePos(canvas, e);
//Calculamos posicion en WebGL
var glPos = {
x: + ((12 * pos.x) / canvas.width - 6),
y: - ((12 * pos.y) / canvas.height - 6)
}
//Rectificamos valores
glPos = {
x: Math.min(Math.max(glPos.x, -6.0), 6.0),
y: Math.min(Math.max(glPos.y, -6.0), 6.0)
}
mousePosition = glPos;
}
Esta función va a ser ejecutada por el evento del movimiento del Mouse. Para esto, se crea un Event Listener:
window.addEventListener('mousemove', refresh, false);
Por ultimo, en la función que dibuja la escena, vamos a hacer que la figura se desplace según la posición del Mouse:
mat4.translate(modelViewMatrix, // destination matrix
modelViewMatrix, // matrix to translate
[mousePosition.x, mousePosition.y, -15.0]);
El resultado final se puede ver en acción haciendo clic en este enlace.
Tiempo dedicado
Para este ejercicio, habia planeado un tiempo de 2 horas, lo cual efectivamente me tome en desarrollar el ejercicio.