Эмуляция gluLookAt с glm::Quat(ernions)
Я пытался эмулировать функциональность gluLookAt, но с Quaternions. Каждый из моих игровых объектов имеет TranslationComponent. Этот компонент хранит позицию объекта (glm::vec3
), вращение (glm::quat
) и масштаб (glm::vec3
). Камера рассчитывает свою позицию каждый тик, выполняя следующие действия:
// UP = glm::vec3(0,1,0);
//FORWARD = glm::vec3(0,0,1);
cameraPosition = playerPosition - (UP * distanceUP) - (FORWARD * distanceAway);
Этот код положения работает как и положено, камера находится на 3 метра позади игрока и на 1 метр вверх. Теперь Quaternion камеры настроен на следующее:
//Looking at the player's feet
cameraRotation = quatFromToRotation(FORWARD, playerPosition);
Теперь механизм рендеринга принимает эти значения и генерирует ViewMatrix (камера) и ModelMatrix (проигрыватель), а затем визуализирует сцену. Код выглядит так:
glm::mat4 viewTranslationMatrix =
glm::translate(glm::mat4(1.0f), cameraTransform->getPosition());
glm::mat4 viewScaleMatrix =
glm::scale(glm::mat4(1.0f), cameraTransform->getScale());
glm::mat4 viewRotationMatrix =
glm::mat4_cast(cameraTransform->getRotation());
viewMatrix = viewTranslationMatrix * viewRotationMatrix * viewScaleMatrix;
quatFromToRotation (glm:: vec3 from, glm:: vec3 to) определяется следующим образом:
glm::quat quatFromToRotation(glm::vec3 from, glm::vec3 to)
{
from = glm::normalize(from); to = glm::normalize(to);
float cosTheta = glm::dot(from, to);
glm::vec3 rotationAxis;
if (cosTheta < -1 + 0.001f)
{
rotationAxis = glm::cross(glm::vec3(0.0f, 0.0f, 1.0f), from);
if (glm::length2(rotationAxis) < 0.01f)
rotationAxis = glm::cross(glm::vec3(1.0f, 0.0f, 0.0f), from);
rotationAxis = glm::normalize(rotationAxis);
return glm::angleAxis(180.0f, rotationAxis);
}
rotationAxis = glm::cross(from, to);
float s = sqrt((1.0f + cosTheta) * 2.0f);
float invis = 1.0f / s;
return glm::quat(
s * 0.5f,
rotationAxis.x * invis,
rotationAxis.y * invis,
rotationAxis.z * invis
);
}
У меня проблемы с тем, что CameraRotation настроен неправильно. Независимо от того, где находится игрок, впереди камеры всегда (0,0,-1)
1 ответ
Ваша проблема в линии
//Looking at the player's feet
cameraRotation = quatToFromRotation(FORWARD, playerPosition);
Вы должны смотреть из положения камеры на ноги игрока, а не "на один метр выше игрока" (при условии, что игрок находится на уровне (0,0,0), когда вы изначально делаете это). замещать FORWARD
с cameraPosition
:
cameraRotation = quatToFromRotation(cameraPosition, playerPosition);
РЕДАКТИРОВАТЬ Я полагаю, у вас есть ошибка в вашем quatToFromRotation
функция также. См. /questions/17061971/nahozhdenie-kvaterniona-predstavlyayuschego-vraschenie-ot-odnogo-vektora-k-drugomu/17061985#17061985 для очень хорошего объяснения (и некоторого псевдокода) вращения кватернионов.