Original Author: Cory Petkovsek (discipline in the forums)
Release Date: June 16th, 2005
Introduction
If you are reading this page, it is probably grudgingly, after working with your objects in Ogre and finding they don't rotate as you think they should. When I started with Ogre, I understood vectors, had taken trigonometry a long time ago, had a faint memory of learning matrices at some point and knew nothing about quaternions. This article has been compiled as a primer for the practical use of quaternion rotations in Ogre, skipping over math and matrices where possible.
Use this thread in the forums to discuss this article or ask questions.
A note to potential wiki editors: Quaternions are hard enough to understand. When posting code snippets try to make each point as clear as possible (i.e. describing why we multiply a vector by a quaternion). Define what each variable is used for and its type. Also only post code that you know works.
Table of contents
[Show/Hide] Introduction
 Prerequisites
 Vectors
 Euler Rotations
 Matrix Rotations
 Quaternion Rotations
 Questions
 Quaternions
 Q. How would I make my object rotate to face another point?
 Q. When debugging, I've printed the individual x, y, z, and w values of the quaternion, but I can't make heads or tails of them. What do they mean?
 Q. I see vectors and quaternions being multiplied together in the code. What does this mean?
 Q. When do I use setOrientation() vs rotate()? When do I multiply quaternions against orientations or vectors? I'm so confused!
 And what about slerp with rotations and orientations?
 Q. Why do I occasionally get a flickering of my object while it is rotating? I'm using slerp to interpolate between two orientations, and calling setOrientation() with the interpolated quaternion.
 Misc
 Quaternions
 Code Snippets
 Flat XZ Rotation of Objects
 Q. I have a character that walks along a set of points on a flat plane. How can I have it rotate to face the direction it is walking?
 Q. The above works great when I have a plane. Now I have an object walking up and down. When it rotates it starts rolling and pitching to all funny directions. How can I have it always have its head up?
 Q. Sometimes my program quits and I get an Assert  Divide by Zero. What's up?
 Smooth Rotation
 Resetting Orientation
 Flat XZ Rotation of Objects
 Problems and solutions
 1. Definitions
 2. Fair Use Rights
 3. License Grant
 4. Restrictions
 5. Representations, Warranties and Disclaimer
 6. Limitation on Liability.
 7. Termination
 8. Miscellaneous
Prerequisites
Before we're talking about quaternions, we'll review some basics regarding vectors, Euler angles, and matrices.
Furthermore, for this document and working within Ogre, we will use a righthanded coordinate system (see also Righthand Rule). This means two things:
 First, we consider +X to point to the right of your monitor (thumb), +Y to point to the top of your monitor (index finger) and +Z to point out of your monitor toward you (middle finger). (You can only do this with your right hand, hence the name.)
 Next, to find out which direction +45 degrees rotates, point the thumb of your right hand down the axis of rotation (i.e. towards positive infinity). The direction your fingers curl is the positive angle.
A quick video introduction to Euler angles, matrices, and quaternions can be found in the Google Tech Talk Sensor Fusion on Android Devices: A Revolution in Motion Processing starting at 35:30.
Vectors
A vector can be thought of as an arrow from a given initial point to another point in 3D space. It describes both the direction and the length of this arrow. The direction not only describes the bearing of the arrow but also where the arrowhead points to. This separates a vector from a line segment which only has a bearing but is "bidirectional". A vector is also different from a ray as rays have an infinite length.
Describing two points would normally require six values for 3D space. In Ogre, vectors are stored in three values by assuming the first point is (0,0,0) and the second point is a relative offset. This is a common use of vectors. This given (0,0,0) can be the world origin, or it can be the origin of an object's local coordinate system. Be aware of which coordinate system you are working with when using transformations. Because vectors have only three values, they are also used to define 3D points.
When a vector is normalized, the vector is scaled to a length of 1. We use normalized vectors (or unit vectors) when we wish to describe only a direction. This is necessary for expected results with many mathematical algorithms.
In Ogre, vectors are commonly used to describe a single point, define a direction with a unit vector, or extract the distance between two points.
Here are some common vector operations and what they are used for:
 Subtracting vector A from vector B generates a third vector that contains the direction and distance from A to B.
