Showing posts with label Rigenerator. Show all posts
Showing posts with label Rigenerator. Show all posts

20 December, 2011

Rigenerator: A Short Introduction

I am updating Rigenerator slowly, but steadily with exciting updates coming soon. Before I post any updates I thought it would be a good idea to post some introduction about this tool.

At a basic level Rigenerator is a tool to regenerate rigs in Maya. It allows you to gather information about selected rig by doing advanced traversal through Maya's scene graph. After gathering information and generating metadata the tool allows you to see what (dag & dg) nodes are part of your rig and then generate MA style code to reproduce the same rig in a single click. However, this is just the basic framework. We can build on top of this to add some really helpful and advanced features. The main features of Rigenerator are listed below.
  • Extract the part of the rig 
  • Rename and regenerate the rig using MA style code
  • Mirror the extracted rig
  • Abstract the rig code into a generalized module
At the core of the framework is a module for traversing maya scene graph with rule based conditions to extract a part of the rig. So you can select just the root nodes of your rig, for example left arm rig, and the rig analyzer will gather all the nodes involved in that rig. So if you have stretchy IK, the rig analyzer will find all the utility calculation nodes involved in the rig as well. There are lots of things to consider when analyzing a rig by traversing a scene graph. One major issue to tackle is to solve cyclic dependency if the nodes are connected in a circular way. Right now Rigenerator's graph analyzer is able to avoid it for the most part and solve it in the post analysis phase for simpler dependencies.

The next module is closer to MA exporter plugin, but with more functionalities. There are few things about maya Ascii code that are not helpful if you want to execute it directly in Maya. For example, -ci (cache internally) flag in addAttr will generate warning. And the major problem comes with all keyframe nodes as mentioned here. Apparently, MA file uses attribute ".ktv" to set key value pairs which cannot be used outside saved MA file because that attribute is configured to work only when reading MA file by Maya. So there are some challenges that can only be solved iteratively as they are discovered. To solve such problems and to support the fourth feature on the list, I have started writing a module that will parse MA commands and based on rules a set of MA commands will be replaced by regular mel commands. 

Mirroring a rig is another project. First I had to learn the logic behind mirroring transforms and orientation. Instead of using mel commands I decided to write functions to mirror transform values giving me the flexibility of playing with any numbers and not just maya nodes. For example, transformGeometry node stores frozen transform values in a matrix attribute ".txf". To decompose or mirror its value I need to feed this attribute to matrix class and use matrix methods. Mirroring logic is actually quite simple once you figure out the logic and math behind it. So I took some time to understand Transform matrix and vector math to be able to code them in python classes and then use them to mirror orientation. I will keep the details for another post. However, these are still very simple things compared to generalization of mirroring any rig. There are many challenges involved in generalized mirroring, some of which includes mirroring constraints based on how other objects are mirrored, using connection sequence to predict the mirroring of custom attributes etc. I believe that it's going to be very difficult to create a perfect solution that always mirrors the rig automatically as intended by the artist/rigger. However we should be able to provide a toolset and workflow to the users so they are able to specify inputs/settings and get the mirrored rig as they want.

Once I finish the brain tearing task of mirroring logic, I want to take Rigenerator further to convert MA style code into proper mel commands. For example if you create a constraint in the rig, MA code actually creates constraint by manually creating the node, setting all the attributes and connecting the constraint node to its input and output nodes. My goal is to convert all these MA commands into just a couple of lines of code by utilizing maya's built-in commands, e.g. pointConstraint, aimConstraint etc. Now that's actually very difficult as I have come to realize after thinking about the logic for a while (say around a year). The most difficult task is to come up with rules for each type of node and specifying logic for each node. The second part makes it very difficult to generalize the main logic. However, by iterative process if I am able to create a database of such rules and some toolset to make the rule/logic generation easier then it should be possible to accomplish this. What this means is that you actually don't have to write the code for your rig from scratch! You get a ready function with inputs to create your rig and you just need to optimize the code! I would love something like that and that's why I am very excited to build this functionality.

