c++ animation 3d

c++ - Cómo restringir rotaciones 3D(Euler)



animation (2)

El problema aquí es que las restricciones que está aplicando no tienen relación con la rotación aplicada. Desde un punto de vista conceptual, esto es lo que intenta lograr:

  • asumir que un hueso está en un estado no restringido.
  • aplicar rotación
  • ha hueso excedido de las limitaciones? En caso afirmativo, gírelo a donde ya no esté restringido

El código que sujeta las rotaciones de Euler es la parte donde se rota el hueso hacia atrás. Sin embargo, este código ignora la rotación ósea original, por lo que verá un comportamiento extraño, como el ajuste que está viendo.

Una forma simple de trabajar con esto es hacer esto en su lugar:

  • asumir que un hueso está en un estado sin restricciones
  • aplicar rotación
  • prueba si el hueso excedió las restricciones
  • si es así, tenemos que encontrar dónde la restricción detiene el movimiento.
    1. reducir a la mitad la rotación, aplicarla en reversa
    2. ¿El hueso excede las limitaciones? Si es sí, ve a 1
    3. Si no, reduzca a la mitad la rotación, aplíquela hacia adelante. Ir a 2
  • sigue haciendo eso hasta que estés dentro de cierta tolerancia de tus ángulos restrictivos

Ahora bien, esto funcionará, pero debido a que sus quarternions de rotación se están aplicando en todos los ángulos, la rotación se detendrá cuando cualquiera de esas restricciones sea neta, incluso si hay libertad en algún otro lugar.

Si, en cambio, aplica rotaciones de forma independiente, podrá usar de manera confiable su sujeción o la técnica anterior para cumplir con las restricciones y también girar lo más cerca posible de su objetivo. - -

¿Cuál es la mejor / la mejor manera de restringir una rotación 3D (usando ángulos de Euler y / o cuaterniones)?

Parece que hay algo mal con mi manera de hacerlo. Estoy aplicando las rotaciones a los huesos en una jerarquía esquelética para la animación, y los huesos a veces visiblemente "saltan" en la orientación incorrecta, y los componentes individuales de Euler se envuelven en el extremo opuesto de sus rangos.

Estoy usando ángulos de Euler para representar la orientación actual, convertir a cuaterniones para hacer rotaciones, y sujetar cada eje de ángulo de Euler de forma independiente. Aquí hay pseudocódigo de C ++ que muestra básicamente lo que estoy haciendo:

Euler min = ...; Euler max = ...; Quat rotation = ...; Euler eCurrent = ...; // do rotation Quat qCurrent = eCurrent.toQuat(); qCurrent = qCurrent * rotation; eCurrent = qCurrent.toEuler(); // constrain for (unsigned int i = 0; i < 3; i++) eCurrent[i] = clamp(eCurrent[i], min[i], max[i]);


Un problema con los ángulos de Euler es que hay varias formas de representar la misma rotación, por lo que puede crear fácilmente una secuencia de rotaciones suaves, pero los ángulos que representan esa rotación pueden saltar. Si los ángulos saltan dentro y fuera del rango restringido, entonces verá efectos como los que está describiendo.

Imagine que solo estaba involucrada la rotación X, y había restringido la rotación X a entre 0 y 180 grados. También imagine que su función que convierte el cuaternión en ángulos de Euler dio ángulos de -180 a 180 grados.

Entonces tienes esta secuencia de rotaciones:

True rotation After conversion After constraint 179 179 179 180 180 180 181 -179 0

Puede ver que, aunque la rotación está cambiando suavemente, el resultado saltará repentinamente de un lado a otro porque la función de conversión fuerza a que el resultado se represente en un cierto rango.

Cuando está convirtiendo el cuaternión en ángulos de Euler, encuentre los ángulos que están más cerca del resultado anterior. Por ejemplo:

eCurrent = closestAngles(qCurrent.toEuler(),eCurrent); eConstrained = clampAngles(eCurrent,min,max);

recuerde los valores de eCurrent para la próxima vez y aplique las rotaciones eConstrained a su esqueleto.