Animation Samples please?

Hey everyone

Just to clarify could I get some examples of how animated rotations, translations, and scaling are performed on different/seperate nodes in “working” collada syntax? Also with use of referencing in params to set things like origin or angle of rotation( an any other transformation).

It want to make sure I understand and write my code properly.

Thank you.

There are animated models in the model bank here at you can use for testing.

Animation channels target COLLADA elements that have an “sid” attribute.

Each <node> is a local coordinate system, that can have an arbitrary transform stack, and you can animate the transform elements discretely.

I suggest reading the COLLADA 1.5 specification: Chapter 3, Address Syntax; chapter 4, Curve Interoplation; chapter 5, animation and animation clip sections.

Thank you marcus.

Another query:
I assume that animating nodes through a skeleton referenced by <controller> and <skin> would allow me to drive a model assembly? This is my goal after all: To skin a model according to a skeleton which is a framework of that same model.

So I am thinking that in order to achieve this that I must do the following:

-Create nodes relating to each segment(set of vertices) of the framework(bones ) and full 3D model to be driven.

-Use a skin controller to link the movement of the framework segments with the corresponding full 3D model segments.

-Then animate the nodes used in the controller to define the skeleton or bones, which in turn animate the full 3D model according to the weights.

Is this correct?

Yes pretty much. Animated skinned models are usually created in DCC tools (by animators and character riggers).

I recommend reading more about <skin> in the COLLADA specification too. The skin mesh is bound to the base mesh geometry and influenced by the skeleton joint (bone) weights. COLLADA uses <node> elements to represent the skeleton joint hierarchy.


whew, I have been trying for a long time to calculate the inverse bind matrix for ‘l_hip’ skeleton node in the Seymour_anim2.dae file from the model bank but can’t seem to get it.

I am writing the section exporter in Matlab and thus can’t leverage the dom C functions easily.

Would someone please explicitly write out the calculation for the bind matrix here using the tranforms applied to ‘l_hip’ node and compare it to the corresponding inverse bind matrix in relevant controller - poses source.

Most likely I am forgetting something as I have tried both pre and post matrix multiplication to be sure.

Many thanks.

“calculate”? They should be stored in the document as a <source>. Look for the “INV_BIND_MATRIX” semantic.

Have you looked in the 1.5 specification in chapter 4, Skin Deformation (Skinning) in COLLADA?

COLLADA describes column-major matrices and vectors, so post multiplication is the norm. Although looking at the equation on page 38 and again on 175, it’s written as row-major with pre multiply. I think this might be a bug in the spec to document skinning in row-major order, especially if it leads to confusion (i.e. transposed data).

I meant to use the previously calculated InvBM so that I can make sure that the algorithm I write for calculatin of the inverse bind matrix in my seperate and different model is correct.

For example:

Assuming from what I have read correctly, a 16 float section of the list in the float array source: 0.140232  -0.988632  0.054244  4.337131 -0.853634 -0.148476 -0.499264 0.700237 0.501642  0.023708  -0.864750  -0.918260  0    0  0  1.000000

becomes InvBM ,as seen below, since it is stored in row major form whilst in the file as a float array:

 0.140232  -0.988632  0.054244  4.337131 
-0.853634 -0.148476 -0.499264 0.700237 
0.501642  0.023708  -0.864750  -0.918260 
0                 0               0                1.000000

