BUG in (NxOgre::Body*)->getGlobalOrientation()???

MarioFrost

12-12-2007 18:11:40

I think there's a bug in the function (NxOgre::Body*)->getGlobalOrientation().
I have compare this function with the one from OGRE, (Ogre::SceneNode*)->getWorldOrientation(); while I rotate a NxOgre::Body.

The bug seams to appear near the inversion of the signs in the quaternions.

Quaternion q1 = (NxOgre::Body*)->getNode()->getWorldOrientation();
Quaternion q2 = (NxOgre::Body*)->getGlobalOrientation();

OUTPUT : ([q1] [q2])


...
[0.773489 0 -0.633809 0] [0.773489 0 -0.633809 0]
[0.715037 0 -0.699086 0] [0.715037 0 -0.699087 0]
[0.664299 0 -0.747467 0] [0.6643 0 -0.747467 0]
[0.610297 0 -0.792173 0] [0.610297 0 -0.792173 0]
[0.538608 0 -0.842557 0] [0.538608 0 -0.842557 0]
[-0.478252 0 0.878223 0] [0.478252 0 -0.878223 0] <<<<< q1 dot q2 = -1
[-0.415545 0 0.909572 0] [-0.415545 0 0.909572 0]
[-0.334327 0 0.942457 0] [-0.334327 0 0.942457 0]
[-0.267474 0 0.963565 0] [-0.267474 0 0.963565 0]
[-0.182098 0 0.98328 0] [-0.182098 0 0.98328 0]
[-0.112758 0 0.993622 0] [-0.112758 0 0.993622 0]
...


When you use NxOgre Orientation, you perform conversion to Axes and finally to Quaternion and you don't get the same Quaternion values! :


Vector3 u[3];
Vector3 v[3];

// Conversion from Quaternion Q1 to Axes U
// [0.517589 0 -0.855629 0]
Quaternion q1 = Quaternion(0.458079, 0, -0.888912, 0); // Value from (NxOgre::Body*)->getGlobalOrientation();
q1.normalise();
q1.ToAxes(u);

// Conversion from Axes U to Quaternion Q2
Quaternion q2 = Quaternion(u);

// Conversion from Quaternion Q2 to Axes V
q2.ToAxes(v);

// Dot product
Real dot1 = q1.Dot(q2);


and the output:


QUAT q1 [0.458079 0 -0.888912 0]
VECTOR u x[-0.580328 0 0.814383]
VECTOR u y[-0 1 0]
VECTOR u z[-0.814383 -0 -0.580328]

QUAT q2 [-0.458079 0 0.888912 0]
VECTOR v x[-0.580328 0 0.814383]
VECTOR v y[0 1 0]
VECTOR v z[-0.814383 0 -0.580328]

q1 DOT q2 [-1]


The axes are the same but the quaternions are inverted. It looks like the value form (NxOgre::Body*)->getGlobalOrientation() is not a valid quaternion for Ogre...

any ideas?


thank you for you help!

betajaen

12-12-2007 18:31:33

This is the complete source of Actor::getGlobalPosition() and toQuaternion().

Ogre::Quaternion Actor::getGlobalOrientation() {
return toQuaternion(mActor->getGlobalOrientationQuat());
}


inline Ogre::Quaternion toQuaternion(const NxQuat& q) {
return Ogre::Quaternion(q.w, q.x, q.y, q.z);
}


Perhaps you can tell me where I have gone wrong.

MarioFrost

12-12-2007 20:27:33

Hi betajaen,

Thank you for the fast answer! ;)

Well, I made this test:


Ogre::Quaternion Actor::getGlobalOrientation()
{
NxMat33 m = mActor->getGlobalOrientation();
NxQuat q = mActor->getGlobalOrientationQuat();

Ogre::Matrix3 mOgre = Ogre::Matrix3(
m(0,0), m(0,1), m(0,2),
m(1,0), m(1,1), m(1,2),
m(2,0), m(2,1), m(2,2));

Ogre::Quaternion q1 = toQuaternion(q);
Ogre::Quaternion q2 = Ogre::Quaternion(mOgre);

assert(q1.Dot(q2) > 0); // THIS IS FALSE when if I turn right at a certain point (yaw at approximately 100 degrees)
// This is when the signs are inverted! dot = -1

return toQuaternion(q);
}



The conversion from NxQuat to Ogre::Quaternion is different if you use Matrix... it may be a bug in Ogre...

So you should use something like that:



Ogre::Quaternion Actor::getGlobalOrientation()
{
NxMat33 m = mActor->getGlobalOrientation();

return Ogre::Quaternion(
Ogre::Matrix3(
m(0,0), m(0,1), m(0,2),
m(1,0), m(1,1), m(1,2),
m(2,0), m(2,1), m(2,2)
)
);
}


to make NxQuaternions compatible with Ogre

Unfortunately, This is not very optimized...

I will search further for a better solution... The quaternions of Ogre seems to be calculated differently that those of PhysX...

What do you think ?

Thank you again!