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, November 15, 2013

Friend in need

Today's post isn't about anything technical, today I want to reach out to ask for help for a fellow artist in need.

Ana Kessel (http://anakessel.weebly.com/3D modeler, was struck by a hit-and-run driver while riding her moped. Her leg has been amputated from the injuries. She is doing OK, but she is going to need as much support as she can in order to get through this. A fundraiser has been started for her to try and raise money to help pay for the medical bills. Any donations will help and they can be submitted at 

http://www.gofundme.com/58oak4

Please share the link and help more people get involved.

Thank you

Thursday, October 31, 2013

Spidey rig update

The Spidey rig has evolved! New look, more intuitive controls, and more advance features. More updates soon.


 

  



Little guy!




Wednesday, October 16, 2013

Droid Game Rig: Collision to Animation test

An early test for a droid game rig. The setup includes a 'breakable' mode where the the rig's 'free ctrls' can move individual body parts freely in world space. On top of that a system was needed that would allow us to simulate collisions for quick animations down onto the controls without weighing down the scene. Once done the simulation can be baked to the controls so that we could continue to animate the controls for cleanup and finessing.

Model: Roberto Saavedra

Monday, October 14, 2013

Clicker Game Rig

Early iteration of animation rig for a game project. Character based on the zombie creature from 'Last of Us'.

Contribution: Retopology and rigging.



Animation: Fabio Ribak
Model: Roberto Saavedra

Monday, September 30, 2013

lpPoser Tool

Updates coming soon!



Proxy Pose


  



Motion Blur

Rotation Select Axis

Handy little tool to select individual rotation axis handle quicker. Good also for when manipulator gets in the way of select correct axis, and when in gimbal lock.


Its a short one, so just quicker to copy and paste :)
Here's the code
import maya.cmds as cmds
from functools import partial

def rotateContext(axis, *args):
 cmds.manipRotateContext( 'Rotate', e=True, ah=axis)
 
if cmds.window("rotateContextUI", exists=True):
 cmds.deleteUI("rotateContextUI")
 
win = cmds.window("rotateContextUI", title="Rotate Axis UI", w=150, sizeable=False)
cmds.rowColumnLayout(nc=3, columnAttach=[(1,"both", 2), (3, "both", 2)])

cmds.button("X", w=30, bgc=[1,0,0], c=partial(rotateContext, 0))
cmds.button("Y", w=30, bgc=[0,1,0], c=partial(rotateContext, 1))
cmds.button("Z", w=30, bgc=[0,0,1], c=partial(rotateContext, 2))

cmds.showWindow(win)

Saturday, September 7, 2013

lpDynamicChains

This a reference page for the lpDynamicChains tool.

DESCRIPTION

This tool allows for the creation of dynamic joint chains. User can specify joints to become dynamic. Can also turn any geometry into a collision object. Simulations can be cached to a file or baked as animation onto joints and dynamic nodes can be removed when done.

Suggested use: for tails, appendages, for secondary delayed movement - ex: jiggle


File:             lpDynamicChains.py

Versions:     1.0  -  06/28/2013  -  first version created
                   1.1  -  07/02/2013  -  changed curve degree to work with 2-3 joints chain. fixed
                                                        complete removal of dynamic nodes for delete dynamic
                   2.0  -  07/13/2013  -  added create collision object option
                   2.1  -  08/15/2013  -  updated collision feature and entire tool to use nDynamics
                                                        and the nucleus solver unifying all simulations under one solver
                   2.2  -  08/19/2013  -  added option to bake sim onto joint

USAGE NOTES
The UI
        1.     Place script in
                    Windows:     C:/Program Files/Autodesk/Maya2013/Python/lib/site-packages/ 
                    Mac:            Users/userName/Library/Preferences/Autodesk/maya/2013
                                        -x64/scripts/
        2.   To open the UI:
import lpDynamicChains
reload(lpDynamicChains)
lpDynamicChains.UI()
The UI allows for the creation and interaction of dynamic chains in the scene. It also allows access to lpDynamicChains commands

Create Dynamic joints

Select the start joint, shift select the end joint and click the 'Make Joints Dynamic' button under the Main section.

Commands:
from lpDynamicChains import *

dynChain = lpDynamiChain(startJoint, endJoint)
dynChain.create()

def lpDyanmicChain(startJoint="", endJoint="", node=""):
    '''
    Create the custom node

    Parameters:
        startJoint        - Name of the first joint in the chain
        endJoint          - Name of the last joint in the chain
        node              - Name of the node to manage by the class

    Returns:
        Nothing
    '''

def create(self):
    '''
    Create the actual dynamic joint chain node network

    Parameters:
        Nothing

    Returns:
        List of all new created nodes
    '''
