So vermeiden Sie eine kardanische Verriegelung

8

Ich versuche, Code zu schreiben, indem ich ein Objekt drehe.

Ich habe es implementiert als:

Die Drehung um die X-Achse ergibt sich aus dem Ausmaß der Änderung der y-Koordinaten einer Maus, und die Drehung um die Y-Achse ergibt sich aus dem Ausmaß der Änderung der x-Koordinaten einer Maus.

Diese Methode ist einfach und funktioniert einwandfrei, bis auf der Achse die Z-Achse übereinstimmt, kurz gesagt, eine Gimble-Sperre auftritt.

Wie kann ich die Drehung um die Z-Achse verwenden, um eine kardanische Verriegelung zu vermeiden?

singingingh
quelle
Kurze Antwort: Verwenden Sie Quaternionen
Robert Rouhani
4
Quaternionen neigen immer noch zur Kardanverriegelung, wenn Sie sie falsch verwenden - es ist nicht das, was Sie verwenden, um Ihre Rotationen darzustellen, es verkettet mehrere Rotationen, die es verursachen. Verketten Sie also keine Rotationen.
Maximus Minimus
Siehe meinen vorherigen Kommentar In Bezug auf den Kommentar von Maik Semder bei gamedev.stackexchange.com/questions/23540/...
Maximus Minimus
Ich wollte gerade den gleichen Kommentar noch einmal schreiben, danke, dass du ihn gefunden hast @ mh01 :)
Maik Semder

Antworten:

14

Die einfache Lösung besteht darin, die Ausrichtung des Objekts nicht als Winkel um Achsen (X-, Y-, Z-Achse) zu speichern, wie beispielsweise in Eulerwinkeln.

Speichern Sie die Ausrichtung des Objekts als Matrix oder Quaternion.

Dies kann bei Verwendung von Eulerwinkeln zu einer Kardanverriegelung führen:

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

Kein Kardanschloss:

class Object
{
    matrix m_orientation;   
};

Auch kein Kardanschloss:

class Object
{
    quaternion m_orientation;   
};

Wenn nun die Maus geändert wird, multiplizieren Sie m_orientation mit der Orientierungsänderung, die sich aus der Mausbewegung in jedem Frame ergibt.

Maik Semder
quelle
0

Dieses Buch (Echtzeit-Rendering) hat mir sehr geholfen! Siehe auf Seite 66 und 70. Es hat sehr gute Grafiken und Erklärungen. Quaternionen finden Sie auch auf Seite 72! :) :)

Drehung um eine beliebige Achse

Dadurch wird die Kamera mit der Drehung per Mauseingabe gerendert:

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;
}

Mit der Mauseingabe ändern Sie Gieren (Kopf), Nick und Roll.

Jinxi
quelle
1
-1 Dies löst die Kardanverriegelung nicht, da Euler-Winkel (m_rotation) für den internen Orientierungsspeicher verwendet werden. Dieses Wiki erklärt warum.
Maik Semder