Soy un desarrollador de juegos y no estudié matemáticas. Así que solo quiero usar Quaternions como herramienta. Y para poder trabajar con rotación 3D, es necesario usar Quaternions (o Matrixes, pero quedémonos en Quaternions aquí en esta pregunta). Creo que es importante que muchos desarrolladores los usen. Es por eso que quiero compartir mi conocimiento y espero llenar los huecos que tengo. Ahora....
Entonces, por lo que entendí:
Un Quaternion puede describir 2 cosas:
- La orientación actual de un objeto 3d.
- La transformación de rotación que un Objeto podría hacer. (rotaciónCambio)
Puedes hacer con un Quaternion:
Multiplicaciones:
Quaternion endOrientation = Quaternion rotacionCambio * Quaternion currentOrientation;
Entonces, por ejemplo: mi objeto 3D se gira 90 ° hacia la izquierda, y mi rotación que multiplico es una rotación de 180 ° hacia la derecha, al final mi objeto 3D 90 ° se gira hacia la derecha.
Quaternion rotacionCambio = Quaternion endRotation * Quaternion.Inverse (startRotation);
Con esto obtienes un rotación de cambio, que se puede aplicar a otra orientación.
Vector3 endPostion = Quaternion rotacionCambio * Vector3 currentPosition;
Entonces, por ejemplo: mi objeto 3D está en posición (0,0,0) y mi rotación que multiplico es una rotación de 180 ° a la derecha, mi posición final es algo así como (0, -50,0). Dentro de ese Quaternion hay un Eje, y una rotación alrededor de ese eje. Gira su punto alrededor de ese eje Y Grados.
Vector3 rotatedOffsetVector = Quaternion rotacionCambio * Vector3 currentOffsetVector;
Por ejemplo: mi dirección de inicio muestra ARRIBA - (0,1,0), y mi rotación que multiplico es una rotación de 180 ° a la derecha, mi dirección de finalización se muestra hacia abajo. (0, -1,0)
Mezcla (Lerp y Slerp):
Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, interpolator)
si el interpolador es 1: currentOrientation = endOrientation
si el interpolador es 0: currentOrientation = startOrientation
Slerp interpola más preciso, Lerp interpola más performant.
Mis preguntas):
¿Todo lo que expliqué hasta ahora es correcto?
¿Es eso "todo" lo que puedes hacer con Quaternions? (obviamente no)
¿Qué más puedes hacer con ellos?
¿Para qué sirven el producto Dot y el producto Cross entre 2 Quaternions?
Editar:
Pregunta actualizada con algunas respuestas
fuente
n
diferentes orientaciones (actitudes, poses, etc.). Luego puede promediarlos usando pesos, generalizando efectivamente slerp / lerp. También puede convertir un cuaternión en un rotor, lo que equivale a aplicar una velocidad angular durante un cierto período de tiempo a un cuerpo rígido. Por lo tanto, también puede describir la integración de la velocidad angular con cuaterniones. También puede estimar cuán diferentes son las dos orientaciones (calcule la longitud del arco atravesado por los dos cuaterniones en la hiperesfera).Respuestas:
Multiplicación
Al menos en términos de la implementación de Unity de Quaternions, el orden de multiplicación descrito en la pregunta no es correcto. Esto es importante porque la rotación 3D no es conmutativa .
Entonces, si quiero rotar un objeto
rotationChange
comenzando desde élcurrentOrientation
, lo escribiría así:(es decir. Las transformaciones se apilan hacia la izquierda, igual que la convención de matriz de Unity. La rotación más a la derecha se aplica primero / en el extremo "más local")
Y si quisiera transformar una dirección o un vector de desplazamiento mediante una rotación, lo escribiría así:
(Unity generará un error de compilación si haces lo contrario)
Mezcla
Para la mayoría de los casos, puedes salirte con la rotación de Lerping Esto se debe a que el ángulo utilizado "debajo del capó" en un cuaternión es la mitad del ángulo de rotación, lo que lo hace sustancialmente más cercano a la aproximación lineal de Lerp que algo así como una Matriz (¡que en general no Lerp bien!). Mira alrededor de 40 minutos en este video para obtener más explicaciones .
El único caso en el que realmente necesita Slerp es cuando necesita una velocidad constante en el tiempo, como la interpolación entre fotogramas clave en una línea de tiempo de animación. Para los casos en los que solo le importa que una salida sea intermedia entre dos entradas (como mezclar capas de una animación), generalmente Lerp sirve bastante bien.
¿Qué más?
El producto de puntos de dos unidades de cuaterniones da el coseno del ángulo entre ellos, por lo que puede usar el producto de puntos como una medida de similitud si necesita comparar rotaciones. Sin embargo, esto es un poco oscuro, por lo que para un código más legible a menudo usaría Quaternion.Angle (a, b) en su lugar, que expresa más claramente que estamos comparando ángulos, en unidades familiares (grados).
Estos tipos de métodos de conveniencia que Unity proporciona para Quaternions son súper útiles. En casi todos los proyectos uso este al menos algunas veces :
Esto genera un cuaternión que:
forward
argumento vectorialup
argumento vectorial, si se proporciona, o(0, 1, 0)
si se omiteLa razón por la que "arriba" solo se "acerca lo más posible" es que el sistema está sobredeterminado. Enfrentando z + a
forward
usa hasta dos grados de libertad (es decir, guiñada y cabeceo), por lo que solo nos queda un grado de libertad (rodar).A menudo encuentro que quiero algo con las propiedades de exactitud opuestas: quiero que y + local apunte exactamente a lo largo
up
, y z + local se acerque lo más posible aforward
la libertad restante.Esto surge, por ejemplo, cuando trato de formar un marco de coordenadas relativo a la cámara para la entrada de movimiento: quiero que mi dirección local hacia arriba permanezca perpendicular al piso o superficie inclinada normal, por lo que mi entrada no intenta hacer un túnel del personaje en el terreno o levitarlos fuera de él.
También puede obtener esto si desea que la torreta de un tanque mire hacia un objetivo, sin despegarse del cuerpo del tanque cuando apunta hacia arriba / abajo.
Podemos construir nuestra propia función de conveniencia para hacer esto, utilizando
LookRotation
para el trabajo pesado:Aquí primero rotamos local y + a z +, y local z + a y-.
Luego, rotamos el nuevo z + hacia nuestra dirección hacia arriba (de modo que el resultado neto es local y + apunta directamente a lo largo
exactUp
), y el nuevo y + lo más cerca posible a la dirección negada hacia adelante (por lo que el resultado neto es local z + puntos lo más cerca posible a lo largoapproximateForward
)Otro método práctico de conveniencia es
Quaternion.RotateTowards
, que a menudo uso así:Esto nos permite acercarnos
targetRotation
a una velocidad constante y controlable, independientemente de la velocidad de fotogramas, importante para las rotaciones que afectan el resultado / la imparcialidad de la mecánica del juego (como girar el movimiento de un personaje o tener una torreta en el jugador). El ingenuo Lerping / Slerping en esta situación puede conducir fácilmente a casos en los que el movimiento se vuelve más ágil a velocidades de cuadro altas, lo que afecta el equilibrio del juego. (Eso no quiere decir que estos métodos sean incorrectos: hay formas de usarlos correctamente sin cambiar la equidad, solo requiere cuidado.RotateTowards
Ofrece un atajo conveniente que se encarga de esto por nosotros)fuente
¿Dónde se usa el producto dot?
En Unity, uno de los usuarios más comunes del producto punto es cada vez que verifica si dos cuaterniones son iguales a través de
==
o!=
. Unity calcula el producto punto para verificar la similitud en lugar de comparar directamente los valores internos x, y, z, w. Vale la pena tener esto en cuenta, ya que hace que la llamada sea más cara de lo que cabría esperar.También lo usamos en un caso de uso interesante.
Diversión con productos de punto cuaternión: mundos esféricos y orbitales
Las simulaciones de planetas enteros e incluso sistemas solares completos se están volviendo cada vez más comunes. Para lograr esto en tiempo real, también necesitamos el producto de punto cuaternión. Muchos de ellos. El producto de punto cuaternión está muy infrautilizado pero ciertamente tiene sus usos. ¡Echemos un vistazo!
En primer lugar, tenemos toda una serie de rotaciones a considerar:
Combínalos todos juntos y terminarás con mucha complejidad (¡y muchos números enormes!). Cuando el espectador está de pie en la superficie del planeta, no queremos que se precipiten a una velocidad loca por nuestro espacio en el mundo del juego. En realidad preferiríamos que estuvieran estacionarios y en algún lugar cerca del origen; en su lugar, mueva el universo alrededor del jugador.
Es importante destacar que, para que podamos obtener el giro y la inclinación del planeta correctos en este escenario, necesitamos bloquear el poste en el eje para que solo pueda oscilar hacia arriba / abajo en la imagen de arriba (es decir, hacia arriba mientras el jugador viaja norte). Ahí es donde entra un producto de punto cuaternión. Si no usáramos un producto de punto aquí y, en su lugar, también multiplicamos la inclinación, esto sucedería:
Observe cómo los polos de nuestros 'planetas' en órbita siempre se inclinan hacia la estrella. Esto no es lo que sucede en realidad: la inclinación está en una dirección fija .
Sin ir demasiado lejos del tema, aquí hay un resumen rápido:
Al obtener solo el ángulo, dejamos caer algo de esa rotación no deseada . Al mismo tiempo, también terminamos con una medición de longitud que es útil tanto para la navegación como para el clima local.
* Los planetas se construyen a partir de muchas celdas de cuadrícula . Solo se muestran los cercanos.
fuente
dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w
en lugar de la composición de cuaternión que usaríamos para encadenar juntos) rotaciones) nos ayudarían a resolver este problema. Con mucho gusto votaré si puedes explicar esto un poco más tarde (no quiero mantenerte alejado de tu slerp ... ¡quiero decir dormir!)