I have been doing this kind of conversions for quite some time now, but I am not so sure anymore, if it's 100% correct or just working regardless somehow...
Just by experimenting I found that I get good results if for PhysX->Irrlicht I simply build the new quaternion from the componens of the other, and in the other direction I use makeInverse afterwards - but that just can't be right.
First of all, is there a way to switch the Irrlicht CS to a left-handed one? That would be the easiest, of course.
If not, I need to find a way to correctly convert quaternion-rotations between both systems, mainly for communication between Irrlicht and PhysX. I have been testing a bit now, but the first problem is that I don't even know for sure, how to tell wether the conversion is right or not. I mean, the Z-axis being inverted probably has an impact on the rotation-directions and I can't just assume that any clockwise rotation in one system should result in a clockwise rotation in the other. So even though I check orientations in Irrlicht and the PhysX Visual Debugger, I am not so sure what to make of it.
On a side-note: can anyone explain to me why you are able to read the transform-matrix of scene-nodes but not set it? Because always having to use euler-angles seems very unreliable to me and of course there's the gimble-lock problem.
Quaternion-conversion between LH and RH coordinate systems
Re: Quaternion-conversion between LH and RH coordinate syste
We use a left-handed system in Irrlicht. But there was a bug in some of the quaternion conversion functions until just a few weeks ago. The fix for that is so far only available in the newest Irrlicht svn trunk version (aka Irrlicht 1.8). If you start a project now I would recommend working with that anyway. You can get it from our svn server or as nightly build from here: ttp://irrlicht.convextech.ca/
And the matrices.. well, Irrlicht internally saves position, rotation, scale and rebuilds the transformation matrix from those. As a workaround when you need to set matrices directly you can add a IDummyTransformationNode as parent of your real node: http://irrlicht.sourceforge.net/docu/cl ... _node.html
That basically does add one transformation matrix, but note that the one from the real node is still calculated as well, so it's a little more expensive. And well, the reason is pretty much that this is how it was coded once... I think we have even some patch-discussion going on about that on the bugtracker.
And the matrices.. well, Irrlicht internally saves position, rotation, scale and rebuilds the transformation matrix from those. As a workaround when you need to set matrices directly you can add a IDummyTransformationNode as parent of your real node: http://irrlicht.sourceforge.net/docu/cl ... _node.html
That basically does add one transformation matrix, but note that the one from the real node is still calculated as well, so it's a little more expensive. And well, the reason is pretty much that this is how it was coded once... I think we have even some patch-discussion going on about that on the bugtracker.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Re: Quaternion-conversion between LH and RH coordinate syste
Thanks a lot for the info. My project has been WIP since a couple of years now (and probably will be for a couple of years to come) and I've ported to every new release since the beginning, starting with 1.6 I believe. So that shouldn't be the problem. Maybe I will look into the latest version soon.
About the coordinate systems, I probably confused the two orientations, but I would still very much appreciate if someone could answer my original question about the conversion of quaternions between LH and RH, maybe there is no special conversion needed at all?... or maybe some uses PhysX as well and knows how to properly convert transformations between both engines otherwise.
Btw: I am not sure wether it's a bug or not - I don't understand anything about the underlying math -, but when I extract euler-angles from a node's transformation matrix or quaternion constructed from that matrix, and then re-apply those via setRotation, it seems that Y-rotations between 90 and 270° don't get converted properly, and "turn back" after those angles. Meaning that a node that constantly turns around the Y-axis and gets its rotation read and re-applied in that way on every frame will get stuck at those angles (but not when you read the euler-angles from the node directly). If however, I use that same matrix/quaternion to apply the rotation to the connected PhysX-Object, that problem doesn't occur. Maybe that's what you were talking about... as I said, don't understand much about it.
About the coordinate systems, I probably confused the two orientations, but I would still very much appreciate if someone could answer my original question about the conversion of quaternions between LH and RH, maybe there is no special conversion needed at all?... or maybe some uses PhysX as well and knows how to properly convert transformations between both engines otherwise.
Btw: I am not sure wether it's a bug or not - I don't understand anything about the underlying math -, but when I extract euler-angles from a node's transformation matrix or quaternion constructed from that matrix, and then re-apply those via setRotation, it seems that Y-rotations between 90 and 270° don't get converted properly, and "turn back" after those angles. Meaning that a node that constantly turns around the Y-axis and gets its rotation read and re-applied in that way on every frame will get stuck at those angles (but not when you read the euler-angles from the node directly). If however, I use that same matrix/quaternion to apply the rotation to the connected PhysX-Object, that problem doesn't occur. Maybe that's what you were talking about... as I said, don't understand much about it.
Re: Quaternion-conversion between LH and RH coordinate syste
Quaternions themself have no orientation, it's the conversion functions that decide in which direction you rotate. So given an axis+angle for example the angle can mean rotate left or right (so to switch you can just use the negative angle instead or flip the axis). But generally we use left-handed rotation throughout in Irrlicht - except this was broken in quaternions until just recently and we had some rotations going left-handed and some right-handed. It's fixed now in latest svn (hopefullly) - so anything you try with 1.7 might be giving plain confusing results, which is why you should switch to svn trunk before trying to figure out in which direction you need to rotate.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Re: Quaternion-conversion between LH and RH coordinate syste
After some browsing, I found sources suggesting that
- a positive rotation in a left-handed cs is clockwise around the axis of rotation
- whereas a positive rotation in a right-handed cs is counterclockwise
- and that a quaternion can be converted between a left- and a right-handed cs by negating the z-component
But on the other hand, I don't think I need to do any such conversions after all, because up to this point I didn't bother that my graphics and physics live in mirrored parallel universes and there is probably no need to try and make one fit onto the other. I guess that would only serve cosmetical purposes. And I never converted translations either. I should probably make sure however, that rotation-directions in both engines really are opposite to each other.
So please correct me if I'm wrong, but I think I should be fine if I "convert" between Irrlicht- and PhysX-quaternions by simply building them from each other's unmodified x,y,z,w-components.
I will get version 1.8 next and see if that solves the transform-problems I'm having.
- a positive rotation in a left-handed cs is clockwise around the axis of rotation
- whereas a positive rotation in a right-handed cs is counterclockwise
- and that a quaternion can be converted between a left- and a right-handed cs by negating the z-component
But on the other hand, I don't think I need to do any such conversions after all, because up to this point I didn't bother that my graphics and physics live in mirrored parallel universes and there is probably no need to try and make one fit onto the other. I guess that would only serve cosmetical purposes. And I never converted translations either. I should probably make sure however, that rotation-directions in both engines really are opposite to each other.
So please correct me if I'm wrong, but I think I should be fine if I "convert" between Irrlicht- and PhysX-quaternions by simply building them from each other's unmodified x,y,z,w-components.
I will get version 1.8 next and see if that solves the transform-problems I'm having.
Re: Quaternion-conversion between LH and RH coordinate syste
Yes, I think quaternions should be identical (note that my information about quaternions is also mostly from Wikipedia + some discussions with Hybrid recently).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Re: Quaternion-conversion between LH and RH coordinate syste
Thanks again for pointing out that quaternion bug to me cuteAlien!
I just downloaded the latest version and so far everything indicates that the problems with quaternion and matrix-transforms I was having are now solved. I also got rid of the unexplicable quaternion.makeInverse-call, I guess that was only needed to compensate for that bug.
There seem to be very few interface-changes since 1.7.4, so an actual port of the code wasn't even necessary.
I just downloaded the latest version and so far everything indicates that the problems with quaternion and matrix-transforms I was having are now solved. I also got rid of the unexplicable quaternion.makeInverse-call, I guess that was only needed to compensate for that bug.
There seem to be very few interface-changes since 1.7.4, so an actual port of the code wasn't even necessary.
Re: Quaternion-conversion between LH and RH coordinate syste
Not sure how I missed this thread. I have the same problem. I am using a 3 weeks old SVN version of Irrlicht 1.8 and 3.2.1 Physx SDK. I am writing a wrapper generic to many Physics Engines. I already added Bullet and Tokamak and now adding Physx 3.2.1.
The problem I face with Physx is, very similar to one discussed here. However, I'll explain it again just to make sure.
Am passing transformation from Irrlicht when Physx objects are built with the following code.
And after iterating physics for each frame, I do the following to sync Irrlicht nodes to Physx objects.
The problem I get is:
Objects that rotate on Y axis in Physx don't sync correctly. Mostly they rotate in the wrong direction. When I profile the physx and see it using viewer, I see the whole physx world looks mirrored in X axis. (What I see on left should be on right.). Am not sure where have I gone wrong.
The problem I face with Physx is, very similar to one discussed here. However, I'll explain it again just to make sure.
Am passing transformation from Irrlicht when Physx objects are built with the following code.
Code: Select all
PxQuat GetQuatFromRotation(vector3df rot) {
float cos_z = cosf(0.5 * rot.Z * 3.1415f / 180.0f);
float cos_y = cosf(0.5 * rot.Y * 3.1415f / 180.0f);
float cos_x = cosf(0.5 * rot.X * 3.1415f / 180.0f);
float sin_z = sinf(0.5 * rot.Z * 3.1415f / 180.0f);
float sin_y = sinf(0.5 * rot.Y * 3.1415f / 180.0f);
float sin_x = sinf(0.5 * rot.X * 3.1415f / 180.0f);
PxQuat q;
q.w = cos_z*cos_y*cos_x + sin_z*sin_y*sin_x;
q.x = cos_z*cos_y*sin_x - sin_z*sin_y*cos_x;
q.y = cos_z*sin_y*cos_x + sin_z*cos_y*sin_x;
q.z = sin_z*cos_y*cos_x - cos_z*sin_y*sin_x;
return q;
}
Code: Select all
vector3df GetRotationFromPhysx(PxQuat q) {
/* Try #1
float sqw = q.w * q.w;
float sqx = q.x * q.x;
float sqy = q.y * q.y;
float sqz = q.z * q.z;
float unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
float test = q.x * q.y + q.z * q.w;
float heading, attitude, bank;
if (test > 0.499f * unit) { // singularity at north pole
heading = 2.0f * (float)atan2(q.x, q.w);
attitude = (float)3.1415f / 2.0f;
bank = 0.0f;
} else if (test < -0.499 * unit) { // singularity at south pole
heading = -2.0f * (float)atan2(q.x, q.w);
attitude = -(float)3.1415f / 2.0f;
bank = 0.0f;
} else {
heading = (float)atan2(2.0f * q.y * q.w - 2.0f * q.x * q.z, sqx - sqy - sqz + sqw);
attitude = (float)asin(2.0f * test / unit);
bank = (float)atan2(2.0f * q.x * q.w - 2.0f * q.y * q.z, -sqx + sqy - sqz + sqw);
}
return vector3df(bank * 180.0f / 3.1415f, heading * 180.0f / 3.1415f, attitude * 180.0f / 3.1415f);
*/
/* Try #2
vector3df v;
v.X = atan2(2 * q.y * q.w - 2 * q.x * q.z,
1 - 2 * pow(q.y, 2) - 2*pow(q.z, 2));
v.Y = asin(2*q.x*q.y + 2*q.z*q.w);
v.Z = atan2(2*q.x*q.w-2*q.y*q.z,
1 - 2*pow(q.x, 2) - 2*pow(q.z, 2));
if(q.x*q.y + q.z*q.w == 0.5) {
v.X = (float)(2 * atan2(q.x,q.w));
v.Z = 0;
} else if(q.x*q.y + q.z*q.w == -0.5) {
v.X = (float)(-2 * atan2(q.x, q.w));
v.Z = 0;
}
return vector3df(v.X* 180.0f / 3.1415f, v.Y* 180.0f / 3.1415f, v.Z* 180.0f / 3.1415f);
*/
const float Epsilon = 0.0009765625f;
const float Threshold = 0.5f - Epsilon;
float yaw;
float pitch;
float roll;
float XY = q.x * q.y;
float ZW = q.z * q.w;
float TEST = XY + ZW;
if (TEST < -Threshold || TEST > Threshold) {
int sign = TEST>0?1:-1;
yaw = sign * 2 * (float)atan2(q.x, q.w);
pitch = sign * 3.14159 / 2.0f;
roll = 0;
} else {
float XX = q.x * q.x;
float XZ = q.x * q.z;
float XW = q.x * q.w;
float YY = q.y * q.y;
float YW = q.y * q.w;
float YZ = q.y * q.z;
float ZZ = q.z * q.z;
yaw = (float)atan2(2 * YW - 2 * XZ, 1 - 2 * YY - 2 * ZZ);
pitch = (float)atan2(2 * XW - 2 * YZ, 1 - 2 * XX - 2 * ZZ);
roll = (float)asin(2 * TEST);
}
return vector3df(pitch* 180.0f / 3.1415f, yaw* 180.0f / 3.1415f, roll* 180.0f / 3.1415f) + vector3df(360, 360, 360);
}
Objects that rotate on Y axis in Physx don't sync correctly. Mostly they rotate in the wrong direction. When I profile the physx and see it using viewer, I see the whole physx world looks mirrored in X axis. (What I see on left should be on right.). Am not sure where have I gone wrong.
IrrNaCl - Irrlicht Port for Google Chrome Native Client - Demo
Iyan 3D - Make your own 3d animation using your iOS Device
Iyan 3D - Make your own 3d animation using your iOS Device
Re: Quaternion-conversion between LH and RH coordinate syste
Sorry for the bump, I fixed it myself using quaternion classes in irrlicht.
IrrNaCl - Irrlicht Port for Google Chrome Native Client - Demo
Iyan 3D - Make your own 3d animation using your iOS Device
Iyan 3D - Make your own 3d animation using your iOS Device