littlewitch (autorig theory part 2)

A good friend and I have been talking about releasing a product lately. Not a specific product, but the release process: how there has been a shift to releasing early and patching often until you get something people want to use.

I was going to delay the release of the code I promised in my last post until I had more of it done, but I could always say that. Instead, here’s the first release:

https://github.com/kattkieru/littlewitch

I’d consider it pre-alpha. Also, I (unapologetically) use tabs, PyMEL, and **kwargs. You’ve been warned.

The good stuff: despite being written from the ground up on the bus over the last three weeks, it’s shaping up well. Without a prior codebase to worry about for compatibility I’ve been able to throw out a bunch of old ideas and replace them with shiny new ones. Untested, shiny new ones. But one of my goals with auto rigs is to both reduce the need for postbuild scripts and to reduce the need for boilerplate code. So far, this new system is doing well for the latter. Here’s the build function for the SimpleFK module (a module that adds one FK control to every joint in a chain, and optionally one to its tip):


def build(self, **kwargs):
  self.pushState()

  self.createModule()
  self.conChain = self.createRigChain('CON', 2.0)

  self.connectChains( self.conChain, self.chain )

  ## controls
  targetControls = self.conChain[:]
  if self.chainLength > 1:
    if not self['addControlToTip']:
      targetControls.pop(-1)

  for index, item in enumerate( targetControls ):
    name = item.partition("_")[0]
    con = self.createControl('fk', name, item, constrain='parent')
    utils.lock(con, s=True, v=True)
    if self.numControls('fk') > 1:
      pm.parent(self.getZero('fk', index), self.getControl('fk', index-1))

  self.popState()

Params mentioned in the last article can be accessed through the __getitem__ method, so there’s no need to have a long list of them being cached at method start (or to pass them between methods in a dictionary). Controls now pull their Parameters directly from the module based on registered categories, and are created with zeros by default. Controls can constrain a target joint at creation time. ¬†Little things.

Anyway, code is up, with more on the way (although not likely before the new year). There are a lot of functions stubbed out that do nothing, and many bugs to be squashed.  Be gentle, and send suggestions if you have them.

autorig theory

A friend has been pushing me to write about how my Maya autorig works, and my thought process on how to write modular autorigs as a whole. Been putting it off for far too long, so here we go!

Problems with Autorigs

I look at modules in an autorigs as simple, replicable pieces that serve a specific purpose without overlapping feature-wise with another module. They’re Lego pieces, and when connected together you get something predictable that can be rebuilt and repurposed across multiple characters.

However, most autorigs I’ve seen or used split their workflow into three stages:

  • The Guide (using Gear parlance): usually a simpler rig setup that allows the user to position the rig without worrying about joint orientation, joint counts, or how modules might need to be connected under the hood to expose certain features.
  • The Bind Joints: generated by the guide, these are used for skinning the character.
  • The Rig: also generated from the guide, these are the controls that move the bind joints.

Usually the rig and bind joints are generated at the same time from the guide. This leads you to the first problem that I’ve tried to solve: when you have to modify the rig in any way, you end up having to delete the rig and the bind joints, modify the guide, regenerate the entire rig from scratch, and then reload the skin weights. We had a character at work two years back that was hella complex, and when the client asked for changes the build alone took a half hour, with weight re-loading taking even longer.

Having to regenerate the rig whenever changes are made at the guide stage is also, in my opinion, quite limiting. You can’t fix a single module in rigs that work like this, and you can’t do iterations as quickly when you’re running through every module’s build and reattaching skins to change a control type.

My Process

I wanted to overcome these specific limitations, so my goal initially was to be able to build, unbuild, rebuild, or upgrade any module in the rig without affecting other modules, within reason (which is a caveat we’ll get to). I also wanted to not delete bind joints unless it was absolutely necessary, so that rig development could continue with skinned characters without having to reload skins every five minutes.

To do this, one thing I’ve done in my system is to remove guides. Instead, modules are built off of the bind joints, each module receiving its own chain. None of the chains are parented to each other, but are instead constrained to each other after module build. Also, as much as possible I try to set up parenting relationships that have control spaces / follows driven by bind joints in other modules. These are special message connections.

Unbuilding, or removing a single module, requires that the module and all nodes related to the rig are deleted from the scene, and the original chain is reset to its default position. This means that a mechanism is needed for saving and restoring those default positions, as well as for keeping track of all nodes added to the scene by a module’s build.

