Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am attempting to rotate a vector3 by a given quaternion.

I know that this is true

v' = q * v * (q^-1)

I know that q^(-1) is the inverse which just -q/magnitude(q), but how do I map the multiplication of the vector to the quaternion to get back a vector?

I have found that you can treat v as a matrix, and convert q, and q' to matrices, and then convert v' from a matrix to a vector, but this seems a little over the top just to get a vector. Is there a cleaner implementation that I could use?

share|improve this question
1  
Cleaner? You are kidding right, quaternions are pure beauty if you ask me :) –  Maik Semder Mar 6 '13 at 16:14

5 Answers 5

up vote 4 down vote accepted

As Nathan Reed and teodron exposed, the recipe for rotating a vector v by a unit-length quaternion q is:

1) Create a pure quaternion p out of v. This simply means adding a fourth coordinate of 0:

p = (vx, vy, vz, 0) <=> p = (v, 0)

2) Pre-multiply it with q and post-multiply it with the conjugate q*:

p' = q x p x q*

3) This will result in another pure quaternion which can be turned back to a vector:

v' = (p'x, p'y, p'z)

This vector v' is v rotated by q.


This is working but far from optimal. Quaternion multiplications mean tons and tons of operations. I was curious about various implementations such as this one, and decided to find from where those came. Here are my findings.

We can also describe q as the combination of a 3-dimensional vector u and a scalar s:

q = (ux, uy, uz, s) <=> q = (u, s)

By the rules of quaternion multiplication, and as the conjugate of a unit length quaternion is simply it's inverse, we get:

this is very long to re-type

The scalar part (ellipses) results in zero, as detailed here. What's interesting is the vector part, AKA our rotated vector v'. It can be simplified using some basic vector identities:

that too

This is now much more optimal; two dot products, a cross product and a few extras: around half the operations. Which would give something like that in source code (assuming some generic vector math library):

void rotate_vector_by_quaternion(const Vector3& v, const Quaternion& q, Vector3& vprime)
{
    // Extract the vector part of the quaternion
    Vector3 u(q.x, q.y, q.z);

    // Extract the scalar part of the quaternion
    float s = q.w;

    // Do the math
    vprime = 2.0f * dot(u, v) * u
          + (s*s - dot(u, u)) * v
          + 2.0f * s * cross(u, v);
}
share|improve this answer
    
Hats off to a better written response. And considering that most performance freaks tend to use intrinsics to perform vector operations, you do get quite a speed-up (even for plain quaternion multiplication, especially on intel architectures). –  teodron Mar 6 '13 at 17:25
    
The final result looks similar to Rodrigues' rotation formula - it has the same basis vectors, anyway; I'd have to dig into some trig identities to see if the coefficients match. –  Nathan Reed Jul 26 '13 at 18:40
    
@NathanReed This seems to be another way to come to the same result. I'd also like to know if this matches. Thanks for pointing that out! –  Laurent Couvidou Jul 26 '13 at 19:34

First of all, q^(-1) is not -q/magnitude(q); it's q*/(magnitude(q))^2 (q* is the conjugate; that negates all the components except the real one). Of course, you can leave off the division by the magnitude if all your quaternions are normalized already, which they typically would be in a rotation system.

As for the multiplication with a vector, you just extend the vector to a quaternion by setting a quat's real component to zero and its ijk components to the vector's xyz. Then you do the quaternion multiplications to get v', and then extract the ijk components again. (The real part of v' should always come out zero, plus or minus some floating-point error.)

share|improve this answer

First observation: The inverse of q is not -q/magnitude(q), that is completely wrong. Rotations with quaternions imply that these 4D complex number equivalents have unitary norm, hence lie on the S3 unit sphere in that 4D space. The fact that a quat is unitary means that its norm is norm(q)^2=q*conjugate(q)=1 and that means that the quat's inverse is its conjugate.

If a unit quaternion is written as q=(w,x,y,z) = (cos(t),sin(t)v), then its conjugate is conjugate(q)=(w,-x,-y,-z)=(cos(t),-sin(t)v), where t is half of the rotation angle and v is the rotation axis (as a unit vector, of course).

