Archive for the ‘ CG ’ Category

Casting variable data from Python to Maya

I’ve recently ran across a nasty… bug, in the Maya-Python integration.  It appears, that if you have a Python module return a list, Maya will convert it to an array. That’s as expected.  However, if the Python list is empty, Maya converts it to a string with two brackets inside of it: “[]”, rather than converting it to an empty array.

I should note, as an update, that this initial presumption (that this is a ‘bug’) is wrong:  Maya variables are always typed (string $foo = “word”;), while Python’s aren’t, they’re just pointers (foo = “word”).  Maya has to auto-detect what type of data (string, float, etc) exists in the passed-in Python object and make a determination for what the conversion should be.  If it just gets an ’empty list’, it really has no idea what type of Maya array (float, string, int, vector) it should be.

Obviously, this can cause some real headaches if you’re trying to capture expected data from Python in Maya.

I found a fix, that I’m… not…. very… happy with.  Explained below the example.

Example:  First, a Python module that will return different types of data, based on the passed in arg:

# Python code
def variableReturn(varType):
    if varType == "str":
        return "string"
    if varType == "listSingle":
        return ["value1"]
    if varType == "listMult":
        return ["value1", "value2"]
    if varType == "listNone":
        return [None]
    if varType == "listEmpty":
        return []

Now, some mel code to capture that data.  I’ve already setup the Maya variable types to be the correct ones based on what the Python module spits out… but you can see that one of them is clearly wrong:

// Mel code:
string $str = python("variableReturn('str')");
string $lstSingle[] = python("variableReturn('listSingle')");
string $listMult[] = python("variableReturn('listMult')");
string $listNone[] = python("variableReturn('listNone')");
string $listEmpty = python("variableReturn('listEmpty')");

print ("Type of 'str' : " + `whatIs "$str"` + "n");
print ("Type of 'listSingle' : " + `whatIs "$lstSingle"` + "n");
print ("Type or 'listMult' : " + `whatIs "$listMult"` + "n");
print ("Type of 'listNone' : " + `whatIs "$listNone"` +"n");
print ("Type of 'listEmpty' : " + `whatIs "$listEmpty"` + "  <--- aaaagh!!!n");

Prints:

Type of 'str' : string variable
Type of 'listSingle' : string[] variable
Type or 'listMult' : string[] variable
Type of 'listNone' : string[] variable
Type of 'listEmpty' : string variable  <--- aaaagh!!!

As you can see, the workaround is to have your Python code return a list with a ‘None’ object in it:

# Python
return [None]

Presumably, you’d do some sort of test before hand in your Python code to know to return things this way:

# Python
if len(myVal) == 0:
    myVal = [None]
return myVal

Of course, in Maya you’d then have to detect if the first item of the list was empty, if it’s size was 1:

// mel
string $result[] = python("myPyFunc()");
if(size($result) && $result[0] != ""){
    // start doing something...
}

Update #1:

After reading through the Maya docs on Python integration, this may make a bit of sense:

Python Return Value MEL Conversion
string string
unicode string
int int
float float
list containing numbers, including at least one float float[]
list containing only integers or longs int[]
list containing a non-number string[]
anything else string

I’m guessing an ’empty list’ falls into the ‘anything else’ category, and thus converts it to a “string”. Even though our above example returns an empty list, and we presume to have string data, it could actually contain float data, int data, etc. But how is Maya to know this if all it gets is an un-typed empty list? It doesn’t, so it turns it into a string.

Update #2:

Looks like (based on comment below) later version of Maya have fixed this issue:  The docs (in 2010) now append this new information:

| empty Python list | empty string array (string $array[]) |

New Processing sketch: scribble04

Take a look for more over on it’s page.

scribble04

scribble04

Joint scaling in Maya

I’ve made my fair share of rigs.  But being on the runtime side of CG development for the past seven years (previous to that I did a lot of game cinematics), I’ve been limited by the runtime engine tech available to me.  And mainly, the only thing the game engine respects are joints, and smooth bound mesh.  Occasionally you’ll get blendshapes, and if you’re lucky, joint scaling.  Only recently have I been able to start using joint scaling in my rigs (and thus have the non-proportional scaling of mesh be supported at runtime).  It would seem like a simple thing to implement.  But like most things I’ve discovered, it was a bit more complex than expected…

I understand there are many ways to approach a subject, so the below example is just the one I tried given the time I had.  I’d be interested to know how others have dealt with this:

Simple requirement:  Tentacle, say, 5 joints down its length.  You have a corresponding set of animation controllers (lets pretend they’re easily-pickable NURBS curves) that have a 1:1 relationship with the joints.  You have the animation controllers setup so that each child controller will follow along with it’s parents transformations (via a parent constraint), aside from scale (scaling a controller will ‘move’ the children, but won’t scale them).  This gives you the effect of localized scale for each controller, and each joint.  You have your joints parent and scale constrained back to each animation controller.  And you start testing:

So here’s our scene:

Our initial Maya Scene

Our initial Maya Scene

You can see we have five polygonal spheres, and they are smooth bound to each of the five joints.  There are five NURBS circles (the animation controllers), each of which has a parental group, both of which pivots live at the respective joint location.  The parental group of each curve is parent constrained to the previous controller, giving us a simple FK system for the animation controllers.  And finally, each joint is both parent and scale constrainted to their respective animation controller.

Let’s non-proportional scale an animation controller!

non-proportional fail

Huh?!?!  Every other sphere has some crazy deformations applied to it.

Ok, let’s turn off each joints “.segmentScaleCompensate” attr, and try non-proportional scaling it again:

.segmentScaleCompensate fail

Nooo…. no good at all.  Ok, let’s try unparenting all the joints from one another, and giving that a shot:

Success!

Hey, NOW we’re getting somewhere…

So it seems, at least with this method, you can’t have you joints parented to each other, and expect non-proportional scale to work.  I briefly tried some direct-connection methods with teh scale attrs, but didn’t get any better results.  Anyone else have a slick soluition, that lets you keep your joints parented?

New Processing sketch: scribble02

It was a slow afternoon, just goofin’ around. Find out more over on it’s page.

scribble02

scribble02

New Processing sketch: trees03

Take a gander over on it’s page…

trees03

trees03