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?


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.


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.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.