A faster quaternion-vector multiplication

Today’s post is only a small gem I accidentally came across while I was looking for something entirely different: a faster method of multiplying a quaternion by a vector.

I use quaternion-vector multiplication (rotating a vector by a quaternion) mostly in two places:

  • When building the global pose of a skeleton from its local pose, as discussed in this blog post.
  • In vertex shaders that are used with instanced rendering, so I only have to send one quaternion (float4) instead of a whole rotation matrix (float3x3).

The canonical way of multiplying a quaternion q by a vector v is given by the following formula:

v' = q * v * conjugate(q)

where the vector v is being treated as a quaternion with w=0, so the above essentially boils down to two quaternion multiplications, which are a bit expensive.

Turns out there is a faster way, which is the following:

t = 2 * cross(q.xyz, v)
v' = v + q.w * t + cross(q.xyz, t)

The faster method comes courtesy of Fabian Giesen (ryg of Farbrausch fame), who posted this to the MollyRocket forums years ago. Another derivation, yielding the same result, can be found here.

In my SSE2 code path, the new method is about 35% faster than the original. Enjoy, and don’t forget to share this gem with other people!

Advertisements

6 thoughts on “A faster quaternion-vector multiplication

  1. Pingback: Understanding quaternions | Light is beautiful

  2. I optimized the quaternion rotation formula for a vector P and came up with this formula. Where v is the vector part of the quaternion and w is the scalar part. It runs about 15% faster than the formula that you posted here.
    p’ = (v*v.dot(p) + v.cross(p)*(w))*2 + p*(w*w – v.dot(v))

    • It is weird, that your method, which contains 22 float multiplications, 15% faster than post-proposed method with 15 float multiplication, If anything – it should yours to slower.

    • I don’t think that’s right, Francisco. You’ve turned the term v.cross(v.cross(p)) into -v.dot(v)*p, which is only true in the special case v and p are perpendicular.

  3. This is also what the glm library uses. I found the implementation changes between versions, so the latest one should reflect what the developer finds the fastest.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s