kvark's picture

[Math] Add vector transformation by quaternion

Project:The Open Toolkit library
Category:feature request

Need something like:
public static Vector3 Vector3::TransformPoint(Vector3 vec, Quaternion quat)
in order to rotate the point by the given quaternion


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kvark's picture


Currently the same transformation is possible through a temporary matrix. But my project aims to avoid using matrices completely, because Vectors+Quaternions+Scaling is enough. Moreover, a direct Quaternion transform can be faster than the one that uses matrix.

the Fiddler's picture


Status:open» confirmed

Just a word of warning: transforming through a matrix is faster if you have a lot of points.

kvark's picture


To say in my defense:
from the link about the quaternion version:
The vertex shader is a little bit more complex, but faster than the matrix version

the Fiddler's picture


Thanks for the link.

I based my observation on the source code of the Allegro library (search for "quat_apply").

A quick calculation seems to confirm that:

  • Matrix-vector transformations require 4 dot products (16 mul-add instructions).
  • Quaternion-vector transformations require a quaternion inversion (8 mul-add plus a division) and two quaternion multiplications (16 mul-adds each).

If you have to transform only a few points, then using quaternions will probably win out. As points increase, the cost of the quat -> matrix conversion will become less significant, making this route faster.

I *think* that the Lumina is optimized to work with normalized vectors only. The don't mention this, but their qrot method looks nothing like typical quaternion-vector rotations.

kvark's picture


Ha! Who is going to pass non-normalized quaternions to GLSL program?
Lumina's qrot uses:
2 vector add
2 vector mul by a scalar
2 vector cross products

Not that big calculation, I think.
Of course, I agree that doing it on CPU is another domain (what is actually happened in OpenTK.Math), but this doesn't stops the idea of doing *all* transformations in quaternions, without matrices, as the major part of them will be produced by GPU inside the vertex shader.

kvark's picture


Moreover, in vertex shader it's often practiced to transform vertex twice:
1) from local to world Coordinate System
2) from world to camera CS

In case of matrices it's implemented as 2 matrix * vector multiplications.
In case of quaternions it's 3 quaternion multiplications plus one normalized quaternion negation (nothing actually).
The second approach seems to me to be a *lot* faster :)

the Fiddler's picture


An interesting read: rotation using quaternions in a shader.

The consensus seems to be that quat-matrix transforms are faster on the CPU but slower on the GPU. Using pure rotation matrices is faster throughout, but quaternions save space which can result in a net win.

In any case, we should add Quaternion overloads to the Vector[234].Transform() methods.

kvark's picture


These guys discussed GPU usage of quaternions but really referred to the external sources (http://www.geometrictools.com/Documentation/RotationIssues.pdf) that concern calculation on the CPU. Therefore, as far as I can see, the "frostburn" statement about matrices 3x3 being faster is incorrect in case of GPU. The conclusion for me is opposite: quaternions can be slower on CPU, but faster on GPU. And, again, these guys wanted to do instance drawing fast, when everything in the vertex input is prepared for drawing. However, In a more general case, it's always required to combine transformations both on GPU and CPU, and it's simpler and faster with Quaternions indeed.

the Fiddler's picture


Version:0.9.9-0» 0.9.x-dev
Status:confirmed» fixed

Initial implementation on rev 2425, please test!

the Fiddler's picture


Version:0.9.x-dev» 1.0-beta-1
Status:fixed» closed

Closing issues fixed in 1.0 beta-1.