Saturday, January 14, 2012

Stretchy IK

Here's a tutorial for a fairly simple stretchy IK method. I'll probably update this later with more bells and whistles like locking knees and elbows, and more choices, but for now, here's a basic setup.

1. I started with a joint chain with an ik handle in it. Also a hand controller and a master control that would be the root control for the entire character.

2. Make a distance node by going to create-measureTools-distanceTool, and clicking on the first and last joints in the chain. This will create two locators and a distance dimension node between them. Parent the ik handle to the end locator, and parent that same locator to the hand control.

3. Create 3 new nodes either in the hypershade or the hypergraph. Two multiply divide nodes and one conditional. I named the muliply/divide nodes Left_Arm_Stretchy_Scale, and Left_Arm_World_Scale. And I named the conditional Left_Arm_Stretchy_Conditional.
4. Connect one of the scale attributes from the master control to Left_Arm_World_Scale.input1X, and set input2X to the whatever the default rest distance is on your distance node. (In this case it was 10.015, but it will vary depending on the size of your chain.) Set the operation to multiply. This makes it that so no matter what size you scale the whole character, the distance will always have the same relationship to the character.
5. Now connect Left_Arm_World_Scale.outputX to Left_Arm_Stretchy_Scale.input2X, and connect distanceDimensionShape.distance to Left_Arm_Stretchy_Scale.input1X. Set the operation to divide. The output of this node will be the actual scale. At default the output is 1, so for example, if you stretch the arm to double the length, the output will be 2.
6. At this point the stretching should work, but if you pull the controller closer to the body to bend the elbow, instead of bending, the joints will just shrink. So we now use the conditional to make the scale of the joints never go below 1. Connect the Stretchy_Scale.outputX to both the conditional.firstTerm, and .colorIfTrueR. Put 1 into the second term, and the colorIfFalseR, and set the operation to GreaterThan. Now if the distance is greater than it's default value, the output of the conditional will be whatever the scale value is. If it's less than the default, the scale will just be 1.
7. Connect the outputColorR of the conditional into the scale X on both the shoulder and the elbow joints.
8. To hook everything up into a hierarchy. group the shoulder joint and the locator at the beginning of the chain, and point constrain or parent them to the clavical tip joint. Now when you move that, the hand should stay in place, and the arm should stretch accordingly. Finally, parent everything under the master control. You can see the outlines in the picture as an example of the hierarchy- but this can all vary based on how the rest of the rig is set up.
9. To make it maintain volume and actually stretch, instead of just growing. Create another multiply/Divide node, and set it to divide. Connect the elbow.scaleX to the input new node's input2X, and set the input1X to one. Connect the outputX to elbow.scaleY and Z. So it will scale oppositely on these axes.
I'll update this some other time for some more features and different methods, but this should be a basic functional setup.

Friday, April 2, 2010

Mix Shapes

This is a tutorial to do a quick and easy mix shape for your blend shapes. For example if you have a smile and a sneer, but when they're together the results don't mix well. This is a case to create another blend shape that only kicks in when the two are combined. If you can get Jason Osipa's book "Stop Staring" I strongly recommend it. It covers complete blend shape driven facial setups, and has some really neat scripts to accomplish mix shapes. This tutorial covers a completely different way of doing that if you have to set it up manually quickly.

I'm just using cubes to illustrate this example, but it works well for an mix of blend shapes. To start out I have 4 cubes. From screen right to left they are the final geometry, the two target shapes, and finally the mix shape.
Here you can see the two target shapes, which could analogous to a left and right lip. But when they're together, we want the middle to raise as well. In the second image I sculpted the fix shape so that when it's added in, the final shape is raised fairly evenly. You can see that there are 3 inputs on the blendShape now.

