Finished the initial sculpt for a clucker, now to retopologize, UV, add detail, and texture said clucker.
Onto joint orients: Maya' joint orient attributes are seen to some as a nicety since you can hide rotate values in them. Others see joint orient attributes as an abomination because they are unique to Maya and obfuscate the actual rotate value. I belong to the latter group. Unfortunately, Maya does not make it easy to create a skeleton without joint orient values. In comes the following couple nifty helper functions I wrote to help with joint hierarchy creation without any joint orient values.
First up, is a function to parent joints while maintaining joint orient values at (0, 0, 0).
def parentTransforms(*transforms):
"""
Parents transforms to the last given transform and gets rid of joint orient values if transform is a joint.
Args:
transforms (list or pm.nodetypes.Transform): Transforms to parent. Last transform is the parent of the rest.
Minimum of two objects.
"""
for joint in transforms[:-1]:
if isinstance(joint, pm.nodetypes.Joint):
matrix = joint.worldMatrix.get()
pm.parent(joint, transforms[-1])
joint.jointOrient.set(0, 0, 0)
pm.xform(joint, ws=True, m=matrix)
else:
pm.parent(joint, transforms[-1])
Example:
import pymel.core as pm
selected = pm.selected()
to_be_child = selected[0]
to_be_parent = selected[1]
parentTransforms([to_be_child, to_be_parent])
With this new parentTransforms function, we can easily mirror joints without having that pesky 180 degrees added to the joint orient value.
def mirrorRotate(transforms=pm.selected(), axis='x', swap=['', '']):
"""
Mirrors the given transforms across the given axis set up to be used as a mirror rotate transform.
Args:
transforms (list): Transforms to mirror across given axis.
axis (string): Name of axis to mirror across.
swap (list): Words to search and replace. Will search for first index, and replace with second index.
Returns:
(list): Joints that were mirrored. Note that all their children get mirrored as well.
"""
mirrored_transforms = []
options = {'mxy': False, 'myz': False, 'mxz': False, 'mb': True, 'sr': swap}
if axis == 'x':
options['myz'] = True
elif axis == 'y':
options['mxz'] = True
elif axis == 'z':
options['mxy'] = True
else:
pm.error('No valid axis given. Pick "x", "y", or "z".')
for transform in transforms:
name = transform.nodeName()
mirrored_joint = pm.mirrorJoint(transform, **options)[0]
mirrored_joint = pm.PyNode(mirrored_joint)
mirrored_transforms.append(mirrored_joint)
parent = mirrored_joint.getParent()
if mirrored_joint.getParent():
pm.parent(mirrored_joint, w=True)
parentTransforms(mirrored_joint, parent)
return mirrored_transforms
Comments