Bv  Av = Av > Bv  Adding vector A and vector B gives vector C. You can visualize this as if you take vector B, and place its tail on vector A's head (like two arrows drawing out a path). Then vector C is the vector from the start of the path (A's tail) to the end of the path (B's head). Equivalently, you could get the same vector C by lining up the vectors in the opposite order: placing vector A's head at vector B's tail.
 Multiplying or dividing a vector by a scalar (read: a number) does not change the direction, but only changes the length of the vector. For instance the vector (1,1,1) describes a line that is angled 45 degrees off the XZ plane (horizontal), 45 degrees off the XY plane (vertical, faces towards you) and 45 degrees off the YZ plane (vertical, faces left/right). The length of the line is sqrt(x^2 + y^2 + z^2)  or, in this example, sqrt(3) which is about 1.73. Now if we multiply this vector by 2 we get (2,2,2). This describes a line with the exact same angles. However the length is now sqrt(12) or 3.46 (which is 1.73 times 2). See Vector3::length().
 A cross product of two vectors provides a third vector that is perpendicular to the initial two. This is a very useful computation. If you want to figure out which way is up/out from a polygon take the cross product of two edges and you have a vector pointing out. The cross product can be calculated for you by ogre. Vector3::crossProduct(Vector3).
 The dot product of two vectors allows us to find the angle between them. It is defined as
DotPr(v1,v2) = Cos(Angle) * Len1 * Len2
Where Len1 and Len2 are the length of the vectors. However typically you should normalize both vectors so the lengths are 1. This means the dot product is the cosine of the angle between the vectors. Stated another way:
Angle = ArcCos(DotPr(v1,v2)) ; where Len1 = Len2 = 1
This is also found in the API under Vector3::dotProduct(Vector3).
Euler Rotations
The method of rotation you may be more accustomed to is using yaw, roll and pitch.
 Yaw would be left/right rotation around the Y axis (vertical) on the XZ plane. Yaw is used when driving a car.
 Pitch is up/down rotation around the X axis (horizontal, pointing right) on the YZ plane. Pitch is used when flying a jet down or up, or when driving up hill or down.
 Roll is tilt rotation around the Z axis (pointing towards you) on the XY plane. Roll is literally what happens to your car when you take a curve too fast!
Euler rotations can be useful and are supported in Ogre's API. There are problems however. One is that the order of operations is important. If you pitch an object 90 degrees, then yaw it 90 you get a different result than if yaw is done before pitch. Try it.
Another big problem is known as gimbal lock. A gimbal is an axis of rotation. This problem occurs when mathematically two axes of rotation become aligned and one gets canceled out.
Finally, euler angles are limited in their practical application. What I mean by this is that to rotate an object arbitrarily it is not very practical to use yaw, roll and pitch operations. They are useful say if you want a yaw/pitch camera like many fps games. With a dual sceneNode trick you can get a camera that will use yaw and pitch operations without inducing roll. However, when you have an object facing one way and you want it to face another object in an arbitrary location, retrieving the current individual yaw, roll and pitch values then calculating the difference needed for a rotation to the new direction is not very efficient. Also, what if you want to do a smooth rotation from the current facing to the new direction? Not very practical. Enter matrices.
Matrix Rotations
Because working with arbitrary three dimensional euler rotations can produce a large amount of operations, matrices are usually used to store and transform them.
One way of working with matrices is to use three, each specifying a certain angle offset from the X, Y and Z axes. This is our pitch (rotation on the X axis), yaw (Y axis) and roll (Z axis). We can store them in individual matrices, say matRotationX, matRotationY and matRotationZ. When we have decided on the angles we wish to rotate by and have stored them in our matrices, we can combine the operations into one transform matrix simply by multiplying them.
matTransform = matRotationX * matRotationY * matRotationZ;
Fortunately for us, Ogre implements a Matrix3 class to handle 3x3 matrices. The class also has the * operator overloaded so the above statement will work right in your code. To rotate an object in Ogre you first need to create a quaternion with this matrix by using the appropriate quaternion constructor or using FromRotationMatrix on a quaternion.
Note that matrix multiplication is not commutative. A * B doesn't always equal B * A. The order in which you apply each matrix rotation is important, just as it is with straight euler angles. Also note that matrices as representations of euler angles are still subject to gimbal lock.
Matrices can also be used to handle axis/angle rotations. The matrices above used concepts of yaw, roll and pitch. Think of these instead as rotation around Y, Z and X axes, respectively. It is possible to achieve any rotation by defining a single arbitrary axis and an angle of rotation. In doing this we avoid the problem of gimbal lock.
There is a problem with both euler angle matrices and axis/angle matrices. It is called matrix drift, which I will describe in the quaternion section under the benefits list.
Quaternion Rotations
Quaternions are an interesting concept probably as new to you as they were to me when I first started this. As described above, when working with quaternions I find it easier to stop thinking about yaw, pitch and roll and instead think of rotation around axes. For instance, let's say we wanted to model a propeller on a jet. The jet faces down the Z axis. In euler terms the rotation would be called roll. In quaternions it is rotation around a vector pointing down the Z axis, or rotation around Vector3::UNIT_Z as we'd refer to it in Ogre.
A quaternion is composed of four components: a vector with x, y, z coordinates and a w rotation. This is an axis/angle representation just as I touched on at the end of the matrix section. Quaternion math can get quite involved, even incorporating imaginary numbers. Fortunately we don't need to use all of that math, nor understand it to work with rotations.
Try this exercise. Point your left index finger straight up. Next grab the tip of a pen with your right hand. Now by moving your wrist and hand around in a circle, try to spin the pen as flatly as possible, always perpendicular to your finger and parallel to the floor. It should look like you had just spun it on a table. Think of this as quaternion rotation around Vector3::UNIT_Y.
Now let's say we have a vector from (0,0,0) to (1,1,1). With our finger pointing straight right, point it up 45 degrees and away from you 45 degrees. Now rotate the pen around your finger, keeping it perpendicular at all times. Notice how the angle of the axis we choose creates a different rotation.
Like matrices, we can combine quaternion rotations by multiplying them. However they are still not commutative. Q1 * Q2 != Q2 * Q1. Thus the order of application is still important. Also like matrices that represent axis/angle rotation, quaternions avoid gimbal lock.
Benefits of Quaternions
Quaternions do have advantages over matrices though. There are implementation pros and cons such as the number of multiplications, or additions during different operations, etc that have been discussed in the forum. Considering practical benefits though, here is a list :
 Axis/angle representation avoids gimbal lock.
 Modifying a rotation is easy. Say we have a rotation describing a 45 degree yaw (left turn). By creating a new quaternion describing a 10 degree yaw (right turn) and multiplying the two, we now have a rotation describing a 35 degree turn. You might use this when applying the same rotation to a number of different objects, or even multiple times to the same object (i.e. the player). The rotation factor increases or decreases depending on circumstances.
 Avoids costly alignment of matrix drift. This drift occurs when performing lots of operations on matrices using finite point precision, which is used in your computer. Rounding of real numbers graudally builds up and inevitably mucks up the matrix. Abnormalities in the rotation will start to appear due to this drift. The matrix must be normalized in order to reset this, however it is a costly operation. Quaternions on the other hand can still suffer from this drift, but it is much cheaper to normalize having only 4 values instead of 9 or more.
 Interpolation of rotations. When rotating an object, we might want the object to rotate smoothly over time. We'd like to say, "From your current orientation, rotate to face this point. But take about 300 frames to do it, so only move 1/300th of the rotation right now." Interpolation with matrices is possible, but then so is anything, isn't it? Quaternions provide two methods of interpolation: linear(slerp) and cubic(squad). Ogre provides three implementations: slerp, nlerp and squad. Linear interpolation allows one to specify the percentage of interpolation between the two quaternions. Linear means your "velocity" of movement is constant, which may feel jerky if used for a camera or object. Slerp and nlerp are both linear. Slerp is more accurate, but slower. Squad or cubic interpolation allows one to specify four quaternions a,p,q,b. P and Q are used to define a curve of interpolation "velocity" between points A and B. This allows us to slowly increase speed, stay constant, then decrease it during interpolation. See the External Resources section for links that will elaborate on this.
 Ogre uses quaternions! That's probably why you are reading this page. Often, you'll need to get the current orientation of an object, which is returned as a quaternion.
Some useful (normalized) quaternions
w  x  y  z  Description 
1  0  0  0  Identity quaternion, no rotation 
0  1  0  0  180° turn around X axis 
0  0  1  0  180° turn around Y axis 
0  0  0  1  180° turn around Z axis 
sqrt(0.5)  sqrt(0.5)  0  0  90° rotation around X axis 
sqrt(0.5)  0  sqrt(0.5)  0  90° rotation around Y axis 
sqrt(0.5)  0  0  sqrt(0.5)  90° rotation around Z axis 
sqrt(0.5)  sqrt(0.5)  0  0  90° rotation around X axis 
sqrt(0.5)  0  sqrt(0.5)  0  90° rotation around Y axis 
sqrt(0.5)  0  0  sqrt(0.5)  90° rotation around Z axis 
These numbers come from this property:
[w, x, y, z] = [cos(a/2), sin(a/2) * nx, sin(a/2)* ny, sin(a/2) * nz]
Where a is the angle of rotation and {nx,ny,nz} is the axis of rotation. (From section 2e of Quaternion Spells)
Questions
This section is for questions or simple one or two line code snippets for the purpose of answering questions. More involved code samples go in the next section.
Quaternions
To get you started, here are some simple things you can do in Ogre with quaternions. This section also has some clarifications of other text. The code samples in the next section will help you with more difficult problems.
Q. How would I make my object rotate to face another point?
A. One way is to use the SceneNode::lookAt method. However this may have unexpected results when used as an object. Besides, we are talking about quaternions here.
Another way is through specifying the individual rotations then multiplying them together.
Rotate around the Z axis 90 degrees:
Quaternion q(Degree(90), Vector3::UNIT_Z);
Next, rotate around the X axis 90 degrees.
Quaternion r(Degree(90), Vector3::UNIT_X);
Rotate the object with both rotations in the above order. mNode is a SceneNode:
q = q * r; mNode>rotate(q);
A better way is to use the Vector3::getRotationTo(Vector3) function to generate a quaternion for us. Look at the code samples to see how this will be used.
Q. When debugging, I've printed the individual x, y, z, and w values of the quaternion, but I can't make heads or tails of them. What do they mean?
A. X, Y and Z describe a vector which is the axis of rotation. In my current project, I have only flat XZ rotation, meaning I zero any potential rotations with pitch or roll. The code sample below shows how to do this. Thus my values will look something like 0, .599, 0. This describes the Y axis, as it is the only value. Actually it is pointing down as it is negative, and I'm not sure why. I'll correct this when I learn why. It may be a bug in my code.
W is the amount of rotation around the vector axis. It is an odd value in itself. This is because it is cos(theta/2), where theta is the angle. Derive the angle like this, which produces an Ogre::Radian:
2*Math::ACos(quat.w))
So my example quaternion looks like this with W in degrees: (0.000,0.599,0.000, 73.602). The reason Y is not 1 or even 1 is because the quaternion is normalized. Normalization includes w, x, y and z, so they all need to give some to equal 1. Of course the 73 is the derived value so doesn't isn't a component of the 1.
Q. I see vectors and quaternions being multiplied together in the code. What does this mean?
A. Multiplying a quaternion by a vector gives us a vector describing the rotational offset from that vector (a rotated vector). For example when one loads the robot.mesh file, by default it points facing UNIT_X. When it has been rotated, we can get its orientation in quaternion form via mNode>getOrientation(). If we then multiply it by Vector3::UNIT_X, we will get a vector pointing in the direction the robot is currently facing.
Q. When do I use setOrientation() vs rotate()? When do I multiply quaternions against orientations or vectors? I'm so confused!
A. SceneNode::getOrientation() returns a quaternion describing how much of a rotational offset the object has acquired from its identity orientation (or the direction it started facing). getWorldOrientation() returns its own rotation offset, plus that of its parent's. If the node's parent is root, these functions return the same thing.
Vector3::getRotationTo(Vector3) returns a quaternion describing a relative rotation from one vector to the next. Remember that quaternions can be thought of as vectors with an angle attached? Remember that Vector A minus Vector B gives Vector C, a relative vector from B to A? Same thing with quaternions. Think of orientations as absolute, relative to the identity. Think of rotations as relative, usually relative to the current orientation.
SceneNode::setOrientation(Quaternion) does exactly that. It sets it based on the object's original facing direction. SceneNode::rotate(Quaternion) sets the orientation based on the current orientation. Thus rotate(q) is equivalent to setOrientation(q * getOrientation()).
If we have a scene node and a calculated rotation from getRotationTo, we only need to use the rotate(quat) function. In fact if we use setOrientation, we'll be rotating more than desired.
And what about slerp with rotations and orientations?
When I first started playing with slerp, I was slerping like this:
mRotSrc = mNode>getOrientation();
mRotDest = src.getRotationTo(mDirection);
...
mNode>rotate(Quaternion::Slerp(mRotProgress, mRotSrc, mRotDest));
My poor robot was spinning round and round like a top on steroids. I made two mistakes above. Can you spot them?
1) The first mistake is that Slerp takes two orientations, not relative rotations. mRotDest is only a relative rotation from mRotSrc to mDirection (where I want to point). I should be able to setOrientation(mRotSrc) or setOrientation(mRotDest) and have my object point to the source or destination accurately. That wouldn't happen with these values. The fix is:
mRotDest = src.getRotationTo(mDirection) * mRotSrc;
2) The next mistake is that Slerp returns an orientation, not a relative rotation. Since it is working with absolute rotations (absolute to the object's identity or starting point), this is what it returns. The fix is:
mNode>setOrientation(Quaternion::Slerp(mRotProgress, mRotSrc, mRotDest));
These were actually the same problem: A misunderstanding about Slerp. When working with these tools, consider whether you are working in relative rotations or orientations.
A few redundant points:
 quaternion * vector is a vector rotationally offset by the quaternion
 quaternion * quaternion is a quaternion with both rotations combined, 'therefore:'
 rotation1 * rotation2 is a quaternion with both rotations, rotation1 is the orientation of the parent node and orientation2 is the orientation of the child node 'and'
 setOrientation(getOrientation() * rotation) == rotate(rotation)
Q. Why do I occasionally get a flickering of my object while it is rotating? I'm using slerp to interpolate between two orientations, and calling setOrientation() with the interpolated quaternion.
A. Quaternion::Slerp(), Quaternion::nlerp() etc. have a "shortestPath" parameter that defaults to false. Ensure it is true, otherwise the interpolation occasionally goes the longer path, which might result in a few frames of completely discontinuous orientations.
Misc
Q. Why do the tutorials and people on the forum suggest using two scene nodes to attach my camera to?
A. The recommendation is to create a scene node, say "CamNode" and a pitch node, say "PitchNode". "PitchNode" is attached to "CamNode" and the camera is attached to "PitchNode". Movement and Yaw are applied to the CamNode. Pitch is applied to the "PitchNode", only. The reason for this is because one can generate roll through euler angles of pitch and yaw. Often one uses the mouse to control the camera look angle. One expects to move the mouse up to look up, right to look right, down to look down. However this is the same as pitch up, yaw right and pitch down. Try this with a desk object. That sequence induces roll. Using two separate nodes gives you the equivalent of a flat disk that floats around. Attached to the bottom of that disk is a camera that can look only up or down. By rotating the disk and moving the camera up or down you can view any angle. Yaw on the disk affects the camera, but pitch on the camera does not affect the disk. This provides the effect that most people expect.
Alternate A. For a simple Free Camera you can use the one node and just rotate in the appropriate coordinate space. Once you want to start mixing "roll" into this, you should go back to completely local space rotationsat which point you're probably not trying to make a simple Free Camera for debug purposes.
node>pitch( mPitch, Node::TS_LOCAL ); node>yaw( mYaw, Node::TS_WORLD ); node>translate( mTranslate, Node::TS_LOCAL );
The effect of this is to pitch the scenenode relative to itself, but to yaw the scenenode relative to the world. This means yaw is always horizontal and no roll is induced by the two rotations. The translate call ensures you are always moving along the SceneNode's z axis. i.e., the direction it is facing.
Code Snippets
Flat XZ Rotation of Objects
Q. I have a character that walks along a set of points on a flat plane. How can I have it rotate to face the direction it is walking?
A. First of all, we need the initial facing vector of the mesh. When you load your mesh in Ogre, which direction is it facing, before any transforms are applied? Hint: The camera starts out facing down Vector3::NEGATIVE_UNIT_Z. You can also load the mesh in your modeller, but beware that the modeller axes are not necessarily aligned with Ogre's. For this code, the initial facing vector is Vector3::UNIT_X.
This code was adapted adapted from Intermediate Tutorial 1:
Vector3 mDestination = mWalkList.front(); // mDestination is the next location Vector3 mDirection = mDestination  mNode>getPosition(); // BA = A>B (see ((Quaternion and Rotation Primer#Vectorsvector questions)) above) Vector3 src = mNode>getOrientation() * Vector3::UNIT_X; // see (1) Real mDistance = mDirection.normalise(); // strip out distance, we only want direction Quaternion quat = src.getRotationTo(mDirection); // Get a quaternion rotation operation mNode>rotate(quat); // Actually rotate the object
(1) From the comments, getOrientation() returns a Quaternion describing the objects rotation in relation to the root. Multiplying it by UNIT_X, which is the object's initial facing position in this case, provides a vector describing its current facing direction.
This works because our object has never been rolled or pitched. All existing points given to it are on a flat plane so there is never any pitch or roll to be wrapped up in the quaternion.
Q. The above works great when I have a plane. Now I have an object walking up and down. When it rotates it starts rolling and pitching to all funny directions. How can I have it always have its head up?
A. We can adapt the above to strip out all Y components before they get into quaternions. This means it only does flat X/Z rotation.
Vector3 mDestination = mWalkList.front( ); // mDestination is the next location Vector3 mDirection = mDestination  mNode>getPosition(); // BA = A>B (see ((Quaternion and Rotation Primer#Vectorsvector questions)) above) Vector3 src = mNode>getOrientation() * Vector3::UNIT_X; // Orientation from initial direction src.y = 0; // Ignore pitch difference angle mDirection.y = 0; src.normalise(); Real mDistance = mDirection.normalise( ); // Both vectors modified so renormalize them Quaternion quat = src.getRotationTo(mDirection); mNode>rotate(quat);
Q. Sometimes my program quits and I get an Assert  Divide by Zero. What's up?
A. This happens due to a peculiarity with quaternion rotation by 180 degrees. When you tell Ogre to rotate 180 degrees, there are an infinite number of paths along which rotation could occur. Rather than picking one you may not want (i.e. rotating through the ground), Ogre asserts. You should make the selection within your code like this:
Vector3 mDestination = mWalkList.front( ); // mDestination is the next location Vector3 mDirection = mDestination  mNode>getPosition(); // BA = A>B (see ((Quaternion and Rotation Primer#Vectorsvector questions)) above) Vector3 src = mNode>getOrientation() * Vector3::UNIT_X; // Orientation from initial direction src.y = 0; // Ignore pitch difference angle mDirection.y = 0; src.normalise(); Real mDistance = mDirection.normalise( ); // Both vectors modified so renormalize them if ((1.0f + src.dotProduct(mDirection)) < 0.0001f) // Work around 180 degree quaternion rotation quirk { mNode>yaw(Degree(180)); } else { Quaternion quat = src.getRotationTo(mDirection); mNode>rotate(quat); }
Smooth Rotation
Q. How can I make my objects rotate smoothly? You mentioned slerp, etc?
A. You'll need to have two places in your code the rotation is established, and an area of shared variables. For my code, I have a class that manages all of my world objects, so the following code is found in one class, but in different methods. Slerp and nlerp are interchangeable here. Just change the name. The difference is slerp is more accurate, but requires more processing. This code has been tested by the author.
Shared variables:
Ogre::Quaternion mOrientSrc; // Initial orientation Ogre::Quaternion mOrientDest; // Destination orientation Ogre::Real mRotProgress; // How far we've interpolated Ogre::Real mRotFactor; // Interpolation step boolean mRotating;
Next, the rotation is initiated somewhere like this. 'frames' is an integer in this case that describes the number of frames to rotate over. Use your own formula to figure the length of time you want to rotate.
mRotating = true; mRotFactor = 1.0f / frames; mOrientSrc = mNode>getOrientation(); mOrientDest = quat * mOrientSrc; // We want dest orientation, not a relative rotation (quat) mRotProgress = 0;
Finally, during an update method called by your frameStarted method:
if(mRotating) // Process timed rotation { mRotProgress += mRotFactor; if(mRotProgress>1) { mRotating = false; } else { Quaternion delta = Quaternion::Slerp(mRotProgress, mOrientSrc, mOrientDest, true); mNode>setOrientation(delta); } } // if mRotating
Q. You mentioned squad?
A. Squad allows you to apply a cubic interpolation instead of a linear interpolation. This means the rate of turn increases and decreases depending on the bezier/hermite curve given to the function. You'll have to experiment with the coefficients given as the first slerp parameters on IntA and IntB. These quaternions are intermediary rotations between the source and destination. I'm telling it to interpolate over the bezier curve mOrientSrc > mOrientDest, and use mOrientIntA and mOrientIntB as intermediate curve points. Basically experiement and see what happens.
To use it make the following changes to the above sections:
Shared variables:
+Ogre::Quaternion mOrientIntA; +Ogre::Quaternion mOrientIntB;
Initiation section (modify .3/.5 values to adjust intermediate points):
mOrientDest = quat * mOrientSrc; +mOrientIntA = Quaternion::Slerp(.3, mOrientSrc, mOrientDest, true); +mOrientIntB = Quaternion::Slerp(.5, mOrientSrc, mOrientDest, true); mRotProgress = 0;
frameStarted section:
Quaternion delta = Quaternion::Slerp(mRotProgress, mOrientSrc, mOrientDest, true); +Quaternion delta = Quaternion::Squad(mRotProgress, mOrientSrc, mOrientIntA, mOrientIntB, mOrientDest, true); mNode>setOrientation(delta);
Q. Great. Now how do I use smooth rotations in two axis?
A. For example, suppose you want to pitch and yaw, but clamp the roll while still using Slerp. You can use a matrix to get the Euler angles and remove the roll component directly.
Let's say you already have your mOrientDest:
Radian yRad, pRad, rRad; Matrix3 mat; mOrientDest.ToRotationMatrix(mat); mat.ToEulerAnglesYXZ(yRad, pRad, rRad);
Now update the pitch and yaw components, and remove roll:
pRad +=Ogre::Degree(0.8 * timeSinceLastFrame); yRad +=Ogre::Degree(0.8 * timeSinceLastFrame); rRad = Ogre::Degree(0);
Update your matrix and reconvert mOrientDest:
mat.FromEulerAnglesYXZ(yRad, pRad, rRad); mOrientDest.FromRotationMatrix(mat);
Everything else is the same:
delta = Quaternion::nlerp(mRotProgress, mOrientSrc, mOrientDest, true); mCamera>setOrientation(delta)
Resetting Orientation
Q How can I make my objects stand upright after a bunch of rotations?
A. Remember that an object has three sets of axes. The world axes, parent axes and local axes. These are also refered to as Transform Spaces (see SceneNode). Assuming the positive Y axis is considered up for the object, all we need to do is figure out how far off the object's Y axis has gotten off from the world Y axis. Note, we could also apply this same principle, if we wanted the object to stand upright relative to it's parent, only. Imagine space (the world), with a starship (the parent) and an object walking on its surface. We want to reset its orientation to stand upright according to its parent, not the world. Finally, we simply rotate to that vector either instantly or by using slerp. One more thing to note is that to align the Y axes, we must rotate in either the parent's or the world's transform space, not the local space.
// Get rotation to UP vector (UNIT_Y assumed) Vector3 localY = mNode>getOrientation() * Vector3::UNIT_Y; Quaternion quat = localY.getRotationTo(Vector3::UNIT_Y); mNode>rotate(quat, Node::TS_PARENT);
Q How can I make my objects resume their initial facing direction?
A. Since we need to know the initial facing vector of the mesh in order to rotate properly, we just rotate back to this vector. mInitFacing is a Vector3 that points down the initial direction your mesh faces upon loading, such as Vector3::UNIT_X.
// Get rotation to original facing Vector3 currentFacing = mNode>getOrientation() * mInitFacing; Quaternion quat = currentFacing.getRotationTo(mInitFacing); mNode>rotate(quat);
Problems and solutions
Problems with implementing the article's suggestions and solutions to fix those problems. Even if you don't have these problems they might help your understanding of the tutorials.
First problem: The character was backflipping occasionally.
Solution: Actually do the next step that suggests getting rid of the y component even if the character is on a plane because the character is not a plane on equal level with the other plane (my rationalization, not necessarily correct).
Second problem: The character was rotating incorrectly in an inconsistent manner.
Solution: Actually use rotate() instead of setOrientation() because those are two very different functions, though you can rotate by multiplying the previous orientation by the quaternion you want to rotate to.

Alias: Quaternion_and_Rotation_Primer
<HR>
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
1. Definitions
 "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License.
 "Derivative Work" means a work based upon the Work or upon the Work and other preexisting works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timedrelation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License.
 "Licensor" means the individual or entity that offers the Work under the terms of this License.
 "Original Author" means the individual or entity who created the Work.
 "Work" means the copyrightable work of authorship offered under the terms of this License.
 "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
 "License Elements" means the following highlevel license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike.
2. Fair Use Rights
Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.
3. License Grant
Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royaltyfree, nonexclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
 to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works;
 to create and reproduce Derivative Works;
 to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works;
 to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works.
 For the avoidance of doubt, where the work is a musical composition:
 Performance Royalties Under Blanket Licenses. Licensor waives the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work.
 Mechanical Rights and Statutory Royalties. Licensor waives the exclusive right to collect, whether individually or via a music rights society or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions).
 Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor waives the exclusive right to collect, whether individually or via a performancerights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions).
The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved.
4. Restrictions
The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
 You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by clause 4(c), as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any credit as required by clause 4(c), as requested.
 You may distribute, publicly display, publicly perform, or publicly digitally perform a Derivative Work only under the terms of this License, a later version of this License with the same License Elements as this License, or a Creative Commons iCommons license that contains the same License Elements as this License (e.g. AttributionShareAlike 2.5 Japan). You must include a copy of, or the Uniform Resource Identifier for, this License or other license specified in the previous sentence with every copy or phonorecord of each Derivative Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Derivative Works that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder, and You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Derivative Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Derivative Work itself to be made subject to the terms of this License.
 If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK ASIS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability.
EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
 This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
 Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
8. Miscellaneous
 Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
 Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
 If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
 No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
 This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.