20 March, 2011

Removing multiple items from textScrollList

I have started working more with Maya UI and I can see why people get frustrated sometimes with handling UI interaction using mel. For example, there is no function to get an item at a given index.

Deletion of multiple items from a list or an array is always tricky because, while deleting multiple items the indices are updated automatically. One solution is to start deleting at the highest index so that the indices to be deleted later are always unaffected.

Here is the function I wrote for the extended textScrollList class. Python's built-in function to sort a list comes in handy here.

def removeAt(self, inds):
    """
    Remove item(s) at given indices from textScrollList
    @inds: takes a single int or a list of int
    """
    if not isinstance(inds,list):
        inds = [inds]
       
    # indices should be sorted first into descending order 
    #   so that the indices to be deleted next are unaffected
    inds.sort(reverse=True)
    for i in inds:
        self.edit(removeIndexedItem=i)

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!

12 February, 2011

New Year New Adventure

It's been very very long since I posted any updates. I have been working on many projects simultaneously so it's been difficult to find time. I have done facial rigging for a friend of mine and I am also working on my Rigenerator project. For Rigenerator, I have started working on converting code for special nodes into the code that uses node's own command, e.g. cluster. Later I have a plan to add support for Python. But there is a lot to be done before that.

However, I have taken a break from my rigging work and I have started diving into two other development projects, a web app and an IPhone game.
I was already building my website using CodeIgniter framework for php and during that time my wife suggested some great ideas for building a web application. Since then I have become passionate about this idea. So I have started building some parts of the app as a prototype. I am using PHP (with CodeIgniter as framework), jQuery and MySQL to build this web app.  It is going to be a long term project so I will be switching between other projects and this one.
I am also exploring some game ideas for iphone while learning Objective C along the way. There are many aspects to consider when designing a game. A good game should keep users interested from beginning to the end and also a good game users will want to play again and again. I am considering coscos2d-iphone game engine for the game and later plan to add box2d physics engine. This will also help me with my technical animation reel.

Here is another blog I started to take notes about the new projects and programming in general.
http://maulik13tech.blogspot.com

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.