Quaternion multiplication
-
- Orc Shaman
- Posts: 788
- Joined: Mon Jan 18, 2010 6:06 pm
- Location: Costa Mesa, California
- x 24
Quaternion multiplication
I've been reading the quaternion primer and found it pretty interesting that multiplication of quaternions is non-commutative. But how does a multiplication result of 2 or more quaternions store the order of those rotations? Also, when multiplying a quat by a vector3, the primer says we get a vector describing the rotational offset from that vector. But, it says further that getting an orientation quat, multiplied by Vector3::UNIT_X, gets us the direction vector. This seems to be saying 2 different things. Is it a rotational offset, or a direction vector? How can it be both?
-
- OGRE Moderator
- Posts: 2819
- Joined: Mon Mar 05, 2007 11:17 pm
- Location: Canada
- x 218
Re: Quaternion multiplication
The best way to think of a quaternion is that it is a rotation.
For example, you could have a quaternion that means "turn 90 degrees left". Or maybe more accurately (for 3D), "turn 90 degrees clockwise around the +Y axis". But it's a little easier to describe the concepts using "left", "right", "north", "south", etc.
By itself, a quaternion can't tell you an absolute orientation. If I told you I turned 90 degrees left, then asked "what direction am I facing?", you would say "it depends on what direction you were facing when you started". If I started out facing north, then I would now be facing west. If I started out by facing south, then I would now be facing east.
But a quaternion often is used to represent an absolute orienation. This is why in Ogre, SceneNodes (and other "Node" classes) store their orientation as a Quaternion. Here's how that works.
When you're making models for your game, your artist should always design them to have the same orientation. In Ogre, the most common convention is: -z is forward, +y is up. So now, since you know exactly how your model is facing by default, you can use a quaternion to rotate it, and get a new orientation.
Using the simplified north/south/east/west/left/right description, it would go like this.
We make all our models so that they're facing north.
Now, if we want a model to face west, we give it a "turn left 90 degrees" quaternion, which results in an orientation of facing west.
If we want a model to face south-east, we give it a "turn right 135 degrees" quaternion, which results in an orientation of facing SE.
Again, this only makes sense if we know the default orientation (northwards).
If I'm facing SouthEast, I could have gotten here by:
1) Turning 180 degrees right, then turning 45 degrees left
or
2) Turning 100 degrees right, then turning 35 degrees right
or
3) Turning 20 degrees left, then turning 155 degrees right
or...
All of these would result in the same final quaternion, which tells you which way I'm facing, but not how I got here.
Although since ogre commonly use Vector3:NEGATIVE_UNIT_Z as the default direction of our models, usually if you want the direction of an Entity, you multiply the Entity's quaternion/orientation by Vector3:NEGATIVE_UNIT_Z to get it's direction vector.
If I wanted to make a space ship fire a bullet, the (simplified) code would look something like this:
For example, you could have a quaternion that means "turn 90 degrees left". Or maybe more accurately (for 3D), "turn 90 degrees clockwise around the +Y axis". But it's a little easier to describe the concepts using "left", "right", "north", "south", etc.
By itself, a quaternion can't tell you an absolute orientation. If I told you I turned 90 degrees left, then asked "what direction am I facing?", you would say "it depends on what direction you were facing when you started". If I started out facing north, then I would now be facing west. If I started out by facing south, then I would now be facing east.
But a quaternion often is used to represent an absolute orienation. This is why in Ogre, SceneNodes (and other "Node" classes) store their orientation as a Quaternion. Here's how that works.
When you're making models for your game, your artist should always design them to have the same orientation. In Ogre, the most common convention is: -z is forward, +y is up. So now, since you know exactly how your model is facing by default, you can use a quaternion to rotate it, and get a new orientation.
Using the simplified north/south/east/west/left/right description, it would go like this.
We make all our models so that they're facing north.
Now, if we want a model to face west, we give it a "turn left 90 degrees" quaternion, which results in an orientation of facing west.
If we want a model to face south-east, we give it a "turn right 135 degrees" quaternion, which results in an orientation of facing SE.
Again, this only makes sense if we know the default orientation (northwards).
It doesn't. It just remembers the result.drwbns wrote:But how does a multiplication result of 2 or more quaternions store the order of those rotations?
If I'm facing SouthEast, I could have gotten here by:
1) Turning 180 degrees right, then turning 45 degrees left
or
2) Turning 100 degrees right, then turning 35 degrees right
or
3) Turning 20 degrees left, then turning 155 degrees right
or...
All of these would result in the same final quaternion, which tells you which way I'm facing, but not how I got here.
It's a direction vector.drwbns wrote:Also, when multiplying a quat by a vector3, the primer says we get a vector describing the rotational offset from that vector. But, it says further that getting an orientation quat, multiplied by Vector3::UNIT_X, gets us the direction vector. This seems to be saying 2 different things. Is it a rotational offset, or a direction vector? How can it be both?
Although since ogre commonly use Vector3:NEGATIVE_UNIT_Z as the default direction of our models, usually if you want the direction of an Entity, you multiply the Entity's quaternion/orientation by Vector3:NEGATIVE_UNIT_Z to get it's direction vector.
If I wanted to make a space ship fire a bullet, the (simplified) code would look something like this:
Code: Select all
void FireBulletFromShip( Ogre::Entity* pShip )
{
// All position and orientation info is stored on the SceneNode
// - this code assumes our SceneNode is attached directly to ogre's root SceneNode.
// - if it's not, use the _getDerivedPosition and _getDerivedOrientation functions instead
Ogre::SceneNode* pSN = pShip->getSceneNode();
Ogre::Vector3 shipPosition = pSN->getPosition();
Ogre::Quaternion shipOrientation = pSN->getOrientation();
// Our models are built with a default forward direction of NEGATIVE_UNIT_Z
Ogre::Vector3 forwardDefault = Ogre::Vector3::NEGATIVE_UNIT_Z;
// What is the ship's current direction?
Ogre::Vector3 currentDirection = shipOrientation * forwardDefault;
// Fire the bullet in the ship's current direction
// Let's pretend the following function can make a bullet, but just has to be told what position and direction to fire it
CreateBullet( shipPosition, currentDirection );
}