A custom locator node will be created at the start joint's position holding the parameters to be tweaked to customize the dynamic behavior of the joint chain.

All nodes created will be stored as meta data on the nodes themselves to allow for the tool to keep track of the nodes associated with every newly created dynamic chain.

You will get a window prompting which nucleus to connect the dynamicChain to.

A log window will display at the end of creation, listing all nodes created with the new dynamicChain.

Remove Dynamic Nodes

Select any node created for the dynamic chain to be deleted or the dynamic chain locator at the start joint, and click the 'Remove Dynamic' button under the Main section.

Commands:
from lpDynamicChains import *

dynChain = lpDynamicChain(node=node)
dynChain.delete()
del(dynChain)
Note: Removing dynamic nodes will also check for any unused nucleus nodes and remove them as well.

All nodes created for the dynamic chain to be deleted will be removed from the scene returning it to its original state before the creation of the dynamic chain.

Iterate Through All Dynamic Chain Nodes

Commands:
# create instance
dynChain = lpDynamicChain()
# create iterable for all dynamic nodes in the scene
dynChains = dynChain.Iter()
for d in dynChains:
    print d
Adding Collision Objects

Select the locator for the dynamic chain to be edited, shift select the geometry to be turned into a collision object and click the 'Create Collision Object' button under the Options section.

Geometry object will be turned into a passive nRigid object to interact with the dynamic joints. A nRigid node will be created and stored in an array attribute keeping track of all collider nodes interacting with it.

Creating nCache

Select the locator or multiple locators for the dynamic chain(s) to be cached and click the 'Cache Simulation' button under the Advanced -> nCache section.

The nCache option window will display so you can choose how to save out the cache file (or multiple files) for the dynamic simulations. For more information please refer to the Autodesk Maya Help Docs

Removing nCache

Select the locator for the dynamic chain to be cached and click the 'Delete Cache' button under Advanced -> nCache section.

Note: Removing dynamic nodes for a given dynamic chain will not delete the cache file on disk.

The Delete nCache option window will display. If there are multiple cache nodes for the dynamic chain, you will be able to select which ones to delete.

The option to delete or keep the cache files on disk will also be available.

Baking Simulation to Joints

Select the locator for the dynamic chain to be bake the simulation for and click the 'Bake Simulation' button under Advanced -> Animation

Utility Commands

In addition to the UI functions, you can also access utility commands available with the script. Below are some examples.

Get and Set the Active Nucleus
from lpDynamicChains import *

nucleus = getActiveNucleus()
setActiveNucleus(nucleus)

def getActiveNucleus():
    '''
    Query the active nucleus node
    
    Parameters:
        Nothing
    
    Returns:
        Name of active nucleus node
    '''

def setActiveNucleus(nucleus):
    '''
    Set the active nucleus node
    
    Parameters:
        nucleus        - Name of nucleus node to set as current active nucleus
    
    Returns:
        Nothing
    '''
Get Connected

Get commands to find the connected DynamicChain node or the nucleus node connected to the dynamicNode
from lpDynamicChains import *

# get selected object
obj = cmds.ls(sl=True)[0]
dNode = getConnectedDynamicChain(obj)
nucleus = getConnectedNucleusNode(dNode)

def getConnectedDynamicChain(node):
    '''
    Look for a valid DynamicChain node connected to the given node
    
    Parameters:
        node             - Name of the node to find connection to DynamicChain
    
    Returns:
        Name of DynamicChain node connected to given node
    '''

def getConnectedNucleusNode(node):
    ''' 
    Look for the nucleus node connected to the given node
    
    Parameters:
        node             - Name of the node to find connection to nucleus
    
    Returns:
        Name of the nucleus node connected to the given node
    '''
Checks

Check commands to verify if node is a DynamicChain node or node is a nucleus compatible nDynamics node.
from lpDynamicChains import *

# get selected object
obj = cmds.ls(sl=True)[0]
if isDynamicChain(obj):
    dynChain = lpDynamicChain(obj)

    # access attribute
    hairShape = dynChain.hairSystemShape[0]
    return isNType(hairShape, "hairSystem")

def isDynamicChain(node):
    '''
    Look for the identifier to check if node is 'dynamic' 
    
    Parameters:
        node         -  Name of node to check for 'nodeType'
    
    Returns:
        Boolean value if node is dynamic or not, True or False
    '''

def isNType(node, nodeType):
    '''
    Check if the given node is a nucleus compatible nDynamics node
    
    Parameters:
        node        - Name of node to check for 'NType' compatibility
        nodeType    - Node type to check
    
    Returns:
        Boolean value if node is compatible with nDynamics solver
    '''
Number of Colliders

Check how many collision objects are attached to the node
from lpDynamicChains import *

