4

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...

genpfault
  • 51,148
  • 11
  • 85
  • 139
danijar
  • 32,406
  • 45
  • 166
  • 297
  • Is the conversion reversible? I.e., what happens if you convert your euler angles to a quaternion and back again without modifying them? Also, isn't there a mistake in the order of the arguments in the first line? Shouldn't it be `input.x, input.y, input.z`? – F.X. Apr 30 '13 at 09:40
  • It seems like a mistake but this is what I randomly came up with. The sequential order as you assumed to be correct doesn't work. I checked if the conversion is reversible and it isn't. For example the euler angles `2, 5, 52` come back as `-3.15, 51.9, 5.56`. But don't know if that represents the same rotation. As far as I know there are infinite different way to represent the same rotation by euler angles. – danijar Apr 30 '13 at 10:30

1 Answers1

2

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.

F.X.
  • 6,809
  • 3
  • 49
  • 71
  • So euler angle order is definitely a reason. Do you know how to simplify the conversions? – danijar Apr 30 '13 at 11:23
  • Hm, it seems as simple as it can get, honestly. Just write some unit tests to ensure you don't mess with it too much afterwards ;) – F.X. Apr 30 '13 at 11:29
  • Does my code seem reasonable to you? I for myself don't understand why it works. – danijar May 01 '13 at 12:54
  • For the first conversion, it makes sense if the two coordinate axes are of different handedness, i.e. you're using XYZ, then you have to convert to a different handedness (XZY) then create a quaternion from those angles. – F.X. May 01 '13 at 13:18
  • Actually, looking back at my answer it might not be accurate. There's something else at play here, and I can't figure out what. Is there a reason why you can't use quaternions all the way, since they don't depend on handedness? – F.X. May 01 '13 at 13:41
  • Yes, I want to use euler angles in the interface because they are easier to imagine, say for artists and scripters. Thanks to your explanation, I do understand the first conversion now, too. Unfortunately the second one is still unclear. – danijar May 02 '13 at 17:54
  • I see your point. Honestly I still don't really understand how the whole thing works, you'll have to delve into the math to do that. But can't you just store and use quaternions internally and only convert them if you display them to the user? It'll be a whole lot easier on your mind since you'll only have to deal with one type of variable. What's more, they handle rotations a lot more naturally, mathematically speaking, than Euler angles. – F.X. May 02 '13 at 20:49
  • I will consider that. Thanks for your help. – danijar May 02 '13 at 22:20