Understanding Skinning

Hi all. I’m newly to skinning/Collada/openGL so sorry for my ignorance and basic questions.

I have a Collada model file that I am working on rendering using openGL. I am currently working on skinning, but am not doing it correctly. I know that the vertex value needs to be computed:

outv = SUM (((v * BSM) * IBMi * JMi) * JW)

Where does the JMi (Transformation matrix of joint i) come from? I assume it comes from the joint node (and the node’s ancestors?). Does it include the “jointOrient{X,Y,Z}” values?

We have it setup so that if we draw the mesh it is placed perfectly in the bind pose (bind pose is the identity matrix). The particular object that we’re trying to render should be in the bind pose … so the final effect of the equation above for this rendering should be: outv = v. Of course I would like to get this equation setup properly for animation.

Thanks,

-joel

Figured out the problem.

Yes, the basis for the JMi matrix comes from joint node (and ancestors), and does include “jointOrient{X,Y,Z}”.

The problem I was actually having was due to the fact that I misunderstood the following:

Matrices in COLLADA are column matrices in the mathematical sense. These matrices are written in row-major order to aid the human reader.

See this thread for more: https://collada.org/public_forum/viewtopic.php?t=677

The .dae file generated has the Inverse Bind Matrices in row-major order. So, if you are parsing … use row-major order.

-joel

Hi Joel,
thanks for your post. I’m trying to implement skinned meshes from collada data as well, but I haven’t been successfull yet.
Can you tell me how you calculated the JMi matrix exactly?
Do the transformations have to be calculated in the order given?
I.e. if you have this node:
<node id=“head” name=“head” sid=“bone12” type=“JOINT”>
<translate sid=“translate”>7.2052 0 0</translate>
<rotate sid=“rotateZ”>0 0 1 90</rotate>
<rotate sid=“rotateX”>1 0 0 -78.8897</rotate>
translate has to be applied first, then rotateZ, then rotateX? Or maybe it uses a right to left convention, in which case it would be the other way around.

Sorry its taken me so long in getting back to this forum CaptainFreedom!

We applied the transformations in the order given. I.e., translate, rotate, rotate, etc.

We also navigated the bone hierarchy and performed matrix multiplications of the ancestors of Joint i.

Our rendering is not exactly right yet, but I’ll explain in a detail what we do and if someone sees our problem that would be nice. :wink:

In our example we have the following joint hierarchy:

bone0 --> bone1 --> bone2, bone3, bone4

[bone0 is the root of the tree, bone{2,3,4} are the leaves]

When parsing the collada file we compute a 4x4 matrix at each JOINT NODE using the translates, rotates (as mentioned above).

In order to compute the joint matrix, JMi, we traverse the tree from root to Joint i multiplying the matrices. Example: JM2 = M0 * M1 * M2.

The problem we are running into is that if say we rotate bone1 45 degrees (by performing a rotation(45) on M1 and then recompute JM2 we will not get the same value for JM2 if we had rotated bone2 45 degrees. Rotating bone1 or bone2 should result in the same rotation for the object we are working with.

Our render code (in OpenGLES) works for the case when we rotate bone2 (a leaf in the tree). We have also checked that with no transformations IBM2 * JM2 = identity, which is what is expected.

So are we correct in computing JM2 = M0 * M1 * M2? How do we handle a rotation that is not in the leaf of the joint tree? <— not really Collada questions … but somewhat related.

Thanks,

-joel

We use a different method. We use the bake transforms in maya for our export which means we will only get matrices, I wouldn’t be surprised if there’s a conditioner for this as well.

what about vertex normals?
what is proper method / equation to rotate those when skinning/animating a mesh?

ok solved it. apparently excatly same as vertices, except you only rotate normals and don’t do any translations :slight_smile: