Cómo evitar el bloqueo del cardán

8

Estoy tratando de escribir código con rota un objeto.

Lo implementé como:

La rotación sobre el eje X viene dada por la cantidad de cambio en las coordenadas y de un mouse y la rotación sobre el eje Y está dada por la cantidad de cambio en las coordenadas x de un mouse.

Este método es simple y funciona bien hasta que en el eje coincida con el eje Z, en resumen, se produce un bloqueo de gimble.

¿Cómo puedo utilizar la rotación alrededor del eje Z para evitar el bloqueo del cardán?

Singingsingh
fuente
Respuesta corta: use quaternions
Robert Rouhani
44
Los cuaterniones siguen siendo propensos al bloqueo de cardán si los usas mal: no es lo que usas para representar tus rotaciones, es la concatenación de rotaciones múltiples lo que lo causa. Entonces no concatene rotaciones.
Maximus Minimus
Con respecto a mi comentario anterior, vea el comentario de Maik Semder en gamedev.stackexchange.com/questions/23540/…
Maximus Minimus
Estaba a punto de escribir el mismo comentario nuevamente, gracias por encontrarlo @ mh01 :)
Maik Semder

Respuestas:

14

La solución simple es no almacenar la orientación del objeto como ángulos alrededor de los ejes (eje X, Y, Z), como por ejemplo en los ángulos de Euler.

Almacene la orientación del objeto como una matriz o un cuaternión.

Esto puede causar bloqueo de cardán, utilizando ángulos de euler:

class Object
{
    float m_angleAxisX;
    float m_angleAxisY;
    float m_angleAxisZ;
};

Sin bloqueo de cardán:

class Object
{
    matrix m_orientation;   
};

Sin bloqueo de cardán tampoco:

class Object
{
    quaternion m_orientation;   
};

Ahora, cada vez que se cambia el mouse, multiplique m_orientation con el cambio de orientación proveniente del movimiento del mouse en cada fotograma.

Maik Semder
fuente
0

¡Este libro (representación en tiempo real) me ayudó mucho! Consulte las páginas 66 y 70. Tiene muy buenos gráficos y explicaciones. ¡Los cuaterniones también están en la página 72! :)

Rotación sobre un eje arbitrario

Esto representa la cámara con la rotación realizada por la entrada del mouse:

void Camera::getVectors(D3DXVECTOR3& up, D3DXVECTOR3& lookAt)
{
    float yaw, pitch, roll;
    D3DXMATRIX rotationMatrix;

    // Setup the vector that points upwards.
    up.x = 0.0f;
    up.y = 1.0f;
    up.z = 0.0f;

    // Setup where the camera is looking by default.
    lookAt.x = 0.0f;
    lookAt.y = 0.0f;
    lookAt.z = 1.0f;

    // Set the yaw (Y axis), pitch (X axis), and roll (Z axis) rotations in radians.
    pitch = m_rotation.x * 0.0174532925f;
    yaw   = m_rotation.y * 0.0174532925f;
    roll  = m_rotation.z * 0.0174532925f;

    // Create the rotation matrix from the yaw, pitch, and roll values.
    D3DXMatrixRotationYawPitchRoll(&rotationMatrix, yaw, pitch, roll);

    // Transform the lookAt and up vector by the rotation matrix so the view is correctly rotated at the origin.
    D3DXVec3TransformCoord(&lookAt, &lookAt, &rotationMatrix);
    D3DXVec3TransformCoord(&up, &up, &rotationMatrix);
}

// The Render function uses the position and rotation of the camera to build and update the view matrix
void Camera::render()
{
    D3DXVECTOR3 up, position, lookAt;

    // Setup the position of the camera in the world.
    position = (D3DXVECTOR3)m_position;

    getVectors(up, lookAt);

    // Translate the rotated camera position to the location of the viewer.
    lookAt = position + lookAt;

    // Finally create the view matrix from the three updated vectors.
    D3DXMatrixLookAtLH(&m_viewMatrix, &position, &lookAt, &up);

    return;
}

Con la entrada del mouse puede modificar el guiñada (cabeza), cabeceo y balanceo.

Jinxi
fuente
1
-1 Esto no resuelve el bloqueo del cardán, ya que utiliza ángulos euler (m_rotation) para el almacenamiento de orientación interna. Este wiki explica por qué.
Maik Semder