Thursday, July 8, 2010

Adding Syntax Highlighing to Blogger

I was doing some digging around last night to see how people inset syntax highlighting to blog posts and came across a really nice demo for it here:

http://codingfreak.blogspot.com/2009/02/blogger-adding-syntax-highlighter-to.html

Means you can do things like:

import pymel.core as pm
def dummystuff():
     node=pm.selected()[0]
     node.name()

It also has syntax highting for most languages supported :)

Tuesday, July 6, 2010

Trax, Character Sets and Referencing

Whilst this stuff is fresh in my mind I wanted to put it down, more for my reference but who knows, it may be useful to others.

How Does Referencing work with Character Sets?
As per previous posts, referencing is nothing more than an import of data from one scene into your current, followed by an edit list applied afterwards. The thing is that the refEdits are all based on full Dag node paths, so if you change the name of a node in the master file, or reparent it, your referencing for that edit fails. Namespaces go some way to eliviate clash issues but other than that, it's all name based. In fact, you really need to think of Maya's scene hieracrhy not as a nested scene graph, but as a flat, dag name based database.

So How Do CharacterSets help?
Unlike normal referencing, all connections to objects that are members of a CharacterSet are based NOT on name, but on the membership index of that set. This means that as long as you carefully maintain the internal order of the chSet, you can rename and regroup at will, the connections for your animations will be maintained.

A Little Deaper:
The CharacterSet in Maya is actually mapped in a totally different way internally to that which the users sees. Rather than using names to pass animations to channels it uses characterMapping and characterAlias's. It's actually split down into 3 main internal arrays,

  • Map 0 : unitlessValues : animCurveTU - attrs like user defined and scales
  • Map 1 : linearValues : animCurveTL - transform data
  • Map 2 : angularValues : animCurveTA- rotational data
in your Master Rig file (.ma) that contains the characterSet you see a block that looks something like this:
setAttr ".rm" -type "characterMapping" 206 "RIG:Shoulders_Ctr.SpineBias"
0 1 "RIG:Shoulders_Ctr.rotateZ" 2 1 "RIG:Shoulders_Ctr.rotateY"
2 2 "RIG:Shoulders_Ctr.rotateX" 2 3 "RIG:Shoulders_Ctr.translateZ"
1 1 "RIG:Shoulders_Ctr.translateY" 1 2 "RIG:Shoulders_Ctr.translateX"
1 3 "RIG:Hips_Ctr.rotateZ" 2 4 "RIG:Hips_Ctr.rotateY"

Here the characterSet has 206 members (channels), "RIG:Shoulders_Ctr.SpineBias 0 1" indictates that this is a unitlessValue (Map 0) and it's unitlessValue[1]. "RIG:Hips_Ctr.rotateZ" 2 4 indicates it's an angularValue (Map 2) and angularValue[4].... and so on....

The channels within the ChSet are mapped to these arrays in the order they're found within the ChSet, but going from bottom to top. It's this mapping thats then used to reConnect channels and animCurves when you load or reference the scene.
In the referenceEdits you'll see the connections from animCurves to these lists, which will give you an idea of just how the data is mapped internally on a real scene.

The key thing here is that because it's all based on order, should you switch your reference to a rig whos chSet mapping is different the whole thing falls apart. Say you had a refEdit :
connectAttr animCurveTL4545 LinearValue[4] 
that connected the translateX of the Wrist to it's animCurve, this edit would still just blindly go and remake this connection, even though LinearValue[4] may now be a completely different object. Now in Maya2011 they try and resolve this issue in a post load script that runs after file load, but's it's better to know about than rely on it.

So the key is, maintain the chSets, order is king.

Maya Animation Layers

I've just spend the last few days moaning at the Animation Layer setups and how poor the merge functionality is in Maya. We had a cutscene here that was 4000frms of baked MoCap, 3 animLayers, which took 40 minutes to merge on a 64bit beast of a machine. I can't understand why Autodesk are running the standard Bake command when it's so slow over large timelines.

Answer, by-pass it and use Trax. Ended up writing a function that would take all the nodes in each layer and generate a clip with the animData in it. So for the above case we end up with 3 clips. Now the Trax merge is FAST. The results meant that the same bake process going via this method went from 40 minutes, to 20 secs :)

And people diss Trax! It may be a little excentric, and lacking in features, but at least it's fast and clean.

Thursday, July 1, 2010

Reference Edits

