Я пишу программу, которая загружает файл, содержащий описание сцены, а затем отображает его с помощью OpenGL. Я использую GLM для всех своих математических операций. Повороты в файле сцены хранятся в кватернионном формате. Моя система управления сценой принимает повороты для объектов в форме углов Эйлера, и эти углы позже преобразуются в матрицу вращения при рисовании.
Таким образом, мой процесс загрузки берет кватернионные вращения, преобразует их в углы Эйлера для хранения в моем классе объектов, а затем преобразует эти углы Эйлера в матрицы вращения для рисования. Я использую функции glm :: eulerAngles и glm :: eulerAngleYXZ (соответственно) для выполнения этих двух операций.
Однако я получаю неверные результаты. Например, если я правильно понимаю, кватернион {0,500 -0,500 0,500 0,500} (это W X Y Z) должен описывать вращение, принимая стрелку от оси + Z к оси + Y. Однако когда я запускаю программу, я получаю стрелку, указывающую вдоль оси + X.
Я бы предположил, что в моем понимании кватернионов есть некоторый изъян, но я могу получить ожидаемые результаты, пропустив промежуточную форму угла Эйлера. Преобразуя кватернион напрямую в матрицу вращения с помощью glm :: toMat4, я получаю вращение, которое указывает стрелку + Z на + Y.
У меня проблемы с согласованием этих двух разных результатов, учитывая, что оба метода кажутся простыми и правильными. Чтобы упростить мой вопрос, почему эти два, казалось бы, эквивалентных метода дают разные результаты:
glm::quat q(.5, -.5, .5, .5);
glm::vec3 euler = glm::eulerAngles(q) * 3.14159f / 180.f; // eulerAngleYXZ takes radians but eulerAngles returns degrees
glm::mat4 transform1 = glm::eulerAngleYXZ(euler.y, euler.x, euler.z);
// transform1 rotates a +Z arrow so that it points at +X
glm::quat q(.5, -.5, .5, .5);
glm::mat4 transform2 = glm::toMat4(q);
// transform2 rotates a +Z arrow so that it points at +Y
glm::eulerAngles(q)
возвращает результат в радианах. См.glm/gtc/quaternion.hpp
. - person wardw   schedule 31.07.2020