Original Post
I've been working for a couple of weeks at getting skinned animation in my game. Its working except for one fundamental detail: the bones are getting screwed up during coordinate system conversions. I'm using the md5mesh format, which stores bones in object space. I'm taking these bones and transforming them into parent space, performing the necessary animations (none at the moment), and converting them back to object space for rendering. Everything works if I just leave them in object space, but then I wouldn't be able to animate them. I realize this might be a bit confusing (its certainly confusing me) so I don't expect anyone to solve the problem for me; just help me figure out what I might have done wrong. I suspect the math logic must be wrong somehow. The general format of my math functions is fn(output, operand1, operand2, ...). Everything is shortened (ie: quat refers to quaternion, conj refers to conjugate). Here's my method for getting the bones from object space into parent space: Now, using the results of the previous method, we try to get the bones back into object space: My bones are stored in an array, sorted with root bones coming first and terminal bones coming last. This is so I can iterate forwards to cumulate the effects of my transformations through the heirarchy, or backwards to avoid cumulation. The first method iterates backwards so that each bone's parent remains in object space until all of its children have been transformed. The second method iterates forwards so that the transformations can be accumulated down the heirarchy. [Edited by - dcosborn on October 23, 2005 4:54:28 PM]
// bone->origin is a 3 component origin vector
// bone->orient is the bone's orientation as a quaternion
// 1. subtract the parent's origin from the bone's origin
util_math_vec3_sub(&bone->origin, &bone->origin, &bone->parent->origin);
// 2. find the inverse of the parent's orientation
struct util_math_quat parent_orient_inv;
util_math_quat_conj(&parent_orient_inv, &bone->parent->orient);
// 3. multiply the inverse with the bone's orientation
util_math_quat_cat(&bone->orient, &bone->orient, &parent_orient_inv);
// now bone->origin and bone->orient should be relative to the parent
// bone->space is the final object space matrix for vertex skinning
// 1. generate the bone's matrix using its orientation
util_math_mat4_quat(&bone->space, &util_math_mat4_id, &bone->orient);
// 2. translate the bone's matrix using its origin
util_math_mat4_tlat(&bone->space, &bone->space, &bone->origin);
// 3. concatenate the bone's matrix onto the parent's matrix
if (bone->parent) util_math_mat4_cat(&bone->space, &bone->space, &bone->parent->space);
// the resulting matrices are used to transform the mesh's weighed vertices