# quaternion subtraction

## Recommended Posts

ms75214    143
I'm trying to understand quaternion subtraction, so I wrote the following small test:

#define RTOD(r) ((r) * 180 / M_PI)

#define DTOR(d) ((d) * M_PI / 180)

void subtractTest(void)
{
D3DXQUATERNION angle45, angle35;

D3DXQuaternionRotationYawPitchRoll(&angle45, 0, 0, DTOR(45));
D3DXQuaternionRotationYawPitchRoll(&angle35, 0, 0, DTOR(35));

D3DXQUATERNION angle10;
angle10=angle45-angle35;

FLOAT w;
D3DXVECTOR3 axis;
D3DXQuaternionToAxisAngle(&angle10,&axis,&w);
float resultAngle = RTOD(w);

}

It tries to take a 45 degree angle and subtract a 35 degree angle from it. I would think the result would be a 10 degree angle, but
it's not. It turns out to be about 183 degrees. Any ideas why I'm not getting a 10 degree angle as the result?

##### Share on other sites
Buckeye    10747
You need to multiply quaternions to get successive changes in angle, not subtract them.

E.g., a quaternion for a y-axis rotation of +45 degrees times a quaternion for a y-axis rotation of -35 degrees gives you a quaternion for a y-axis rotation of 10 degrees.

##### Share on other sites
alvaro    21246
Quote:
 Original post by BuckeyeYou need to multiply quaternions to get successive changes in angle, not subtract them.E.g., a quaternion for a y-axis rotation of +45 degrees times a quaternion for a y-axis rotation of -35 degrees gives you a quaternion for a y-axis rotation of 10 degrees.

Well, he has a rotation of +45 degrees and a rotation of +35 degrees, so he probably wants to divide them.

##### Share on other sites
ms75214    143
Quote:
Original post by alvaro
Quote:
 Original post by BuckeyeYou need to multiply quaternions to get successive changes in angle, not subtract them.E.g., a quaternion for a y-axis rotation of +45 degrees times a quaternion for a y-axis rotation of -35 degrees gives you a quaternion for a y-axis rotation of 10 degrees.

Well, he has a rotation of +45 degrees and a rotation of +35 degrees, so he probably wants to divide them.

I tried this:

angle10=angle45/angle35;

I got this error:

Error 22 error C2679: binary '/' : no operator found which takes a right-hand operand of type 'D3DXQUATERNION' (or there is no acceptable conversion)

I don't think DirectX supports quaternion division.

##### Share on other sites
Buckeye    10747
Quote:
 angle10=angle45/angle35;

That makes no sense, I'm afraid. What happened when you tried multiplication as I suggested (using -35 instead of +35)?

##### Share on other sites
ms75214    143
Quote:
Original post by Buckeye
Quote:
 angle10=angle45/angle35;

That makes no sense, I'm afraid. What happened when you tried multiplication as I suggested (using -35 instead of +35)?

Ok. This seems to do roughly what I was trying to do:

D3DXQUATERNION angleNeg35;
D3DXQuaternionInverse(&angleNeg35, &angle35);

angle10=angle45*angleNeg35;

Here's the full code:

void subtractTest(void)
{
D3DXQUATERNION angle45, angle35;

D3DXQuaternionRotationYawPitchRoll(&angle45, 0, 0, DTOR(45));
D3DXQuaternionRotationYawPitchRoll(&angle35, 0, 0, DTOR(35));

D3DXQUATERNION angle10;

D3DXQUATERNION angleNeg35;
D3DXQuaternionInverse(&angleNeg35, &angle35);

angle10=angle45*angleNeg35;

FLOAT w;
D3DXVECTOR3 axis;
D3DXQuaternionToAxisAngle(&angle10,&axis,&w);
float resultAngle = RTOD(w);

}

##### Share on other sites
alvaro    21246
Quote:
Original post by Buckeye
Quote:
 angle10=angle45/angle35;

That makes no sense, I'm afraid. What happened when you tried multiplication as I suggested (using -35 instead of +35)?

Why do you think it makes no sense? It might be that Direct3D's quaternion implementation doesn't overload the / operator, but mathematically it makes perfect sense.

#include <iostream>
#include <cmath>
#include <boost/math/quaternion.hpp>

typedef boost::math::quaternion<double> Q;

const double deg = std::atan(1.0)/45.0;
int main() {
Q a(std::cos(45*deg/2), 0, std::sin(45*deg/2), 0);
Q b(std::cos(35*deg/2), 0, std::sin(35*deg/2), 0);

Q c = a / b;

std::cout << c << '\n';
}

##### Share on other sites
Buckeye    10747
Quote:
 It might be that Direct3D's quaternion implementation doesn't overload the / operator, but mathematically it makes perfect sense.

It's the former I was commenting on. I actually checked the docs to see if / were overloaded.