Pages

Thursday, 14 March 2013

Maya Python API and my Custom Deformer Node

Its been an interesting couple of weeks.
For some time now I've been reading up on the Maya API (this is how plug-ins are made for Maya), but never delving right in because it looked so daunting. Why? Well, learning the API and yet another language (C++) at the same time seemed just too much to take in.

Thankfully, it turns out that there are two Maya APIs, one in C++ (the original), and the other in Python (not to be confused with Python scripting in Maya, which is what I have been doing up until this point).

The main differences between the two is that C++ plugins run much faster than python plugins. However Python plugins don't need to be re-compiled for the many different versions of Maya on different operating systems; and as I'm more fammilliar with Python code is also much easier to read.

So what I have been working on is a custom deformer node with the Python API. I've called it ecs_Displace (prefixed with my initials), and what it does is it displaces geometry based off of a texture. In much the same way as using a displacement map at render time, this will deform the geometry directly, with visible results in the Maya viewport.
It can take any kind of image, including animated procedural textures, both 2D and 3D.
It can even be used to create simple bulging effects without a texture plugged in, using weight painting to isolate the effect.
Here is a demo.

Supports 2D and 3D Textures - Including projected 2D textures. Textures can be layered and animated to build up different effects.

Supports Vector Displacement Maps - Works in both Object Space and Tangent Space to create deformations that can overlap.

Smart Sampling Feature - To increase the performance, rather than re-sampling the textures every time the deformer needs to re-evaluate, it can optionally store and remember that sampled data; only re-sampling when the texture is changed. It can be switched off entirely, and forced to always sample.

Capping Options - Provides a simple way to limit the amount that the geometry can be displaced, by capping the values at the desired threshold.

Supports Multiple Objects - One deformer can be applied to multiple meshes.

Supports Deformer Membership - Limits the number of vertices to run the calculations on.

Supports Weight Painting - Smoothly paint the influence of displacement over the mesh.

Of course, I'm not the first person to do this though, as there are a couple of other plug-ins that do the same basic thing; iDisplace, SOuP (specificity the peak node, although not quite a simple to setup) and L3Deformer(which isn't free). In all these cases, they are C++ plug-ins, so they are much faster, but the code is inaccessible as they are compiled, and they do not provide the source code. Which of course means that if you need a specific compiled version and they don't have it, then your're a bit stuck.

Anyway, after spending the time to recreate this kind of deformer, I am very happy with what I have learnt, and maybe eventually, when I've had more experience with the API, I will attempt to convert my deformer to C++... and then multi-thread it! OK, I'm getting a bit ahead of myself!

Meanwhile, on the Scripting side of things, I am in the process of creating a base template UI for all my custom tools. Kind of like how all of the tools in Maya follow the same basic template, which is basicaly just a box with widgets in that is not dock-able, can be scaled to sizes that don't even fit the widgets, and can only have one tool open at a time! Mine will be better ;)
But more on that another day.