Как избежать блокировки карданного подвеса

8

Я пытаюсь написать код с вращающимся объектом.

Я реализовал это как:

Вращение вокруг оси X определяется величиной изменения координат Y мыши, а вращение вокруг оси Y определяется величиной изменения координат X мыши.

Этот метод прост и работает нормально до тех пор, пока ось не совпадет с осью Z, короче говоря, происходит блокировка gimble.

Как я могу использовать вращение вокруг оси Z, чтобы избежать блокировки карданного подвеса.

singingsingh
источник
Краткий ответ: используйте кватернионы
Роберт Рухани
4
Кватернионы по-прежнему склонны к блокировке карданного подвеса, если вы используете их неправильно - это не то, что вы используете для представления своих вращений, а объединение нескольких вращений, которые вызывают его. Так что не объединяйте вращения.
Максимус Минимус
Что касается моего предыдущего комментария, см. Комментарий Майка Земдера на gamedev.stackexchange.com/questions/23540/…
Maximus Minimus
Я собирался написать тот же комментарий снова, спасибо, что нашли его @ mh01 :)
Maik Semder

Ответы:

14

Простое решение - не сохранять ориентацию объекта в виде углов вокруг осей (осей X, Y, Z), как, например, в углах Эйлера.

Сохраните ориентацию объекта в виде матрицы или кватерниона.

Это может вызвать блокировку карданного подвеса, используя углы Эйлера:

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

Нет карданного замка:

class Object
{
    matrix m_orientation;   
};

Также нет блокировки карданного подвеса:

class Object
{
    quaternion m_orientation;   
};

Теперь, когда мышь изменяется, умножьте m_orientation на изменение ориентации, возникающее при движении мыши в каждом кадре.

Майк Земдер
источник
0

Эта книга (рендеринг в реальном времени) очень мне помогла! Смотрите на страницах 66 и 70. У него очень хорошая графика и объяснение. Кватернионы на странице 72 также! :)

Вращение вокруг произвольной оси

Это рендерит камеру с поворотом, сделанным с помощью мыши:

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

С помощью мыши вы изменяете рыскание (голову), тангаж и крен.

Цзиньси
источник
1
-1 Это не решает проблему блокировки карданного подвеса, поскольку для хранения внутренней ориентации используются углы Эйлера (m_rotation). Эта вики объясняет почему.
Maik Semder