I know that quaternions need to be normalized if I want to rotate a vector.
But are there any reasons to not automatically normalize a quaternion? And if there are, what quaternion operations do result in non-normalized quaternions?
Sorry, if this question is a little bit fuzzy. I'm still trying wrap my head around quaternions.
When normalized, a quaternion keeps the same orientation but its magnitude is 1.0. Note that this method will change the current quaternion. If you want to keep the current quaternion unchanged, use the normalized property instead. If this quaternion is too small to be normalized it will be set to Quaternion.
They also can offer better performance: Although a single rotation using a quaternion is a little slower than one using a matrix, when combining actions, quaternions can be up to 30% faster.
A quaternion represents two things. It has an x, y, and z component, which represents the axis about which a rotation will occur. It also has a w component, which represents the amount of rotation which will occur about this axis. In short, a vector, and a float.
Quaternions are mainly used in computer graphics when a 3D character rotation is involved. Quaternions allows a character to rotate about multiple axis simultaneously, instead of sequentially as matrix rotation allows.
Late response; this answer is for people who come across this question in the future rather than for the questioner.
I disagree with the other two answers regarding only normalizing a quaternion occasionally. The standard formulae for using a quaternion to rotate/transform a vector or to generate a rotation/transformation matrix implicitly assume the quaternion is normalized. The errors that result from using an unnormalized quaternion are proportional to the square of the quaternion's magnitude. Quadratic error growth is something best avoided.
If you normalize frequently you don't need square root. A first order approximation works quite nicely. Here's what I use for quaternions as IEEE doubles, somewhat stylized:
double qmagsq = quat.square_magnitude(); if (std::abs(1.0 - qmagsq) < 2.107342e-08) { quat.scale (2.0 / (1.0 + qmagsq)); } else { quat.scale (1.0 / std::sqrt(qmagsq)); }
Note that I'm using the first order Padé approximant 2.0/(1.0+qmagsq)
rather than the first order Taylor expansion 0.5*(3.0-qmagsq)
to estimate 1.0/std::sqrt(qmagsq)
. This approximation, if valid, replaces the square root call by a simple division. The key is to find when that approximation is valid, which is where that magic number 2.107342e-08 comes into play.
Why a Padé approximant? Two reasons. One is that for values of qmagsq
close to one, 1+qmagsq
loses less precision than does 3-qmagsq
. The other is that the Padé approximant cuts the error by a factor of three compared to the Taylor expansion. For values of qmagsq
between 0 and 2, the error in this approximation is less than (1-qmagsq)^2 / 8
. The magic number 2.107342e-08 represents where this error is more that half an ULP for IEEE doubles. If you are taking reasonable small steps, the square of the magnitude of the quaternion will always be within that limit. You'll never be calling sqrt
.
The one exception to this "normalize always" paradigm might be if you are using a Lie group integration technique to propagate quaternions. If you don't know what that means, you are probably using the equivalent of q(t+Δt) = q(t) + dq(t)/dt*Δt
to propagate a quaternion. You're still using that Euler step somewhere even if you are using a higher order integration technique that isn't a Lie group integrator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With