3
\$\begingroup\$

In tutorials regarding the MD5Mesh format, like this one, we often see code like

float t = 1.0f - (q.x * q.x) - (q.y * q.y) - (q.z * q.z);

if (t < 0.0f) {
   q.w = 0.0f;
} else {
   q.w = -sqrt (t);
}

for computing the w-component of a unit quaternion given x, y, z. Why do we obtain w in this manner?

\$\endgroup\$
3
\$\begingroup\$

The MD5 file format assumes unit quaternions, which are of norm one. The norm of some quaternion q is:

|q| = sqrt((x * x) + (y * y) + (z * z) + (w * w))

You can rearrange this equation in terms of w by squaring both sides and then subtracting the terms containing x, y and z to yield:

(w*w) = (|q|*|q|) - (x*x) - (y*y) - (z*z)

Since the quaternion is assumed to be of norm 1, the |q|*|q| term is thus 1, and that's how you arrive at the initialization of t in your code snippet. Taking the square root of t yields the value of the final component, the sign of which is chosen as an orientation convention.

\$\endgroup\$
2
  • \$\begingroup\$ Working the problem by hand, I arrived at w = ± sqrt(1 - x^2 - y^2 - z^2), but I am shaky on the if-statement logic. Does t < 0 occur often in practice? What I am trying to figure out is if we are mitigating the effects of bad input by setting w to a reasonable value of 0 (I am new to quaternions, so forgive my greenness). \$\endgroup\$ – pcapp May 3 '13 at 2:18
  • \$\begingroup\$ @pcapp, you could add logging to that branch, but I think it's less about mitigating bad input and more about not getting NaN when rounding causes t to be something like -1E-9. \$\endgroup\$ – Peter Taylor May 3 '13 at 8:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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