Skinning - does it make sense?

Started by
7 comments, last by Nik02 14 years, 8 months ago
Hi, I'm currently working on an inverse kinematics project. The skinning on the GPU via DirectX has already been implemented by someone else and is working fine. The animation comes from 3DS but due to a special export, I can only access the bones' matrices before rendering. Before even thinking about IK, I would like to change the rotation of the knee as a test, I would like to know if it makes sense to get the local matrix of the knee joint before rendering, apply a rotation to it, and then let the rendering do the skinning. I tried it and got weird stuff... I don't know if that's because my rotation is messed up, or simply if because the method doesn't make any sense (considering how skinning works afterward). Please let me know what you think about it. Thanks
Advertisement
Are you updating the bone hierarchy after the transformation? Do the transformation get to the shader correctly? What wierd stuff are you experiencing? Can you post a screenshot (if available)?
Sorry for not getting back to you earlier, I messed up my code at some point and it took me forever to fix it :/ The vertex shader performing skinning is working fine, but I think I misunderstood how it deals with the transformations applied to the vertices. I also don't know what you mean by "updating the bone hierarchy". I was just trying to rotate the right knee (the next step being to recompute it using inverse kinematics).

Here are example screenshots:

The model walking normally:



Here is the result after applying a simple rotation of a few degrees around the Z axis of the right knee (Z is the axis I have to use if I want to bend the leg).



As you can see the result is quite unexpected... there is a serious scaling problem, it means that applying the rotation:

nRightCalf->setLocalTransform(nRightCalf->localTransform() * rotationZ(RAD(-45.0f)));


is not the good way to rotate the knee :) Any idea why?

Thanks for helping.

[Edited by - gOOze55 on July 29, 2009 3:48:15 AM]
Each node (bone) of the tree (skeleton), except the root, has a transformation relation to its parent. This is what Bangladesh meant by hierarchy.

The error you see in the image is due to the fact that the root node has scaling (approximately 0.25) and rotation (-90° around x-axis) applied, but the lower leg doesn't apply the transforms of the hierarchy so far, so it doesn't follow the root or other bones before it in the hierarchy.

For each bone, you need to apply the transforms of all its ancestors in the bone hierarchy. This is easiest to do with a matrix stack.

Niko Suni


Hi Nik02,

Thanks for the explanation.

When my code gets to the point where I want to rotate the knee, the local transformation matrix is already computed and correct (first screenshot, so transforms of all its ancestors have already been used for computing the local matrix). But as soon as I apply the rotation:

nRightCalf->setLocalTransform(nRightCalf->localTransform() * rotationZ(RAD(-45.0f)));


I get to the second screenshot. It looks like it's just a scaling problem on that picture but the leg is actually completely messed up, it's not even scaled proportionally. And the distortion is not constant as the animation goes on.



I wonder if this is just a transformation problem (wrong axis or another minor mistake), or if the way I'm proceeding (altering only 1 matrix manually before sending to the vertex shader) is wrong.

Thanks
Now that I have a clear view of the problem:

The rotation happens about the origin of the model space now. You should do the rotation of the leg bone before concatenating the transform hierarchy, not after like you're doing now.

In effect, the actual problem is that the transform hierarchy has been calculated before the rotation.

Remember, matrix multiplication is non-commutive; that is, the order of the transforms is important.

Niko Suni

That makes sense. Weird that when I just try to translate the foot using

Matrix4 mOffset = Matrix4::translation(offset, 0.0f, 0.0f);nRightFoot->setLocalTransform(mOffset * nRightFoot->localTransform());


I pretty much get what I want. The translation works fine even at that stage maybe. The foot is translated along the local X axis.



I'm going to check where this hierarchy transformations are concatenated and see if I can't do something before that. The animation being exported from 3D studio max (using a module I don't know anything about), I worry that there is no way to modify stuff the way I want :(

Thanks for your help ;)
Very nice model :D
The translation "works" because its effect doesn't depend on any axis unlike rotation. However, the end result is still incorrect as you can see :)

In practice, it is best to handle all the individual bone transforms in the modeling program, and just transform the root bone manually (+ update the hierarchy after that if needed) when you need to move the model in general.

If you do implement IK in your engine, you have to update the whole bone hierarchy manually anyway. It is not enough that you transform one of the leaf nodes (such as the leg bone) - you need to calculate the transforms of all bones below that in the hierarchy as well. This means quite a bit of work for you, but if you understand the concepts involved, it shouldn't be hard.

Niko Suni

This topic is closed to new replies.

Advertisement