# get selected object
obj = cmds.ls(sl=True)[0]
if isDynamicChain(obj):
    numColliders = findNumberOfCollisionObjects(obj)

def findNumberOfCollisionObjects(node):
    '''
    Find the number of collision objects attached to the node
    
    Parameters:
        node         - Name of the node to check for collision objects
    
    Returns:
        Integer number of collision objects attached to the node
    '''
Delete Unused Nucleus Nodes

Check nucleus nodes in the scene for their connections and remove any that are not being used.
from lpDynamicChains import *

deletedNodes = deleteUnusedNucleusSolvers()

def deleteUnusedNucleusSolvers():
    '''
    Delete all nucleus nodes not being used
    
    Parameters:
        Nothing
    
    Returns:
        List of nucleus node deleted
    '''
Create and Connect

Creation and connection commands to create new nucleus nodes, nRigid nodes, connect DynamicChain node to nucleus or to connect a nRigid node to a nucleus.
from lpDynamicChains import *

# get selected objects
selected = cmds.ls(sl=True)[0]

dNode = selected[0]
mesh = selected[1]

nucleus = createNucleus()
if isDynamicChain(dNode):
    nucleus = connectToNucleus(dNode, nucleus)
nRigid = createNRigid(mesh, nucleus)
index = connectNRigidToNucleus(nRigid, nucleus)

def createNucleus(name="", setActive=True):
    '''
    Create nucleus node
    
    Parameters:
        name             - Name for the new nucleus node
        setActive        - Boolean to set the new nucleus as the current active nucleus
        
    Returns:
        Name of new nucleus node
    '''

def createNRigid(obj, nucleus=""):
    '''
    Create a nRigig node from the given obj
    
    Parameters:
        obj              - Name of the geo to create nRigid from
        nucleus          - Name of the nucleus to connect nRigid to
        
    Returns:
        Name of new nRigid node
    '''

def connectToNucleus(node, nucleus):
    '''
    Connect the given node to the nucleus node
    
    Parameters:
        node             - Name of the node to connect to the nucleus solver
        nucleus          - Name of nucleus solver to connect to
    
    Returns:
        Name of nucleus node (debug)
    '''

def connectNRigidToNucleus(nRigid, nucleus, newNucleus=True):
    '''
    Connect the given nRigid node to the nucleus node, maintaining prior connections to
    other nucleus nodes
    
    Parameters:
        nRigid         - Name of nRigid node to connect to nucleus
        nucleus        - Name of nucleus node to connect
        newNucleus     - Boolean to create a new nucleus node if the specified nucleus doesn't exist
    
    Returns:
        Integer index of next available passive nRigid for the given nucleus
    '''
Access connections

Command to get all nodes connected to custom node, like hairSystem, or the ikHandle. Access custom attributes through class _getattr_ method

from lpDynamicChains import *

# get selected object
obj = cmds.ls(sl=True)
if isDynamicChain(obj):
    dNode = lpDynamicChain(node=obj)
    nodes = dNode.listConnections()
# get hairSystemShape node
hairShape = dNode.hairSystemShape[0]

def listConnections(self):
    '''
    Wrapper to get all connections to the node to message attributes
        
    Parameters:
        Nothing
        
    Returns:
        List of connected nodes to all custom message attributes
    '''

Wednesday, September 4, 2013

Node Based Pivot Switching

Hello guys. I was going to write a post to show how you can setup pivot switching to be built in your own rigs using native maya nodes.

However, this time, I thought just a video would cover what you need to know.

As you will see, this is a fairly straightforward approach once you've done it once. It just requires a little creativity. The idea here obviously is to look for an alternative to setting pivot switching for your controls, so you can interactively switch the pivot of your controls, without having to rely on an external tool or script.

If you need to refer back at some of the steps, here are some notes.


Here is the video.


Dynamic Chains Comeback

I did a video awhile back showing how to setup dynamic joint chains using Maya Hair. The idea was to show a quick and easy process to get those working. Since then I put together a tool to automate the setup process and to allow for easy management of multiple dynamic joint chains in the scene.

This is the original video posted.


The tool was planned out, and I've been updating it as I used it and as needed. Here is the original plan for the tool.


In the process, the setup also got update to utilize nDynamics and the nucleus solver, unifying all dynamic simulations under one solver.

In summary, the tool will allow the creation of multiple dynamic joint chain driven by nHair. The user will also be able to turn any geometry into a collision object, in order to have the joint interact with it. The simulations created with the setup can also be cached to a file or baked as animation onto joints, through the tool, and the dynamic nodes can be removed at any point in time.

I'll be making the tool script available soon in the Downloads section, and I will be posting a reference page with instructions on using the tool's UI.

Hope you guys enjoy it. Any feedback or comments will be very appreciated.

Friday, August 30, 2013

Lion Rig Update

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