Я пытался эмулировать функциональность 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 из, glm :: vec3 в) определяется как следующее:
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)
Ваша проблема в линии
//Looking at the player's feet
cameraRotation = quatToFromRotation(FORWARD, playerPosition);
Вам нужно посмотреть из положения камеры к ногам игрока — не от «одного метра над игроком» (при условии, что игрок находится на (0,0,0), когда вы изначально делаете это). замещать FORWARD
с cameraPosition
:
cameraRotation = quatToFromRotation(cameraPosition, playerPosition);
РЕДАКТИРОВАТЬ Я полагаю, у вас есть ошибка в вашем quatToFromRotation
функция также. Увидеть https://stackoverflow.com/a/11741520/1967396 за очень хорошее объяснение (и некоторый псевдокод) вращения кватернионов.
Других решений пока нет …