So now we need to set it up so that when either the left and the right is utilized, the mix stays off. But as soon as we start to mix the right and the left, the mix starts working. Probably the easiest and cheapest way of doing this is a blendColors node. After creating it, we'll connect the outPut R to the weight of the mix shape. This makes whatever value comes out of the blendColor node drive the mix.
We then connect the weight of either the right or the left (which one doesn't matter) to the Blender attribute on the blendColor. We then connect the weight of the other (either right or left) to the inputColor 1R, while keeping the inputColor2R at 0. And that's it.
What this does is take the weight of one of the shapes and stores it in the blendColor, with the other weight controlling the blender. As long as the blender (or one of the weights) is at 0, the outColor will take its value from input2, and remain at 0, forcing the mix shape to stay at 0, regardless of what the input1 is. Likewise, regardless of what the blender is, as long as input1 is 0, the outColor will remain 0. Only when the two input shapes are above 0 does the mix shape start kicking in.
Try it out and see how it works. Hope it helps.

Friday, March 5, 2010

Eye Setup

For my first tutorial I decided to show a technique for setting up eyes that I've worked out. I've many different ways for doing it. Some produce beautiful photo-real results, but are overly complicated for most needs. This method gives some nice realistic results, is fairly simple, and most importantly, gives the animator as much control as possible.

When coming with this set-up, there were several things that I needed the eye rig to be able to do. First, I wanted independent control for the top and bottom lids. Second, I wanted a defined blink line, so that no matter where the lids were positioned, it would close into a nice looking blink (preventing the animator from having to take the time to animate a blink with each lid unless desired). Third, I wanted fleshy eyes, where the lids react to the eye movement. And finally, I wanted the amount the lids follow the eyes to able to be determined by the animator. I think this setup is best suited to a fairly realistic model, but not super realistic, as the fleshy eye movement doesn't necessarily act as it would in real life.

Special thanks to Orey Spear for the model.


So I start out with joint placement. I have essentially 3 chains of joints. I have a single joint that controls the eye movement. And a two joint chain for the top lid, and a two joint chain for the bottom lid. Only one joint is needed for these (the base joint of each of the chains is what we'll be skinning), but I just point the second one in to see the rotations. Also, for this tutorial I'm going to assuming the joints are oriented to the world.

To accurately see how the lids are going to act, I roughly skin the base joint for the top and bottom lid chains.

Finally, to complete the initial setup I make some sort of control to drive what the eyes are going to be doing. For this I just put attributes on a controller for blink, top, and bottom lid movement.


For the actual setup we're going to work from the end, out to the beginning. So we're going to be starting with the inputs for the joints themselves, and work our way out to the controls. I start by finding the blink line. I simply rotate the lids to a blink line I find desirable. Mostly the top lid, but for realism I include a little bottom lid movement.


Then I connect what will be directly driving those joints. I create two blend color nodes, and name them appropriately. I called these ones (side)_top(and bottom)Lid_blend_final. I connect the out colors for these to the rotations of the joints. All of our inputs will pass through these blend colors.

For the input Color1R of each blend I put the rotations for the blink lines. These will control be passed on to the rotate X of the joints. For this particular case it was about 43 for the top lid, and -3.5 for the bottom.

I then connect the blink attribute from the controller to the blender attribute on the blendColor nodes. This enables the joints to automatically rotate to those angles when the blink attribute is set to 1.
Now we wants two more ways to the control the eye lids. We want to control them from those attributes, and in response to the eye movement. To do this we're going to need to blend those two controls as well. Probably cheapest way of doing this is to create a pairBlend node. This isn't readily available in the create render nodes menu, but you can make one by typing in "createNode pairBlend" in the MEL command line.

Once I create it I name it appropriately, like "left_topLid_blend." And despite what it shows in the picture, set the Weight to 0.5. Do the same for the bottom lid.


Unfortunately these nodes do not show up in the hyper shade, so if you accidentally click on something else and lose one, you can find it again in the outliner. Just turn off display DAG objects only, and then you can look through the long list and find it again.

You'll see when you bring it up in the connection editor, it has actual attributes that relate to transformations. I take the out rotate, and connect it to the color2 inputs on the blendColor nodes we created earlier. This enables the output of this blend to control the joints when the blink attribute is not at 1.


After we connect the top and bottom lids, this is what the shading network should look like.


Now we need to hook up the controls to go into those new pairBlend nodes. We're going to start by connecting our top and bottom lid attributes on our controller that control the lids independently. To do this we simply connect those attributes to the inRotateX1 on each of our pairBlend nodes. We do RotateX1 because we want these to only control the X rotation on the lids.

Now we're going to work out to the fleshy eyes. We could simply connect the rotations of the eye joint to the inRotate2 of the pairBlends. This however, would create a 1 to 1 ratio of the eye to the lids, which is way too much. We only want the lids to move a fraction of the amount the eye does. To compensate for this, we're going to create a multiplyDivide node to dampen that movement. Create one for the top and one for the bottom and name them. I called them left_top(bottom)_lid_damp.


Then connect the ouput of each of these in the inRotate2 on the pairBlends.

Then on the damp nodes, set the input 2 attributes to a fairly small number. This may take some testing to find what works. For the top lid I put 0.1, and for the bottom I put 0.05, since the top lid naturally moves a lot more than the bottom.

Next we'll connect the rotations from the eye joint in the input1 on both of the damp nodes. This is the shading network after we do that.
To control the eye movement itself, I simply use an aim contraint to my eye controllers. For the controllers themselves I use a standard setup of one for each eye, which in turn are parented to a controller that moves both of them together. When setting the aim constraint, make sure the aim vector in on the z axis (0, 0, 1).

We could leave it like this, and it would give us mostly I set out at the beginning. If you test it, the blink should work, the fleshy eyes should work, and the attributes for the lids should work. But I wanted to let the animator decide how much (if at all) the lids would follow the eyes. I think this adds a little more versatility to the setup. To accomplish this I added a few attributes to the eye controls. One for the top lid follow, and one for the bottom, so the animator can set each one independently.

We could connect these directly into the input2 of our damp nodes (the ones we previously set at .1 and .05. These are very small numbers to be working with, however, so I'm going to add another multiplyDivide node to allow for larger numbers on our controller attributes. This new node I call left_lid_remap (we only need one that we can use on both lids).

I connect the top lid follow from the eye controllers into the input 1X of the remap node, the bottom lid follow into the input 1Y. Then for the input 2X and 2Y I set a small number (for here I put .05). This allows numbers that are larger and more manageable to be transformed into the smaller numbers needed for the damp nodes.


Finally, I connect the ouputX of the remap node into all three input 2's for the top lid damp node. And do the same from the ouputY into the bottom lid damp. Now, everything should be set up and working.

The eye controllers are able to control how much the top and bottom lids follow the eye movement. If you set those to 0, there will be no movement of the lids with the eye, and if you set it to a high number (say 10 or more) then you'll notice there's a lot of movement. At the same time you can control the lids with our top and bottom lid attributes. Finally, no matter where the lids are positioned, when you set the blink attribute to 1, they will always close to the same blink line.

Hope this was useful. As this is the first tutorial I've put together, let me know if it wasn't clear, or if it was too simple, or if you've got ideas that would make it better.

Welcome

I've always been able to find great tutorials that people put up on their websites, often times helping me out of a jam when rigging. Now that I've been developing techniques and ideas of my own, I thought it was time I start contributing to the discussion. So with any of these, feel free to leave comments if something's not clear, or if you other ideas. Hope these tutorials prove to be useful.