2013-04-30 7 views
4

Прежде всего, я не был уверен, что этот вопрос приветствуется здесь, и я проверил 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); 

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

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

+0

Является ли конверсия обратимой? I.e., что произойдет, если вы преобразуете углы Эйлера в кватернион и обратно, не изменяя их? Кроме того, нет ли ошибки в порядке аргументов в первой строке? Не должно быть 'input.x, input.y, input.z'? –

+0

Это кажется ошибкой, но это то, к чему я случайно придумал. Последовательный порядок, который вы считаете правильным, не работает. Я проверил, является ли обращение обратимым, а это не так. Например, углы Эйлера '2, 5, 52' возвращаются как« -3.15, 51.9, 5.56'. Но не знаю, представляет ли это тот же поворот. Насколько я знаю, существует бесконечный различный способ представления одного и того же вращения по углам Эйлера. – danijar

ответ

2

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

От GLM's source они используют тангаж, рыскание, крен:

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's documentation они используют рыскание, тангаж, крен.

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

+0

Таким образом, порядок углов Эйлера определенно является причиной. Вы знаете, как упростить конверсии? – danijar

+0

Хм, кажется, так просто, как может, честно. Просто напишите некоторые модульные тесты, чтобы убедиться, что вы не слишком много с ним связаны;) –

+0

Является ли мой код для вас разумным? Я сам себе не понимаю, почему это работает. – danijar