One crucial thing with referencing is that the Reference Edit List isn't just a macro that's run in the order you performed the actions. Instead it's grouped and more importantly applied by function types. If you open the refEdit List up you'll see the grouped calls:

: setAttr
: addAttr
: connectAttr
: disconnectAttr
: deleteAttr

To get to the edit List open the referenceEditor then File > List ReferenceEdits

This is a contentious issue and has been bought up on the Autodesk Beta forums many times. In Maya2011 there has been some fixes to this to make it more intelligent. Try the following in 2010 and then 2011.

Make a cube and reference it into a new scene, run the following and save this new scene. Now open the file again...
import maya.cmds as cmds
cube=cmds.ls(sl=True)[0]
cmds.addAttr(cube, ln='Test')
cmds.deleteAttr('%s.Test' % cube)
cmds.addAttr(cube, ln='Test')
So we've added an attribute 'Test', then deleted it, then added it again in a referenced file. Now this looks like a stupid thing to do, but lets say you're using attributes as markers in a function, maybe exportFlags etc. In 2010 if you look at the edits you'll see the addAttr, then under that the deleteAttr.... regardless of the fact that the last action was to add the attribute again. When the scene is saved the new attribute won't be there because the delete was the last thing in the editList. More over, unless you go and remove that deleteAttr from the editList itself, you'll never be able to remake it.

2011 has a fix for this case.

Maya Referencing

I've spent the last month or so updating our Referencing Pipeline in Maya and thought I'd share a few tips in light of changes in Maya 2011. This will probably be a multi-part post... too much for one.

Part1: Background and Workflows - Reference crash course

At work we run a fully referenced animation setup, carefully managed by custom character checkers, loaders and asset management systems all designed to by-pass bugs and limitations in Maya native referencing setups.

Where to begin.... How and what should you reference?

Firstly referencing is designed to make life easier, a change in a source file will automatically ripple into all your working files. So in the case of Character Rigs ideally you'd want to reference the modelGeo into a skin file, skin it, reference that into a rig file, rig it, reference that into an animation and animate it. GREAT, you change the mesh and ......BOOOOOOOM! oops wait all my animations broken.. WTF?. In the real world there are just too many unknowns and possible conflicts to go that far. Also you really want to isolate certain changes from stages of production. So point one:

Avoid nesting your references if you can.

We run a 2 stage reference setup, based around a Rig that carries the skinned master character around with it... basically the output skeleton and geo piggy-back the rig's internal skeleton. This means that the riggers can run rig files that have a reference to the characters skin file - a scene with the skeleton and geo skinned, basically the output file required for the game. What this means is that to generate a new animation rig all that's required is to open up the master rig file, switch the reference to the skin file to the new character and bingo, rig done. This is very fast and ensures consistency in the rig itself. The piggy backing also isolates any small changes in skeleton, making it possible to tweak the characters internal structure if really required without destroying all your animation files. This referenced rig is itself then referenced into a second level where the facial is added.

Now that gives you a working rig, and for a short period we used these files for animation. But referencing is based on macros, referenceEdits, and they're just not stable enough to cope with this level of complexity, it means production gets flaky and that comes back to you, the TD. So before passing the files to the animators dereference it. flatten those references out of the file isolating them from rig production.

Referencing the Rig - Naming conventions:
So now we have a production ready rig, no references in it, and most crucially, all nodes NAMED IDENTICALLY in all rigs.. or at least all the master controllers the animators will touch are all named generically. Why not name the rig nodes to match the characters, why not prefix things in the rig file eg BOND_Wrist_Ctr? You need to understand the way referencing is managed internally. Think of it like this, referencing just imports a scene and runs a macro on it which is NAME DEPENDENT, that's crucial and there are ways to by-pass it, we'll get to those later. So in the case above if you'd animated Bond_Wrist_Ctr and then switched reference to Odjob who's rig file had Odjob_Wrist_Ctr nothing would connect up and you'd be left with a broken scene... not good.

Namespaces:
These are the devils work, but required to make referencing in Maya work. The idea is that the generic rig has everything none specifically named, then when you make the reference you use namespaces to denote who the character is. So you'd end up with BOND:Wrist_Ctr. This is a crucial distinction to prefixing. Namespaces are handled by the reference command/file command, when you switch the reference to a rig all you're doing is pointing it to a new file, replacing the imported file nodes and then rerunning that refEdit macro. The namespace will remain as it was after the switch, but that's easily changed from inside the reference editor itself.

I'll explain the tech side of namespace management in the next part..