eduardo simioni


understanding transformation matrices

by on Aug.28, 2016, under Uncategorized

After some children hiatus, I need to finish this post I’ve drafted a while ago. I’ll do another one when I get my hands on a Maya install, in the meantime copy this into the Maxscript editor and try it out:

pt = point axistripod:true size:1 name:"trMatrix"

spX = sphere wirecolor:red radius:0.05 name:"xVector"
spY = sphere wirecolor:green radius:0.05 name:"yVector"
spZ = sphere wirecolor:blue radius:0.05 name:"zVector"

ctrl = position_script()
ctrl.addNode "pt" pt 
spX.position.controller.script ="[pt.transform[1][1], pt.transform[1][2], pt.transform[1][3]]"

ctrl = position_script()
ctrl.addNode "pt" pt 
spY.position.controller.script ="[pt.transform[2][1], pt.transform[2][2], pt.transform[2][3]]"

ctrl = position_script()
ctrl.addNode "pt" pt 
spZ.position.controller.script ="[pt.transform[3][1], pt.transform[3][2], pt.transform[3][3]]"

This will create a point that we will call trMatrix, this is “the matrix we will be trying to understand”. Together with the point it will create three spheres, one for each axis. With a Script Controller, it will also constraint the position of each sphere to each row of the transformation matrix. So red spX will be constrained to the first row, the “x vector”, of trMatrix.transform, green spY to the second row, the “y vector”, and blue spZ to the third row, the “z vector”.

Now rotate trMatrix (don’t move it just yet, only rotate it), run this afterwards and try to understand what’s happening:

print pt.transform
print "Sphere X position: " + (spX.position as string)
print "Sphere Y position: " + (spX.position as string)
print "Sphere Z position: " + (spX.position as string)

Due to the script controller from before, each position in global space for each sphere is actually a row from trMatrix point’s transform matrix. So in this case, each row of the transform matrix is actually just “an offset from zero”. In other words, it’s simply a vector in 3d space whose origin is 0, 0, 0.

Now if you move trMatrix point the spheres will stay in the same place. They are constrained to each vector in the transform matrix, but those are not affected by the point position, the last row. If you want the spheres to follow the point, you simply need to add each value from the position vector on the script controller expression, with this:

spX.position.controller.script ="[pt.transform[1].x+pt.position.x, pt.transform[1].y+pt.position.y, pt.transform[1].z+pt.position.z]"--set the expression
spY.position.controller.script ="[pt.transform[2].x+pt.position.x, pt.transform[2].y+pt.position.y, pt.transform[2].z+pt.position.z]"--set the expression
spZ.position.controller.script ="[pt.transform[3].x+pt.position.x, pt.transform[3].y+pt.position.y, pt.transform[3].z+pt.position.z]"--set the expression

All animators already know this intuitively but here’s the thing: a local matrix position is simply an offset, a vector offset, from its parent, as if that parent was the origin (0,0,0). The global matrix is the object matrix in relation to the origin itself, but the local one is as if the origin “moved” to its parent. And so is with a hierarchical skeleton up until the root.

Lastly, here’s quickly two ways in Maxscript to get the local matrix:

$.transform * (inverse $.parent.transform)
Leave a Comment more...

Python, modules and static objects

by on Jan.17, 2014, under python, Uncategorized

There’s this little caveat about python I recently learned that would have helped me understand some of its concepts much more clearly if I was told this earlier on:

A module is a static object.

That means, and please someone correct me if I’m wrong, but maybe with the exception of global variables (which you should avoid anyway), you can treat a module as a static object. So instead of creating a static class for some tool functions you can just group all those functions into a separate .py.

One of the best things in python is how easy and robust is to work with modules, do take your time to get to know how they work. It will help tons to organize your tools and re-use code.

Another thing to remember: is used by the python interpreter to treat directories as packages. And a must read literature on the subject is Python documentation on Modules.

Leave a Comment :, , , , , more...

retargeting animation, howto/tutorial/whatis

by on Feb.06, 2011, under Uncategorized

I think a couple more words for new animators might be helpful.

Retargeting is just the process of “copying” the animation from one skeleton to the other. As you probably know, the simple cut and paste of keyframes between characters do not work. The joints might have different names, might have different rotations, different zeroed rotations, positions, etc etc. Some real time engines are able to do this with very strict rules of how the skeletons must be made, most of the time the difference are just and only the proportions, where just the rotation of the joints (except the root node) are used between skeletons that are mostly equal.

When characters have different skeletons, even with different hierarchies, you have to use some sort of tool, like Motionbuidler. The way it does is to have two characters in the scene, and copy it from “one control rig to the other”. If you haven’t, you should familiarize yourself completely with Motionbuilder’s characterize tools, since they are essential to fully use the software. Characters in Motionbuilder can have many inputs, like an Actor from mocap software, the control rig, which is used to animate or edit the animation of a skeleton, or another character, to “retarget” the animation from this character to the current one.

Getting into more detail, to do this, you import or merge both skeleton hierarchies into one scene. You characterize each one of them, correctly. They need both to be on tpose, and ideally should have all their bones above ground (above 0 y). Refer to Motionbuilder help for this, it’s thoroughly explained there. And this is one of the tricky parts, to use the retargeter script, each animation to be imported must be on tpose on frame 0. You don’t actually need to create a control rig for each one of them, after both are characterized, you just need to select the input type of the new character to the old character, and activate it. Animation on both characters should then be synched, regardless of differences in hierarchies or proportions.

The retargeter script just automates this process, loading a folder containing .fbx or .bvh animations over the new character. It does characterize the animations if needed, but they need to follow either Motionbuilder nomenclature or 3dsMax Biped to be correctly characterized. If they are not, you can just edit the Motionbuilder one inside the script, changing the right column to match the names on your skeleton. You don’t need to change all of them, just the ones present on your skeleton (if you don’t have finger animations don’t bother, for example).

You can, for example, get all or some of the 2600+ mocap files from Carnegie Mellon University Motion Capture Database at, which has .bvh’s and .fbx’s with a tpose on frame 0, and with the retargeter script quickly retarget them over your character.

2 Comments :, , , , , , more...

Hello world!

by on Dec.27, 2010, under Uncategorized

Finally installed and activated WordPress. I will be posting mostly about scripting with Python, Maxscript and MEL. Occasionally some small simple script also, bigger scripts and projects will probably go under technical, and maybe only mentioned here.

Leave a Comment more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!