Because constraints between modules are largely between bind joints, one nice feature of the system is that unbuilding a module and resetting its joints to their default position leaves the rigs of other modules in tact. You can change a IK Limb into an FK chain, for example, and modules that rely on its bind joints will follow the new setup without needing to be rebuilt.

Tagging and Upgrading

To identify joint chains in the scene which can be turned into rigs, the system can be passed a selection of joints or can search through all joints; in both cases, the roots of the chains are tagged with Params, which are special user attributes applied before the build. Params could be things like the token used to identify the module and name controls uniquely, control scale, number of controls (for things like Spine rigs), and so on. Params don’t get removed during normal usage, so settings used to build a module persist in the Maya file on the root joints and don’t require a separate offline file. A template for a rig can be just the bind joints and their connections, saved as a .ma file.

A benefit of this is that when the code for the module changes and Params are added or removed, they can be upgraded on joint roots easily. I’ve used this trick to update parts of older rigs while maintaining animation compatibility in scenes with references.

Controllers and Orientation

Controllers pull their setup information from the Params as well. This includes type, size, color, and orientation. As all bones in the system are oriented X-down, Y-up (to provide a predictable set of inputs as well as to match Maya’s defaults), orientations allow the controllers to be turned in their default position with axes oriented in a different manner. More simply, if the animators want fingers to be X down and Z up, or Z down and -Y up, this preference can be set in Params on the root joint of the chain and will take effect at build time. Different control types and their Parameters are registered in the __init__() of a rig module.

Postbuilds and Seaming

One of the hardest things to reconcile when making modules work together is when dependencies from one module must exist before another can be built. An example: a reverse-foot setup requires that the leg module it’s going to drive and be driven by (depending on whether the combination is in IK or FK mode) exists prior to connection.

I solved this by having builds run in stages: build, postbuild, and seam.

The build is what you expect: it sets up the control structure for the module, constraining the bind hierarchy to it and returning the module group. If you’ve ever scripted a rig setup you’ll find the build() function of a module easy to follow.

Postbuild happens as the name suggests: after the build. In fact, the postbuild functions of the modules are run after all module build() functions have returned. This guarantees that the pre-conditions that might be required for the postbuild() will be complete without having to explicitly track the order in which modules are built. That aforementioned Foot module, for example, can depend on the Leg it’s attached to existing by the time the master build function runs its postbuild(), and it can use that knowledge to ask the built Leg module for controllers and other information.

Seaming is the constraining together of modules. Each module has one or more targets for constraints. The root input moves the entire rig, so you can be sure that if it is constrained your module’s controls will move (and scale) properly with it. There might also be an IK goal input that gets constrained to another module to move the IK goal: the tip of a limb, or a Spine.

My previous design had seaming as a function outside the module that’s run by the master build process, but I’ve moved it into the modules themselves so that custom seaming overrides can be created. Each module also handles unseaming, or the removal of input constraints and the resetting of the input objects to their original positions. Also, with seaming moving into its own module-level function, while I may be keeping the postbuild() method in the base class I’m not sure currently how much it will be needed moving forwards.

Try It Out For Yourself

In writing this I’ve also gone and written an entirely new system from the ground up in an effort to showcase my thoughts in working code. It requires Maya 2014 or greater and is Python-only. The first version only has two modules and no UI, but there are example files to test the builds. If there’s enough interest I’ll fill out the module library a bit more and possibly throw a UI on it. I’ll update this post soon with a link to the Github repo.

Tags: , , ,

aimConstraints with no up vector

I’m pretty good about looking at the docs for nodes I use in Maya, because often there’s hidden functionality or switches that make nodes behave completely differently, and these things are often not apparent. A good example is on the extendCurve node– there’s a “join” attribute that’s completely hidden, but I found that setting it to zero was the difference between having a useful node and not.

A few weeks ago I discovered, much to my embarrassment, that I had not done my homework on aimConstraints. It turns out that the aimConstraint node’s up vector type can be set to “none”, which converts the aimConstraint into a quaternion-slerp-based orienter. This means that whatever you’ve picked will still aim at the target, but it won’t twist on the aim axis relative to the parent transform.

This is a lot like the SingleChainIK solver, but it has one important benefit: Not being an IK solver. IK solvers / handles in Maya have some very strange and esoteric bugs that don’t show themselves in every situation or even on every show, but when they hit, they hit hard. The more I use Maya, the more I find that skipping an IK handle wherever possible is the Right Thing.

