3

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?

Kevin Reid
  • 5,498
  • 19
  • 30
pcapp
  • 33
  • 2

1 Answers1

3

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 03 '13 at 02: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 03 '13 at 08:19