Updates coming soon!
Proxy Pose
Motion Blur
3D sculpt inspired by mixed martial arts.
A video series explaining the concept and scripting a tool to setup and interact with space switching setup for rigs.
Small project with simulated rigid bodies and nParticle effects.
A tutorial on using the spline deformer on custom geometry to create muscle flexing and stretching behavior.
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)
import lpDynamicChains reload(lpDynamicChains) lpDynamicChains.UI()
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.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.
# create instance
dynChain = lpDynamicChain()
# create iterable for all dynamic nodes in the scene
dynChains = dynChain.Iter()
for d in dynChains:
print d
Adding Collision Objectsfrom 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 Connectedfrom 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
'''
Checksfrom 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 Collidersfrom 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 Nodesfrom lpDynamicChains import *
deletedNodes = deleteUnusedNucleusSolvers()
def deleteUnusedNucleusSolvers():
'''
Delete all nucleus nodes not being used
Parameters:
Nothing
Returns:
List of nucleus node deleted
'''
Create and Connectfrom 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 connectionsfrom 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
'''