The SingleChain solver is extremely useful for a variety of setups, but one problem I’ve encountered is that the handle itself doesn’t like to be scaled. I had some rigs where if the character were scaled below 0.5 or above 2.0, Maya would freeze for a few seconds and the SC solver would be broken once that number was passed. I fixed the issue by moving the IK handle into a group outside the hierarchy and pointConstraining it to the IK goal object, but the extra work bugged me. With an up-vectorless aimConstraint, I can remove a few extra transforms.

Another interesting node is that the RPSolver behaves exactly the same as both the SCSolver and the up-vectorless aimConstraint if its poleVector attribute is set to (0,0,0), and the solver is operating on a single bone chain. Not sure what use this is, but it’s in there.

How about an example use?


arm with pole chain
( download example .ma )

Adding an SCsolver chain from the shoulder to the wrist (aimed at the wrist control), then using it to move the pole vector around, can often be a very good way to extend the reach of a character’s IK arms without forcing the animator to constantly move the pole vector control. Give it a go– you’ll see what I mean. This setup doesn’t work on legs, depending on the animator, but for arms it’s not bad and with space switching you can still have the standard pole vector placement behind the chest if so desired.

Intro to Parallel Programming on Udacity

It’s been a while since I was able to have a look at processing using CUDA, and I’ve forgotten everything I learned. I went a-Googling again for information and this time I came across a wonderful course on Udacity called Intro to Parallel Programming. It uses CUDA, and is the best explanation I’ve seen on the topic, anywhere.

Also it’s free, so what do you have to lose? With CUDA 6 adding unified memory support, there hasn’t been a better time to jump in.

robocop 2014

Trailer for the remake of Robocop is up! This is the most work I’ve done on any film so far, which included a customized modular autorig system, a system for overriding driven key animation, and a lot of upgrades to my general setup. The best part of this trailer is that it has a lot of shots I personally worked on in it.

I rigged Robocop and one other robot you see from 1:19 to 1:25. Please check out the trailer, and mark that calendar date so it can have an amazing opening weekend!

Also: this.

surface pro and sdl 2.0

I’ve been working on a game in my spare time, which has led me to look for easy ways to create pixel art. So far my running favorite is grafx2, which is one of the few that runs almost perfectly with pen and touch (many pixel editors don’t like the newfangled bits of Windows 8).

However, grafx2 has a few oddities, which has kept pushing me on my search. Eventually I came across the SDL site after a loooong time not looking at it, and discovered that v2.0 has finally been released. It’s a modern update, and I figured I might have a go at writing a very simple pixel art editor in all the spare time I don’t have.

Anyway, since I want to edit the art on my Surface Pro, I downloaded the latest version of MinGW and set about building a testbed using SDL 2.0. First few things went well, but then it crashed when I attempted to create an accelerated SDL_Renderer.

The culprit seems to be the Intel Graphics driver that’s on the Surface Pro by default. After installing the new version from this link, I’m able to create the accelerated renderer and the program does not crash.

If you’re wondering if your own crashes are related, and they occur around program startup or just after the first real window has been opened, look in the crash log for mentions of ig7icd32.dll — that’s part of the Intel driver.

Interestingly, this update has also made Analogue: A Hate Story work on my Surface Pro again! And I’ve heard that this fixes the crash on startup experienced by some players of FTL.

Tags: , , ,

grafx2

If you’re someone looking for a good pixel art editor, and like me you also need it to be cross-platform, I highly recommend downloading Grafx2. They’ve tried to mimic as much of Deluxe Paint as they could while also updating techniques for editing and adding support for more modern computers. Full source is available as well. So far I’m having a lot of fun with it, and since it’s free I recommend checking it out.

Tags: , , ,

the mortal instruments: city of bones

I’m excited to say that The Mortal Instruments: City of Bones is now in theatres! I worked on the wolves, designing an autorig for their bodies as well as a new type of animal leg rig. The faces and finaling were done by the talented Farrukh “King” Khan.

As an aside, I saw the movie last week with my family and it turned out wonderful, especially when compared to the Twilight series. Here’s hoping it does well!

welcome nayeli!

This summer has been the best of my life, in no small part due to the birth of my healthy and adorable daughter. Her full name is Nayeli June Martina Yvonne, and she was born on July 2nd.

My wife, who became even more my hero through the birth, is doing well and we’ve all been enjoying maternity / paternity leave together. I’ve been around for all of the firsts so far, and I feel very blessed to have been able to take the three months away from work.

Okay, enough with the personal stuff. Back to nerd stuff and programming!

mama

The second movie I’ve worked on is out soon. It’s called Mama, and trust me, the trailer does not show even a corner of the creepiness.

Without giving too much away, I worked on an important shot during the climax of the film, and I rigged Mama’s hair.

Tags: ,