Question

First of all, I wasn't sure if this question is welcome here and I checked the FAQ and found out that "I would like others to explain" questions are.

The main issue is that I need to store rotations of all objects twice in my application. That is because on the one hand the physics simulation, where I use Bullet Physics for, stores its representation. On the other hand I store rotations on my own which all objects have in common regardless of whether they are in the physics simulation or not, like lights, quest targets, and so on. In addition to the physics library I make use of the GLM maths library.

I have to synchronize both representations. By the way, positions and scale don't make any problems. The difficulty is that physics simulation any my own representation are different, so I can't just copy values. I haven't found out all those differences but it may be related to left handed versus right handed coordinate system, degrees versus radians and Y coordinate up versus Z up.

My own representation simply stores Euler angles in a glm::vec3 vector. Since I use OpenGL for drawing, I guess the space is right handed. For euler angles, the order matters. What I do to calculate a rotation matrix is to first create a matrix of each component and then multiply those in X * Y * Z order. Moreover in my own representation, the positive Y coordinate points upwards.

The physics simulation uses quaternions to store rotations. After some research I read the assumption that space is left handed in this library. I have no information about which coordinate is up nor in which order euler angles are returned.

Here comes the code to convert rotations from physics simulation to my own representation and vice versa.

#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);

I found this dirty code by trial and error and it works. But as you can see there negations, component swizzling and type conversions via different quaternion types. I guess many of those are unnecessary and the task can be performed much simpler.

Could you please explain why my conversions do work and how to simplify them? By the way, I you want to see how it looks if the conversion doesn't work, here is a screenshot...

Était-ce utile?

La solution

Apparently there are a lot of different definitions of the Euler angles, and your two libraries use different conventions.

From GLM's source they use Pitch, Yaw, Roll :

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));
}

...while in Bullet's documentation they use Yaw, Pitch, Roll.

I haven't checked, but composing rotations is definitely not commutative, which would explain taking the negative values of some coordinates -- same as taking the inverse rotation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top