Smooth skinning algorithm

Started by
6 comments, last by deh0512 15 years, 11 months ago
I've read a few articles (and skimmed through a bunch of posts) about CPU skinning. I've tried to implement it for a while, but it just doesn't seems to work for me. I know that the equation looks something like this, v' = sum( Weight * TransformMatrix * ReferencePose^-1 ) * v; But when I try to implement this on a single point, it fails. Below are 2 screen shots I took. The first pic is a skeleton in its reference pose, with left arm rotated at -90 degrees in the z axis, and the right arm rotated in 90 degrees in the z axis. and the blue point is a vertex of a mesh, its coords are (19.426800, 9.168850, 0.129585) the second pic is the skeleton's right arm is in its default pose, where all its matrices are set to their identities. since the blue point is at the edge, I assume its under the influence of just 1 bone. So I don't have to calculate the sum of the weights, I just calculate: v'= TransformMatrix * ReferencePose^-1 * v where: v = (19.426800, 9.168850, 0.129585) TransformMatrix = Identity Matrix ReferencePose^-1 = the inverse matrix of 90 degrees in the z axis And when I compute the result, I get v'=(9.168850, -19.426800, 0.129585) As you can see in the second pic, that is not where v' should be. Any ideas on what I'm doing wrong?
Advertisement
noone know what Im doing wrong?
well any suggestions would be appreciated.
Quote:Original post by FireVipersince the blue point is at the edge, I assume its under the influence of just 1 bone. So I don't have to calculate the sum of the weights, I just calculate:

v'= TransformMatrix * ReferencePose^-1 * v

where:
v = (19.426800, 9.168850, 0.129585)
TransformMatrix = Identity Matrix
ReferencePose^-1 = the inverse matrix of 90 degrees in the z axis


I'm not sure what your specific problem is, but it sounds like you might be misunderstanding the data you're working with.

The point may be under the influence of a single bone, but that bone is under the influence of every other bone up the hierarchy. So for a point attached to the hand, the matrices should have some translation at least.

Think of the inverse reference pose as moving the bone to the origin, and rotating it to 0, which drags all the vertices along with it. Then TransformMatrix moves everything over to the new position.
Quote:So for a point attached to the hand, the matrices should have some translation at least.


The only thing Im doing to the bones are rotating them, where does the translation come from?
Are you referring to the distance from the start of the bone to the end as the translation?

Your vert is rotation around the world origin, while the bone is rotating around the bones further up the heirarchy.

You need to be effectively rotating the vert around the same point as the bones are rotating around. I think what DekuTree is saying is to translate so the world origin is the correct point of rotation, perform the rotation, and then translate back.
I get what you'er saying, but Im not sure how to do it. I mean I know I have to translate the matrix by a certain point, then rotate it, and translate it back, but I'm not sure how to calculate the translation?
ok, let me clarify a few things. Each Bone has:

Parent - A pointer to its parent
length - (float) the length of the bone
Rotation/Position - (vector) The Rotation and Position
Direction - (vector) Bone's Direction
Transform - The Transformation Matrix
InverseBind - The Inverse of Transform in the reference pose
Start/End - The Start and End points of the bone

This is the code I use to move a Bone.

void bone::Set(){    //Calculate Bone's Relative Matrix  Transform = matrix4(); //Set Transform to its Identity  Transform.SetRotation( Rotation );  //If parent exist  if(Parent!=NULL)    //Combine Relative Matrix with Parent's Matrix to form Absolute Matrix    Transform = Transform * Parent->Transform;      //Calculate Bone's orientation  vector3 tempVec = (Direction * length) * Transform;  if(Parent!=NULL)     Start = Parent->End;  else     Start = vector3();   End = Start + tempVec;   }


The only translation I see here is the distance from Start to End, which is calculated in tempVec. Are you saying I should combine this with the Transformation Matrix?
Fireviper,

I don't know if you've figured this one out just yet since it was posted a week ago, but...

Quote:The only translation I see here is the distance from Start to End, which is calculated in tempVec. Are you saying I should combine this with the Transformation Matrix?

Basically, yes. The Start is (more or less) the translation of the bone. If that value is kept in the transformation matrix, there is no need to keep it separately.

To be honest, you could conveniently not keep track of most of the information you have. You definitely don't need to know the length, direction, start, or end of a bone (you can figure it out at any point you need it fairly easily)... and you really don't need to know the rotation and position in vector format (the rotation especially might become hard to compute from the matrices). You should specify a bone's transformation in terms of the parent's transformation, not in terms of a global reference frame. And keep a combined transform matrix at each bone, so that updating a bone becomes natural by recursion. Simply set the root's combined matrix to the local matrix, then step through the skeleton/tree recursively passing the combined matrix to the child. The child in turn sets its combined matrix to the value it receives * the local matrix, and passes that on. Use the combined matrix to update vertices (or its inverse...). That's it. Everything else is extraneous.

As a side note, drawing each bone (as in the program you are working on) can be done as you step through the skeleton/tree. Points that represent each bone's start can be drawn by extracting the translation element of the combined matrix after the multiplication takes place. The root node will not draw any lines, but each successive bone will draw a line from the previous translation (extracted from the transformation matrix it receives) to the new combined translation (extracted from its combined matrix after the multiplication).

Hope that helps.
David Hooks

This topic is closed to new replies.

Advertisement