In summary, what I want to accomplish using Rigenerator is to allow riggers to focus more on inventing and experimenting in the rig creation process and not worry about reproducing it. Hopefully when the tool becomes stable enough I would like to release it for free and later make it open source when the code is a bit more cleaner (easily readable to others :) ). Stay tuned!

15 October, 2011

Bare essential commands that create Maya's scene

If you open .MA maya file in notepad, you will see many lines of code based on your scene size. If you go through the code, no matter how big the scene is or how many nodes are there, the whole scene is created by only 4 commands! That's it! It's very easy to find this information, but what amazes me is that the programmers were able to abstract the logic of scene creation to the following atomic tasks:
  1. Creating nodes with parenting info
  2. Adding attributes
  3. Setting changed attributes
  4. Connecting the nodes
It is very easy to generate .MA style code by following the example of MA exporter plugin. I am using some parts of it in Rigenerator to save the part of the rig as code. My next goal is to be able to analyze this code and extract metadata information for each line. This will allow me to extract scene graph information by just looking at the code. So I am currently in process of designing the logic for a code parser module which will parse the code to extract node/attribute/connection information.

14 March, 2011

Rigenerator Update

I have switched back to rigging related work. I have resumed my work on Rigenerator by analyzing my existing code. It can be very helpful to take a break from the work and revisit it later. I found many ideas to improve and more importantly simplify the logic for Rigenerator. Earlier it was not very bad, but I always felt that the code and logic I had written was a bit twisted and difficult to understand. I have put so many comments in the code, but still I was not satisfactory with the logical structure. So I have gone through the code many times as I kept refining it and simplifying the logic.

The first thing I did was to divide the code into proper modules (which I had to do anyway). While doing so I also kept the UI in mind. This will make plugging the UI process easier. There are some changes in logic for exploring the graph. It will allow more possibilities in conditional gathering of graph nodes. Finally I have moved Rigenerator out of my rigging framework project and it is a tool by itself now.

The major changes are in the graph rule structure. It is much more flexible and easy to follow now. The new rule structure allows the following,
# A value can be a node type or a node name
# Neighbor node(s) can be specified for rule condition
# Also, connection attributes can be specified for the rule
# Any value in the above conditions can use simple regular expression (RegEx.)
# Simple RegEx. can be extended in the future to allow more complicated RegEx. syntax
# Rule conditions can be grouped to force AND operation (all conditions should match)

Since I have made a lot of changes, this also requires for more testing. But I am looking forward to finishing the new algorithm and start testing the results!

20 July, 2010

Rigenerator: Update 1

The major change in the new version is the rule based DG traversal. Earlier DG traversal was unrestricted and it will fetch all the nodes involved in the scene. In the new version I have added rules that are stored in a simple dictionary structure which can be updated dynamically. This allows me to select a DAG structure and Rigenerator will only get the rig involved in that selected DAG tree.

Rules are used by algorithm to decide if it needs to ignore a node, or ignore a branch or end at a particular node in DG. These conditions are triggered when we encounter specified node type or name. I will add regular expression to both, node name and type, so that we can target more generalized types of nodes. Later on, my plan is to be able to specify node patterns and levels in the rules. This rule based DG traversal is very powerful as I can fine tune the algorithm dynamically to extract any kind of rig.

I have also fixed problems with DG connection sequence in the code. So now there will be no connection dependency problems like this:
connectAttr nurbsCurveShape.worldSpace[0] curveInfo1.inputCurve;
connectAttr makeNurbsCircle1.outputCurve nurbsCurveShape.create;
// This will be an error since nurbsCurveShape is not created 
//  when doing first connection
// Shape is created when we make the second connection