The corresponding node definition and transformations on 'l_hip' joint node from which I presume can be used to calculate the InvBM ( above) or BM :
   <visual_scene id="VisualSceneNode" name="untitled">

      <node id="group1" name="group1" type="NODE">

        <rotate sid="rotateZ">0 0 1.000000 0</rotate>

        <rotate sid="rotateY">0 1.000000 0 0</rotate>

        <rotate sid="rotateX">1.000000 0 0 0</rotate>

        <node id="root" name="root" sid="root" type="JOINT">

          <translate sid="translate">0 4.363676 -1.020067</translate>

          <rotate sid="jointOrientZ">0 0 1.000000 0</rotate>

          <rotate sid="jointOrientY">0 1.000000 0 0</rotate>

          <rotate sid="jointOrientX">1.000000 0 0 0</rotate>

          <node id="l_hip" name="l_hip" sid="l_hip" type="JOINT">

            <translate sid="translate">0.450181 0.049889 0.340342</translate>

            <rotate sid="jointOrientZ">0 0 1.000000 -81.926788</rotate>

            <rotate sid="jointOrientY">0 1.000000 0 -3.109476</rotate>

            <rotate sid="jointOrientX">1.000000 0 0 0</rotate>

            <rotate sid="rotateY">0 1.000000 0 0</rotate>

            <rotate sid="rotateAxisX">1.000000 0 0 -150.000000</rotate>

            <node id="l_knee" name="l_knee" sid="l_knee" type="JOINT">

              <translate sid="translate">1.833014 -0.024761 -0.002519</translate>

              <rotate sid="jointOrientZ">0 0 1.000000 2.742172</rotate>

              <rotate sid="jointOrientY">0 1.000000 0 -8.695618</rotate>

              <rotate sid="jointOrientX">1.000000 0 0 -120.102058</rotate>

              <rotate sid="rotateZ">0 0 1.000000 0</rotate>

              <rotate sid="rotateAxisX">1.000000 0 0 -167.476486</rotate>

So I am testing my calculation of the InvBM using this example data so that when I write the controller I can populate the InvBM appropriately for my skeleton. Am I thinking about this correctly?


Ok, I solved it.

Here is my matlab code to recalculate the inverse binding matrix from the sample data above. It helped me understand further what the BM is. Maybe you could sticky this info in some form marcus as it would help anyone trying to write an exporter from “raw data”.

Note: That I have left out a few transforms since their angles were 0 and not necessary in the verification.

TA1 = [1.000000 0.0        0.0        0.0 ; ...
       0.0        1.000000 0.0       4.363676 ;...
       0.0      0.0       1.000000 -1.020067 ;...
       0.0       0.0       0.0       1.000000];
angleZ = -81.926788;
angleY = -3.109476;
angleX = 0.0;
angleX2= -150.000000;

TB1 = [[eye(3) ; 0.0 0.0 0.0 ] [0.450181 0.049889 0.340342 1.0]'];

TB2 =[cosd(angleZ) -sind(angleZ) 0.0 0.0 ; sind(angleZ) cosd(angleZ) 0.0 0.0 ; 0.0 0.0 1.0 0.0 ; 0.0 0.0 0.0 1.0]
TB3 = [cosd(angleY) 0.0 sind(angleY) 0; 0.0 1.0 0.0 0.0 ; -sind(angleY) 0.0 cosd(angleY) 0.0 ; 0.0 0.0 0.0 1.0] 
TB4 = [ 1.0 0.0 0.0 0.0 ; 0.0 cosd(angleX2) -sind(angleX2) 0.0 ; 0.0 sind(angleX2) cosd(angleX2) 0.0 ; 0.0 0.0 0.0 1.0 ]

T1= TA1*TB1;
T2 = T1*TB2;
T3 = T2*TB3;
T4 = T3*TB4; % Calculates the Binding Matrix for l_hip

inv(T4)  % The inverse binding matrix

This code was written according to the following as before I was trying the pre multiplication mentioned earlier in the same topic by the same person but using his definition for post multiplication I managed to finally get the right values and verify that it is the post multiplication that I needed:

The full topic is here: . Read this to see how TA1 and TB1 are the hierarchy of node transformations.

For post-multiplication:
M = (T1A x T1B x T1C) x (T2A x T2B x T2C) x (T3A x T3B x T3C)
wv = M x v
v = vertex in local space
wv = vertex in world space

For OpenGL:
is equal to
glMultMatrix(T1A x T1B x T1C);

For <translate> to <matrix> conversion:
<translate>2 3 4</translate>
is equal to
<matrix>1 0 0 2 0 1 0 3 0 0 1 4 0 0 0 1</matrix>

For OpenGL:
GLfloat T1A[] = {2, 3, 4};
is equal to
GLfloat T1A[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 3, 4, 1};

Mark, does this make sense?


Thanks for your help marcus

You’re very welcome Edward!

ps: stickied.