Обведите камеру вокруг сферы, глядя в центр (используя кватернионы) - PullRequest
1 голос
/ 12 февраля 2012

Я посмотрел тонну примеров кватернионов на нескольких сайтах, включая этот, но не нашел ни одного, который бы отвечал на это, так что вот так ...

Я хочу развернуть свою камеру вокруг большой сферы, икамера всегда должна быть в центре сферы.Чтобы упростить задачу, сфера находится в мире {0,0,0}.Я использую кватернион для ориентации камеры и вектор для положения камеры.Проблема заключается в том, что положение камеры вращается вокруг сферы идеально, как и должно, но всегда смотрит в одно постоянное направление прямо вперед, а не регулируется так, чтобы указывать на центр, когда она вращается.

Это должно быть что-то простое, но я новичок в кватернионах ... что мне не хватает?

Я использую C ++, DirectX9.Вот мой код:

// Note: g_camRotAngleYawDir and g_camRotAnglePitchDir are set to either 1.0f, -1.0f according to keypresses, otherwise equal 0.0f
// Also, g_camOrientationQuat is just an identity quat to begin with.

float theta = 0.05f;
D3DXQUATERNION g_deltaQuat( 0.0f, 0.0f, 0.0f, 1.0f );
D3DXQuaternionRotationYawPitchRoll(&g_deltaQuat, g_camRotAngleYawDir * theta, g_camRotAnglePitchDir * theta, g_camRotAngleRollDir * theta);
D3DXQUATERNION tempQuat = g_camOrientationQuat;
D3DXQuaternionMultiply(&g_camOrientationQuat, &tempQuat, &g_deltaQuat);

D3DXMatrixRotationQuaternion(&g_viewMatrix, &g_camOrientationQuat);
g_viewMatrix._41 = g_camPosition.x;
g_viewMatrix._42 = g_camPosition.y;
g_viewMatrix._43 = g_camPosition.z;

g_direct3DDevice9->SetTransform( D3DTS_VIEW, &g_viewMatrix );

[РЕДАКТИРОВАТЬ - 13 февраля 2012]

Хорошо, вот мое понимание:

перемещайте камеру, используя угловую дельту каждыйРамка.Получить вектор из центра в камеру-поз.Вызовите quaternionRotationBetweenVectors с вектором, обращенным к z, и целевым вектором.Затем используйте результат этой функции для ориентации матрицы вида, и положение камеры переходит в часть перевода матрицы вида.

Вот новый код (называемый каждым кадром) ...

//  This part orbits the position around the sphere according to deltas for yaw, pitch, roll
D3DXQuaternionRotationYawPitchRoll(&deltaQuat, yawDelta, pitchDelta, rollDelta);

D3DXMatrixRotationQuaternion(&mat1, &deltaQuat);

D3DXVec3Transform(&g_camPosition, &g_camPosition, &mat1);

// Эта часть настраивает ориентацию камеры так, чтобы она указывала на центр сферы

dir1 = normalize(vec3(0.0f, 0.0f, 0.0f) - g_camPosition);

QuaternionRotationBetweenVectors(&g_camOrientationQuat, vec3(0.0f, 0.0f, 1.0f), &dir1);


D3DXMatrixRotationQuaternion(&g_viewMatrix, &g_camOrientationQuat);

g_viewMatrix._41 = g_camPosition.x;
g_viewMatrix._42 = g_camPosition.y;
g_viewMatrix._43 = g_camPosition.z;


g_direct3DDevice9->SetTransform( D3DTS_VIEW, &g_viewMatrix );

... Я попробовал это решение, но безуспешно.Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 12 февраля 2012

Это должно быть так же просто, как делать следующее при обновлении положения (при условии, что камера направлена ​​вдоль оси z):

direction = normalize(center - position)
orientation = quaternionRotationBetweenVectors(vec3(0,0,1), direction)

Довольно легко найти примеры того, как реализовать quaternionRotationBetweenVectors. Вы можете начать с вопроса " Нахождение кватерниона, представляющего вращение от одного вектора к другому ".

Вот непроверенный эскиз реализации с использованием DirectX9 API:

D3DXQUATERNION* quaternionRotationBetweenVectors(__inout D3DXQUATERNION* result, __in const D3DXVECTOR3* v1, __in const D3DXVECTOR3* v2)
{
    D3DXVECTOR3 axis;

    D3DXVec3Cross(&axis, v1, v2);
    D3DXVec3Normalize(&axis, &axis);

    float angle = acos(D3DXVec3Dot(v1, v2));

    D3DXQuaternionRotationAxis(result, &axis, angle);

    return result;
}

Эта реализация ожидает нормализации v1, v2.

0 голосов
/ 12 февраля 2012

Вам нужно показать, как вы рассчитываете углы.Есть ли причина, по которой вы не используете D3DXMatrixLookAtLH?

...