Como evitar o bloqueio do cardan

8

Eu estou tentando escrever código com gira um objeto.

Eu o implementei como:

A rotação sobre o eixo X é dada pela quantidade de alteração nas coordenadas y de um mouse e a rotação sobre o eixo Y é dada pela quantidade de alteração nas coordenadas x de um mouse.

Este método é simples e funciona bem até que no eixo coincida com o eixo Z. Em resumo, ocorre um bloqueio flexível.

Como posso utilizar o eixo Z da rotação para evitar o bloqueio do cardan.

singingsingh
fonte
Resposta curta: uso quaternions
Robert Rouhani
4
Os quaternions ainda são propensos ao bloqueio do cardan, se você usá-los incorretamente - não é o que você usa para representar suas rotações, é concatenar várias rotações que causam isso. Portanto, não concatene rotações.
Maximus Minimus
Com relação ao meu comentário anterior, consulte o comentário de Maik Semder em gamedev.stackexchange.com/questions/23540/…
Maximus Minimus
Eu estava prestes a escrever o mesmo comentário mais uma vez, obrigado por encontrá-la @ mh01 :)
Maik Semder

Respostas:

14

A solução simples é não armazenar a orientação do objeto como ângulos em torno dos eixos (eixos X, Y, Z), como por exemplo nos ângulos de Euler.

Armazene a orientação do objeto como uma matriz ou um quaternion.

Isso pode causar o bloqueio do cardan, usando ângulos de euler:

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

Sem bloqueio do cardan:

class Object
{
    matrix m_orientation;   
};

Nenhum bloqueio do cardan também:

class Object
{
    quaternion m_orientation;   
};

Agora, sempre que o mouse for alterado, multiplique m_orientation com a mudança de orientação proveniente do movimento do mouse em cada quadro.

Maik Semder
fonte
0

Este livro (renderização em tempo real) me ajudou muito! Veja nas páginas 66 e 70. Possui gráficos e explicações muito bons. Os quaternions também estão na página 72! :)

Rotação em torno de um eixo arbitrário

Isso renderiza a câmera com a rotação feita pela entrada do 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;
}

Com a entrada do mouse, você modifica a guinada (cabeça), o pitch and roll.

Jinxi
fonte
11
-1 Isso não resolve o bloqueio do cardan, pois usa ângulos de euler (m_rotation) para o armazenamento interno da orientação. Este wiki explica o porquê.
Maik Semder 20/03/2013