-
- Orc Shaman
- Posts: 788
- Joined: Mon Jan 18, 2010 6:06 pm
- Location: Costa Mesa, California
- x 24
Re: Quaternion multiplication
Thanks for that info. How would I make a player control style where movement is based upon the camera angle to the player?
-
- OGRE Moderator
- Posts: 2819
- Joined: Mon Mar 05, 2007 11:17 pm
- Location: Canada
- x 218
Re: Quaternion multiplication
That's a fairly complicated question. But it would involve getting the direction the camera is pointing, and gradually (or immediately) rotating the character to face that direction. Check the "character" sample program which comes with Ogre3D. Maybe that's close to what you're looking for?

-
- Orc Shaman
- Posts: 788
- Joined: Mon Jan 18, 2010 6:06 pm
- Location: Costa Mesa, California
- x 24
Re: Quaternion multiplication
Yeah, that's what I'm working with but somehow my rotations are off. Pressing left makes him walk away from the camera, up makes him move right from the camera, right makes him move towards the camera, and down makes him move left from the camera. The only thing I'm not using is the cameraNode, as I'm passing the camera's orientation in place of the cameraNode, and I'm using Havok for physics.
If I remove my physics update, and leave the original code as is, minus using the cameraNode ( mCamera instead ) and minus the translate call, the character doesn't even turn. Only just very slightly can I see some hint of turning left and right, maybe a degree if that. Like there's a lock on turning somehow.
I noticed that my Sinbad character is actually facing +Z when loaded, is this a rotation problem with the Sinbad character? I'm not rotating the node...
If I remove my physics update, and leave the original code as is, minus using the cameraNode ( mCamera instead ) and minus the translate call, the character doesn't even turn. Only just very slightly can I see some hint of turning left and right, maybe a degree if that. Like there's a lock on turning somehow.
I noticed that my Sinbad character is actually facing +Z when loaded, is this a rotation problem with the Sinbad character? I'm not rotating the node...
-
- OGRE Moderator
- Posts: 2819
- Joined: Mon Mar 05, 2007 11:17 pm
- Location: Canada
- x 218
Re: Quaternion multiplication
Here's some code I wrote.
It's completely untested and uncompiled, but hopefully if I didn't screw up too bad, it might help.
It's completely untested and uncompiled, but hopefully if I didn't screw up too bad, it might help.
Code: Select all
Quaternion cameraOrientation = pCamera->getDerivedOrientation();
// You could get the camera's direction like this:
Vector3 cameraDirection = cameraOrientation * Vector3::NEGATIVE_UNIT_Z;
// Alternatively, you can use this function: Camera::getDerivedDirection
// but if you look at the source code for that (OgreCamera.cpp), it's doing the exact same thing as the code above.
// If your character is standing on the ground, you probably want to ignore the y ("up/down") component of your camera direction,
// since the character can't walk into the air or into the ground.
cameraDirection.y = 0.f;
// TODO: check if cameraDirection is now 0, which would now be the case if the cameraDirection was pointing straight up (UNIT_Y) or straight down (NEGATIVE_UNIT_Y)
// If so, return now since we can't move the player relative to the camera.
// - this could be done by checking the result of the normalise() function call below.
// Lots of functions require normalized (unit) direction vectors.
cameraDirection.normalise();
// Now we can compute the desired rotation of the player, based on which direction she is pressing the controls.
Quaternion inputRotation = Quaternion::IDENTITY;
switch( input )
{
case( forward ):
break;
case( backward ):
inputRotation = Quaternion( Degree( 180.f ), Vector3::UNIT_Y );
break;
case( left ):
inputRotation = Quaternion( Degree( 90.f ), Vector3::UNIT_Y );
break;
case( right ):
inputRotation = Quaternion( Degree( -90.f ), Vector3::UNIT_Y );
break;
}
// So the player direction should be the camera direction, rotated by the inputRotation
Vector3 playerDirection = inputRotation * cameraDirection;
// In case you need a player orientation as well as a player direction, you can get it like this
Vector3 playerForwardDefault = Vector3::NEGATIVE_UNIT_Z; // if your player model isn't facing down the -z axis by default, change this as required.
Quaternion playerOrientation = playerForwardDefault.getRotationTo( playerDirection, Vector3::UNIT_Y );
// Now use the playerDirection or playerOrientation to orient and move your character...

