Я пишу программу, которая загружает файл, содержащий описание сцены, а затем отображает его с помощью 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