Page 1 of 1

[wontfix] Quaternion behave different to matrix operation

Posted: Sun Feb 08, 2015 12:00 pm
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

Re: Re: Quaternion behave different to matrix operation

Posted: Sun Feb 08, 2015 5:51 pm
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.

Re: Re: Quaternion behave different to matrix operation

Posted: Mon Feb 09, 2015 6:53 am
by thanhle
Hi CuteAlien,
It was Irrlicht trunk version from your last update on saving obj file texture scale.

Regards
thanh

Re: Quaternion behave different to matrix operation

Posted: Mon Feb 09, 2015 12:41 pm
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.

Re: Re: Quaternion behave different to matrix operation

Posted: Mon Feb 09, 2015 2:33 pm
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.

Re: Quaternion behave different to matrix operation

Posted: Tue Feb 10, 2015 4:14 am
by thanhle
Thanks guys,
Keep up the great work.
Regards
thanh

Re: Re: Quaternion behave different to matrix operation

Posted: Mon Mar 30, 2015 9:43 pm
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.

Re: [wontfix] Quaternion behave different to matrix operatio

Posted: Tue Mar 31, 2015 9:20 am
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.

Re: [wontfix] Quaternion behave different to matrix operatio

Posted: Tue Mar 31, 2015 9:47 am
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.

Re: [wontfix] Quaternion behave different to matrix operatio

Posted: Tue Mar 31, 2015 11:59 am
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*.