Audiogames: usando cuaterniones para interpolar un giro…

Cuando hace un tiempo publiqué el ejemplo para comunicar OSC con Blender y mover un objeto con la rotación del telefono movil, me tope con un problema matemático que no sabía resolver. (ver entrada aquí)

El movil entrega los giros en el eje Z en grados (de 0 a 360) y sucede que los valores saltan abruptamente de 360 a 0 cuando pasamos por el norte girando hacia la derecha, y de 0 a 360 hacia la izquierda.

Esto hizo que me complicase la vida excesivamente intentando trasladar estos angulos al objeto 3d, y que intentase interpolar el movimiento. Lo mas cercano que conseguí es una rotacion bastante suave siempre que no nos acercasemos al norte. En el momento en que el movil rotaba a traves del norte, el objeto se volvia loco trazando giros absurdos…

Para la instalación audigames decidimos utilizar un movil para obtener la orientacion del jugador, que llevará el movil sobre la cabeza, sujeto a los cascos. Así que por fin me he tenido que enfrentar nuevamente al problema, y he encontrado la solución cambiando de modo de representación matemática de la orientación.

Para representar la orientacion de un objeto en 3 dimensiones, existen cuatro metodos, los cuarto presentes en blender, a saber:

Tanto los Angulos Euler como Angulo y Eje son notaciones intuitivas y faciles de entender (basadas en grados sexagesimales en un espacio euclideo), pero tienen varios problemas:

  • El problema del salto de 0 a 360 que antes mencioné.
  • La posibilidad de que suceda un bloqueo de cardán, o ‘gimbal lock’. (ver video explicativo)
  • Cuando se aplican dos rotaciones consecutivas, no se puede asegurar que la rotacion resultante sea la suma total de las rotaciones individuales.

La aritmetica de los cuaterniones sin embargo, puede representar operaciones en 3d de una manera similar a como la aritmetica de los números complejos pueden representar operaciones en un espacio 2d. De modo que los cuaterniones sí pueden ser usados para calcular interpolaciones, sin sufrir las inestabilidades de los metodos anteriores.

Las matrices nos permiten tambien hacer estas operaciones correctamente, y ademas aplicar traslaciones, pero su uso y comprension es un tanto más complicado, de modo que simplemente, me las saltaré.

La explicación de como funcionan los cuaterniones me ha parecido muy interesante y clarificadora, pero como entender es una cosa bien distinta de saber explicar, mejor dejo aquí los links que me ayudaron:

http://www.euclideanspace.com/maths/geometry/rotations/index.htm

http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/index.htm

*     *    *

Para utilizar cuaterniones en blender disponemos de una serie de metodos del modulo mathutils, bien documentados en la API de Blender

A continuacion un ejemplo de como girar un objeto aplicandole un giro de 90 grados en el eje Z interpolando con un factor de 0.25 (cada paso el objeto girará solo un cuarto de la diferencia de rotacion, para suavizar el movimiento)

# para crear un cuaternion partiendo de un Angulo y un Eje:

rot_A = mathutils.Quaternion((0.0,0.0,1.0), math.radians(90))

# obtener un cuaternion de la orientacion actual del objeto

rot_ob = ob.localOrientation.to_quaternion()

# para calcular la diferencia de rotacion entre dos cuateriones

rot_diff = rot_ob.rotation_difference(rot_A)

# para calcular una interpolacion

rota = rot_ob.slerp(rot_diff, 0.25)

#asignacion de la rotacion al objeto

ob.localOrientation = rota