То, к чему я пришел путем проб и ошибок, не могли бы вы объяснить, почему?

Прежде всего, я не был уверен, что этот вопрос приветствуется здесь, и я проверил FAQ и обнаружил, что "я хотел бы, чтобы другие объясните" вопросы.

Основная проблема заключается в том, что мне нужно дважды сохранять повороты всех объектов в моем приложении. Это связано с тем, что, с одной стороны, физическое моделирование, для которого я использую Bullet Physics, сохраняет его представление. С другой стороны, я храню собственные повороты, общие для всех объектов, независимо от того, находятся ли они в физической симуляции или нет, например, источники света, цели квестов и так далее. В дополнение к физической библиотеке я использую математическую библиотеку GLM.

Я должен синхронизировать оба представления. Кстати, с позициями и масштабом проблем нет. Сложность в том, что симуляция физики и мое собственное представление отличаются, поэтому я не могу просто скопировать значения. Я не обнаружил всех этих различий, но это может быть связано с левой и правой системой координат, градусами и радианами и координатой Y вверх по сравнению с Z вверх.

Мое собственное представление просто хранит углы Эйлера в векторе glm::vec3. Поскольку я использую OpenGL для рисования, я предполагаю, что пространство правостороннее. Для углов Эйлера порядок имеет значение. Что я делаю для вычисления матрицы вращения, так это сначала создаю матрицу каждого компонента, а затем умножаю их в порядке X * Y * Z. Более того, в моем собственном представлении положительная координата Y указывает вверх.

Моделирование физики использует кватернионы для хранения вращений. После некоторых исследований я прочитал предположение, что пространство в этой библиотеке левостороннее. У меня нет информации о том, какая координата выше и в каком порядке возвращаются углы Эйлера.

Вот код для преобразования вращения из физического моделирования в мое собственное представление и наоборот.

#include <GLM/glm.hpp>
#include <GLM/gtc/quaternion.hpp>
#include <BULLET/btBulletDynamicsCommon.h>

/*******************************************************************
 * euler angles "glm::vec3 input" from my own representation
 * to quaternion "btQuaternion output" of physics simulation
 *******************************************************************/
glm::quat quaternion(glm::vec3(input.x, input.z, input.y) * 3.14159f / 180.f);
btQuaternion output(quaternion.x, quaternion.y, quaternion.z, quaternion.w);

/*******************************************************************
 * quaternion "btQuaternion input" from physics simulation
 * to euler angles "glm::vec3 output" of my own representation
 *******************************************************************/
glm::quat quaternion(input.getW(), -input.getX(), -input.getY(), -input.getZ());
glm::vec3 angles = glm::eulerAngles(quaternion);
glm::vec3 output(-angles.x, -angles.y, -angles.z);

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

Не могли бы вы объяснить, почему мои преобразования работают и как их упростить? Кстати, я хочу посмотреть, как это выглядит, если преобразование не работает, вот скриншот...


person danijar    schedule 30.04.2013    source источник
comment
Является ли преобразование обратимым? То есть, что произойдет, если вы преобразуете свои углы Эйлера в кватернион и обратно, не изменяя их? Кроме того, нет ли ошибки в порядке аргументов в первой строке? Разве это не должно быть input.x, input.y, input.z?   -  person F.X.    schedule 30.04.2013
comment
Это похоже на ошибку, но это то, что я случайно придумал. Последовательный порядок, который вы считали правильным, не работает. Я проверил, является ли преобразование обратимым, и это не так. Например, углы Эйлера 2, 5, 52 возвращаются как -3.15, 51.9, 5.56. Но не знаю, представляет ли это то же вращение. Насколько я знаю, существует бесконечное множество способов представить одно и то же вращение углами Эйлера.   -  person danijar    schedule 30.04.2013


Ответы (1)


По-видимому, существует множество различных определений углов Эйлера. две библиотеки используют разные соглашения.

Из источника GLM они используют Pitch , рыскание, вращение :

template <typename T> 
GLM_FUNC_QUALIFIER detail::tvec3<T> eulerAngles
(
    detail::tquat<T> const & x
)
{
    return detail::tvec3<T>(pitch(x), yaw(x), roll(x));
}

...в то время как в документации Bullet используется Yaw, Pitch, Roll .

Я не проверял, но составление вращений определенно не коммутативно, что объясняет отрицательные значения некоторых координат — так же, как и обратное вращение.

person F.X.    schedule 30.04.2013
comment
Таким образом, порядок углов Эйлера определенно является причиной. Вы знаете, как упростить преобразования? - person danijar; 30.04.2013
comment
Хм, это кажется настолько простым, насколько это возможно, честно. Просто напишите несколько модульных тестов, чтобы потом не возиться с этим слишком много;) - person F.X.; 30.04.2013
comment
Мой код кажется вам разумным? Я лично не понимаю, почему это работает. - person danijar; 01.05.2013
comment
Для первого преобразования имеет смысл, если две координатные оси имеют разную направленность, т. е. вы используете XYZ, тогда вам нужно преобразовать в другую направленность (XZY), а затем создать кватернион из этих углов. - person F.X.; 01.05.2013
comment
На самом деле, оглядываясь назад на мой ответ, он может быть неточным. Здесь что-то еще в игре, и я не могу понять, что. Есть ли причина, по которой вы не можете использовать кватернионы полностью, поскольку они не зависят от хиральности? - person F.X.; 01.05.2013
comment
Да, я хочу использовать углы Эйлера в интерфейсе, потому что их легче представить, скажем, художникам и скриптерам. Благодаря вашему объяснению я теперь тоже понимаю первое преобразование. К сожалению, второй до сих пор не ясен. - person danijar; 02.05.2013
comment
Я вижу вашу точку зрения. Честно говоря, я до сих пор не очень понимаю, как все это работает, вам придется углубиться в математику, чтобы сделать это. Но разве вы не можете просто хранить и использовать кватернионы внутри и преобразовывать их только в том случае, если вы показываете их пользователю? Вам будет намного легче, поскольку вам придется иметь дело только с одним типом переменных. Более того, с математической точки зрения они гораздо более естественно обрабатывают повороты, чем углы Эйлера. - person F.X.; 03.05.2013
comment
Я учту это. Спасибо за вашу помощь. - person danijar; 03.05.2013