I need the heading (i.e. rotation around up axis) from a rotation, and since the euler functions restrict the returned heading to be between -90 and 90 degrees (I need between -180 and 180), I decided to try using quaternions directly (with which I am not too familiar).
I tried using a unit vector (facing in the original direction of the rigib body, i.e. (0,0,1)) and multiply it with the rotation quaternion as contained in the transform of the body, e.g.:
Code: Select all
btTransform trans;
m_body->getMotionState()->getWorldTransform(trans);
btQuaternion q =trans.getRotation();
btVector3 forward(0,0,1);
btVector3 direction = quatRotate(cur, forward);
(atan2(direction.getX(), direction,getZ()). I hope this approach makes sense
Unfortunately, quatRotate does not return what I expect it to return. If for example the rotation is the identity (q=(0,0,0,1)), I would expect that the result 'direction' is still (0,0,1). But in fact it is (0,0,-1). On the other hand, if I use the matrix instead (get the basis from the world transform, and multiply it with the forward vector), everything works as expected.
I think my problem can be summarised in the simple test case:
Code: Select all
btQuaternion q;
btMatrix3x3 m;
m.setIdentity();
m.getRotation(q);
btVector3 v(0,0,1);
btVector3 v2 = quatRotate(q,v); // should be v pointing in the current direction
btVector3 v3 = m*v; // I expect this to be the same
printf("q=(%f %f %f %f) * v=(%f %f %f) = %f %f %f\n",
q.getX(), q.getY(), q.getZ(), q.getW(),
v.getX(),v.getY(),v.getZ(),
v2.getX(),v2.getY(),v2.getZ());
printf("matrix*vector= %f %f %f\n",
v3.getX(),v3.getY(),v3.getZ());
Code: Select all
q=(0.000000 0.000000 0.000000 1.000000) * v=(0.000000 0.000000 1.000000) = 0.000000 0.000000 -1.000000
matrix*vector= 0.000000 0.000000 1.000000
I can get the expected behaviour if I change bQuaternion::inverse() to return:
(-m_x, -m_y, -m_y, m_unusedW) instead of (m_x, m_y, m_z, -m_unusedW).
But not having too much an idea about quaternions, I am not sure what I am doing
Is my original idea simply wrong of using quaternions the way I did?
Besides, what is actually faster? After studying the bullet code I realised that btTransform is actually using a matrix (and not a quaternion as I suspected), so the quaternion is not the 'natural' data structure. And I guess that converting the matrix to a quaternion before the multiplication is actually more expensive than just multiplying the matrix by the vector.
Cheers,
Joerg