Archive for January, 2010

fast skin loading!

Friday, January 29th, 2010

I finally spent a bit of time re-implementing my skin weight loading script in the api – more specifically, the python api bindings.  why?  well mel is super slow when working with skinning and I figured doing it in the api might help relieve the problem.

some numbers for you.  for a 3000 vert character its roughly 21 seconds using maya.cmds.  if you tune the numbers you can get that down to 12 seconds, but lets assume worst case scenarios here which I’ll describe in a bit more detail soon.  so using the api to do vertex iteration and skin weight assignment takes that down to 8 seconds.  thats a speed up of 2.4 times – which is not huge, but nothing to be scoffed at either.  lets looks at some details.

first up, the searching is being done entirely in python.  so given a vertex, i need to search through a cloud of 3000 points to find the closest matches in python.  the best case scenario above (12 seconds) uses a tiny search radius, which is useful for restoring weighting with minimal mesh changes.  the worst case scenario is for restoring weighting when the mesh has changed drastically – which happens, especially early on.  so the worst case scenario the search radius grows until it finds some matches, and then it averages the weighting found for the found verts and applies the weighting.  so it is this worst case scenario which is the most interesting.

so how does the searching work?  well basically it uses a binary search algorithm on the point cloud.  what does this mean?  i didn’t really know what a binary search was either until recently when a programmer friend of mine told me.  its pretty simple: basically given a sorted list of values, you look at the middle value and figure out whether the value you want to match is greater than or less than that value and throw away the other half of the values.  because its sorted you know the best match cannot be in that half.  so with each iteration of doing this, you cut the number of values you need to search in half.  do this a few times and you’ve narrowed the number of values you need to do more expensive comparisons on to a mere handful.

so using a simple binary search algorithm you can do searching pretty quickly.  ideally you’d write some sort of spatial partitioning that considers all 3 values instead of just one value, but that is more complex and I got really good results using a simple binary search.

so anyway, the search uses the same code for the maya.cmds and api method (this code sharing is one of the many awesome things about python.  in fact I also use the same search code for tools that don’t live in maya at all).  the main difference between them is how the skin weights are actually set.  using maya.cmds.skinPercent is really slow when you’re doing it many thousands of times.  but swapping this out for the api (which isn’t quite as easy as you’d think – you basically need to restructure the entire loop to use the MIt classes for iteration) gives you the speed improvements above.  so now i just need to figure out how to speed up the search algorithm.

i could write it all in c++, but then I have to worry about things like writing data to and from disk when storing and loading weighting data.  plus its harder to share code.  the way i’ve done it now, the searching algorithms are actually used by non maya tools, so improvements there are felt across tools instead of just within maya.  so yeah, c++ sucks for all of the above.

my verdict on pymel

Tuesday, January 19th, 2010

after using it on a fairly surface level for about a few weeks its pretty obvious that I should be using pymel.  its not easy to describe why, but I’ll take a shot.  the main reason is kinda “fluffy”, but basically it lowers mental friction when you need to interact with maya via script.  and lowering mental friction means you just get more done.

mel (and thus default maya python) is pretty straight forward – in theory.  but in practice there are all these stupid little gotchas, and most of those gotchas made their way across to the python binding of maya’s scripting interface.  awesome things like “hey I want to add an attribute.  do I use the dt or at flag?”.  or other little things like “hey I want to set a string attribute to something – don’t forget to use the -type string flag for whatever reason”, or “hey I want to query something about an attribute, which command do I use?”, or “hey, are these two objects equal?  you’ll need 10 lines of code to be sure!”.

also mel has no data structures that make sense for a 3d app.  hello?  its a 3d app, how about vector, matrix, euler and quaternion data types?  its weird that they never added these – oh and don’t tell me about the “vector” data type in mel.  its essentially useless, and seems largely unsupported.  sure the python bindings allow you to roll your own data types, but you still need to cast return values from mel commands to their appropriate type.

there are a lot of weird commands in mel, and there is a lot of mental friction involved in trying to think whether querying data about a reference is done with the file command, or the referenceQuery command.

why does pymel help?  well, in some ways it just changes the problem, but in many ways alot of things are simplified.  there is generally less typing – which again goes to the lower friction point above.  commands that return vector data actually return vector data – which means you can add and subtract them, ask for their magnitudes etc…  there are nice methods for things like querying hierarchy.  someNode.getParent() or someNode.getChildren( type=’joint’ ) for example.

of course, if you’ve already got a heap of python scripts written you may find it annoying to integrate pymel into your code.  pymel fixes a bunch of issues, and many of those fixes mean small changes which mean you can’t just drop in pymel.  and because pymel data types aren’t strings you can’t pass a PyNode to a non pymel command.  so there are a bunch of issues doing anything but a wholesale integration of pymel, and if you have a lot of code already, a wholesale integration can mean a huge amount of work.

I’ve gone the path of a partial integration.  It was originally kinda painful, but I think I’ve found most of the parts of the tangled web that is our code base that pass data across boundaries, and its working really well.  but it was initially a pain in the ass – so be warned.  I believe this problem may get worse going forward I’m not sure.

anyway, thats my experience thus far.  if you’re doing reasonably isolated tool work you should definitely be using pymel.  if you’re doing work on more integrated code then its probably not worth doing until you have a better handle on where the problems will occur.  I stupidly decided to use it on some new rigging tools which has been kinda painful tracking down all the points of failure.  and while painful so far its been worth it.

oh and I’m using 0.9.2 – the pymel guys are already way ahead with their alpha 1.0 release.

what happened to highend3d?

Thursday, January 14th, 2010

whatever happened to this site?  the “creative crash” site that seems to have replaced it is beyond horrible.  they’ve done a great job of making it nigh impossible to navigate, and holy cow is it BUSY!

does anyone use this resource anymore?