[wontfix] Quaternion behave different to matrix operation

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

[wontfix] Quaternion behave different to matrix operation

Post by thanhle »

Hi guys,
Not a bug, but it seems to me that matrix multiplication is left handed while quaternion is right handed.
Should we standardize it across different conventions?

For example: if I want to rotate a b3d anim mesh shoulder->elbow to an abs target position, I would do the below:

Irrlicht version: svn trunk from last obj file scale update.

1) Matrix method: (target is a target position)

Code: Select all

irr::scene::IBoneSceneNode *base = ((IAnimatedMeshSceneNode *)this->sceneNode)->getJointNode("Rshoulder");
irr::scene::IBoneSceneNode *endEffector = ((IAnimatedMeshSceneNode *)this->sceneNode)->getJointNode("Relbow");
 
vector3df p1 = endEffector->getAbsolutePosition() - base->getAbsolutePosition();
vector3df p2 = target - base->getAbsolutePosition();
 
 matrix4 m1;
m1.buildRotateFromTo(p1, p2);
 
 vector3df cAngle = base->getRotation();
matrix4 m2;
m2.setRotationDegrees(cAngle);
m2 = m1*m2;                      //Left handed multiplication
 
base->setRotation( m2.getRotationDegrees());
base->updateAbsolutePosition();
endEffector->updateAbsolutePositionOfAllChildren();   //or just call endEffector->updateAbsolutePosition()
 
2) Quaternion method

Code: Select all

irr::scene::IBoneSceneNode *base = ((IAnimatedMeshSceneNode *)this->sceneNode)->getJointNode("Rshoulder");
irr::scene::IBoneSceneNode *endEffector = ((IAnimatedMeshSceneNode *)this->sceneNode)->getJointNode("Relbow");
 
vector3df p1 = endEffector->getAbsolutePosition() - base->getAbsolutePosition();
vector3df p2 = target - base->getAbsolutePosition();
 
                 quaternion q1;
         q1.rotationFromTo(p1, p2);
 
         quaternion q2;
         q2.set(base->getRotation()*DEGTORAD);
 
         q2 = q2*q1;                          //Right handed multiplication
 
         vector3df anglexx = q2.getMatrix().getRotationDegrees();
 
             base->setRotation(anglexx);
         base->updateAbsolutePosition();
         
         endEffector->updateAbsolutePositionOfAllChildren();
 
//Just a quick question.
If my target flying in a circle. After one revolution the shoulder seems to twist a little. Is this due to floating point rounding error? Should I always reset the shoulder rotation to zero between calculations?

Thanks
thanh
Last edited by thanhle on Mon Feb 09, 2015 6:52 am, edited 2 times in total.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Re: Quaternion behave different to matrix operation

Post by CuteAlien »

@thanhle. First some small hint - you can use a code tag in the forum. That makes post with code a lot more readable.
Then - which Irrlicht version are you using? Because I know we changed a few function about quaterionions rotating the other direction in Irrlicht 1.8.
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
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: Re: Quaternion behave different to matrix operation

Post by thanhle »

Hi CuteAlien,
It was Irrlicht trunk version from your last update on saving obj file texture scale.

Regards
thanh
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Quaternion behave different to matrix operation

Post by Mel »

I am not sure if this would solve your small arm twisting, but you could try to normalize the quaternions when operating with them. Just in case.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Re: Quaternion behave different to matrix operation

Post by CuteAlien »

OK, sorry, I only did a quick-read over your post last time. I see now it's the operator* that is wrong and not one of the rotation function (those got fixed). This likely didn't. Unfortunately I'm not very familiar with quaternions, so I didn't even know the multiplication was not commutative. Although I should have guessed they work similar like matrices in that regard.

You are very likely right that this has to be changed (will run your test as soon as I find some time... a little short on that as I'm working on getting a game out this week). Unfortunately it seems to be used already in some places (on a quick check I found it used in COgreMeshFileLoader.cpp but there might be more), so it means we have to go over all those. And it will break user-code, so I guess we have to put IRR_TEST_BROKEN_QUATERNION_USE around operator* and operator*= so they have at least a chance of finding those bugs (or better a new define IRR_TEST_BROKEN_QUATERNION_USE2 as it's a new incompatibility).

I really wish Hybrid was here for that kind of stuff as he's more familiar with this. But thanks anyway for reporting. I think breaking code once is better than having left and right-handed multiplications mixed up forever.
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
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: Quaternion behave different to matrix operation

Post by thanhle »

Thanks guys,
Keep up the great work.
Regards
thanh
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Re: Quaternion behave different to matrix operation

Post by CuteAlien »

I looked at this for a while last week, but can't bring myself to change it. The parameter in quaternion::operator* is indeed the opposite of the matrix4::operator*. While the operator *= was done the same way in both classes. I think it's not left-handed/right-handed but pre- vs post-multiplication. It's bad, but it's easy to work-around right now for users. I fear changing it in the engine will be worse as that is hard to catch for users. Just things suddenly breaking.
So I will leave it like it is. Sometimes you only have 1 shot at a good interface and I fear in this case it has missed :-(

But thanks for telling, at least now we know.

edit: I've added at least a small warning.
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
AReichl
Posts: 270
Joined: Wed Jul 13, 2011 2:34 pm

Re: [wontfix] Quaternion behave different to matrix operatio

Post by AReichl »

Aha! - this would solve one of my problems.
So instead of
Q = Q1 * Q2;
it's
Q = Q2 * Q1;
?
I WOULD change it to be right; with a BIG warning in the Readme and during compilation.
At least for one of the next major releases.
AReichl
Posts: 270
Joined: Wed Jul 13, 2011 2:34 pm

Re: [wontfix] Quaternion behave different to matrix operatio

Post by AReichl »

I will look into other solutions from other engines.

One thing i "found" already is that some other libraries declare their Quaternions as
Q( w, x, y, z )
and Irrlicht has
Q( x, y, z, w ).

That's not right or wrong but only different, so when copying source one must be careful.
If you give me some time i will set up a testprogram with "old" and "new" behaviour.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: [wontfix] Quaternion behave different to matrix operatio

Post by CuteAlien »

AReichl wrote:Aha! - this would solve one of my problems.
So instead of
Q = Q1 * Q2;
it's
Q = Q2 * Q1;
?
Yes, exactly.
AReichl wrote: I WOULD change it to be right; with a BIG warning in the Readme and during compilation.
At least for one of the next major releases.
As you see above I also thought first it's better to change. But it's really hard to warn about this as it's just an internal change in an operator. Enabling a warning always is not good - that's annoying everyone for a year for something that affects only a few people. And there is no way to enable it only for people who need that. Also both solutions are correct - just mixing them is bad. So - that leaves me with a hard to detect API change that can break user-apps for something which is ugly but not really a bug and which is easy to work around. I think adding the warning in the comment is the least evil solution. Unfortunately there's no nice solution anymore once something like that happened.

There's other places... like parameter order in constructor of SColor vs. SColorf *sigh*.
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
Post Reply