def __init__(self, name, wireType, facingAxis, aOffset=(0,0,0), size=10, colorId=0, snap=None, ctlOffsets=[]): ''' Initializes control curve snap - transform node (or nodes) to set initial position for home group (if None, set to origin) ctlOffsets - list of groups nodes above control ''' self.crv = abRT.makeWireController(wireType, facingAxis, aOffset, size) self.crv = mc.rename(self.crv, name) # color control abRT.colorObj(self.crv, colorId) # set pivot to local origin mc.setAttr(self.crv+'.rp', 0,0,0) mc.setAttr(self.crv+'.sp', 0,0,0) # snap control to position if snap is defined, otherwise leave it at origin if snap: abRT.snapToPosition(snap, self.crv) # all controls have a home group, to "freeze" the local transforms self.home = abRT.groupFreeze(self.crv) self.home = mc.rename(self.home, name+'_hm') # add optional offset groups between home and actual control self.grp = {} for offsetGrp in ctlOffsets: self.grp[offsetGrp] = abRT.groupFreeze(self.crv) self.grp[offsetGrp] = mc.rename(self.grp[offsetGrp], name+'_'+offsetGrp)
def __init__(self, name, wireType, facingAxis, aOffset=(0, 0, 0), size=10, colorId=0, snap=None, ctlOffsets=[]): ''' Initializes control curve snap - transform node (or nodes) to set initial position for home group (if None, set to origin) ctlOffsets - list of groups nodes above control ''' self.crv = abRT.makeWireController(wireType, facingAxis, aOffset, size) self.crv = mc.rename(self.crv, name) # color control abRT.colorObj(self.crv, colorId) # set pivot to local origin mc.setAttr(self.crv + '.rp', 0, 0, 0) mc.setAttr(self.crv + '.sp', 0, 0, 0) # snap control to position if snap is defined, otherwise leave it at origin if snap: abRT.snapToPosition(snap, self.crv) # all controls have a home group, to "freeze" the local transforms self.home = abRT.groupFreeze(self.crv) self.home = mc.rename(self.home, name + '_hm') # all controls also have a space group, for space-switching self.space = abRT.groupFreeze(self.crv) self.space = mc.rename(self.space, name + '_space') # add optional offset groups between space and actual control self.grp = {} for offsetGrp in ctlOffsets: self.grp[offsetGrp] = abRT.groupFreeze(self.crv) self.grp[offsetGrp] = mc.rename(self.grp[offsetGrp], name + '_' + offsetGrp)
def rigEyes(): # eyeBall - eyeLids intersections surf1 = 'LT_eyeBallIntersect_srf_0' surf2 = 'CT_eyeBallHeadIntersecter_srf_0' jntsNum = 20 addJntsOnSurfIntersection(surf1, surf2, jntsNum) # eyeBall pop controls baseTangentMP = ms.addTangentMPTo('LT_eyeBase_mPt', 'LT_eyeTip_mPt', 'z', default=0.2, reverse=False) tipTangentMP = ms.addTangentMPTo('LT_eyeTip_mPt', 'LT_eyeBase_mPt', 'z', default=0.2, reverse=True) midMP = ms.addMidMP(baseTangentMP, tipTangentMP, 'LT_eyeBase_mPt', 'LT_eyeTip_mPt', (0, 0, 1), (0, 1, 0), 'LT_mid_mPt') crv = ms.createSplineMPs(('LT_eyeBase_mPt', baseTangentMP, midMP, tipTangentMP, 'LT_eyeTip_mPt'), 8, 'LT_eyeSpine', (0, 3, 0)) baseTangentMP = ms.addTangentMPTo('RT_eyeBase_mPt', 'RT_eyeTip_mPt', 'z', default=0.2, reverse=False) tipTangentMP = ms.addTangentMPTo('RT_eyeTip_mPt', 'RT_eyeBase_mPt', 'z', default=0.2, reverse=True) midMP = ms.addMidMP(baseTangentMP, tipTangentMP, 'RT_eyeBase_mPt', 'RT_eyeTip_mPt', (0, 0, 1), (0, 1, 0), 'RT_mid_mPt') crv = ms.createSplineMPs(('RT_eyeBase_mPt', baseTangentMP, midMP, tipTangentMP, 'RT_eyeTip_mPt'), 8, 'RT_eyeSpine', (0, 3, 0)) #=========================================================================== # add IK offset ctrls to eyeball #=========================================================================== lfMps = mc.ls(sl=True) ctls = [] # create left controls for ctlId in range(0, len(lfMps)): ctl = cs.ctlCurve(lfMps[ctlId].replace('_MPJnt_', '_ctl_'), 'circle', 0, size=6, snap=lfMps[ctlId]) ctl.setSpaces([lfMps[ctlId]], ['Eye']) ctls.append(ctl) rtMps = mc.ls(sl=True) ctls = [] # create right controls for ctlId in range(0, len(rtMps)): ctl = cs.ctlCurve(rtMps[ctlId].replace('_MPJnt_', '_ctl_'), 'circle', 0, size=6, snap=rtMps[ctlId]) ctl.setSpaces([rtMps[ctlId]], ['Eye']) ctls.append(ctl) #=========================================================================== # Add stretchy volume for eyeBall spine #=========================================================================== stretchAmts = { 'LT_eyeSpine_ctl_0_space': 10, 'LT_eyeSpine_ctl_1_space': 9, 'LT_eyeSpine_ctl_2_space': 8, 'LT_eyeSpine_ctl_3_space': 5, 'LT_eyeSpine_ctl_4_space': 3, 'LT_eyeSpine_ctl_5_space': 1.25, 'LT_eyeSpine_ctl_6_space': 0, 'LT_eyeSpine_ctl_7_space': -1 } ms.addVolume('LT_eyeSpine_uniform_crv_crv', stretchAmts) stretchAmts = { 'RT_eyeSpine_ctl_0_space': 10, 'RT_eyeSpine_ctl_1_space': 9, 'RT_eyeSpine_ctl_2_space': 8, 'RT_eyeSpine_ctl_3_space': 5, 'RT_eyeSpine_ctl_4_space': 3, 'RT_eyeSpine_ctl_5_space': 1.25, 'RT_eyeSpine_ctl_6_space': 0, 'RT_eyeSpine_ctl_7_space': -1 } ms.addVolume('RT_eyeSpine_uniform_crv_crv', stretchAmts) #=========================================================================== # Add control lattice to eyeBall nurbs #=========================================================================== # Create lattice - hard coded to 8 ctls in Z eyeSphere = 'LT_eyeBallIntersect_srf_0' prefix = 'LT_eyeBallIntersect_' ffd, lat, latBase = mc.lattice(eyeSphere, n=prefix + 'ffd', oc=True, dv=(4, 4, 8)) grp = abRT.groupFreeze(lat) rt.transferAttrValues(lat + '.s', grp + '.s', False) mc.setAttr(lat + '.s', 1, 1, 1) mc.parent(latBase, grp) # Create lattice - hard coded to 8 ctls in Z eyeSphere = 'RT_eyeBallIntersect_srf_0' prefix = 'RT_eyeBallIntersect_' ffd, lat, latBase = mc.lattice(eyeSphere, n=prefix + 'ffd', oc=True, dv=(4, 4, 8)) grp = abRT.groupFreeze(lat) rt.transferAttrValues(lat + '.s', grp + '.s', False) mc.setAttr(lat + '.s', 1, 1, 1) mc.parent(latBase, grp) # DO THIS FOR LEFT AND RIGHT SIDES # Create joints under each ctl ctls = mc.ls(os=True) jnts = [] for eachCtl in ctls: mc.select(cl=True) jnt = mc.joint(n=eachCtl.replace('_ctl', '_jnt')) rt.parentSnap(jnt, eachCtl) jnts.append(jnt) mc.setAttr(jnt + '.radius', 3) mc.setAttr(jnt + '.jointOrient', 0, 0, 0) # Weight joints to lattice skn = mc.skinCluster(jnts, lat, name=lat + '_skn')[0] for jnt in jnts: i = jnts.index(jnt) mc.skinPercent(skn, lat + '.pt[*][*][%d]' % i, tv=((jnt, 1)))
def rigEyes(): # eyeBall - eyeLids intersections surf1 = 'LT_eyeBallIntersect_srf_0' surf2 = 'CT_eyeBallHeadIntersecter_srf_0' jntsNum = 20 addJntsOnSurfIntersection(surf1, surf2, jntsNum) # eyeBall pop controls baseTangentMP = ms.addTangentMPTo('LT_eyeBase_mPt', 'LT_eyeTip_mPt', 'z', default=0.2, reverse=False) tipTangentMP = ms.addTangentMPTo('LT_eyeTip_mPt', 'LT_eyeBase_mPt', 'z', default=0.2, reverse=True) midMP = ms.addMidMP(baseTangentMP, tipTangentMP, 'LT_eyeBase_mPt', 'LT_eyeTip_mPt', (0,0,1), (0,1,0), 'LT_mid_mPt') crv = ms.createSplineMPs(('LT_eyeBase_mPt', baseTangentMP, midMP, tipTangentMP, 'LT_eyeTip_mPt'), 8, 'LT_eyeSpine', (0,3,0)) baseTangentMP = ms.addTangentMPTo('RT_eyeBase_mPt', 'RT_eyeTip_mPt', 'z', default=0.2, reverse=False) tipTangentMP = ms.addTangentMPTo('RT_eyeTip_mPt', 'RT_eyeBase_mPt', 'z', default=0.2, reverse=True) midMP = ms.addMidMP(baseTangentMP, tipTangentMP, 'RT_eyeBase_mPt', 'RT_eyeTip_mPt', (0,0,1), (0,1,0), 'RT_mid_mPt') crv = ms.createSplineMPs(('RT_eyeBase_mPt', baseTangentMP, midMP, tipTangentMP, 'RT_eyeTip_mPt'), 8, 'RT_eyeSpine', (0,3,0)) #=========================================================================== # add IK offset ctrls to eyeball #=========================================================================== lfMps = mc.ls(sl=True) ctls = [] # create left controls for ctlId in range(0,len(lfMps)): ctl = cs.ctlCurve(lfMps[ctlId].replace('_MPJnt_', '_ctl_'), 'circle', 0, size=6, snap=lfMps[ctlId]) ctl.setSpaces([lfMps[ctlId]], ['Eye']) ctls.append(ctl) rtMps = mc.ls(sl=True) ctls = [] # create right controls for ctlId in range(0,len(rtMps)): ctl = cs.ctlCurve(rtMps[ctlId].replace('_MPJnt_', '_ctl_'), 'circle', 0, size=6, snap=rtMps[ctlId]) ctl.setSpaces([rtMps[ctlId]], ['Eye']) ctls.append(ctl) #=========================================================================== # Add stretchy volume for eyeBall spine #=========================================================================== stretchAmts = {'LT_eyeSpine_ctl_0_space':10, 'LT_eyeSpine_ctl_1_space':9, 'LT_eyeSpine_ctl_2_space':8, 'LT_eyeSpine_ctl_3_space':5, 'LT_eyeSpine_ctl_4_space':3, 'LT_eyeSpine_ctl_5_space':1.25, 'LT_eyeSpine_ctl_6_space':0, 'LT_eyeSpine_ctl_7_space':-1} ms.addVolume('LT_eyeSpine_uniform_crv_crv', stretchAmts) stretchAmts = {'RT_eyeSpine_ctl_0_space':10, 'RT_eyeSpine_ctl_1_space':9, 'RT_eyeSpine_ctl_2_space':8, 'RT_eyeSpine_ctl_3_space':5, 'RT_eyeSpine_ctl_4_space':3, 'RT_eyeSpine_ctl_5_space':1.25, 'RT_eyeSpine_ctl_6_space':0, 'RT_eyeSpine_ctl_7_space':-1} ms.addVolume('RT_eyeSpine_uniform_crv_crv', stretchAmts) #=========================================================================== # Add control lattice to eyeBall nurbs #=========================================================================== # Create lattice - hard coded to 8 ctls in Z eyeSphere = 'LT_eyeBallIntersect_srf_0' prefix = 'LT_eyeBallIntersect_' ffd, lat, latBase = mc.lattice(eyeSphere, n=prefix+'ffd', oc=True, dv=(4,4,8)) grp = abRT.groupFreeze(lat) rt.transferAttrValues(lat+'.s', grp+'.s', False) mc.setAttr(lat+'.s',1,1,1) mc.parent(latBase, grp) # Create lattice - hard coded to 8 ctls in Z eyeSphere = 'RT_eyeBallIntersect_srf_0' prefix = 'RT_eyeBallIntersect_' ffd, lat, latBase = mc.lattice(eyeSphere, n=prefix+'ffd', oc=True, dv=(4,4,8)) grp = abRT.groupFreeze(lat) rt.transferAttrValues(lat+'.s', grp+'.s', False) mc.setAttr(lat+'.s',1,1,1) mc.parent(latBase, grp) # DO THIS FOR LEFT AND RIGHT SIDES # Create joints under each ctl ctls = mc.ls(os=True) jnts = [] for eachCtl in ctls: mc.select(cl=True) jnt = mc.joint(n=eachCtl.replace('_ctl', '_jnt')) rt.parentSnap(jnt, eachCtl) jnts.append(jnt) mc.setAttr(jnt+'.radius', 3) mc.setAttr(jnt+'.jointOrient', 0,0,0) # Weight joints to lattice skn = mc.skinCluster(jnts, lat, name=lat+'_skn')[0] for jnt in jnts: i = jnts.index(jnt) mc.skinPercent(skn, lat+'.pt[*][*][%d]'%i, tv=((jnt, 1)))
def addReverseRoll(jnts, bendPivot, leftPivot, rightPivot): ''' add reverse roll to hand or foot setups jnts - [base, [digitBase, digitEnd], ... ] digitBase joints will be parentConstrained to the new "stableDigitJoints" that sticks with the IK handles (so you should pass in an offset grp above the actual joint) *** ASSUME ONE SPLIT JOINT BETWEEN BASE AND DIGIT TO BE CUSTOMIZED *** returns rollGrp, baseJnt EXAMPLE USE ON HAND: rollGrp (TRS, and attributes Bend & Side) should be driven by Ik/FKHand rollLocs rotations are driven by attributes on the Hand baseStableJnt is a child of the rollLocs, and therefore rotate with pivots at the rollLocs baseStableJnt drives the child of Ik/FkHand ''' #=========================================================================== # BUILD DRIVER JOINT CHAIN #=========================================================================== baseJnt = jnts[0] digitJnts = jnts[1:] basePos = mc.xform(baseJnt, q=True, t=True, ws=True) # base joint mc.select(cl=True) baseStableJnt = mc.joint(n=baseJnt+'_stable') rt.parentSnap(baseStableJnt, baseJnt) mc.setAttr(baseStableJnt+'.jointOrient', 0,0,0) mc.parent(baseStableJnt, w=True) ikHs = [] # digit joints for base, tip in digitJnts: #======================================================================= # MAKE JOINTS #======================================================================= mc.select(cl=True) # split joint digitPos = mc.xform(base, q=True, t=True, ws=True) # get midPoint between base to digitBase midPoint = [(b + d)/2 for b, d in zip(basePos, digitPos)] splitJnt = mc.joint(p=midPoint, n=base+'_mid') # digit base jnt digitBaseJnt = mc.joint(p=digitPos, n=base+'_stable') # digit end jnt tipPos = mc.xform(tip, q=True, t=True, ws=True) digitEndJnt = mc.joint(p=tipPos, n=base+'_stableTip') # orient joint chain mc.joint(splitJnt, oj='xyz', ch=True, sao='yup', e=True) mc.setAttr(digitEndJnt+'.jointOrient', 0,0,0) mc.parent(splitJnt, baseStableJnt) #======================================================================= # MAKE IKHANDLE #======================================================================= ikH = mc.ikHandle(solver='ikSCsolver', n=base+'_ikH', sj=digitBaseJnt, ee=digitEndJnt)[0] ikHs.append(ikH) #======================================================================= # PARENT CONSTRAINT original joints to stable joints #======================================================================= mc.parentConstraint(digitBaseJnt, base, mo=True) ikHdlGrp = mc.group(ikHs, n=baseJnt+'reverseRoll_ikHdl_grp') # parent baseStableJnt under locators to make multiple pivots rollGrp = abRT.groupFreeze(baseStableJnt) mc.parent(bendPivot, rollGrp) mc.parent(leftPivot, bendPivot) mc.parent(rightPivot, leftPivot) mc.parent(baseStableJnt, rightPivot) mc.parent(ikHdlGrp, rollGrp) # hide locators for debugging rt.connectVisibilityToggle([bendPivot, leftPivot, rightPivot], rollGrp, 'debugPivotLocs', False) # add attributes for controlling bend and side-to-side mc.addAttr(rollGrp, ln='bend', at='double', min=-10, max=10, dv=0, k=True) mc.addAttr(rollGrp, ln='side', at='double', min=-10, max=10, dv=0, k=True) rt.connectSDK(rollGrp+'.bend', bendPivot+'.rz', {-10:90, 10:-90}) rt.connectSDK(rollGrp+'.side', leftPivot+'.rx', {0:0, 10:-90}) rt.connectSDK(rollGrp+'.side', rightPivot+'.rx', {0:0, -10:90}) return rollGrp, baseStableJnt