What is the rationale behind this method of computing the w-component from MD5 mesh files?

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?

-

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.

-
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). –  pcapp May 3 '13 at 2:18
@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. –  Peter Taylor May 3 '13 at 8:19