ZBrush modeling

3D sculpt inspired by mixed martial arts.

Space Switching Video Series

A video series explaining the concept and scripting a tool to setup and interact with space switching setup for rigs.

Rigid Bodies Simulation

Small project with simulated rigid bodies and nParticle effects.

Maya Muscle Tutorial

A tutorial on using the spline deformer on custom geometry to create muscle flexing and stretching behavior.

Friday, August 30, 2013

Lion Rig Update

Update on a quadruped rig for a Lion model.
Model credit: Attakarn Vachiravuthichai





Sunday, August 11, 2013

Joint Relocation

In this post I want to show you a quick and easy way of reposing your joint layout to make it easier for you to reuse a skeleton if you already have one laid out that you want to reuse. The idea here is to be able to just worry about where the joint is positioned, and not have to worry about maintaining joint orientation.

To accomplish this we will rely mainly on one thing, and that is an aim constraint, to allow us to aim the rotation axis we want down the joint chain.

Ok, so to break it down, lets just start with a 3 joint chain. To visualize this better lets go ahead and turn Local Rotation Axis on for all joints.

By default we have the x axis going down the joints. To keep our joint intact we will use locators to actually move around the joints to reposition them. The aim constraints will be applied to these locators.

So we need to start by breaking up the joint hierarchy. Parent each to world, you can do that by hitting Shift + P with the joint selected.

We will then create a locator at each joints position. In fact we want to maintaing the joints orientation as well. So for each joint, select the joint, select the locator, and goto Constraint -> Parent Constraint. We want to uncheck maintain offset. That will position and orient the locators to match the joints. We can then delete the constraint, and parent the joint under the locator.


Now we go ahead and set the aim constraints. This will mimic our original hierarchy and allow us to keep the joint orientation.

Select the second locator and shift select the first locator. And goto Constraint -> Aim Constraint.
We can repeat the steps for the third and second locators.
We can now relocate the joints. When we are ready we can unparent the joints (Shift + P) and parent the joints back into the hierarchy.


We can then delete the locators, and everything we be gone with them.


And there we go! Now, obviously it wouldn't be too efficient to have to redo this every single time. So if you want, check out lpJointRelocation.py

And here is a quick overview of how to use it.

Break Hierarchy: This will break down the hierarchy, create locators and constraints, and hook up message attributes to manage the connections with the tool. Select the first joint in the hierarchy you want to adjust.

Rebuild Hierarchy: To put the joints back into the hierarchy in the new position. This will also get rid of the created nodes that are no longer required. Select the first locator.

Select Hierarchy: To make it easier to select all the joint in the hierarchy starting from the selected joint.

Toggle Local Axis: To toggle on and off the local rotation axis to help with some visual feedback.

Hope you guys find it useful!

Tuesday, August 6, 2013

Turning Off Local Rotation Axis

If you ever have been frustrated with the local axis toggle in maya like I once was you might find this little script useful. Sometimes you forget or loose track of what you've toggled on. Today I saw a friend spend so much time trying to figure out what node has local axis on, that while it was kinda of funny, I felt it couldn't be a bad thing to share something that can fix it in just a few lines. As I'm sure there are more people who have struggled with this at some point. So, using good old fashion MEL, you can just create a shelf button and copy these lines

// Turn off LRA for all the selected objects
$sl = `ls -sl`; for ($s in $sl) { $on = `toggle -q -localAxis $s`; if ($on == 1) { toggle -localAxis $s; } };
You can now select the objects you want and click the shelf button to run the code, and it will toggle only the ones that are on. Essentially making sure everything is off.

Saturday, August 3, 2013

Extracting Twist Controls for IK Spline

Being able to have twisting propagate down a joint chain is a common feature for character rigs. An automated approach over a manual approach might be a quicker and easier solution, however as we'll discuss below might end up presenting problems. A manual method of animating twisting in the other hand while giving exactly what the animator want, is also more work for the animator.  There are many ways to setup twisting, each with their own advantages and issues. However, this post won't be about the best solution for twisting, so much as it will be a practical solution for providing the animator with more control over the twist action of the joints by having both an automated and a manual solution.

I've tried many different setups and upon arriving at this solution I found it to be the most stable and practical for when dealing with twisting.

Watch the video demonstrating the setup here.

So let's get started. Before we start lets create a quick setup to try this out. The first thing we will need is a Spline IK driven joint chain. 