Next addition is the option to include top hierarchy nodes of the selected rig. There are three options for this:
1. Recreate the top hierarchy
2. Use existing top hierarchy
3. Just group the rig under a separate node

For example, you Rignerate the Arm setup and also want all the top hierarchy nodes, e.g. shoulder, upper_body, root etc, then you can include those transform nodes, so it maintains the hierarchy. Using existing hierarchy helps, if you are mirroring the rig. And you can group the rig under a single node, in case you want to move it somewhere else.

Right now the code generation is still in .MA format and even if its simplicity is very useful it adds limitations because certain type of code cannot be executed with MEL! I can understand the reasons behind it, but it has added complexity to the code generation.
For example,
createNode animCurveUA -n L_Index2_rotateZ;
setAttr "L_Index2_rotateZ.wgt" no;
setAttr "L_Index2_rotateZ.tan" 10;
setAttr -s 3 "L_Index2_rotateZ.ktv[0:2]"  -10 26.247651337441738 0 0 10 -77.759996825174923;
Last line will silently fail and also the code following that line. This thread explains this: LINK

Hence the next step is to add special processing for special nodes, in this case animCurveUA. So instead of using MPlug.getSetAttrCmds() I will query attribute using normal mel commands. But, I need to generalize this into a proper system, instead of going and adding so many specific if conditions. This will also allow me to generate special commands for deformers as I have posted in one of my earlier posts. So that's the next goal.

14 July, 2010

Rigenerator : Converting deformer network into its command

While developing my Rigenerator tool, I am studying more and more about Maya DG graph and how to reproduce it. Right now I can create all the nodes individually and put them together to recreate the rig. However, I want to be able to replace those individual commands with a specific command e.g. use cluster instead of individual create, addAttr, setAttr, connectAttr commands for each node involved in that cluster deformation.

I believe this feature is going to be very helpful since, it can literally give you a major part of code for your rig already laid out. So you don't have to go back in Maya to check all connections and then come back to editor to code. But, implementing this feature is very tricky so I am studying how deformer network is created, how a deformer gets all the inputs and what each node in that network is used for. I have taken some notes from this study and I want to post them once I have some example images ready.

21 June, 2010

Rigenerator: Rules Based Graph Traversal

It is not very difficult to traverse the whole graph in Maya and make a data structure to be able to analyze it. In "Rigenerator" I can select one node in the outliner and I am able to get all the nodes related to it in anyway possible. The next step I want to add is to be able to specify rules in the graph traversal algorithm so that I can restrict the network within the specified hierarchy. This is so that my "Rigenerator" tool can extract only a part of the rig.

My goal is to come up with some kind of short hand notation for specifying these rules. I am trying to come up with different possible scenarios to be able to generalize these rules. So for example, I can specify levels and combine it with a node type(s) and their relationships with the source node. This is just theory and hopefully I can find some way to implement this idea.

06 June, 2010

Rigenerator: Rig Code Generator, Milestone 1

Rigenerator is one of the toolsets from my modular rigging framework (which is still in very very early stage). My goal with this tool is to help riggers speed up the coding and modularizing of the rig components. This can also be used for copying, mirroring rigs of any kind. The first step for this tool is to generate the raw code which is the same as .MA file commands. There are some very useful functions in API to generate a lot of code directly (e.g. setAttr commands for given plug, check MPlug class). You can check an example plugin called MA exporter in devkit. Later based on this raw code this tool allows to organize it and add modularity.

In my previous planning, I wanted to work on this tool at a later stage. But, since I have to create many rig parts for the framework, I thought I would actually finish Rigenerator first. So I can create rigs in different ways and whichever I find the best, I can convert it into code using this tool. This will speed up the coding process for my rigs.

I have reached the first Milestone for this module. I am able to generate the raw commands to regenerate the rigs. I have planned many features for this tool which includes, mirroring, code analysis/modification, dg graph inclusion/exclusion options, mel or python options,  etc. I will post more on this as I make some progress.