def buildHairRigFromGrp(crvGrp, jntsNum=3): ''' hairGrp is a group with curves Z-axis is used for joint chain's up vector crvGrp = nt.Transform(u'RT_hairGrpE_crv_grp') jntsNum = 3 ''' headLat = pm.PyNode('CT_headLattice_dfm') headSkn = pm.PyNode('NEWGEO:CT_hair_geoShapeDeformed_skn') crvs = crvGrp.getChildren(ad=True, type='nurbsCurve') # create master for the group masterCtl = createControl(crvGrp.replace('_crv_grp','_master')) wMat = crvGrp.getMatrix(ws=True) masterCtl[0].setMatrix(wMat, ws=True) # add attrs for joint multipliers for jntId in range(jntsNum): # defaultMult = 1.0 / pow(2, jntId) masterCtl[2].addAttr('jnt_%d_mult'%jntId, dv=1, k=True) jntMults = [masterCtl[2].attr('jnt_%d_mult'%jntId) for jntId in range(jntsNum)] # multiply for rotations mds = [] for jntId in range(jntsNum): md = pm.createNode('multiplyDivide', n=crvGrp.replace('_crv_grp','_master_rotMult%d'%jntId)) masterCtl[2].r >> md.input1 jntMults[jntId] >> md.input2X jntMults[jntId] >> md.input2Y jntMults[jntId] >> md.input2Z mds.append(md) # calculate upvector to orient joints upVec = pm.dt.Vector(0,0,1) * wMat upVec.normalize() # build controls for hair strands # iter through hair strands # store nodes so we can group things later wsDagList = [] wsSurfList = [] allCtlsList = [] dcmList = [] for crv in crvs: # get points on curve totalLen = crv.length() sectionLens = [totalLen/jntsNum*jntId for jntId in range(jntsNum+1)] params = [crv.findParamFromLength(length) for length in sectionLens] points = [crv.getPointAtParam(param) for param in params] # create controls parentPnts = points[:-1] childPnts = points[1:] parentCtl = None parentWsDag = None for ctlId, pPnt, cPnt in zip(range(jntsNum), parentPnts, childPnts): # calculate matrrix for control xVec = (cPnt - pPnt ).normal() yVec = upVec.cross(xVec).normal() zVec = xVec.cross(yVec).normal() mat = pm.dt.Matrix(xVec, yVec, zVec, pm.dt.Vector(pPnt)) # this matrix should be affected by the headLattice latticeDag = pm.group(em=True, n=crv.replace('_crv','_latDag%d'%ctlId)) latticeDagHm = pm.group(latticeDag, n=crv.replace('_crv','_latDagHm%d'%ctlId)) latticeDagHm.setMatrix(mat, ws=True) wsDag, surf = surfOffset.addOffset(latticeDag) wsDagList.append(wsDag) wsSurfList.append(surf) # wsDag is the worldSpace transforms after headLattice deformation surfOffset.addSurfToDeformer([surf], headLat) # add control ctlList = createControl(crv.replace('_crv','_ctl%d'%ctlId)) ctlList[0].setMatrix(mat, ws=True) # get transforms from wsDag (from lattice deformations) if parentCtl == None: # no parent, so just use wsDag directly xformPlug = wsDag.worldMatrix allCtlsList.append(ctlList[0]) else: # get inversematrix of parent # so we can put this in parent space mm = pm.createNode('multMatrix', n=crv.replace('_crv','_mm%d'%ctlId)) wsDag.worldMatrix >> mm.matrixIn[0] parentWsDag.worldInverseMatrix >> mm.matrixIn[1] xformPlug = mm.matrixSum # hierarchy ctlList[0].setParent(parentCtl) # update for the next iteration parentCtl = ctlList[2] parentWsDag = wsDag # set transforms on cth from xformPlug dcm = pm.createNode('decomposeMatrix', n=crv.replace('_crv','_dcm%d'%ctlId)) dcmList.append(dcm) xformPlug >> dcm.inputMatrix dcm.outputTranslate >> ctlList[0].t dcm.outputRotate >> ctlList[0].r # connect master multipliers mds[ctlId].output >> ctlList[1].r # add joint under control pm.select(cl=True) jnt = pm.joint(n=crv.replace('_crv','_jnt%d'%ctlId)) jnt.setParent(ctlList[2]) jnt.setMatrix(pm.dt.Matrix()) # bind joint to skin cluster headSkn.addInfluence(jnt, lw=True, wt=0) bindPostMatrixPlug = jnt.worldMatrix.outputs(p=True)[0] bindPreMatrixPlugName = bindPostMatrixPlug.replace('.matrix', '.bindPreMatrix') bindPreMatrixPlug = pm.PyNode(bindPreMatrixPlugName) wsDag.worldInverseMatrix >> bindPreMatrixPlug # organize stuff wsDagTops = [dag.getParent() for dag in wsDagList] wsSurfTops = [dag.getParent(2) for dag in wsSurfList] wsDagGrp = pm.group(wsDagTops, n=crvGrp.replace('_crv_grp','_wsDagGrp')) wsSurfGrp = pm.group(wsSurfTops, n=crvGrp.replace('_crv_grp','_wsSurfGrp')) ctlsGrp = pm.group(masterCtl[0], allCtlsList, n=crvGrp.replace('_crv_grp','_allCtlsGrp')) masterGrp = pm.group(wsDagGrp, wsSurfGrp, crvGrp, n=crvGrp.replace('_crv_grp','_rig_grp')) # move masterCtl with the first wsDag origMat = masterCtl[0].getMatrix(ws=True) dcmList[0].outputTranslate >> masterCtl[0].t dcmList[0].outputRotate >> masterCtl[0].r masterCtl[1].setMatrix(origMat, ws=True) return ctlsGrp, masterGrp
nt.Transform(u'RT_upperInner_eyelid_ctrl_negRev'), nt.Transform(u'RT_upper_eyelid_ctrl_negRev'), nt.Transform(u'RT_upperOuter_eyelid_ctrl_negRev'), nt.Transform(u'RT_outer_eyelid_ctrl_negRev'), nt.Transform(u'RT_lowerOuter_eyelid_ctrl_negRev'), nt.Transform(u'RT_lower_eyelid_ctrl_negRev'), nt.Transform(u'RT_lowerInner_eyelid_ctrl_negRev'), nt.Transform(u'RT_upper_eyelid_pri_ctrl_negRev'), nt.Transform(u'RT_outer_eyelid_pri_ctrl_negRev'), nt.Transform(u'RT_lower_eyelid_pri_ctrl_negRev'), nt.Transform(u'RT_inner_eyelid_pri_ctrl_negRev'), nt.Transform(u'RT__eyeMover_pri_ctrl_negRev'), nt.Transform(u'LT_in_brow_ctrl_negRev'), nt.Transform(u'LT_mid_brow_ctrl_negRev'), nt.Transform(u'LT_out_brow_ctrl_negRev'), nt.Transform(u'LT_mid_brow_pri_ctrl_negRev'), nt.Transform(u'RT_mid_brow_ctrl_negRev'), nt.Transform(u'RT_out_brow_ctrl_negRev'), nt.Transform(u'RT_in_brow_ctrl_negRev'), nt.Transform(u'RT_mid_brow_pri_ctrl_negRev') ] offsets = [] for n in nodes: offsetGrp = surfOffset.addOffset(n) offsets.append(offsetGrp[1]) pm.select(offsets) dfm = pm.PyNode('CT_spine_lattice_dfm') surfOffset.addSurfToDeformer(offsets, dfm)
nt.Transform(u'RT_upperInner_eyelid_ctrl_negRev'), nt.Transform(u'RT_upper_eyelid_ctrl_negRev'), nt.Transform(u'RT_upperOuter_eyelid_ctrl_negRev'), nt.Transform(u'RT_outer_eyelid_ctrl_negRev'), nt.Transform(u'RT_lowerOuter_eyelid_ctrl_negRev'), nt.Transform(u'RT_lower_eyelid_ctrl_negRev'), nt.Transform(u'RT_lowerInner_eyelid_ctrl_negRev'), nt.Transform(u'RT_upper_eyelid_pri_ctrl_negRev'), nt.Transform(u'RT_outer_eyelid_pri_ctrl_negRev'), nt.Transform(u'RT_lower_eyelid_pri_ctrl_negRev'), nt.Transform(u'RT_inner_eyelid_pri_ctrl_negRev'), nt.Transform(u'RT__eyeMover_pri_ctrl_negRev'), nt.Transform(u'LT_in_brow_ctrl_negRev'), nt.Transform(u'LT_mid_brow_ctrl_negRev'), nt.Transform(u'LT_out_brow_ctrl_negRev'), nt.Transform(u'LT_mid_brow_pri_ctrl_negRev'), nt.Transform(u'RT_mid_brow_ctrl_negRev'), nt.Transform(u'RT_out_brow_ctrl_negRev'), nt.Transform(u'RT_in_brow_ctrl_negRev'), nt.Transform(u'RT_mid_brow_pri_ctrl_negRev')] offsets = [] for n in nodes: offsetGrp = surfOffset.addOffset(n) offsets.append(offsetGrp[1]) pm.select(offsets) dfm = pm.PyNode('CT_spine_lattice_dfm') surfOffset.addSurfToDeformer(offsets, dfm)
def buildHairRigFromGrp(crvGrp, jntsNum=3): ''' hairGrp is a group with curves Z-axis is used for joint chain's up vector crvGrp = nt.Transform(u'RT_hairGrpE_crv_grp') jntsNum = 3 ''' headLat = pm.PyNode('CT_headLattice_dfm') headSkn = pm.PyNode('NEWGEO:CT_hair_geoShapeDeformed_skn') crvs = crvGrp.getChildren(ad=True, type='nurbsCurve') # create master for the group masterCtl = createControl(crvGrp.replace('_crv_grp', '_master')) wMat = crvGrp.getMatrix(ws=True) masterCtl[0].setMatrix(wMat, ws=True) # add attrs for joint multipliers for jntId in range(jntsNum): # defaultMult = 1.0 / pow(2, jntId) masterCtl[2].addAttr('jnt_%d_mult' % jntId, dv=1, k=True) jntMults = [ masterCtl[2].attr('jnt_%d_mult' % jntId) for jntId in range(jntsNum) ] # multiply for rotations mds = [] for jntId in range(jntsNum): md = pm.createNode('multiplyDivide', n=crvGrp.replace('_crv_grp', '_master_rotMult%d' % jntId)) masterCtl[2].r >> md.input1 jntMults[jntId] >> md.input2X jntMults[jntId] >> md.input2Y jntMults[jntId] >> md.input2Z mds.append(md) # calculate upvector to orient joints upVec = pm.dt.Vector(0, 0, 1) * wMat upVec.normalize() # build controls for hair strands # iter through hair strands # store nodes so we can group things later wsDagList = [] wsSurfList = [] allCtlsList = [] dcmList = [] for crv in crvs: # get points on curve totalLen = crv.length() sectionLens = [ totalLen / jntsNum * jntId for jntId in range(jntsNum + 1) ] params = [crv.findParamFromLength(length) for length in sectionLens] points = [crv.getPointAtParam(param) for param in params] # create controls parentPnts = points[:-1] childPnts = points[1:] parentCtl = None parentWsDag = None for ctlId, pPnt, cPnt in zip(range(jntsNum), parentPnts, childPnts): # calculate matrrix for control xVec = (cPnt - pPnt).normal() yVec = upVec.cross(xVec).normal() zVec = xVec.cross(yVec).normal() mat = pm.dt.Matrix(xVec, yVec, zVec, pm.dt.Vector(pPnt)) # this matrix should be affected by the headLattice latticeDag = pm.group(em=True, n=crv.replace('_crv', '_latDag%d' % ctlId)) latticeDagHm = pm.group(latticeDag, n=crv.replace('_crv', '_latDagHm%d' % ctlId)) latticeDagHm.setMatrix(mat, ws=True) wsDag, surf = surfOffset.addOffset(latticeDag) wsDagList.append(wsDag) wsSurfList.append(surf) # wsDag is the worldSpace transforms after headLattice deformation surfOffset.addSurfToDeformer([surf], headLat) # add control ctlList = createControl(crv.replace('_crv', '_ctl%d' % ctlId)) ctlList[0].setMatrix(mat, ws=True) # get transforms from wsDag (from lattice deformations) if parentCtl == None: # no parent, so just use wsDag directly xformPlug = wsDag.worldMatrix allCtlsList.append(ctlList[0]) else: # get inversematrix of parent # so we can put this in parent space mm = pm.createNode('multMatrix', n=crv.replace('_crv', '_mm%d' % ctlId)) wsDag.worldMatrix >> mm.matrixIn[0] parentWsDag.worldInverseMatrix >> mm.matrixIn[1] xformPlug = mm.matrixSum # hierarchy ctlList[0].setParent(parentCtl) # update for the next iteration parentCtl = ctlList[2] parentWsDag = wsDag # set transforms on cth from xformPlug dcm = pm.createNode('decomposeMatrix', n=crv.replace('_crv', '_dcm%d' % ctlId)) dcmList.append(dcm) xformPlug >> dcm.inputMatrix dcm.outputTranslate >> ctlList[0].t dcm.outputRotate >> ctlList[0].r # connect master multipliers mds[ctlId].output >> ctlList[1].r # add joint under control pm.select(cl=True) jnt = pm.joint(n=crv.replace('_crv', '_jnt%d' % ctlId)) jnt.setParent(ctlList[2]) jnt.setMatrix(pm.dt.Matrix()) # bind joint to skin cluster headSkn.addInfluence(jnt, lw=True, wt=0) bindPostMatrixPlug = jnt.worldMatrix.outputs(p=True)[0] bindPreMatrixPlugName = bindPostMatrixPlug.replace( '.matrix', '.bindPreMatrix') bindPreMatrixPlug = pm.PyNode(bindPreMatrixPlugName) wsDag.worldInverseMatrix >> bindPreMatrixPlug # organize stuff wsDagTops = [dag.getParent() for dag in wsDagList] wsSurfTops = [dag.getParent(2) for dag in wsSurfList] wsDagGrp = pm.group(wsDagTops, n=crvGrp.replace('_crv_grp', '_wsDagGrp')) wsSurfGrp = pm.group(wsSurfTops, n=crvGrp.replace('_crv_grp', '_wsSurfGrp')) ctlsGrp = pm.group(masterCtl[0], allCtlsList, n=crvGrp.replace('_crv_grp', '_allCtlsGrp')) masterGrp = pm.group(wsDagGrp, wsSurfGrp, crvGrp, n=crvGrp.replace('_crv_grp', '_rig_grp')) # move masterCtl with the first wsDag origMat = masterCtl[0].getMatrix(ws=True) dcmList[0].outputTranslate >> masterCtl[0].t dcmList[0].outputRotate >> masterCtl[0].r masterCtl[1].setMatrix(origMat, ws=True) return ctlsGrp, masterGrp