When that Hamilton dude decided to play around with complex number equivalents in higher dimensions, he also stumbled upon some nice properties. For example, if you employ a completely pure quaternion q=(0,x,y,z) (no scalar part w !), you can consider that crap as being a vector (it's actually a quat on what people might call the equator of the S3 sphere, which is an S2 sphere!! - mind bending stuff if we consider how technically impaired the people in the 19th century seem to us eyePhone cowboys nowadays). So Hamilton took that vector in its quat form: v=(0,x,y,z) and did a series of experiments considering the geometric properties of quats.. Long story short:

INPUT: _v=(x,y,z)_ a random 3D vector to rotate about an __u__ unit axis by an angle of _theta_

OUTPUT: q*(0,_v_)*conjugate(q)

where

 q = (cos(theta/2), sin(theta/2)*u)
 conjugate(q) = inverse(q) = (cos(theta/2), -sin(theta/2)*u)
 norm(q)=magnitude(q)=|q|=1

Observation: the q*(0,v)*conj(q) has to be another quat of the form (0,v'). I won't go through all that apparently complicated explanation of why this happens, but if you rotate a pure imaginary quaternion (or a vector in our case!) through this method,you must get a similar kind of object: pure imaginary quat.. and you take its imaginary part as your result. There you have it, the wonderful world of rotations with quaternions in a nut(ty)shell.

NOTE: to whomever jumps in with that overused phrase: quats are good because they avoid 'em gimbal lock.. should unlock their imagination first!! Quats are a mere "elegant" mathematical apparatus and can be avoided altogether by using other approaches, the one I find completely geometrically equivalent being the axis angle approach.

CODE: the C++ library I fancy is rather simplistic, but has all the matrix, vector and quat operations a 3D graphics experimentalist should need without having to waste more than 15 minutes to learn it.. You can test the things I wrote here using that in 15 minutes if you're not a C++ novice. Good luck!

share|improve this answer
    
+1 for your note. I bet most folks couldn't achieve real gimbal lock if they tried.It has become a catch all phrase for any unexpected behavior when performing rotations. –  Steve H May 1 '12 at 20:51
    
Most people can't build a proper gimbal mechanism and think that if they chain together 3 rotations matrices, they automatically end up with the "Euler angles" representation.. The gimbal thingie is just one of the simplest robot-arm-type of rotational joints that can experience redundancy when trying to perform inverse kinematics (it has more degrees of freedom than it actually needs to produce the desired orientation). Oh well, that's another topic, but I thought it's nice to stay away from the hype this "legendary" issue has generated among CG programmers.. –  teodron May 1 '12 at 21:11
    
Nitpickery: while axis-angle is equivalent in that both representations can represent all rotations in SO(3) uniquely (okay, modulo the usual double-cover) and of course there's a nearly-trivial transformation back and forth between them, quaternions do have the advantage of being much easier to compose than all of the other non-matrix representations. –  Steven Stadnicki May 3 '12 at 6:09
    
They have the advantage of being easier to compose due to their nice behaviour in any object oriented programming language, especially when using operator overloading. I'm not sure, but perhaps even their spherical interpolation properties preserve for axis-angle (except for SQUAD maybe?!). –  teodron May 3 '12 at 8:34

Here is an alternative way to transform a vector by a quaternion. It is the way MS does it in the xna framework. http://pastebin.com/fAFp6NnN

share|improve this answer

I tried to work this out by hand, and came up with the following equation/method:

// inside quaterion class
// quaternion defined as (r, i, j, k)
Vector3 rotateVector(const Vector3 & _V)const{
    Vector3 vec();   // any constructor will do
    vec.x = 2*(r*_V.z*j + i*_V.z*k - r*_V.y*k + i*_V.y*j) + _V.x*(r*r + i*i - j*j - k*k);
    vec.y = 2*(r*_V.x*k + i*_V.x*j - r*_V.z*i + j*_V.z*k) + _V.y*(r*r - i*i + j*j - k*k);
    vec.z = 2*(r*_V.y*i - r*_V.x*j + i*_V.x*k + j*_V.y*k) + _V.z*(r*r - i*i - j*j + k*k);
    return vec;
}

I would appreciate if someone would look over mt deriviation I used http://pastebin.com/8QHQqGbv I would suggest to copy to a text editor that supports side scrolling

in my notation I used q^(-1) to mean conjugate, and not inverse, and different identifiers, but I hope that it is follow-able. I think that the majority is right especially where on proving the real portion of the vector would disappear.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.