-
- Orc Shaman
- Posts: 788
- Joined: Mon Jan 18, 2010 6:06 pm
- Location: Costa Mesa, California
- x 24
Re: Quaternion multiplication
That looks like it should help. I'll post back if I run into problems, thanks.
-
- OGRE Moderator
- Posts: 7157
- Joined: Sun Jan 25, 2004 7:35 am
- Location: Brisbane, Australia
- x 535
Re: Quaternion multiplication
Unfortunately none of the Ogre sample meshes follow standardised dimensions or orientations. The Ninja faces -Z, the robot faces +X and Sinbad faces +Z. They are all different sizes too.I noticed that my Sinbad character is actually facing +Z when loaded, is this a rotation problem with the Sinbad character? I'm not rotating the node...
-
- Orc Shaman
- Posts: 788
- Joined: Mon Jan 18, 2010 6:06 pm
- Location: Costa Mesa, California
- x 24
Re: Quaternion multiplication
lol, I noticed 3d max's covention is different from ogre's as well, I think X and Z are flipped compared to Ogre, not sure, but I noticed it on an export.
-
- OGRE Moderator
- Posts: 7157
- Joined: Sun Jan 25, 2004 7:35 am
- Location: Brisbane, Australia
- x 535
Re: Quaternion multiplication
Yep, Ogre uses right handed Y up. 3DS Max is right handed Z up. Maya is right handed Y up but can switch to Z up.
UDK is left handed Z up. Unity3D is left handed Y up.
Quake3 is right handed Z down, which is just odd.
UDK is left handed Z up. Unity3D is left handed Y up.
Quake3 is right handed Z down, which is just odd.