Next, we will need to make our IK controls. To keep everything simple for now, lets just use empty transform nodes for our controls. As an observation, this step isn't really necessary, we just want to have a way of driving the curve shape to drive the joint's position.

Let's start by making a single joint, group it twice and name the nodes,
GRP_Start_IK, CTRL_Start_IK, jnt_StartCurveDriver

Duplicate the top group and rename the new nodes,
GRP_End_IK, CTRL_End_IK, jnt_EndCurveDriver


Now we can move the corresponding groups to the start and end of the joint chain.


Finally we can select the driver joints and select the curve last, and goto Skin -> Bind -> Smooth Bind
we can then choose the following options


Now, we can drive the Spline IK with our controls. So this will be our starting point.

Notice that we can move and rotate our controls to drive the curve that is driving the joint chain. However, we can't seem to rotate the controls to get twisting. The reason for this is that components, such as the CVs on the curve only represent points in space, and because we don't get normals with curves, we can't get rotation information from the curve points. Now, some of you may be familiar with the Advance Twist Controls setup for spline IK. If not, you can check out the post here that goes over the setup.

The advance twist setup is nice to quickly get twisting with your Spline IK. However, we mentioned that we want to have not only the option to toggle auto twisting on and off, but to also offset the twisting. In addition we will also look at how this new setup will give us a nice solution for a common problem that comes with using the advance twist controls. Lets take a look now at how we can extract the twist from the spline IK solver and give it to the animator to control and give them the option to automate or not the twisting.

Lets start by creating some attributes on our end control to drive the twisting. Lets create an autoTwist and a twistOffset attribute.




We can now start creating and hooking up the math nodes to help us with this setup. The first thing we want to create is a multiplyDivide node to multiply the rotationX (that is our twist axis for our control in this case) of our end control by our autoTwist attribute value. Lets rename this md_autoTwist and hook up our attributes.

Connect CTRL_End_IK.rotateX to md_autoTwist.input1X
Connect CTRL_End_IK.autoTwist to md_autoTwist.input2X


Next we want to create a plusMinusAverage node to sum our twistOffset value to the output of the multiplyDivide node. So lets do that and rename this pma_twistOffset.

Connect md_autoTwist.outputX to pma_twistOffset.input1D[0]
Connect CTRL_End_IK.twistOffset to pma_twistOffset.input1D[1]


Finally, we are ready to connect it to our ikHandle.

Connect pma_twistOffset.output1D to ikHandle1.twist



There we go! So with not a lot of extra work, just 2 extra nodes we get a clean setup for twisting. And that is actually not the best part. I mentioned earlier that this setup would also help solve an issue of the advance twist control. Or with most automated solutions. And that is the flip that occurs at 180 degrees. This problems occurs because of how rotations are being calculated (Euler rotations). This ends up leading us into problems such as Gimbal locking and making the setup fragile if we are relying on any one rotation axis to get our twisting. So as it turns out its not so advance after all! :)

As this is another whole discussion in itself, I'll just leave it at that. For now, be assured that this setup will handle with no problems rotations beyond 180 degrees or -180 degrees for that matter with no problems because of how the spline IK is solving for twisting.

The setup in its current state is an example in which the twist propagates up the joint chain. However, what if we need the CTRL_Start_IK to also be able to control the twisting. To have the twisting propagate down the joint chain. Let's take a look at that.

If we go ahead and use the roll attribute on the ikHandle notice that the entire joint chain rotates. The obvious thing to do is to counter rotate using the twist and we then get the effect the rotation came from the start of the joint chain. 

So let's start with that first.

Connect CTRL_Start_IK.rotateX to ikHandle1.roll

Now, for the start control to work with the end control at the same time and for our autoTwist attribute to work on CTRL_Start_IK as well, we will create another multiplyDivide node, we can call this md_autoTwist2.

Connect CTRL_End_IK.autoTwist to md_autoTwist2.input1X
Connect CTRL_Start_IK.rotateX to md_autoTwist2.input2X

To counter rotate we will use a plusMinusAverage node. We will call this pma_twistOffset2. However, we also need to account for whatever twist offset already exists from the CTRL_End_IK.

Connect pma_twistOffset.output1D to pma_twistOffset2.input1D[0]
Connect md_autoTwist2.outputX to pma_twistOffset2.input1D[1]
Connect pma_twistOffset2.output1D to ikHandle1.twist

And we can set the operation to Subtract.


And there it is! Now go and have fun making your joints twist!

I realize although its not too complicated you probably don't want to have to setup it every single time. Hopefully you still were able to understand it so that you could :)

