02 August, 2010

MSyntax Flag Definition & Invalid Flag Error

I had some frustrating moments in making flags work for a command using MSyntax. A part of it was my ignorance in reading the function detail, but the other one I am not sure is mentioned in docs. Here is what it says in the doc. for MSyntax::addFlag(const char* shortFlag, const char* longFlag, ......)

shortName  the string representing the short (< 4 character) version of the flag
longName   the string representing the int (> 3 character) version of the flag


=> Short flag name should always be < 4 characters.
=> I defined one flag name like this:  syntax.addFlag("-it", "-infType", MSyntax::kDouble);
and used it with my command like this: myCmd -infType 2 Maya gave me an error, "invalid flag -infType"!

Then I changed the flag long name from -infType to -influenceType it all worked fine. So I wonder there is a problem with defining a long flag name beginning with three lower case characters, followed by an upper case character.

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.

19 July, 2010

FreeMind: Mind mapping tool

It is very important to organize not only your code but the thought process and all the ideas that come up during planning of a project. I started with my rigging framework and then branched to make Rigenerator, which by itself is now a big project. Each feature of Rigenerator requires good amount of planning to consider all possible cases. At the current stage code of Rigenerator is turning very complex for me even with lines and lines of comments. I have started loosing myself in these different possible scenarios and ideas to solve them. The problem is that going back to a particular problem after few days is not easy.

So I have decided to document as much thought process as I can so that resuming to the last problem is easier and I can trace old problems and their solutions. I found that I can do this by a technique called mind mapping. Basically you write everything in nodes which are interconnected and organized as a tree. I am using FreeMind (open source) to document my ideas and its helping me so much. And I always feel good when I am organized :)

You may find this tool very helpful. Check out the video demo at the bottom of the screenshot page.
FreeMind

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.

13 July, 2010

Cluster Deformer Weights

Each component affected by a cluster has its own weight stored in the deformer attribtue .wl (weightList). This attribute is inherited from weightGeometryFilter node. ".wl" is a two dimensional array with first dimension specifying an array related to each geometry object a cluster affects.e.g.
cluster1.wl[0] => array of weight values for nurbsCurve1
cluster1.wl[1] => array of weight values for nurbsCurve2
cluster1.wl[0][3] =>  cluster weight of nurbsCurve1.cv[3]

Now, let's say nurbsCurve1 has 8 CVs, out of which first four (0:3)  are affected by cluster1. Hence the cluster1.wl[0] will have 8 actual weight values (keep in mind that you can do "getAttr cluster1.wl[0][1000]" even if 1000th CV does not exist, more on that later). Now,we change all weights to 0.5 using cmds.percent("cluster1", "nurbsCircle1", v=0.5). That will also change weights of CVs which are not affected by cluster1. Now if I go to "Edit Membership Tool" and add a CV to cluster1, by default its weight would be 0.5 instead of 1.

This may not be very useful, but this is one of those good to know aspects of Maya.

22 June, 2010

maulik13: New Design coming soon...

I am going a bit slow on my rigging framework since I decided to redesign my website (maulik13). I needed more space to put some content and share some of my scripts. And I wanted to add a simple database so that I can update downloads and portfolio easily. It's taking some time, but I have finished the new logo, layout, colors, login and database connectivity. So hopefully I will have my downloads section up and running live soon.
edit:
I just forgot to mention that I am using codeigniter php framework for my website and I am loving it. This is one of those few frameworks that I absolutely appreciate because of its ease and smooth learning curve. Hopefully I can get those characteristics in my rigging framework as well.

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.

02 June, 2010

Parenting a Shape the Right Way

I had written a script some time ago to parent a shape to a given transform. I took into account frozen transformation on both source and target. However, script would not place the shape on to pivot point of the target in some cases. Recently I fixed this script as I need to use it quite often. I had to change the logic compeltely to parent a shape to account for different orientations on the source(s) and the target. The main idea is to match the pivots of both the objects before parenting. I will make this script avaiable for download once I create a download section on my website (hopefully very soon). Meanwhile if you need to try this script let me know and I will send it to you.

06 May, 2010

Conditions: No Need for Extra "else"

Sometimes when I am writing code quickly and jumping between functions, I miss a bit obvious logic and end up having multiple "else" statements. Below are two examples doing the same thing. Here the logic itself is not important, this is just to make a note.
...
   if trueKey != "":
       modObj = pkgDict[trueKey]
       if modObj.__dict__.haskey(className):
           return modObj.__dict__[className]
       else:
           return None
   else:
       return None 

In above example, two else conditions are unnecessary and messy. Concise version,
...
    if trueKey != "":
        modObj = pkgDict[trueKey]
        if modObj.__dict__.haskey(className):
            return modObj.__dict__[className]

    return None