Archive for category Uncategorized

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:

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.conChain = self.createRigChain('CON', 2.0)

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

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

  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))


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: , , ,

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.


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 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: ,

man has it been a while

Strange how you can blink and six months pass. A lot has happened but I wake up daily wondering how it became 2012 and where I was when 2011 decided to forever sleep.

Oh right: I was in Simcoe, in front of a fireplace, with a glass of champagne. The drive out there was brutal: a slush storm hit complete with fog, and the road felt more like one going through Twin Peaks than through rural Ontario. We made it in safely, however, and got some much-needed rest.

Also managed to finish Super Mario Bros. 3 on Holly’s old NES. I swear she has the only working original style machine around (not a top-loading NES 2), and the authenticity was not lost on me even though Mario was about five inches tall on the 42″ screen. There is video. I’m still considering sending it in to Nintendo power.

I’ve been reading a lot lately on the topic of game design, and playing through SMB3 with an eye towards learning was very instructive. I marvel at how much the true game trailblazers had figured out on their first few projects. If you read similar blogs to myself you may have seen the Iwata Asks on Zelda 1 [link] or the follow up here [link]. Highly entertaining. I can’t believe that the second quest only exists because the dungeon designer mistakenly used half the available RAM.

I find most modern games don’t have the same attention to gameplay detail that those old ones did. There are the odd gems, like Arkham City, which wrap tried-and-true mechanics in a fully-realized virtual landscape, but more often than not I find myself either annoyed by a mechanic that seems thrown in for marketing or was not considered in conjunction with other mechanics, or the lack of clear goals.

Anyway, I also bought a 3DS and I’m thinking to play through a cross-section of games I’ve never tried and games I loved from the old 8-bit platforms as a learning experience. (Side note: Super Mario 3D may be the best Mario game ever made, and is a shining example of old lessons and mechanics applied to new dimensions and technology.)

The bad news from the past little while is that I dropped my MacBook Pro so I am currently without a home machine. Apple can’t get it fixed with anything resembling a quick turnaround, which led me to two decisions: First, forget Applecare. It’s a waste of money in situations where you need repairs done quickly. The company has made it pretty clear where they sit with professional users. Remember ProCare? It’s not even offered any more. Second decision: buy a second laptop from a company that understands some customers need things to happen on their schedules. I have a Lenovo W-series machine on the way with way better specs than my MacBook and an anti-glare screen in the resolution I want plus three years of next business day support. Apple, I would rather not use a PC! But if you won’t even let me pay for the option of expedited repairs, and want to keep hundreds of spare iPods and iPhones on hand instead of a few monitors for laptop repair, I have no choice.

It may be a while before I post again– it’s moving time! And the new laptop is something like six weeks away.

coming up for air

I upgraded my Blackberry last night to the Bold 9780. The initial shock of an OS two major number revisions after what I’d been using was huge, but the guy at the shop transferred all my contacts and email and everything was up and running again with almost no pain. That’s something Blackberry has up on the iPhone– had I gone for an iPhone 4, I’d have had to take the phone home to transfer my contacts as opposed to having a working phone 30 minutes after purchase for a night on the town.

January has been a rough month. There was a seriously crazy deadline at work that has now been pushed, so the first half of the month found me working a lot. Now, I find myself with time again, and that’s pretty exciting.

Work lately has been mostly about asset manipulation– shader updates, automatic updates, and so forth. I’ve been learning a lot about the limitations of such things and about how to determine when a scripted approach can be beneficial, provided all assets are in the same format. That’s not saying there isn’t a bunch of work to be done up front. A lot needs to be scripted or done by a very meticulous person.

I think I might do a few short tutorials here on 3Delight, because the more I use it the more I love it and the more I realize there are a number of things about it that are quite confusing. Here’s hoping my free time stays free.

moving house

This is just a parker post for the moment. I’ve just upgraded from Yahoo to Dreamhost.  I’ve disabled the link on the main page.  It turns out that the SQL backups WordPress sends aren’t as easy to restore from. ^_^;

lots of stuff

Geekery: The open source community received a few nice promises over the past few weeks. How on the heels of the Humble Indy Bundle experiment (pay-what-you-will MacHeist-style bundle of games from indepedent developers), the creators of the games in the bundle have said they’ll be open sourcing their games. The two that interest me are Gish and Aquaria. Aquaria has been very open to the modding community, allowing much of the game to be completely redone by enterprising fans. I hope the source for it gets released soon; I’m particularly interested in their editors.

The other good news was that the Lightworks NLE software package, promised to go open source after it’s parent company’s acquisition, will actually be released this fall. It sounds a little too good to be true, and is all about interoperability with other editing suites. I know people mention projects like Cinelerra when asked about open-source video editing, but having a real editor that’s been put through its paces on real films (Lightworks was apparently used on The Hurt Locker) will be great for the community.

Music: I’ve met a number of like-minded people lately who’ve turned me onto some new artists (or at least, new to me). Lykke Li’s debut has found a permanent place on my iPods. I knew it was a winner when a friend at work told me over messenger to listen to her song Little Bit, because she was listening to it right then and enjoying the heck out of it; my reply was that I was listening to it at the same moment.

I also picked up The Postal Service’s debut, Give Up. It’s an “oldie” but holds up well even now. The sound they created is very popular now, almost like they’ve managed to find a timelessness despite being an electronic band. I’m not one for Death Cab for Cutie, not usually, but side projects of lead singers often surprise. (See: Lotte Kestner, The Soft Skeleton.)

Work: I probably shouldn’t say anything but I’m too excited to stay quiet! The other night we rendered out poses for the characters on Yoko, Mo, and Me. We’ve recently hired on an experienced texture artist, and between him and the tireless efforts of the other talented folks at March, the look blew me away and the assets aren’t even final!

There are two times when I remember why I got into CG. One is when you get a face rig, even a temporary one, onto a character. Until that point the character is just a lifeless statue, but raise an eyebrow or put a mouth into a moue and suddenly they’re a person. The second time is when the flat lambert of OpenGL displays turn into the beautiful shades and hues of a final render. Last night’s images were good reminders of why I do what I do.

Life: Getting the Epic Flu a few weeks back made me re-evaluate how I spend my off time. That, and a Tarot reading warning me to stop putting all my energies into things for other people. Sunday, I rode my bike up to the local EB and picked up a copy of Super Mario Galaxy 2.

Holy crap.

See, I only finished Galaxy a few months back, me being a late Wii-bloomer. (Still have yet to play Twilight Princess.) I thought it was brilliant both in terms of design and in how they used the Wiimote to interact with the world; for the most part you could trust your jumps and the cameras, which was totally unlike Super Mario Sunshine. Galaxy 2 seems to have fixed every complaint about Galaxy I didn’t know I had. For example, having to traipse through that space ship back to the galaxy entrance you wanted after collecting every star is gone. In it’s place is a New Super Mario Brothers-style world map, along which your ship snaps from level to level. So far there’s also a lot more variety– no levels have more than two visible stars to collect, so you finish them off quickly and move on. I don’t find myself getting bored while clearing stars out of a single map.

I think that’s enough for now… Good thing I can do drafts on my phone or I’d never have the time to blog any more!