IK Back Script

Here is a script I finished up a couple of weeks ago for scripting an IK back. All that’s left is the neck, head, and arms… Then the hard part is figuring out how to correctly connect them all!

import maya.cmds as cmds
import bm_curveCube as curveCube
reload(curveCube)
import bm_jointGeo as bm_jointGeo
reload(bm_jointGeo)

# In all scripts, joints and controls must have a rot order of either ** YZX or ZXY.
# That means that all objects will point down the ** X axis and their secondary axis Y or Z and that orientation set to X
# ** Problem: spline curves only support joints that are oriented down the X axis. 

# joint -e  -oj yxz -secondaryAxisOrient xup -ch -zso;
# cmds.joint
#cmds.joint(cmds.ls(sl=1,o=1),edit=1,orientJoint="yxz",secondaryAxisOrient="xup",children=1,zeroScaleOrient=1,rotationOrder="zxy")
# And use ORIENT groups!
class ikBack(object):
    def __init__(self):
        self.name = "ikBack"
        self.divisions = 6
        
    def setupBack(self):
        cmds.select(cl=1)
        self.lowerBackLoc = cmds.xform("lowerBack",q=1,t=1,ws=1)
        self.upperBackLoc = cmds.xform("upperBack",q=1,t=1,ws=1)
        self.backLen = self.upperBackLoc[1] - self.lowerBackLoc[1]
        self.jointLen = self.backLen / self.divisions
        self.lowerBackJnt = cmds.joint(n=self.name + "_1_B",p=self.lowerBackLoc,rad=.3)
        
        a = 1 
        while(a < self.divisions):
            cmds.joint(n=self.name + "_" + str((a+1)) + "_B",p=(self.lowerBackLoc[0],self.lowerBackLoc[1] + self.jointLen * a,self.lowerBackLoc[2]),rad=.3)
            a += 1
        
        self.upperBackJnt = cmds.joint(n=self.name + "_7_B",p=self.upperBackLoc,rad=.3)
        cmds.joint(self.lowerBackJnt,edit=1,orientJoint="xzy",secondaryAxisOrient="yup",children=1,zeroScaleOrient=1,rotationOrder="yzx")
        
        # setup ik setup
        self.ikSpline = cmds.ikHandle(sj=self.lowerBackJnt,ee=self.upperBackJnt,sol="ikSplineSolver",scv=0,n="back_IK_#")
        # [u'ikSpline2', u'effector1', u'curve1']
        self.ikSpline[2] = cmds.rename(self.ikSpline[2],"back_CRV_#")
        cmds.hilite(self.ikSpline[2])
        cmds.select(self.ikSpline[2] + ".cv[4:8]")
        self.upperBackCluster = cmds.cluster(n="upperBack_Cluster_#")
        cmds.setAttr(self.upperBackCluster[1] + ".rotateOrder",2)
        
        cmds.hilite(self.ikSpline[2])
        cmds.select(self.ikSpline[2] + ".cv[0:3]")
        self.lowerBackCluster = cmds.cluster(n="lowerBack_Cluster_#")
        cmds.setAttr(self.lowerBackCluster[1] + ".rotateOrder",2)
        
        self.upperBackCtrl = curveCube.curveCube()
        cmds.xform(self.upperBackCtrl.myCube,t=(self.upperBackLoc))
        cmds.FreezeTransformations(self.upperBackCtrl)
        cmds.setAttr(self.upperBackCtrl.myCube + ".rotateOrder",2)
        cmds.delete(self.upperBackCtrl.myCube,ch=1)
        self.upperBackCtrl.myCube = cmds.rename(self.upperBackCtrl.myCube,"upperBack_ANIM")
        cmds.parentConstraint(self.upperBackCtrl.myCube,self.upperBackCluster[1],mo=0)
        
        self.lowerBackCtrl = curveCube.curveCube()
        cmds.xform(self.lowerBackCtrl.myCube,t=(self.lowerBackLoc))
        cmds.FreezeTransformations(self.lowerBackCtrl)
        cmds.setAttr(self.lowerBackCtrl.myCube + ".rotateOrder",2)
        cmds.delete(self.lowerBackCtrl.myCube,ch=1)
        self.lowerBackCtrl.myCube = cmds.rename(self.lowerBackCtrl.myCube,"lowerBack_ANIM")
        cmds.parentConstraint(self.lowerBackCtrl.myCube,self.lowerBackCluster[1],mo=1)
        cmds.select(cl=1)
        cmds.select(self.lowerBackJnt,self.upperBackJnt,add=1)
        bm_jointGeo.jntGeo()
        
        # setup advanced twist so that the shoulders and hips both control the twist
        cmds.setAttr(self.ikSpline[0] + ".dTwistControlEnable",1)
        cmds.setAttr(self.ikSpline[0] + ".dWorldUpType",4)
        cmds.setAttr(self.ikSpline[0] + ".dWorldUpAxis",4)
        cmds.setAttr(self.ikSpline[0] + ".dWorldUpVectorY",0)
        cmds.setAttr(self.ikSpline[0] + ".dWorldUpVectorZ",-1)
        cmds.setAttr(self.ikSpline[0] + ".dWorldUpVectorEndY",0)
        cmds.setAttr(self.ikSpline[0] + ".dWorldUpVectorEndZ",-1)
        cmds.connectAttr(self.lowerBackCtrl.myCube + ".matrix",self.ikSpline[0] + ".dWorldUpMatrix")
        cmds.connectAttr(self.upperBackCtrl.myCube + ".matrix",self.ikSpline[0] + ".dWorldUpMatrixEnd")

        # setup squash stretch
        self.distanceDim = cmds.arclen(self.ikSpline[2],ch=1)
        self.spineLen = cmds.getAttr(self.distanceDim + ".arcLength")
        
        # distance factor makes the ditance value 1. If it stretches or squashes, that becomes the scale 
        # value of the joint
        self.distanceFactor = cmds.createNode("multiplyDivide")
        cmds.setAttr(self.distanceFactor + ".op",2)
        cmds.setAttr(self.distanceFactor + ".i2x",self.spineLen)
        cmds.connectAttr(self.distanceDim + ".arcLength",self.distanceFactor + ".i1x")
        
        myJnts = cmds.listRelatives(self.lowerBackJnt,ad=1,type="joint")
        myJnts.reverse()
        myJnts.insert(0,self.lowerBackJnt)
        
        i = 1
        while i < self.divisions - 1:
            cmds.connectAttr(self.distanceFactor + ".ox",myJnts[i] + ".sx")
            i += 1
            
        self.inverseNode = cmds.createNode("multiplyDivide")
        cmds.setAttr(self.inverseNode + ".op",2)
        cmds.setAttr(self.inverseNode + ".i1x",1)
        cmds.connectAttr(self.distanceFactor + ".ox",self.inverseNode + ".i2x")
        # these next "Exponent Nodes" will setup the squash and stretch for our joints
        self.expNode1 = cmds.createNode("multiplyDivide")
        cmds.setAttr(self.expNode1 + ".op",3)
        cmds.setAttr(self.expNode1 + ".i2x",1.6)
        cmds.connectAttr(self.inverseNode + ".ox",self.expNode1 + ".i1x")
        
        self.expNode2 = cmds.createNode("multiplyDivide")
        cmds.setAttr(self.expNode2 + ".op",3)
        cmds.setAttr(self.expNode2 + ".i2x",1.2)
        cmds.connectAttr(self.inverseNode + ".ox",self.expNode2 + ".i1x")
        
        self.expNode3 = cmds.createNode("multiplyDivide")
        cmds.setAttr(self.expNode3 + ".op",3)
        cmds.setAttr(self.expNode3 + ".i2x",.5)
        cmds.connectAttr(self.inverseNode + ".ox",self.expNode3 + ".i1x")
        
        cmds.connectAttr(self.expNode3 + ".ox",myJnts[1] + ".sy")
        cmds.connectAttr(self.expNode3 + ".ox",myJnts[1] + ".sz")
        cmds.connectAttr(self.expNode3 + ".ox",myJnts[4] + ".sy")
        cmds.connectAttr(self.expNode3 + ".ox",myJnts[4] + ".sz")
        cmds.connectAttr(self.expNode2 + ".ox",myJnts[2] + ".sy")
        cmds.connectAttr(self.expNode2 + ".ox",myJnts[2] + ".sz")
        cmds.connectAttr(self.expNode2 + ".ox",myJnts[3] + ".sy")
        cmds.connectAttr(self.expNode2 + ".ox",myJnts[3] + ".sz")
        
        # create the FK joints and controls
        
        self.backJnts = cmds.listRelatives(self.lowerBackJnt,s=0,typ="joint",ad=1)
        self.backJnts.reverse()
        self.backFKjnt = cmds.joint(n="back_FK",p=self.lowerBackLoc)
        self.lowerBackFKjnt = cmds.joint(n="lowerBack_FK",p=cmds.xform(self.backJnts[1],q=1,t=1,ws=1))
        self.upperBackFKjnt = cmds.joint(n="upperBack_FK",p=cmds.xform(self.backJnts[3],q=1,t=1,ws=1))
        self.neckFKjnt = cmds.joint(n="neck_FK",p=cmds.xform(self.backJnts[5],q=1,t=1,ws=1))
        cmds.joint(self.backFKjnt,edit=1,orientJoint="xzy",secondaryAxisOrient="yup",children=1,zeroScaleOrient=1,rotationOrder="yzx")
        
        self.lowerBack_FK_ANIM = cmds.circle()
        self.lowerBack_FK_ANIM[0] = cmds.rename(self.lowerBack_FK_ANIM[0],"body_ANIM")
        cmds.xform(self.lowerBack_FK_ANIM[0],ro=(90,0,0),t=self.lowerBackLoc,ws=1)
        cmds.connectAttr(self.lowerBack_FK_ANIM[0] + ".ry",self.ikSpline[0] + ".roll")
        cmds.setAttr(self.lowerBack_FK_ANIM[0] + ".rotateOrder",3)
        cmds.FreezeTransformations(self.lowerBack_FK_ANIM[0])
        
        cmds.parent(self.backFKjnt,self.lowerBack_FK_ANIM[0])
        self.lowerBackCtrlGRP = cmds.group(self.lowerBackCtrl.myCube,n="lowerBackCtrl_GRP")
        self.upperBackCtrlGRP = cmds.group(self.upperBackCtrl.myCube,n="upperBackCtrl_GRP")
        
        cmds.parent(self.lowerBackCtrlGRP,self.backFKjnt)
        cmds.parent(self.upperBackCtrlGRP,self.neckFKjnt)
        
        self.lowerBackANIM = cmds.circle()
        self.lowerBackANIM[0] = cmds.rename(self.lowerBackANIM[0],"lowerBack_FK_ANIM")
        self.lowerBackANIM_ORIENT = cmds.group(self.lowerBackANIM[0],n=self.lowerBackANIM[0] + "_ORIENT")
        cmds.xform(self.lowerBackANIM_ORIENT,t=cmds.xform(self.lowerBackFKjnt,q=1,t=1,ws=1),ro=(90,0,0))
        cmds.setAttr(self.lowerBackANIM[0] + ".rotateOrder",2)
        
        self.upperBackANIM = cmds.circle()
        self.upperBackANIM[0] = cmds.rename(self.upperBackANIM[0],"upperBack_FK_ANIM")
        self.upperBackANIM_ORIENT = cmds.group(self.upperBackANIM[0],n=self.upperBackANIM[0] + "_ORIENT")
        cmds.xform(self.upperBackANIM_ORIENT,t=cmds.xform(self.upperBackFKjnt,q=1,t=1,ws=1),ro=(90,0,0))
        cmds.setAttr(self.upperBackANIM[0] + ".rotateOrder",2)
        
        cmds.parent(self.lowerBackANIM_ORIENT,self.backFKjnt)
        cmds.parent(self.lowerBackFKjnt,self.lowerBackANIM[0])
        cmds.parent(self.upperBackANIM_ORIENT,self.lowerBackFKjnt)
        cmds.parent(self.upperBackFKjnt,self.upperBackANIM[0])
        
        self.ikGRP = cmds.group(self.ikSpline[0],self.ikSpline[2],self.upperBackCluster,self.lowerBackCluster,n="ikBack_IK_GRP")
        self.ctrlGRP = cmds.group(self.lowerBack_FK_ANIM,self.lowerBackJnt,n="ikBack_CTRL_GRP")
        cmds.group(self.ikGRP,self.ctrlGRP,n="ikBack_ALL")
        
myBack = ikBack()
myBack.setupBack()
    
Advertisements
Image

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s