But to speed up the process here's a script to set it up for you. It takes in the start control, the end control, the control object, the ikHandle, and the twist axis for the control rotation (this can be negative as well).

import maya.cmds as cmds

def twist(startCtrl, endCtrl, ctrlObj, ikHandle, axis):
 '''
 Create twist control for the spline IK setup
  
  startCtrl : node controlling the start of the joint chain
  endCtrl  : node controlling the end of the joint chain
  ctrlObj  : control object to host the twist attributes
  ikHandle : the spline IK handle
  axis  : the rotation axis for twisting on the controls : "x", "y", "z", "-x", "-y", "-z"
 '''
 # check nodes
 for node in [startCtrl, endCtrl, ctrlObj, ikHandle]:
  if not cmds.objExists(node):
   cmds.error("%s does not exist." % node)
 # check axis
 if axis not in ["x", "y", "z", "-x", "-y", "-z"]:
  cmds.error("Invalid axis.")
  
 # check if our twist axis is on the negative side
 neg = False
 splitString = axis.split("-")
 if splitString[0] == "":
  axis = splitString[1]
  neg = True
 axis = ".r" + axis
 
 # create new attributes
 cmds.addAttr(ctrlObj, ln="autoTwist", at="double", dv=1, min=0, max=1, k=True)
 cmds.addAttr(ctrlObj, ln="twistOffset", at="double", dv=0, k=True)
  
 # create nodes for autoTwist and twistOffset
 autoTwist1 = cmds.createNode("multiplyDivide", n="md_" + ctrlObj + "_autoTwist1")
 autoTwist2 = cmds.createNode("multiplyDivide", n="md_" + ctrlObj + "_autoTwist2")
 twistOffset1 = cmds.createNode("plusMinusAverage", n="pma_" + ctrlObj + "_twistOffset1")
 twistOffset2 = cmds.createNode("plusMinusAverage", n="pma_" + ctrlObj + "_twistOffset2")

 # connect the end control
 cmds.connectAttr(endCtrl + axis, autoTwist1 + ".input1X")
 cmds.connectAttr(ctrlObj + ".autoTwist", autoTwist1 + ".input2X")
 
 cmds.connectAttr(autoTwist1 + ".outputX", twistOffset1 + ".input1D[0]")
 cmds.connectAttr(ctrlObj + ".twistOffset", twistOffset1 + ".input1D[1]")
 
 # connect the start control
 cmds.connectAttr(startCtrl + axis, autoTwist2 + ".input1X")
 cmds.connectAttr(ctrlObj + ".autoTwist", autoTwist2 + ".input2X") 

 cmds.connectAttr(twistOffset1 + ".output1D", twistOffset2 + ".input1D[0]")
 cmds.connectAttr(autoTwist2 + ".outputX", twistOffset2 + ".input1D[1]")
 
 cmds.setAttr(twistOffset2 + ".operation", 2) # subtract
 
 # connect to the ikHandle
 cmds.connectAttr(startCtrl + axis, ikHandle + ".roll")
 cmds.connectAttr(twistOffset2 + ".output1D", ikHandle + ".twist")
 
 # make changes if the twist axis is on the negative side
 if neg:
  invTwist1 = cmds.createNode("multiplyDivide", n="md_" + ctrlObj + "_invTwist1")
  invTwist2 = cmds.createNode("multiplyDivide", n="md_" + ctrlObj + "_invTwist2")
  
  cmds.setAttr(invTwist1 + ".input2X", -1)
  cmds.setAttr(invTwist2 + ".input2X", -1)
  
  cmds.connectAttr(endCtrl + axis, invTwist1 + ".input1X")
  cmds.connectAttr(startCtrl + axis, invTwist2 + ".input1X")
  
  cmds.connectAttr(invTwist1 + ".outputX", autoTwist1 + ".input1X", f=True)
  cmds.connectAttr(invTwist2 + ".outputX", autoTwist2 + ".input1X", f=True)
  cmds.connectAttr(invTwist2 + ".outputX", ikHandle + ".roll", f=True)

Hope you guys liked it! Feel free to share!
And to leave any comments or questions!

Enjoy!

Friday, August 2, 2013

Rigging the Eye Brows

Check out the video tutorial on rigging eye brow controls for your characters. For my friend Rafael Salvador who asked me to put this together.
Im also going to start embedding the videos here in the website and see how that goes.


This is the concept shown in the video.


Enjoy!