def buildIkCtrlSetup(self, side): """ Builds IK control for the limb. Create a controller and it places the controller to the right place and create the pole vector and the constrains plus connections :param side: string - 'L' or 'R' """ ikCtrl = self.placeCtrl(self.endJoint, type='ik') if not self.limbPart == 'leg': pm.delete(pm.orientConstraint(self.endJoint, ikCtrl, mo=True)) # create ik handle and pole vector for the IK limb ikh = pm.ikHandle(name=side + '_' + self.limbPart + '_limb_ikh', sj=self.startJoint.replace('_jnt', '_IK_jnt'), ee=self.endJoint.replace('_jnt', '_IK_jnt'), sol='ikRPsolver')[0] rigUtils.setControlColor(ikCtrl) self.placePoleVectorCtrl((self.startJoint, self.midJoint, self.endJoint)) pm.poleVectorConstraint(self.poleVectCtrl, ikh) # End limb control constraint # pm.parentConstraint(ikCtrl, ikh) if self.limbPart == 'arm': pm.parent(self.side + '_arm_limb_ikh', self.side + '_arm_ik_ctrl') else: pm.parent(self.side + '_leg_limb_ikh', self.side + '_leg_ik_ctrl') rigUtils.hideAttributes(ikCtrl, trans=False, scale=True, rot=False, vis=True, radius=False) rigUtils.hideAttributes(self.poleVectCtrl, trans=False, scale=True, rot=True, vis=True, radius=False)
def addIkHandle(parent, name, chn, solver="ikRPsolver", poleV=None): """ Creates and connect an IKhandle to a joints chain. Args: parent (dagNode): The parent for the IKhandle. name (str): The node name. chn (list): List of joints. solver (str): the solver to be use for the ikHandel. Default value is "ikRPsolver" poleV (dagNode): Pole vector for the IKHandle Returns: dagNode: The IKHandle >>> self.ikHandleUpvRef = pri.addIkHandle(self.root, self.getName("ikHandleLegChainUpvRef"), self.legChainUpvRef, "ikSCsolver") """ # creating a crazy name to avoid name clashing before convert to pyNode. node = pm.ikHandle(n=name + "kjfjfklsdf049r58420582y829h3jnf", sj=chn[0], ee=chn[-1], solver=solver)[0] node = pm.PyNode(node) pm.rename(node, name) node.attr("visibility").set(False) if parent: parent.addChild(node) if poleV: pm.poleVectorConstraint(poleV, node) return node
def rig_ik(self): self.ik_joints = self.create_chain(rn.IK) self.create_chain_ctrls(rn.IK) extra_jnt = pm.duplicate(self.ik_joints[-1])[0] extra_jnt.rename(self.ik_joints[-1].name() + '_palm') pm.parent(extra_jnt, self.ik_joints[-1]) extra_jnt.translateX.set(4 * self.side_sign) self.ik_joints.append(extra_jnt) pm.parent(self.ik_joints[0], self.rig_grp) # Create Iks arm_ik = pm.ikHandle(sol='ikRPsolver', sticky='sticky', startJoint=self.ik_joints[0], endEffector=self.ik_joints[2], name=self.side + '_arm_ikHandle')[0] hand_ik = pm.ikHandle(sol='ikSCsolver', sticky='sticky', startJoint=self.ik_joints[2], endEffector=self.ik_joints[3], name=self.side + '_palm_ikHandle')[0] pm.select(cl=1) iks_grp = pm.group(n=self.side + '_arm_ikHandles_grp') iks_grp.visibility.set(0) wrist_pos = self.ik_joints[2].getTranslation(space='world') iks_grp.setPivots(wrist_pos) pm.parent([arm_ik, hand_ik], iks_grp) pm.poleVectorConstraint(self.ik_ctrls[1], arm_ik) pm.parent(iks_grp, self.ik_ctrls[0])
def insert_dummy_arm(self, arm_comp): # IK dummy Chain ----------------------------------------- chain_pos = [ self.guide.apos[0], arm_comp.guide.apos[1], arm_comp.guide.apos[2] ] arm_comp.dummy_chain = pri.add2DChain(arm_comp.root, arm_comp.getName("dummy_chain"), chain_pos, arm_comp.normal, arm_comp.negate) arm_comp.dummy_chain[0].attr("visibility").set(arm_comp.WIP) arm_comp.dummy_ikh = pri.addIkHandle(arm_comp.root, arm_comp.getName("dummy_ikh"), arm_comp.dummy_chain) arm_comp.dummy_ikh.attr("visibility").set(False) pm.poleVectorConstraint(arm_comp.upv_ctl, arm_comp.dummy_ikh) pm.makeIdentity(arm_comp.dummy_chain[0], a=1, t=1, r=1, s=1) t = tra.getTransform(arm_comp.dummy_chain[0]) arm_comp.dummy_chain_npo = pri.addTransform( arm_comp.dummy_chain[0], self.getName("dummychain_npo"), t) arm_comp.dummy_chain_offset = pm.createNode("math_MatrixFromRotation") mult = pm.createNode("multMatrix") pm.connectAttr("{}.matrix".format(arm_comp.dummy_chain[0]), "{}.matrixIn[0]".format(mult)) pm.connectAttr("{}.output".format(arm_comp.dummy_chain_offset), "{}.matrixIn[1]".format(mult)) rot = pm.createNode("math_RotationFromMatrix") cmds.setAttr( "{}.rotationOrder".format(rot), cmds.getAttr("{}.rotateOrder".format(arm_comp.dummy_chain[0]))) pm.connectAttr("{}.matrixSum".format(mult), "{}.input".format(rot)) pm.connectAttr("{}.output".format(rot), "{}.rotate".format(arm_comp.dummy_chain_npo))
def setup_swivel_ctrl(self, base_ctrl, ref, pos, ik_handle, name='swivel', constraint=True, **kwargs): ''' Create the swivel ctrl for the ik system :param base_ctrl: The ctrl used to setup the swivel, create one if needed :param ref: Reference object to position the swivel :param pos: The computed position of the swivel :param ik_handle: The handle to pole vector constraint :param name: Part name used to resolve the object rig name :param constraint: Do we contraint the ik handle to the swivel ctrl :param kwargs: Additionnal parameters :return: The created ctrl swivel ''' nomenclature_anm = self.get_nomenclature_anm() ctrl_swivel = self.init_ctrl(self._CLASS_CTRL_SWIVEL, base_ctrl) ctrl_swivel.build(refs=ref) ctrl_swivel.setParent(self.grp_anm) ctrl_swivel.rename(nomenclature_anm.resolve(name)) ctrl_swivel._line_locator.rename(nomenclature_anm.resolve(name + 'LineLoc')) ctrl_swivel._line_annotation.rename(nomenclature_anm.resolve(name + 'LineAnn')) ctrl_swivel.offset.setTranslation(pos, space='world') ctrl_swivel.create_spaceswitch(self, self.parent, local_label='World') if constraint: # Pole vector contraint the swivel to the ik handle pymel.poleVectorConstraint(ctrl_swivel, self._ik_handle) return ctrl_swivel
def poleVector(self, name='', mid='', posMultiplier=1): if name == '': name = self.name poleVector = rig_transform(0, name=name + 'PoleVector', type='locator').object pm.delete(pm.parentConstraint(self.start, self.end, poleVector)) pm.delete(pm.aimConstraint(mid, poleVector, mo=False)) startPos = pm.xform(self.start, translation=True, query=True, ws=True) midPos = pm.xform(self.end, translation=True, query=True, ws=True) poleVectorPos = pm.xform(poleVector, translation=True, query=True, ws=True) pvDistance = lengthVector(midPos, poleVectorPos) pm.xform(poleVector, translation=[pvDistance * posMultiplier, 0, 0], os=True, r=True) pm.poleVectorConstraint(poleVector, self.handle) # create pv return poleVector
def bind(self): self.handle = pmc.ikHandle(sj=self.start_joint, ee=self.end_joint)[0] self.handle.hide() pmc.parent(self.handle, self.ik_control) pmc.poleVectorConstraint(self.pole_control, self.handle) pmc.parentConstraint(self.base_control, self.start_joint, mo=True) pmc.orientConstraint(self.ik_control, self.end_joint, mo=True)
def poleVectorConstraintRename(sels): if len(sels) >= 3 or len(sels) <= 1: pm.error('Please select two') part = sels[1].split("_") renameConstraint = '_'.join(['pvc', part[1], part[2], part[3]]) pm.poleVectorConstraint(sels[0], sels[1], n=renameConstraint, w=1)
def _generate_ik(start, end, description, side, parent=None, visible=False, solver='ikRPsolver', polevector=None, **kwargs): """ Private function to generate the ik, returning the result from the ik handle call :param start: :param end: :param description: :param side: :param parent: :param visible: :param solver: :param polevector: :param kwargs: :return: """ # -- Hook up the Ik Handle result = pm.ikHandle(startJoint=start, endEffector=end, solver=solver, priority=1, autoPriority=False, enableHandles=True, snapHandleToEffector=True, sticky=False, weight=1, positionWeight=1, **kwargs) ikh = result[0] ikh.visibility.set(visible) ikh.rename(config.name( prefix='IKH', description=description, side=side, ), ) if parent: ikh.setParent(parent) if polevector: pm.poleVectorConstraint( polevector, ikh, ) return result
def run(self): # retrieve mid and root joints self.midJoint = self.endJoint.getParent() self.rootJoint = self.midJoint.getParent() # duplicate joints for ik chain ikJointNameFmt = '{0}_ik' ikjnts = pulse.nodes.duplicateBranch(self.rootJoint, self.endJoint, nameFmt=ikJointNameFmt) for j in ikjnts: # TODO: debug settings for build actions j.v.set(True) self.rootIkJoint = ikjnts[0] self.midIkJoint = ikjnts[1] self.endIkJoint = ikjnts[2] # parent ik joints to root control self.rootIkJoint.setParent(self.rootCtl) # create ik and hook up pole object and controls handle, effector = pm.ikHandle(n="{0}_ikHandle".format( self.endIkJoint), sj=self.rootIkJoint, ee=self.endIkJoint, sol="ikRPsolver") # add twist attr to end control self.endCtl.addAttr('twist', at='double', k=1) self.endCtl.twist >> handle.twist # connect mid ik ctl (pole vector) pm.poleVectorConstraint(self.midCtlIk, handle) # parent ik handle to end control handle.setParent(self.endCtl) # constraint end joint scale and rotation to end control pm.orientConstraint(self.endCtl, self.endIkJoint, mo=True) pm.scaleConstraint(self.endCtl, self.endIkJoint, mo=True) # constraint the original joint branch to the ik joint branch pulse.nodes.fullConstraint(self.rootIkJoint, self.rootJoint) pulse.nodes.fullConstraint(self.midIkJoint, self.midJoint) pulse.nodes.fullConstraint(self.endIkJoint, self.endJoint) # setup ikfk switch # ... # cleanup for jnt in ikjnts: # TODO: lock attrs jnt.v.set(False) handle.v.set(False)
def __finalizeIkChain(self): ''' Create the ikHandle and the constraints to the control ''' #create ikHandle ikHandleName = nameUtils.getUniqueName(self.side, self.baseName, "IK") self.ikHandle = pm.ikHandle(n = ikHandleName, sj = self.chain[0], ee = self.chain[-1], solver = "ikRPsolver")[0] #create parent constraint from the ikHandle to the last control pm.pointConstraint(self.controlsArray[-1].control, self.ikHandle, mo = 1) #create a pole vector control pm.poleVectorConstraint(self.controlsArray[0].control, self.ikHandle)
def _buildDrivers(xforms, controls, root, drivers, pole_offset=50.0, **kwargs): # Position pole vector control pole_xf = controls[1].getParent() pole_xf.setTranslation(xforms[1].getTranslation(space='world') + getPoleVector(*xforms).normal() * pole_offset, space='world') # Apply pole vector constraint to ik handle ikh = root.listRelatives(ad=True, type='ikHandle')[0] pm.poleVectorConstraint(controls[1], ikh) return drivers
def add_pole_vector(cls, three_joints, ik_handle): """ create pole vector from a temp loc parented to start and end JNT chn and movnig it forward """ name = "_".join(three_joints[0].split("_")[:2] + ["poleVector_LOC"]) temp_locator, pole_locator = pm.spaceLocator(), pm.spaceLocator( name=name) pm.pointConstraint([three_joints[0], three_joints[-1]], temp_locator) pm.delete(pm.aimConstraint(three_joints[1], temp_locator)) transform.match(temp_locator, pole_locator) pm.move(pole_locator, 5, 0, 0, r=True, os=True) pm.poleVectorConstraint(pole_locator, ik_handle) pm.delete(temp_locator) return pole_locator
def attach_ik_to_joints(i_joints, handle_name, pv_name, i_ik_icon, i_pv_icon, i_ik_color, i_pv_pos, i_ik_icon_scale, i_pv_icon_scale): # duplicates result joint chain to create ik joints ik_joints = pm.duplicate(i_joints, po=True) pm.rename(ik_joints[0], ik_joints[0][:-12] + "_IK_JNT") for joint in ik_joints[1::]: pm.rename(joint, joint[:-11] + "_IK_JNT") # create IK HDL and Curve ik_handle = pm.ikHandle(sj=ik_joints[0], ee=ik_joints[2], n=handle_name + "_HDL") pm.rename("effector1", handle_name + "_EFF") ik_handle_control = CreateCurveShapes.create_shape_from_string( i_ik_icon, handle_name + "_IK_CTRL", i_ik_color) pm.setAttr(ik_handle_control.scale, i_ik_icon_scale) pm.makeIdentity(ik_handle_control, apply=True, t=1, r=1, s=1, n=0) handle_pos = pm.xform(i_joints[-1], query=True, worldSpace=True, translation=True) pm.xform(ik_handle_control, worldSpace=True, translation=handle_pos) pm.parent(ik_handle[0], ik_handle_control) # create Ankle Handles and parent to curve ankle_ik_handle = pm.ikHandle(sj=ik_joints[2], ee=ik_joints[3], n=handle_name + "Ankle_HDL") pm.rename("effector1", handle_name + "_Ankle_EFF") pm.parent(ankle_ik_handle[0], ik_handle_control) # Create Toe IK Handles and Parent to curve toe_ik_handle = pm.ikHandle(sj=ik_joints[3], ee=ik_joints[4], n=handle_name + "Toe_HDL") pm.rename("effector1", handle_name + "_EFF") pm.parent(toe_ik_handle[0], ik_handle_control) # create knee pole vector constraint pv_control = CreateCurveShapes.create_shape_from_string( i_pv_icon, pv_name + "_CTRL", i_ik_color) pm.setAttr(pv_control.scale, i_pv_icon_scale) pm.xform(pv_control, worldSpace=True, translation=i_pv_pos) pm.makeIdentity(pv_control, apply=True, t=1, r=1, s=1, n=0) pm.poleVectorConstraint(pv_control, ik_handle[0]) return ik_joints
def ik_chain_duplicate(): self.ik_AutoShoulder_joint = [ pm.duplicate(joint, parentOnly=True)[0] for joint in arm_ik_joints ] pm.parent(self.ik_AutoShoulder_joint[-1], self.ik_AutoShoulder_joint[-2]) pm.parent(self.ik_AutoShoulder_joint[-2], self.ik_AutoShoulder_joint[0]) pm.PyNode(self.ik_AutoShoulder_joint[0]).rename( '{Side}__Auto{Basename}_Ik_Shoulder'.format( **self.nameStructure)) pm.PyNode(self.ik_AutoShoulder_joint[1]).rename( '{Side}__Auto{Basename}_Ik_Elbow'.format(**self.nameStructure)) pm.PyNode(self.ik_AutoShoulder_joint[2]).rename( '{Side}__Auto{Basename}_Ik_Wrist'.format(**self.nameStructure)) adb.AutoSuffix(self.ik_AutoShoulder_joint) self.nameStructure['Suffix'] = NC.IKHANDLE_SUFFIX autoShoulder_IkHandle, autoShoulder_IkHandle_effector = pm.ikHandle( n='{Side}__Auto{Basename}__{Suffix}'.format( **self.nameStructure), sj=self.ik_AutoShoulder_joint[0], ee=self.ik_AutoShoulder_joint[-1]) autoShoulder_IkHandle.v.set(0) self.autoShoulder_IkHandle = autoShoulder_IkHandle adb.makeroot_func(self.autoShoulder_IkHandle) pm.poleVectorConstraint(poleVector_ctl, autoShoulder_IkHandle, weight=1) self.AUTO_CLAVICULE_MOD.setFinalHiearchy( RIG_GRP_LIST=[self.autoShoulder_IkHandle.getParent()], OUTPUT_GRP_LIST=[self.ik_AutoShoulder_joint[0]]) adb.matrixConstraint(arm_ik_offset_ctrl, self.autoShoulder_IkHandle.getParent()) pm.parent(self.AUTO_CLAVICULE_MOD.MOD_GRP, self.RIG.MODULES_GRP) self.nameStructure['Suffix'] = NC.VISRULE moduleBase.ModuleBase.setupVisRule( [self.ik_AutoShoulder_joint[0]], self.AUTO_CLAVICULE_MOD.VISRULE_GRP, name='{Side}__{Basename}_IK_JNT__{Suffix}'.format( **self.nameStructure), defaultValue=False)
def set_as_pole_vector(self, control): """ Sets any given transform as a pole vector control (transform): The transform node that will become the pole vector. """ self._model.pole_vector = control self._model.pole_vector_constraint = pm.poleVectorConstraint( self.pole_vector, self.ik_handle, name="poleVector") self.name_convention.rename_name_in_format(self.pole_vector_constraint)
def createManipulatorAndIkHandleConstraints(self): pm.select(cl = True) #manip_aim indicator aim grp pm.aimConstraint(self.manip_leg_complete, self.manip_aim_indicator_aim_grp, aim = (1,0,0), u = (0,1,0), wut = 'objectrotation' , wu = (0,1,0) ,mo = True) pm.select(cl = True) #manip_leg_ik pm.parentConstraint(self.manip_aim_indicator, self.manip_leg_ik_grp, mo = True) pm.scaleConstraint(self.manip_aim_indicator, self.manip_leg_ik_grp, mo = True) pm.pointConstraint(self.manip_leg_complete, self.manip_leg_ik_point_grp, mo = True) pm.select(cl = True) #poleVector pm.parentConstraint(self.manip_aim_indicator, self.leg_ik_pole_vector_locator_grp, mo = True) pm.scaleConstraint(self.manip_aim_indicator, self.leg_ik_pole_vector_locator_grp, mo = True) pm.select(cl = True) #poleVectorConstraint pm.poleVectorConstraint(self.leg_ik_pole_vector_locator, self.leg_ik_handle) pm.select(cl = True) #IkHandle pm.parentConstraint(self.manip_leg_ik, self.leg_ik_handle_grp, mo = True) pm.scaleConstraint(self.manip_leg_ik, self.leg_ik_handle_grp, mo = True) pm.select(cl = True) #ik_j_tip pm.orientConstraint(self.manip_leg_ik, self.leg_ik_j_tip, mo = True) pm.select(cl = True) #ik_j_grp pm.parentConstraint(self.manip_leg_base, self.leg_ik_j_grp, mo = True) pm.scaleConstraint(self.manip_leg_base, self.leg_ik_j_grp, mo = True) pm.select(cl = True)
def CreateIK(prefix, jntIKList, ctrl_GRP): offset_GRP_Name = '_offset_GRP' # create arm CTRL ======================== Arm_CTRL = str(prefix) + "arm_IK_CTRL" Arm_Offset_GRP = str(Arm_CTRL) + str(offset_GRP_Name) createControllers.CreateStarCTRL(Arm_CTRL, ctrl_GRP, 0.6, [0.4, 0.4, 0.4], (1, 0, 0)) # move offset GRP to wrist jnt, remove const tempConst = pm.parentConstraint(jntIKList[2], str(Arm_Offset_GRP)) pm.delete(tempConst) # create IK handle arm_ik = pm.ikHandle(n=str(prefix) + 'IK_Handle', sj=jntIKList[0], ee=jntIKList[2]) pm.parent(arm_ik[0], Arm_CTRL) # create pole vector CTRL ================ poleVector_CTRL = str(prefix) + 'pole_vector' pole_GRP = str(poleVector_CTRL) + str(offset_GRP_Name) createControllers.CreateBallCTRL(str(poleVector_CTRL), ctrl_GRP, 0.15) # move offset GRP to wrist jnt, remove const tempConst = pm.parentConstraint(jntIKList[1], str(pole_GRP), sr=['x', 'y', 'z']) pm.delete(tempConst) createControllers.CleanHist(pole_GRP) # point + aim constraint CTRL to prevent joint from moving after pole V Constr pointConst = pm.pointConstraint(str(jntIKList[0]), str(jntIKList[2]), str(poleVector_CTRL), mo=False, w=1) pm.delete(pointConst) aimConst = pm.aimConstraint(str(jntIKList[1]), str(poleVector_CTRL), mo=False, w=1) pm.delete(aimConst) # constrain PV PVConstr = pm.poleVectorConstraint(poleVector_CTRL, arm_ik[0], n=str(poleVector_CTRL) + '_constraint') pm.move(str(poleVector_CTRL), (1, 0, 0), os=True, wd=False, relative=True) # clean hist, parent and add CTRS to list createControllers.CleanHist(poleVector_CTRL) pm.parent(poleVector_CTRL, pole_GRP) ctrl_GRP.extend([str(Arm_Offset_GRP), pole_GRP])
def connect_poleVector(self, ikHandle): poleVector_locator_grp = self.createPV(ikHandle) # Calculate ikHandle lenght to set as pv -X axis distance = int(self.getJointDistance(ikHandle) / 2) # Move the Locator Group in the -X axis (Object Space) pm.move(distance, 0, 0, poleVector_locator_grp, objectSpace=True, relative=True) # Connect PoleVector poleVector_loc = pm.listRelatives(poleVector_locator_grp, children=True)[0] pm.poleVectorConstraint(poleVector_loc, ikHandle) return poleVector_loc, poleVector_locator_grp
def buildPVConstraint(self): # Position And Align The Pole Vector Control default_pole_vector = libVector.vector(list(self.ikHandle.poleVector)) # Check user user defined pos. If not then take then find the vector from the second joint in the chain pv_position = self.pvPosition if not pv_position: second_joint_position = self.jointSystem.joints[self.absStartJointNumber + 1].pynode.getTranslation( space="world") self.pvPosition = list( (default_pole_vector * [30, 30, 30] * ([self.scaleFactor] * 3)) + second_joint_position) # Get the Pole vector position that it wants to snap to self.pv.prnt.pynode.setTranslation(self.pvPosition, space="world") pvTwist = 0 # Find the twist of the new pole vector if to a new position if self.pvPosition: pm.poleVectorConstraint(self.pv.mNode, self.ikHandle.mNode, w=1) offset_pole_vector = self.ikHandle.poleVector # Delete the pole vector pm.delete(self.ikHandle.mNode, cn=1) self.ikHandle.pynode.poleVector.set(default_pole_vector) # Find the twist value so it goes back to zero from PKD_Tools.Rigging import nilsNoFlipIK pvTwist = nilsNoFlipIK.nilsNoFlipIKProc(offset_pole_vector[0], offset_pole_vector[1], offset_pole_vector[2], self.ikHandle.mNode) # Pole vector points at second joint aimCon = pm.aimConstraint(self.jointSystem.joints[self.startJointNumber + 1].pynode, self.pv.pynode, aimVector=self.upVector, upVector=self.upVector) self.constraintToMetaConstraint(aimCon, "AimCon{}".format(self.pv.rigType), "PVAim") pvCon = pm.poleVectorConstraint(self.pv.mNode, self.ikHandle.mNode, weight=1) self.constraintToMetaConstraint(pvCon, "PVCon", "poleVectorConstraint") self.ikHandle.twist = pvTwist
def buildIKChainSelected(): def createScaledLocator(name='unnamed'): loc = pmc.spaceLocator(name) loc.localScaleX.set(20) loc.localScaleY.set(20) loc.localScaleZ.set(20) return loc with _undoBlock(): targets = [ obj for obj in pmc.selected() if isinstance(obj, pmc.nodetypes.Joint) ] assert len(targets) >= 2, 'Not enough valid targets selected.' start_joint = targets[0] pole_joint = targets[0].getChildren()[0] end_joint = targets[1] handle = pmc.ikHandle(sj=start_joint, ee=end_joint)[0] ik_ctrl = createScaledLocator(name='ik_ctrl') ik_ctrl.setTranslation(end_joint.getTranslation(space='world'), space='world') pmc.orientConstraint(ik_ctrl, end_joint, mo=True) pmc.parent(handle, ik_ctrl) start_ctrl = createScaledLocator(name='start_ctrl') start_ctrl.setMatrix(start_joint.getMatrix(worldSpace=True), worldSpace=True) pmc.parentConstraint(start_ctrl, start_joint, mo=True) group = pmc.group(empty=True, name=targets[0].name() + '_IKGRP') pole_ctrl = createScaledLocator(name='pole_ctrl') pole_ctrl.setTranslation(pole_joint.getTranslation(space='world'), space='world') pmc.poleVectorConstraint(pole_ctrl, handle) pmc.parent([ik_ctrl, start_ctrl, pole_ctrl], group)
def generatePoleVectorCtrl(self, _handedness, _jointChain, _ikHandle, _ctrlDist=2): # Pole vector control positioning calculations j2Trans = pm.PyNode(_jointChain[2]).getTranslation(space='world') j1Trans = pm.PyNode(_jointChain[0]).getTranslation(space='world') # Get the aim vector between the top and bottom joints aimBetweenJoints = pm.datatypes.Vector(j2Trans - j1Trans) aimBetweenJoints.normalize() # Get the distance between the top and bottom joints aimLengthJoints = self.distanceBetween(j1Trans, j2Trans) # Half it p = aimLengthJoints / 2 # Get the vector3 position directly half way between the top and # bot midPos = pm.datatypes.Vector(j1Trans + (aimBetweenJoints * p)) # Get the world pos of the middle joint jMidTrans = pm.PyNode(_jointChain[1]).getTranslation(space='world') # Get the aim vector between the mid point and the mid joint midAim = pm.datatypes.Vector(jMidTrans - midPos) # Get the vector3 position that is midDistance along the midAim vector pvPos = jMidTrans + (midAim * _ctrlDist) # Create a locator there poleVectorCtrl = pm.spaceLocator(n=_handedness + '_' + str(_jointChain[1])[7:] + '_ctrl', p=pvPos) pm.xform(cp=1) poleVectorCtrl.localScale.set([0.001, 0.001, 0.001]) pm.poleVectorConstraint(poleVectorCtrl, _ikHandle) ctrlShape = pm.listRelatives(poleVectorCtrl) ctrlShape[0].overrideEnabled.set(True) if 'r_' in str(poleVectorCtrl): ctrlShape[0].overrideColor.set(13) if 'l_' in str(poleVectorCtrl): ctrlShape[0].overrideColor.set(6) self.lockHideAttr(poleVectorCtrl, ['rx', 'ry', 'rz', 'sx', 'sy', 'sz']) return poleVectorCtrl
def build_ik_chain(targets, name='Unnamed'): with UndoOnError(): start_joint = targets[0] pole_joint = targets[0].getChildren()[0] end_joint = targets[1] handle = pmc.ikHandle(sj=start_joint, ee=end_joint)[0] pmc.hide(handle) ik_ctrl = ControlCurve.create(name=name + '_Ik_CTRL', shapeType='circle') ik_ctrl.scaleShape([10, 10, 10]) ik_ctrl.setTranslation(end_joint.getTranslation(worldSpace=True), worldSpace=True) ik_ctrl.addBuffer() ik_ctrl.lockTransform(scale=True, hide=True) pmc.orientConstraint(ik_ctrl, end_joint, mo=True) pmc.parent(handle, ik_ctrl) start_ctrl = ControlCurve.create(name=name + '_Base_CTRL', shapeType='circle') start_ctrl.scaleShape([10, 10, 10]) start_ctrl.setMatrix(start_joint.getMatrix(worldSpace=True), worldSpace=True) start_ctrl.addBuffer() start_ctrl.lockTransform(rotate=True, scale=True, hide=True) pmc.parentConstraint(start_ctrl, start_joint, mo=True) pole_ctrl = ControlCurve.create(name=name + '_Pole_CTRL', shapeType='octohedron') pole_ctrl.scaleShape([10, 10, 10]) pole_ctrl.setTranslation(pole_joint.getTranslation(worldSpace=True), worldSpace=True) pole_ctrl.addBuffer() pole_ctrl.lockTransform(rotate=True, scale=True, hide=True) pmc.poleVectorConstraint(pole_ctrl, handle) return ik_ctrl, pole_ctrl, start_ctrl
def square(self, joint, arm, side): p0 = Point(0, 0.08, -0.08) p1 = Point(0, 0.08, 0.08) p2 = Point(0, -0.08, 0.08) p3 = Point(0, -0.08, -0.08) points = [p0, p1, p2, p3, p0] pts = [] for point in points: pts.append(point.getPoint()) pm.curve(per = True, d = 1, p = pts, k = [0, 1, 2, 3, 4]) curve = "%s" % str(pm.ls(sl = True)[0]) pm.parent(curve, "%s" % str(joint), relative = True) pm.parent(curve, world = True) if arm == True: pm.move(-0.5, moveZ = True) if arm == False: pm.move(0.5, moveZ = True) pm.makeIdentity(r = True) pm.makeIdentity(a = True) pm.poleVectorConstraint(curve, side + "IK")
def setup_swivel_ctrl(self, base_ctrl, ref, pos, ik_handle, name='swivel', constraint=True, **kwargs): ''' Create the swivel ctrl for the ik system :param base_ctrl: The ctrl used to setup the swivel, create one if needed :param ref: Reference object to position the swivel :param pos: The computed position of the swivel :param ik_handle: The handle to pole vector constraint :param name: Part name used to resolve the object rig name :param constraint: Do we contraint the ik handle to the swivel ctrl :param kwargs: Additionnal parameters :return: The created ctrl swivel ''' nomenclature_anm = self.get_nomenclature_anm() ctrl_swivel = base_ctrl if not isinstance(base_ctrl, self._CLASS_CTRL_SWIVEL): ctrl_swivel = self._CLASS_CTRL_SWIVEL() ctrl_swivel.build(refs=ref) ctrl_swivel.setParent(self.grp_anm) ctrl_swivel.rename(nomenclature_anm.resolve(name)) ctrl_swivel._line_locator.rename( nomenclature_anm.resolve(name + 'LineLoc')) ctrl_swivel._line_annotation.rename( nomenclature_anm.resolve(name + 'LineAnn')) ctrl_swivel.offset.setTranslation(pos, space='world') ctrl_swivel.create_spaceswitch(self, self.parent, default_name='World') if constraint: #Pole vector contraint the swivel to the ik handle pymel.poleVectorConstraint(ctrl_swivel, self._ik_handle) return ctrl_swivel
def create_PV(self): # getTranslation returns vector jnt_A_vector = self.jnt_A.getTranslation(space = 'world') jnt_B_vector = self.jnt_B.getTranslation(space = 'world') jnt_C_vector = self.jnt_C.getTranslation(space = 'world') jnt_A_B_vector = jnt_B_vector - jnt_A_vector jnt_A_C_vector = jnt_C_vector - jnt_A_vector # * means vector dot operation dot_vector = jnt_A_B_vector * jnt_A_C_vector # dot product is an abstract projection value, not a magnitude(length) or angle # dot product = |A| x |B| x cos(a) # dot product = |A| x |B| x 1, if both A and B are codirectional (a = 0 degree) # dot product / |B| = |A|, |A| is projection_length projection_length = float(dot_vector) / float(jnt_A_C_vector.length()) # Any nonzero vector can be divided by its length to form a unit vector. # normal = vector / length jnt_A_C_normal = jnt_A_C_vector.normal() # normal * length = vector, on the direction of normal, and the magnitude of length projection_vector = jnt_A_C_normal * projection_length # arrow_vector is a vector between A & C, through B arrow_vector = jnt_A_B_vector - projection_vector # PV will be 0.5 arrow length away from jnt B arrow_vector *= 0.5 final_vector = arrow_vector + jnt_B_vector self.pv_IK = pm.spaceLocator() self.pv_IK.setTranslation(final_vector, space = 'world') pm.poleVectorConstraint(self.pv_IK, self.hdl_IK)
def setup_swivel_ctrl(self, base_ctrl, ref, pos, ik_handle, constraint=True, mirror_setup=True, adjust_ik_handle_twist=True, **kwargs): """ Create the swivel ctrl for the ik system. Redefined to add the possibility to create a mirror swivel setup to prevent flipping problem with pole vector when using ikSpringSolver :param base_ctrl: The ctrl used to setup the swivel, create one if needed :param ref: Reference object to position the swivel :param pos: The computed position of the swivel :param ik_handle: The handle to pole vector contraint :param constraint: Do we contraint the ik handle to the swivel ctrl :param mirror_setup: Is the swivel need a mirror setup (Hack to bypass ikSpringSolver flipping problem :param adjust_ik_handle_twist: In some cases, the ikSpringSolver will flip when the poleVector is applied. If True, this will use brute-force to adjust it. :param kwargs: Additionnal parameters :return: The created ctrl swivel """ # Do not contraint the ik handle now since we could maybe need the flipping setup ctrl_swivel = super(LegIkQuad, self).setup_swivel_ctrl(base_ctrl, ref, pos, ik_handle, constraint=False, **kwargs) if constraint: pymel.poleVectorConstraint(ctrl_swivel, ik_handle) if adjust_ik_handle_twist: # Hack: For strange reasons, creating the ikSpringSolver can make the leg flip. # This is applicable after assigning the pole vectors. # To bypass this, we'll look for flipping and compensate with the ikHandle 'twist' attribute. self.adjust_spring_solver_twist( self.jnts[0], self.jnts[1], self._chain_ik[0], self._chain_ik[1], self._ik_handle ) return ctrl_swivel
def createIkAnimatedSystemConstraints(self): pm.select(cl = True) #ikRpHandleGrp pm.poleVectorConstraint(self.manipIkAnimatedPoleVector, self.ikHandleAnimated) pm.scaleConstraint( self.manipIkAnimated, self.ikHandleAnimatedGrp, mo = True ) pm.parentConstraint( self.manipIkAnimated, self.ikHandleAnimatedGrp, mo = True ) pm.select(cl = True) #poleVectorGrp pm.scaleConstraint( self.manip_master, self.manipIkAnimatedPoleVectorGrp, mo = True ) pm.parentConstraint( self.manip_master, self.manipIkAnimatedPoleVectorGrp, mo = True ) pm.select(cl = True) #manipIkAnimatedGrp pm.scaleConstraint( self.manip_master, self.manipIkAnimatedGrp, mo = True ) pm.parentConstraint( self.manip_master, self.manipIkAnimatedGrp, mo = True ) pm.select(cl = True) #ikAnimatedJointsGrp pm.scaleConstraint( self.manip_master, self.ikAnimatedJointsGrp, mo = True ) pm.parentConstraint( self.manip_master, self.ikAnimatedJointsGrp, mo = True ) pm.select(cl = True)
def CreateIK(jntIKList, ctrl_GRP): prefix = str(jntIKList[0][0:2]) # create arm CTRL Arm_CTRL = str(prefix) + "arm_IK_CTRL" CreateStarCTRL(Arm_CTRL, 0.6, [0.4, 0.4, 0.4], (1,0,0)) # move offset GRP to wrist jnt, remove const tempConst = pm.parentConstraint(jntIKList[2], str(Arm_CTRL) + '_offset_GRP') pm.delete(tempConst) # create IK handle arm_ik = pm.ikHandle( n = str(prefix) + 'IK_Handle', sj=jntIKList[0], ee=jntIKList[2]) pm.parent(arm_ik[0],Arm_CTRL) # create pole vector CTRL poleVector_CTRL = str(prefix) + 'pole_vector' pole_GRP = str(poleVector_CTRL) + '_offset_GRP' CreateBallCTRL(str(poleVector_CTRL), 0.15) # move offset GRP to wrist jnt, remove const tempConst = pm.parentConstraint(jntIKList[1], str(pole_GRP), sr = ['x', 'y', 'z']) pm.delete(tempConst) CleanHist(pole_GRP) # point + aim constraint CTRL to prevent joint from moving after pole V Constr pointConst = pm.pointConstraint( str(jntIKList[0]), str(jntIKList[2]), str(poleVector_CTRL), mo= False, w=1 ) pm.delete(pointConst) aimConst = pm.aimConstraint( str(jntIKList[1]), str(poleVector_CTRL), mo= False, w=1 ) pm.delete(aimConst) # constrain PV PVConstr = pm.poleVectorConstraint(poleVector_CTRL, arm_ik[0], n = str(poleVector_CTRL) + '_constraint') pm.move(str(poleVector_CTRL), (1,0, 0 ), os = True, wd = False, relative = True) CleanHist(poleVector_CTRL) pm.parent(poleVector_CTRL, pole_GRP) for x in jntIKList: RecolourObj(x) ctrl_GRP.extend([str(Arm_CTRL) + '_offset_GRP', pole_GRP])
def kiddoRigModules(): print 'Create kiddo rig modules' bodyModule = rig_module('body') pm.parent('mainJA_JNT', bodyModule.skeleton) main = rig_control(name='main', shape='box', targetOffset='mainJA_JNT', constrain='mainJA_JNT', parentOffset=bodyModule.controls, scale=(45, 10, 50), colour='white') main.gimbal = createCtrlGimbal(main) main.pivot = createCtrlPivot(main, overrideScale=(10, 10, 10)) upperBody = rig_control(name='upperBody', shape='box', modify=1, targetOffset='mainJA_JNT', constrainOffset=main.con, scale=(35, 15, 40), colour='yellow', parentOffset=bodyModule.controls, lockHideAttrs=['tx', 'ty', 'tz'], rotateOrder=2) pm.move(upperBody.ctrl.cv, [0, 10, 0], relative=True, objectSpace=True) upperWaistXYZ = simpleControls( ['upperWaistY_JA_JNT', 'upperWaistZ_JA_JNT', 'upperWaistX_JA_JNT'], modify=1, scale=(45, 10, 50), parentOffset=bodyModule.parts, lockHideAttrs=['tx', 'ty', 'tz']) upperWaistY = upperWaistXYZ['upperWaistY_JA_JNT'] upperWaistZ = upperWaistXYZ['upperWaistZ_JA_JNT'] upperWaistX = upperWaistXYZ['upperWaistX_JA_JNT'] pm.hide(upperWaistY.offset, upperWaistZ.offset, upperWaistX.offset) constrainObject(upperBody.modify, [upperBody.offset, 'worldSpace_GRP'], upperBody.ctrl, ['main', 'world'], type='orientConstraint') constrainObject(upperWaistY.modify, [upperWaistY.offset, 'worldSpace_GRP'], upperBody.ctrl, ['main', 'world'], type='orientConstraint', skip=('x', 'z')) constrainObject(upperWaistZ.modify, [upperWaistZ.offset, 'worldSpace_GRP'], upperBody.ctrl, ['main', 'world'], type='orientConstraint', skip=('x', 'y')) constrainObject(upperWaistX.modify, [upperWaistX.offset, 'worldSpace_GRP'], upperBody.ctrl, ['main', 'world'], type='orientConstraint', skip=('z', 'y')) pm.connectAttr(upperBody.ctrl.rotateX, upperWaistX.ctrl.rotateX) pm.connectAttr(upperBody.ctrl.rotateY, upperWaistY.ctrl.rotateY) pm.connectAttr(upperBody.ctrl.rotateZ, upperWaistZ.ctrl.rotateZ) lowerBody = rig_control(name='lowerBody', shape='box', modify=1, targetOffset='lowerBodyJA_JNT', constrainOffset=main.con, scale=(40, 20, 30), colour='green', parentOffset=bodyModule.controls, lockHideAttrs=['tx', 'ty', 'tz', 'rx', 'rz'], rotateOrder=2) constrainObject(lowerBody.modify, [lowerBody.offset, 'worldSpace_GRP'], lowerBody.ctrl, ['main', 'world'], type='orientConstraint', skip=('x', 'z')) pm.parentConstraint(lowerBody.con, 'lowerBodyJA_JNT', mo=True) pm.move(lowerBody.ctrl.cv, [0, -10, 0], relative=True, objectSpace=True) biped = rig_biped() biped.spineConnection = 'upperWaistX_JA_JNT' biped.pelvisConnection = 'lowerBodyJA_JNT' biped.centerConnection = 'mainJA_JNT' for side in ['l', 'r']: armModule = biped.arm(side, ctrlSize=10) fingersModule = biped.hand(side, ctrlSize=2.5) shoulderModule = biped.shoulder(side, ctrlSize=12) biped.connectArmShoulder(side) secColour = 'deepskyblue' if side == 'r': secColour = 'magenta' # make leg legName = side + '_leg' legModule = rig_module(legName) hipZJnt = side + '_hipZ_JA_JNT' hipYJnt = side + '_hipY_JA_JNT' legJnt = side + '_legJA_JNT' kneeJnt = side + '_kneeJA_JNT' ankleJnt = side + '_ankleJA_JNT' footJnt = side + '_footJA_JNT' pm.setAttr(hipYJnt + '.rotateOrder', 2) # chain IK legJntIK = rig_transform(0, name=side + '_legIK', type='joint', target=legJnt, parent=legModule.parts).object kneeJntIK = rig_transform(0, name=side + '_kneeIK', type='joint', target=kneeJnt).object ankleJntIK = rig_transform( 0, name=side + '_ankleIK', type='joint', target=ankleJnt, ).object footJntIK = rig_transform( 0, name=side + '_footIK', type='joint', target=footJnt, ).object chainIK = [legJntIK, kneeJntIK, ankleJntIK, footJntIK] chainParent(chainIK) chainIK.reverse() # create ik ik = rig_ik(legName, legJntIK, footJntIK, 'ikSpringSolver') pm.parent(ik.handle, legModule.parts) # pole vector legPoleVector = rig_control(side=side, name='legPV', shape='pointer', modify=1, lockHideAttrs=['rx', 'ry', 'rz'], targetOffset=[legJnt, footJnt], parentOffset=legModule.parts, scale=(2, 2, 2)) pm.delete(pm.aimConstraint(ankleJnt, legPoleVector.offset, mo=False)) kneePos = pm.xform(kneeJnt, translation=True, query=True, ws=True) poleVectorPos = pm.xform(legPoleVector.con, translation=True, query=True, ws=True) pvDistance = lengthVector(kneePos, poleVectorPos) pm.xform(legPoleVector.offset, translation=[-25, 0, 0], os=True, r=True) pm.poleVectorConstraint(legPoleVector.con, ik.handle) # create pv #pm.parentConstraint(biped.centerConnection, legPoleVector.offset, mo=True) pm.parentConstraint(hipYJnt, legPoleVector.offset, mo=True) if side == 'r': pm.rotate(legPoleVector.ctrl.cv, 0, -90, 0, r=True, os=True) else: pm.rotate(legPoleVector.ctrl.cv, 0, 90, 0, r=True, os=True) # create foot control foot = rig_control(side=side, name='foot', shape='box', modify=1, scale=(13, 13, 13), parentOffset=legModule.controls, lockHideAttrs=['rx', 'ry', 'rz']) pm.delete(pm.pointConstraint(footJnt, foot.offset)) pm.parentConstraint(foot.con, ik.handle, mo=True) #pm.pointConstraint( foot.con, legPoleVector.modify, mo=True ) foot.gimbal = createCtrlGimbal(foot) foot.pivot = createCtrlPivot(foot) constrainObject( foot.offset, [biped.pelvisConnection, biped.centerConnection, 'worldSpace_GRP'], foot.ctrl, ['pelvis', 'main', 'world'], type='parentConstraint') pm.setAttr(foot.ctrl.space, 2) pm.addAttr(foot.ctrl, longName='twist', at='float', k=True) pm.addAttr(foot.ctrl, longName='springBiasBottom', at='float', min=0, max=1, k=True, dv=0) pm.addAttr(foot.ctrl, longName='springBiasTop', at='float', min=0, max=1, k=True, dv=0.5) pm.connectAttr(foot.ctrl.twist, ik.handle.twist) pm.connectAttr(foot.ctrl.springBiasBottom, ik.handle + '.springAngleBias[0].springAngleBias_FloatValue', f=True) pm.connectAttr(foot.ctrl.springBiasTop, ik.handle + '.springAngleBias[1].springAngleBias_FloatValue', f=True) # create hip aims hipAimZ_loc = rig_transform(0, name=side + '_hipAimZ', type='locator', parent=legModule.parts, target=hipZJnt).object footAimZ_loc = rig_transform(0, name=side + '_footAimZ', type='locator', parent=legModule.parts).object pm.pointConstraint(biped.pelvisConnection, hipAimZ_loc, mo=True) pm.parentConstraint(foot.con, footAimZ_loc) # z rotation hipAimZ = mm.eval('rig_makePiston("' + footAimZ_loc + '", "' + hipAimZ_loc + '", "' + side + '_hipAimZ");') hipZ = rig_control(side=side, name='hipRoll', shape='sphere', modify=1, scale=(5, 5, 7), parentOffset=legModule.parts, targetOffset=hipZJnt, lockHideAttrs=['tx', 'ty', 'tz', 'rx', 'ry'], rotateOrder=0) pm.parentConstraint(hipZ.con, hipZJnt, mo=True) pm.parentConstraint(lowerBody.con, hipZ.offset, mo=True) rotCon = pm.orientConstraint(hipZ.offset, hipAimZ_loc, hipZ.modify, mo=True, skip=('x', 'y')) targetZ = rotCon.getWeightAliasList() #pm.addAttr(hipZ.ctrl, longName='aim', at='float', k=True, min=0, max=1, # dv=1) #pm.connectAttr ( hipZ.ctrl.aim, target ) # y rotation hipAimY_loc = rig_transform(0, name=side + '_hipAimY', type='locator', parent=legModule.parts, target=hipYJnt).object footAimY_loc = rig_transform(0, name=side + '_footAimY', type='locator', parent=legModule.parts).object pm.pointConstraint(hipZJnt, hipAimY_loc, mo=True) pm.parentConstraint(foot.con, footAimY_loc) hipAimY = mm.eval('rig_makePiston("' + footAimY_loc + '", "' + hipAimY_loc + '", ' '"' + side + '_hipAimY");') pm.setAttr(side + '_hipAimZ_LOC.rotateOrder', 4) hipY = rig_control(side=side, name='hipYaw', shape='sphere', modify=2, scale=(5, 7, 5), parentOffset=legModule.controls, targetOffset=hipYJnt, lockHideAttrs=['tx', 'ty', 'tz', 'rx', 'rz'], rotateOrder=2) pm.parentConstraint(hipY.con, hipYJnt, mo=True) pm.parentConstraint(hipZ.con, hipY.offset, mo=True) #rotCon = pm.parentConstraint(hipAimY_loc, hipY.modify, mo=True, # skipTranslate=('x', 'y', 'z'), # skipRotate=('x', 'z')) rotCon = pm.orientConstraint(hipY.offset, hipAimY_loc, hipY.modify[0], mo=True, skip=('x', 'z')) targetY = rotCon.getWeightAliasList() pm.addAttr(hipY.ctrl, longName='aim', at='float', k=True, min=0, max=1, dv=1) pm.connectAttr(hipY.ctrl.aim, targetY[1]) pm.connectAttr(hipY.ctrl.aim, targetZ[1]) connectReverse(name=side + '_leg', input=(hipY.ctrl.aim, hipY.ctrl.aim, 0), output=(targetY[0], targetZ[0], 0)) pm.setAttr(rotCon.interpType, 2) pm.transformLimits(hipY.modify[0], ry=(-30, 10), ery=(1, 1)) pm.addAttr(hipY.ctrl, longName='aimRotation', at='float', k=True, min=0, max=10, dv=0) pm.addAttr(hipY.ctrl, longName='limitOutRotation', at='float', k=True, min=0, max=10, dv=3) pm.addAttr(hipY.ctrl, longName='limitInRotation', at='float', k=True, min=0, max=10, dv=0) hipY.ctrl.limitOutRotation.set(cb=True) hipY.ctrl.limitInRotation.set(cb=True) pm.setDrivenKeyframe(hipY.modify[0] + '.minRotYLimit', cd=hipY.ctrl.limitOutRotation, dv=0, v=-45) pm.setDrivenKeyframe(hipY.modify[0] + '.minRotYLimit', cd=hipY.ctrl.limitOutRotation, dv=10, v=0) pm.setDrivenKeyframe(hipY.modify[0] + '.maxRotYLimit', cd=hipY.ctrl.limitInRotation, dv=0, v=10) pm.setDrivenKeyframe(hipY.modify[0] + '.maxRotYLimit', cd=hipY.ctrl.limitInRotation, dv=10, v=0) rotCon = pm.orientConstraint(hipY.offset, hipY.modify[0], hipY.modify[1], mo=True) conTargets = rotCon.getWeightAliasList() pm.setDrivenKeyframe(conTargets[0], cd=hipY.ctrl.aimRotation, dv=0, v=1) pm.setDrivenKeyframe(conTargets[0], cd=hipY.ctrl.aimRotation, dv=10, v=0) connectReverse(name=side + '_hipYTarget', input=(conTargets[0], 0, 0), output=(conTargets[1], 0, 0)) # constrain shizzle legTop = rig_transform(0, name=side + '_legTop', target=legJnt, parent=legModule.skeleton).object pm.setAttr(legTop + '.inheritsTransform', 0) pm.scaleConstraint('worldSpace_GRP', legTop) legSkeletonParts = rig_transform(0, name=side + '_legSkeletonParts', parent=legTop).object pm.parent(hipAimY, hipAimZ, legModule.parts) pm.parent(legJntIK, legJnt, legSkeletonParts) pm.hide(legJntIK) pm.parentConstraint(hipYJnt, legTop, mo=True, skipRotate=('x', 'y', 'z')) #pm.connectAttr(legJntIK+'.rotate', legJnt+'.rotate') pm.connectAttr(kneeJntIK + '.rotate', kneeJnt + '.rotate') pm.connectAttr(ankleJntIK + '.rotate', ankleJnt + '.rotate') multiplyDivideNode('legRotate', 'multiply', input1=[ legJntIK + '.rotateX', legJntIK + '.rotateY', legJntIK + '.rotateZ' ], input2=[1, hipY.ctrl.aim, hipY.ctrl.aim], output=[ legJnt + '.rotateX', legJnt + '.rotateY', legJnt + '.rotateZ' ]) pm.parent(hipZJnt, legModule.skeleton) pm.parent(hipYJnt, legModule.skeleton) footJnts = [ side + '_heelRotY_JA_JNT', side + '_footRotX_JA_JNT', side + '_footRotY_JA_JNT', side + '_footRotZ_JA_JNT' ] footControls = simpleControls(footJnts, modify=2, scale=(11, 3, 20), parentOffset=legModule.parts, colour=secColour, lockHideAttrs=['tx', 'ty', 'tz']) #footControls[side+''] ankle = rig_control(side=side, name='ankle', shape='box', modify=1, scale=(10, 6, 8), colour=secColour, parentOffset=legModule.controls, targetOffset=side + '_footRotZ_JA_JNT', lockHideAttrs=['tx', 'ty', 'tz', 'ry']) pm.parentConstraint(footJnt, ankle.offset, mo=True) heel = footControls[side + '_heelRotY_JA_JNT'] footRotX = footControls[side + '_footRotX_JA_JNT'] footRotY = footControls[side + '_footRotY_JA_JNT'] footRotZ = footControls[side + '_footRotZ_JA_JNT'] pm.parent(heel.offset, legModule.controls) heel.ctrl.rotateX.setKeyable(False) heel.ctrl.rotateX.setLocked(True) heel.ctrl.rotateZ.setKeyable(False) heel.ctrl.rotateZ.setLocked(True) pm.parentConstraint(footRotY.con, heel.modify[0], mo=True) pm.parentConstraint(footRotZ.con, footRotY.modify[0], mo=True) pm.parentConstraint(footRotX.con, footRotZ.modify[0], mo=True) footSpace = footJnt if side == 'l': footSpace = rig_transform(0, name='l_footSpace', parent=legModule.parts, target=footJnt).object pm.setAttr(footSpace + '.rotateX', 0) pm.parentConstraint(footJnt, footSpace, mo=True) toeSpaceList = ('lowerBody', 'foot', 'main', 'world') constrainObject(heel.modify[1], [ biped.pelvisConnection, footSpace, biped.centerConnection, 'worldSpace_GRP' ], heel.ctrl, toeSpaceList, type='orientConstraint', skip=('x', 'z')) constrainObject(footRotX.modify[0], [ biped.pelvisConnection, footSpace, biped.centerConnection, 'worldSpace_GRP' ], footRotX.ctrl, toeSpaceList, type='orientConstraint', skip=('y', 'z')) constrainObject(footRotZ.modify[1], [ biped.pelvisConnection, footSpace, biped.centerConnection, 'worldSpace_GRP' ], footRotZ.ctrl, toeSpaceList, type='orientConstraint', skip=('x', 'y')) pm.connectAttr(ankle.ctrl.rotateX, footRotX.ctrl.rotateX) #pm.connectAttr( ankle.ctrl.rotateY, heel.ctrl.rotateY ) #connectNegative(ankle.ctrl.rotateY, heel.ctrl.rotateY) pm.connectAttr(ankle.ctrl.rotateZ, footRotZ.ctrl.rotateZ) pm.addAttr(ankle.ctrl, ln='SPACES', at='enum', enumName='___________', k=True) ankle.ctrl.SPACES.setLocked(True) pm.addAttr(ankle.ctrl, ln='rollSpace', at='enum', enumName='lowerBody:foot:main:world', k=True) #pm.addAttr(ankle.ctrl, ln='yawSpace', at='enum', # enumName='lowerBody:foot:main:world', k=True) pm.addAttr(ankle.ctrl, ln='pitchSpace', at='enum', enumName='lowerBody:foot:main:world', k=True) pm.connectAttr(ankle.ctrl.rollSpace, footRotX.ctrl.space) #pm.connectAttr( ankle.ctrl.yawSpace, heel.ctrl.space) pm.connectAttr(ankle.ctrl.pitchSpace, footRotZ.ctrl.space) pm.addAttr(ankle.ctrl, ln='MOTION', at='enum', enumName='___________', k=True) ankle.ctrl.MOTION.setLocked(True) pm.addAttr(ankle.ctrl, longName='footFangs', at='float', k=True, min=0, max=10, dv=0) pm.addAttr(ankle.ctrl, longName='toeFangs', at='float', k=True, min=0, max=10, dv=0) fangsJnt = pm.PyNode(side + '_toeFangsJA_JNT') toeFangsJnt = pm.PyNode(side + '_footFangsJA_JNT') fangsTranslate = fangsJnt.translate.get() pm.setDrivenKeyframe(fangsJnt.translateX, cd=ankle.ctrl.footFangs, dv=0, v=fangsTranslate[0]) pm.setDrivenKeyframe(fangsJnt.translateY, cd=ankle.ctrl.footFangs, dv=0, v=fangsTranslate[1]) pm.setDrivenKeyframe(fangsJnt.translateZ, cd=ankle.ctrl.footFangs, dv=0, v=fangsTranslate[2]) pm.move(0, 1.5, 0, fangsJnt, r=True, os=True) fangsTranslate = fangsJnt.translate.get() pm.move(0, -1.5, 0, fangsJnt, r=True, os=True) pm.setDrivenKeyframe(fangsJnt.translateX, cd=ankle.ctrl.footFangs, dv=10, v=fangsTranslate[0]) pm.setDrivenKeyframe(fangsJnt.translateY, cd=ankle.ctrl.footFangs, dv=10, v=fangsTranslate[1]) pm.setDrivenKeyframe(fangsJnt.translateZ, cd=ankle.ctrl.footFangs, dv=10, v=fangsTranslate[2]) # foot fangs fangsTranslate = toeFangsJnt.translate.get() pm.setDrivenKeyframe(toeFangsJnt.translateX, cd=ankle.ctrl.toeFangs, dv=0, v=fangsTranslate[0]) pm.setDrivenKeyframe(toeFangsJnt.translateY, cd=ankle.ctrl.toeFangs, dv=0, v=fangsTranslate[1]) pm.setDrivenKeyframe(toeFangsJnt.translateZ, cd=ankle.ctrl.toeFangs, dv=0, v=fangsTranslate[2]) pm.move(0, 0, -4.7, toeFangsJnt, r=True, os=True) fangsTranslate = toeFangsJnt.translate.get() pm.move(0, 0, 4.7, toeFangsJnt, r=True, os=True) pm.setDrivenKeyframe(toeFangsJnt.translateX, cd=ankle.ctrl.toeFangs, dv=10, v=fangsTranslate[0]) pm.setDrivenKeyframe(toeFangsJnt.translateY, cd=ankle.ctrl.toeFangs, dv=10, v=fangsTranslate[1]) pm.setDrivenKeyframe(toeFangsJnt.translateZ, cd=ankle.ctrl.toeFangs, dv=10, v=fangsTranslate[2]) pm.addAttr(ankle.ctrl, longName='toeCapRotate', at='float', k=True, dv=0) if side == 'l': pm.connectAttr(ankle.ctrl.toeCapRotate, 'l_footCapJA_JNT.rotateX', f=True) else: connectReverse(ankle.ctrl.toeCapRotate, 'r_footCapJA_JNT.rotateX') # simple controls legSidesSimpleControls(legModule, side, secColour) armSidesSimpleControls(armModule, side, secColour) # asymettrical controls bodySimpleControls(bodyModule)
def createPoleVector(self,*args): """ Create the pole vector control curve. Create plane with points on shoulder, elbow and wrist. Translate elbow point of plane along the normal, then snap the control curve to the point. Zero controller and setup elbow attribute on ikControl """ self.pv_cnt = '%s_pv_cnt' % self.prefix if self.up == 1: self.upAxis = (1,0,0) if self.up == 2: self.upAxis = (0,1,0) if self.up == 3: self.upAxis = (0,0,1) #Create the pole vector control curve melString = 'createNode transform -n "%s";' % self.pv_cnt melString = melString + 'setAttr ".ove" yes;' melString = melString + 'setAttr ".ovc" 15;' melString = melString + 'createNode nurbsCurve -n "%sShape1" -p "%s";' % (self.pv_cnt,self.pv_cnt) melString = melString + 'setAttr -k off ".v";' melString = melString + 'setAttr ".cc" -type "nurbsCurve"' melString = melString + ' 1 7 0 no 3' melString = melString + ' 8 0 1 2 3 4 5 6 7' melString = melString + ' 8' melString = melString + ' -2 0 0' melString = melString + ' 1 0 1' melString = melString + ' 1 0 -1' melString = melString + ' -2 0 0' melString = melString + ' 1 1 0' melString = melString + ' 1 0 0' melString = melString + ' 1 -1 0' melString = melString + ' -2 0 0' pm.mel.eval( melString ) #Get locators positions loc1Pos = pm.xform(self.loc1,q=True,ws=True,t=True) loc2Pos = pm.xform(self.loc2,q=True,ws=True,t=True) loc3Pos = pm.xform(self.loc3,q=True,ws=True,t=True) # Get Move vector mid_point = ((loc1Pos[0]+loc3Pos[0]) / 2.0, (loc1Pos[1]+loc3Pos[1]) / 2.0, (loc1Pos[2]+loc3Pos[2]) / 2.0) move_vec = dt.Vector(loc2Pos[0]-mid_point[0], loc2Pos[1]-mid_point[1], loc2Pos[2]-mid_point[2]) move_vec.normalize() move_vec *= 10 #move pv_cnt to the vert pm.move(loc2Pos[0], loc2Pos[1], loc2Pos[2], self.pv_cnt, moveXYZ=True) pm.move(move_vec[0], move_vec[1], move_vec[2], self.pv_cnt, r=1, moveXYZ=True) self.zero(self.pv_cnt) #Create the constraint pm.poleVectorConstraint(self.pv_cnt, self.arm_ikHandle[0]) #Get buffer group of pv, create new group and snap it to ikControl pv_buffer = pm.listRelatives(self.pv_cnt, parent=True) pv_parent = pm.group(n='%sprnt' % pv_buffer, world=True, em=True) self.snapping( pv_parent, self.ikControl[0] ) #Create locator, snap to pv_parent locTemp = pm.spaceLocator() loc = pm.spaceLocator(n='%s_pvAim_loc'%self.prefix) self.snapping(locTemp, pv_buffer) self.snapping(loc, pv_parent) #Match locator orientations to pv_parent temp = pm.orientConstraint(pv_buffer, locTemp) pm.delete(temp) temp = pm.orientConstraint(pv_parent, loc) pm.delete(temp) #Move locator 1 in up direction if self.up == 1: pm.move(self.upPolarity, loc, x=1, r=1) if self.up == 2: pm.move(self.upPolarity, loc, y=1, r=1) if self.up == 3: pm.move(self.upPolarity, loc, z=1, r=1) #Aim buffer at elbow temp = pm.aimConstraint(self.jointChain[1], pv_buffer, aimVector=self.aimAxis, upVector=self.upAxis, worldUpType="object", worldUpObject=locTemp) pm.delete(temp) pm.delete(locTemp) #Aim pv_parent at shoulder temp = pm.aimConstraint(self.jointChain[0], pv_parent, aimVector=self.aimAxis, upVector=self.upAxis, worldUpType="object", worldUpObject=loc) #Hide the up locator pm.setAttr('%s.visibility'%loc, 0) #point constraint pv_parent to ik_control pm.pointConstraint(self.ikControl[0], pv_parent, mo=True) #PV elbow twist/ vis switch pm.addAttr(self.ikControl[0], ln='elbow', k=True, at='float') pm.connectAttr('%s.elbow' % self.ikControl[0], '%s.rotateX' % pv_parent, f=True) pm.addAttr(self.ikControl[0], ln='pv_vis', k=True, at='short',hasMinValue=True,hasMaxValue=True,min=0,max=1,dv=1) pm.connectAttr('%s.pv_vis' % self.ikControl[0], '%s.visibility' % self.pv_cnt, f=True) #Parent the buffer grp to the parent grp pm.parent(pv_buffer, pv_parent) #scale pv_cnt aim -1 so it points at the elbow pm.setAttr('%s.scale%s' % (self.pv_cnt, self.aim), -1) pm.makeIdentity(self.pv_cnt, scale=True, apply=True)
def setup_swivel_ctrl(self, base_ctrl, ref, pos, ik_handle, constraint=True, mirror_setup=True, **kwargs): """ Create the swivel ctrl for the ik system. Redefined to add the possibility to create a mirror swivel setup to prevent flipping problem with pole vector when using ikSpringSolver :param base_ctrl: The ctrl used to setup the swivel, create one if needed :param ref: Reference object to position the swivel :param pos: The computed position of the swivel :param ik_handle: The handle to pole vector contraint :param constraint: Do we contraint the ik handle to the swivel ctrl :param mirror_setup: Is the swivel need a mirror setup (Hack to bypass ikSpringSolver flipping problem :param kwargs: Additionnal parameters :return: The created ctrl swivel """ # Do not contraint the ik handle now since we could maybe need the flipping setup ctrl_swivel = super(LegIkQuad, self).setup_swivel_ctrl(base_ctrl, ref, pos, ik_handle, constraint=False, **kwargs) nomenclature_rig = self.get_nomenclature_rig() flip_swivel_ref = None if mirror_setup: # HACK - In case the ikpringSolver is used, a flip can happen if the foot pos is behind the thigh pos # Since we already have a plane, only compare the world Z pos to know if the foot is behind the thigh thigh_pos = self.chain_jnt[0].getTranslation(space='world') foot_pos = self.chain_jnt[self.iCtrlIndex].getTranslation(space='world') # TODO - The check is not stable at all. The best we could do is to do real test on the bones # if foot_pos.z < thigh_pos.z: if foot_pos.z < thigh_pos.z and nomenclature_rig.side != nomenclature_rig.SIDE_R: # Flip will occur log.warning("Using the mirror swivel setup for {0}".format(self.name)) # The goal is to create a swivel ref that will be at the good position for the poleVectorContraint # to not flip and drive it by the pole vector ctrl that is in the real position we really wanted flip_swivel_ref = pymel.spaceLocator() flip_swivel_ref.rename(nomenclature_rig.resolve('swivelFlipRefBack')) flip_pos = pymel.dt.Vector(pos.x, pos.y, -pos.z) flip_swivel_ref.setTranslation(flip_pos, space='world') # Setup a ref parent that will always look at the foot ref_parent_name = nomenclature_rig.resolve('swivelParentFlipRef') ref_parent = pymel.createNode('transform', name=ref_parent_name, parent=self.grp_rig) ref_parent.setMatrix(self.chain_jnt[0].getMatrix(ws=True), ws=True) pymel.pointConstraint(self.parent, ref_parent, mo=True) pymel.aimConstraint(self.ctrl_ik, ref_parent, mo=True) ref_parent.setParent(self.grp_rig) # Parent the ref flipping swivel on it's parent flip_swivel_ref.setParent(ref_parent) # Create a ref that will be at the same position than the swivel ctrl # and that will control the flipping swivel ref_swivel_ctrl = pymel.spaceLocator() ref_swivel_ctrl.rename(nomenclature_rig.resolve('swivelCtrlRef')) ref_swivel_ctrl.setMatrix(ctrl_swivel.getMatrix(ws=True), ws=True) pymel.pointConstraint(ctrl_swivel, ref_swivel_ctrl) ref_swivel_ctrl.setParent(ref_parent) # Now, mirror position from the ref swivel ctrl to the flipping swivel ctrl inverse_MD = pymel.createNode('multiplyDivide') inverse_MD.input2.set(-1.0, -1.0, -1.0) ref_swivel_ctrl.translate.connect(inverse_MD.input1) inverse_MD.output.connect(flip_swivel_ref.translate) if constraint: # Pole vector contraint the swivel to the ik handle if flip_swivel_ref: # Use the flipping ref if needed pymel.poleVectorConstraint(flip_swivel_ref, ik_handle) else: pymel.poleVectorConstraint(ctrl_swivel, ik_handle) return ctrl_swivel
def RigIK(jnts=None, side='L', ctrlSize=1.0, mode='arm', characterMode='biped', mirrorMode=False, poleVectorTransform=None, footRotate=None, rigHandOrFoot=False): # find color of the ctrls color = 'y' if side == 'L': color = 'r' elif side == 'R': color = 'b' # biped mode # ----------------------------------------------------------- if characterMode == 'biped': # biped inputs check if not jnts: jnts = pm.ls(sl=True) if not len(jnts) == 4: pm.error( 'ehm_tools...rigIK: (biped mode) select uparm, elbow, hand and hend end joints.' ) # check mode - arm or leg if mode == 'arm': limbName = 'hand' secondLimb = 'elbow' elif mode == 'leg': limbName = 'foot' secondLimb = 'knee' else: pm.error( 'ehm_tools...rigIK: mode argument must be either "arm" or "leg"!' ) # start rigging biped uparmJnt = jnts[0] elbowJnt = jnts[1] handJnt = jnts[2] handEndJnt = jnts[3] # find control size if mode == 'arm': ctrlSize = Dist(uparmJnt, elbowJnt) * 0.4 * ctrlSize elif mode == 'leg': ctrlSize = Dist(uparmJnt, elbowJnt) * 0.3 * ctrlSize # find arm limbs position uparmPos = pm.xform(uparmJnt, q=True, t=True, ws=True) elbowPos = pm.xform(elbowJnt, q=True, t=True, ws=True) handPos = pm.xform(handJnt, q=True, t=True, ws=True) # create ik handle armIKStuff = pm.ikHandle(sj=uparmJnt, ee=handJnt, solver="ikRPsolver") armIK = pm.rename(armIKStuff[0], (side + "_arm_ikh")) # make Ik Stretchy locs, dists = MakeIkStretchy(ikh=armIK, elbowLock=True) #======================================================================================================== # create and position the IK elbow control curve if mode == 'arm': elbowIKCtrl = SoftSpiralCrv(ctrlSize, '%s_%s_IK_ctrl' % (side, secondLimb)) # rotate elbowIKCtrl to be seen from side view elbowIKCtrl.rotateZ.set(90) elbowIKCtrl.scaleZ.set(-1) if mirrorMode: ReverseShape(objs=elbowIKCtrl, axis='y') ReverseShape(objs=elbowIKCtrl, axis='z') elif mode == 'leg': elbowIKCtrl = SharpSpiralCrv(ctrlSize, '%s_%s_IK_ctrl' % (side, secondLimb)) # rotate elbowIKCtrl to be seen from side view elbowIKCtrl.rotate.set(90, 90, -90) if mirrorMode: ReverseShape(objs=elbowIKCtrl, axis='y') ReverseShape(objs=elbowIKCtrl, axis='z') pm.makeIdentity(elbowIKCtrl, apply=True) # give it color Colorize(shapes=elbowIKCtrl.getShape(), color=color) tmpAim = pm.group(em=True) if poleVectorTransform: # pole vector position is given elbowIKCtrl.translate.set(poleVectorTransform[0]) elbowIKCtrl.rotate.set(poleVectorTransform[1]) else: # pole vector position is NOT given, we'll guess it aimPos = FindPVposition(objs=(uparmJnt, elbowJnt, handJnt)) if aimPos: # if pole vector position was found by FindPVposition def, we're done :) pm.xform(elbowIKCtrl, ws=True, t=aimPos) else: # limb is straight pm.delete(pm.pointConstraint( elbowJnt, elbowIKCtrl)) # position the elbowIKCtrl if mode == 'arm': # find elbow pole vector position and rotation tmpAim.translate.set( elbowPos[0], elbowPos[1], elbowPos[2] - ctrlSize) # position it slightly behind elbow joint pm.delete( pm.aimConstraint( tmpAim, elbowIKCtrl, upVector=(0, 1, 0), aimVector=( 0, 0, -1))) # rotate elbowIKCtrl to point to tmpAim if mode == 'leg': # find knee pole vector position tmpAim.translate.set( elbowPos[0], elbowPos[1], elbowPos[2] + ctrlSize) # position it slightly behind elbow joint pm.delete( pm.aimConstraint(tmpAim, elbowIKCtrl, upVector=(0, 1, 0), aimVector=(0, 0, 1))) # elbow IK control is in place now, parent elbow loc to it and offset it from arm a bit elbowIKCtrlZeros = ZeroGrp(elbowIKCtrl) pm.parent(locs[1], elbowIKCtrl) locs[1].translate.set(0, 0, 0) locs[1].rotate.set(0, 0, 0) ''' if mode=='arm': elbowIKCtrl.translateZ.set( -ctrlSize*2.0 ) if mode=='leg': elbowIKCtrl.translateZ.set( ctrlSize*2.0 ) ''' # use elbow control curve instead of locator as the pole vector TransferOutConnections(source=locs[1], dest=elbowIKCtrl) LockHideAttr(objs=elbowIKCtrl, attrs='r') LockHideAttr(objs=elbowIKCtrl, attrs='s') # create pole vector pm.poleVectorConstraint(locs[1], armIK) #======================================================================================================== # rig hand or foot and position them in the correct place if mode == 'arm': # position the hand control handIKCtrl = Circle3ArrowCrv(ctrlSize, '%s_%s_IK_ctrl' % (side, limbName)) MatchTransform(force=True, folower=handIKCtrl, lead=handJnt) if rigHandOrFoot: RigHand(handJnt, handEndJnt, handIKCtrl) locs[2].setParent(handIKCtrl) elif mode == 'leg': # position the foot control handIKCtrl = CubeCrv(ctrlSize, '%s_%s_IK_ctrl' % (side, limbName)) handIKCtrl.translate.set(pm.xform(handJnt, q=True, ws=True, t=True)) handIKCtrl.rotate.set(footRotate) if rigHandOrFoot: # rig foot ankleJnt = jnts[2] ballJnt = jnts[3] toeEndJnt = jnts[4] ballPos = pm.xform(jnts[3], q=True, t=True, ws=True) toeEndPos = pm.xform(jnts[4], q=True, t=True, ws=True) heelPos = pm.xform(jnts[5], q=True, t=True, ws=True) outsidePos = pm.xform(jnts[6], q=True, t=True, ws=True) insidePos = pm.xform(jnts[7], q=True, t=True, ws=True) # create foot ik handles ankleBallIKStuff = pm.ikHandle(sj=ankleJnt, ee=ballJnt, solver="ikSCsolver") ankleBallIK = pm.rename(ankleBallIKStuff[0], (side + "_ankleBall_ikh")) ballToeEndIKStuff = pm.ikHandle(sj=ballJnt, ee=toeEndJnt, solver="ikSCsolver") ballToeIK = pm.rename(ballToeEndIKStuff[0], (side + "_ballToeEnd_ikh")) # add attributes to foot controler pm.addAttr(handIKCtrl, ln="roll", at='double', min=-10, max=10, dv=0, keyable=True) pm.addAttr(handIKCtrl, ln="sideToSide", at='double', min=-10, max=10, dv=0, keyable=True) pm.addAttr(handIKCtrl, ln="toes", at='double', min=-10, max=10, dv=0, keyable=True) # toe group toeGrp = pm.group(ballToeIK, name='%s_toe_IK_grp' % side) pm.xform(toeGrp, os=True, piv=(ballPos)) # heelUp group heelUpGrp = pm.group(ankleBallIK, locs[2], name='%s_heelUp_IK_grp' % side) pm.xform(heelUpGrp, os=True, piv=(ballPos)) # pivOnToe group outsideGrp = pm.group(toeGrp, heelUpGrp, name='%s_outside_IK_grp' % side) pm.xform(outsideGrp, os=True, piv=(outsidePos)) # pivOnHeel group insideGrp = pm.group(outsideGrp, name='%s_inside_IK_grp' % side) pm.xform(insideGrp, os=True, piv=(insidePos)) # pivOutSide group toeTipGrp = pm.group(insideGrp, name='%s_toeTip_IK_grp' % side) pm.xform(toeTipGrp, os=True, piv=(toeEndPos)) # pivInSide group heelGrp = pm.group(toeTipGrp, name='%s_heel_IK_grp' % side) pm.xform(heelGrp, os=True, piv=(heelPos)) footGrp = pm.group(heelGrp, name='%s_foot_IK_grp' % side) footGrp.setParent(handIKCtrl) # toe set driven keys pm.setDrivenKeyframe(toeGrp.rotateX, currentDriver=handIKCtrl.toes, itt='linear', ott='linear', driverValue=10, value=-90) pm.setDrivenKeyframe(toeGrp.rotateX, currentDriver=handIKCtrl.toes, itt='linear', ott='linear', driverValue=-10, value=90) # roll set driven keys pm.setDrivenKeyframe(heelUpGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=0, value=0) pm.setDrivenKeyframe(heelUpGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=-5, value=45) pm.setDrivenKeyframe(heelUpGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=10, value=0) pm.setDrivenKeyframe(toeTipGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=-5, value=0) pm.setDrivenKeyframe(toeTipGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=-10, value=60) pm.setDrivenKeyframe(heelGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=10, value=-45) pm.setDrivenKeyframe(heelGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=0, value=0) # sideToSide set driven keys value = 45 if mirrorMode: value = -45 pm.setDrivenKeyframe(outsideGrp.rotateZ, currentDriver=handIKCtrl.sideToSide, itt='linear', ott='linear', driverValue=0, value=0) pm.setDrivenKeyframe(outsideGrp.rotateZ, currentDriver=handIKCtrl.sideToSide, itt='linear', ott='linear', driverValue=10, value=-value) pm.setDrivenKeyframe(insideGrp.rotateZ, currentDriver=handIKCtrl.sideToSide, itt='linear', ott='linear', driverValue=0, value=0) pm.setDrivenKeyframe(insideGrp.rotateZ, currentDriver=handIKCtrl.sideToSide, itt='linear', ott='linear', driverValue=-10, value=value) # delete joint that determine foot's different pivots pm.delete(jnts[-3:]) # hide extras LockHideAttr(objs=(ankleBallIKStuff, ballToeEndIKStuff), attrs='vv') handIKCtrlZeros = ZeroGrp(handIKCtrl) handIKCtrlZero = handIKCtrlZeros[0] TransferOutConnections(source=locs[2], dest=handIKCtrl) # colorize hand control Colorize(shapes=handIKCtrl.getShape(), color=color) # check if joints are mirrored, if so, we must reverse the hand control vertices if mirrorMode: ReverseShape(axis='x', objs=handIKCtrl) # hide extra stuff LockHideAttr(objs=locs, attrs='vv') LockHideAttr(objs=dists, attrs='vv') ikGrp = pm.group(jnts[0], dists, locs[0], name='%s_ik_arm' % side) pm.xform(ikGrp, os=True, piv=(0, 0, 0)) # create guide curves for pole vector elbowGuide = GuideCrv(elbowIKCtrl, elbowJnt) elbowIKCtrl.v >> elbowGuide.getShape().v elbowGuide.setParent(ikGrp) # clean up pm.delete(tmpAim) # return return (handIKCtrl, elbowIKCtrl, jnts, locs, dists, handIKCtrlZeros, elbowIKCtrlZeros, ikGrp) # quadruped mode # ----------------------------------------------------------- if characterMode == 'quadruped': # quadruped inputs check if not jnts: jnts = pm.ls(sl=True) if not len(jnts) == 7: pm.error( 'ehm_tools...rigIK: (quadruped mode) jnts arguments needs 7 joints.' ) # check mode - arm or leg if mode == 'arm': pm.error('ehm_tools...rigIK: quadruped arm is not defined yet!') elif mode == 'leg': firstLimbName = 'pelvis' secondLimbName = 'hip' thirdLimbName = 'stifle' forthLimbName = 'hock' fifthLimbName = 'ankle' sixthLimbName = 'hoof' seventhLimbName = 'hoofEnd' else: pm.error( 'ehm_tools...rigIK: mode argument must be either "arm" or "leg"!' ) # start rigging the quadruped pelvisJnt = jnts[0] hipJnt = jnts[1] stifleJnt = jnts[2] hockJnt = jnts[3] ankleJnt = jnts[4] hoofJnt = jnts[5] hoofEndJnt = jnts[6] # find arm limbs position pelvisPos = pm.xform(pelvisJnt, q=True, t=True, ws=True) hipPos = pm.xform(hipJnt, q=True, t=True, ws=True) stiflePos = pm.xform(stifleJnt, q=True, t=True, ws=True) hockPos = pm.xform(hockJnt, q=True, t=True, ws=True) anklePos = pm.xform(ankleJnt, q=True, t=True, ws=True) hoofPos = pm.xform(hoofJnt, q=True, t=True, ws=True) hoofEndPos = pm.xform(hoofEndJnt, q=True, t=True, ws=True) # find control size ctrlSize = Dist(hipJnt, hockJnt) * 0.2 * ctrlSize # set preferred angle if mode == 'arm': pm.error('ehm_tools...rigIK: quadruped arm is not defined yet!') else: stifleJnt.preferredAngleZ.set(10) hockJnt.preferredAngleZ.set(-10) # create ik handle for main joint chain IKstuff = pm.ikHandle(sj=hipJnt, ee=hockJnt, solver="ikRPsolver") ankleIKstuff = pm.ikHandle(sj=hockJnt, ee=ankleJnt, solver="ikSCsolver") # create 3 extra joint chains for making some auto movements on the leg: # chain 1. upper leg, lower leg, foot # - this chain is used for automatic upper leg bending when foot control is moved pm.select(clear=True) autoUpLegJnt_tmp = pm.duplicate(hipJnt)[0] autoJnts_tmp = GetAllChildren(objs=autoUpLegJnt_tmp, childType='joint') autoUpLegJnt = pm.rename(autoJnts_tmp[0], '%s_autoUpLegJnt' % side) autoLowLegJnt = pm.rename(autoJnts_tmp[1], '%s_autoLowLegJnt' % side) autoKneeJnt = pm.rename(autoJnts_tmp[2], '%s_autoKneeJnt' % side) autoKneeEndJnt = pm.rename(autoJnts_tmp[3], '%s_autoKneeEndJnt' % side) autoIKstuff = pm.ikHandle(sj=autoUpLegJnt, ee=autoKneeEndJnt, solver="ikRPsolver") # chain 2 and 3: # - these chains are needed for automatic pole vector PV = autoPoleVector(baseJnt=hipJnt, endJnt=hockJnt, side=side) autoPV = autoPoleVector(baseJnt=autoUpLegJnt, endJnt=autoKneeEndJnt, side='L') # create automatic pole vector and set the twist parameter pm.poleVectorConstraint(PV[0], IKstuff[0]) pm.poleVectorConstraint(autoPV[0], autoIKstuff[0]) if side == 'L': IKstuff[0].twist.set(90) autoIKstuff[0].twist.set(90) elif side == 'R': IKstuff[0].twist.set(-90) autoIKstuff[0].twist.set(-90) # parent all ikhandles to auto kneeEnd joint. # now we're controling 3 joint chain ik handle with one joint # which itself is being controled by foot control. IKstuffGrp = pm.group(ankleIKstuff[0], IKstuff[0], PV[1][0]) pm.xform(os=True, piv=(pm.xform(ankleJnt, q=True, t=True, ws=True))) IKstuffGrp.setParent(autoKneeEndJnt) autoIKstuffZeros = ZeroGrp(autoIKstuff[0]) autoPV[1][0].setParent(autoIKstuffZeros[1]) # make Ik Stretchy locs, dists = MakeIkStretchy(ikh=autoIKstuff[0], elbowLock=False) # Finally, parent main upLeg joint to autoUpLegJnt. The purpose of whole auto joint chain pm.parent(locs[0], autoUpLegJnt) ZeroGrp() pm.parentConstraint(autoUpLegJnt, hipJnt, mo=True) # create IK hand control if mode == 'arm': pm.error('ehm_tools...rigIK: quadruped arm is not defined yet!') else: IKCtrl = CubeCrv(size=ctrlSize, name='%s_%s_IK_ctrl' % (side, ankleJnt)) # position the hand control pm.addAttr(IKCtrl, ln="upLeg_rotation", at='double', keyable=True) # find color of the ctrls color = 'y' if side == 'L': color = 'r' elif side == 'R': color = 'b' Colorize(shapes=IKCtrl.getShape(), color=color) # position the hand control if mode == 'arm': pm.error('ehm_tools...rigIK: quadruped arm is not defined yet!') else: pm.delete(pm.pointConstraint(ankleJnt, IKCtrl)) IKCtrl.rotateY.set( ProjectedAim(objs=(hipJnt, stifleJnt), fullCircle=False)) IKCtrlZeros = ZeroGrp(IKCtrl) #IKCtrlZero = IKCtrlZeros[0] pm.pointConstraint(IKCtrl, PV[1][0]) pm.parent(autoIKstuff[0], locs[2], IKCtrl) TransferOutConnections(source=locs[2], dest=IKCtrl) # check if joints are mirrored, if so, we must reverse the hand control vertices #x = kneeEndJnt.translateX.get() #y = kneeEndJnt.translateY.get() #z = kneeEndJnt.translateZ.get() #if x < 0: # ReverseShape( axis = 'x', objs = IKCtrl ) #elif y < 0: # ReverseShape( axis = 'y', objs = IKCtrl ) #elif z < 0: # ReverseShape( axis = 'z', objs = IKCtrl ) # hide extra stuff LockHideAttr(objs=locs, attrs='vv') LockHideAttr(objs=dists, attrs='vv') LockHideAttr(objs=PV[0], attrs='vv') LockHideAttr(objs=PV[1], attrs='vv') LockHideAttr(objs=autoIKstuff, attrs='vv') LockHideAttr(objs=autoUpLegJnt, attrs='vv') LockHideAttr(objs=PV[2][0], attrs='vv') # cleaup outliner ikGrp = pm.group(hipJnt, autoUpLegJnt, PV[2][0], dists, locs[1], PV[1][0], IKCtrlZeros[0], name='%s_ik_leg' % side) pm.xform(ikGrp, os=True, piv=(0, 0, 0))
def bdRigLegBones(side): ikAnimCon = pm.ls(side + '*foot*IK_CON', type='transform')[0] legBonesNames = ['thigh', 'knee', 'foot', 'toe'] legBones = [] for bone in legBonesNames: legBone = pm.ls(side + '_' + bone + '_ik')[0] legBones.append(legBone) print legBone.name() toeEnd = pm.ls(side + '_' + 'toe_ik_end')[0] legBones.append(toeEnd) # START setup foot roll footIk = pm.ikHandle(sol='ikRPsolver', sticky='sticky', startJoint=legBones[0], endEffector=legBones[2], name=side + '_foot_ikHandle')[0] footIk.visibility.set(0) ballIk = pm.ikHandle(sol='ikSCsolver', sticky='sticky', startJoint=legBones[2], endEffector=legBones[3], name=side + '_ball_ikHandle')[0] ballIk.visibility.set(0) toeIk = pm.ikHandle(sol='ikSCsolver', sticky='sticky', startJoint=legBones[3], endEffector=legBones[4], name=side + '_toe_ikHandle')[0] toeIk.visibility.set(0) # create the groups that will controll the foot animations ( roll, bend, etc etc) footHelpers = pm.ls(side + '*_helper', type='transform') ankleLoc = bdCreateOffsetLoc(legBones[2], side + '_ankle_loc') footLoc = bdCreateOffsetLoc(legBones[2], side + '_foot_loc') ballLoc = bdCreateOffsetLoc(legBones[3], side + '_ball_loc') ballTwistLoc = bdCreateOffsetLoc(legBones[3], side + '_ball_twist_loc') toeLoc = bdCreateOffsetLoc(legBones[4], side + '_toe_loc') toeBendLoc = bdCreateOffsetLoc(legBones[3], side + '_toe_bend_loc') innerLoc = outerLoc = heelLoc = '' for helper in footHelpers: if 'inner' in helper.name(): innerLoc = bdCreateOffsetLoc(helper, side + '_inner_bank_loc') elif 'outer' in helper.name(): outerLoc = bdCreateOffsetLoc(helper, side + '_outer_bank_loc') elif 'heel' in helper.name(): heelLoc = bdCreateOffsetLoc(helper, side + '_heel_loc') # pm.delete(footHelpers) pm.parent(footIk, footLoc) pm.parent(ballIk, ballLoc) pm.parent(toeIk, toeBendLoc) pm.parent(toeBendLoc, toeLoc) pm.parent(footLoc, ballLoc) pm.parent(ballLoc, toeLoc) pm.parent(toeLoc, ballTwistLoc) pm.parent(ballTwistLoc, innerLoc) pm.parent(innerLoc, outerLoc) pm.parent(outerLoc, heelLoc) pm.parent(heelLoc, ankleLoc) print "start adding attributes" # add atributes on the footGrp - will be conected later to an anim controler autoRollAttrList = ['Roll', 'ToeStart', 'BallStraight'] footAttrList = [ 'HeelTwist', 'BallTwist', 'TipTwist', 'Bank', 'ToeBend', 'KneeTwist' ] normalRollAttrList = ['HeelRoll', 'BallRoll', 'TipRoll'] pm.addAttr(ikAnimCon, ln='__AutoFootRoll__', nn='__AutoFootRoll__', at='bool') ikAnimCon.attr('__AutoFootRoll__').setKeyable(True) ikAnimCon.attr('__AutoFootRoll__').setLocked(True) pm.addAttr(ikAnimCon, ln='Enabled', nn='Enabled', at='long') ikAnimCon.attr('Enabled').setKeyable(True) ikAnimCon.attr('Enabled').setMin(0) ikAnimCon.attr('Enabled').setMax(1) ikAnimCon.attr('Enabled').set(1) pm.addAttr(ikAnimCon, ln='______', nn='______', at='bool') ikAnimCon.attr('______').setKeyable(True) ikAnimCon.attr('______').setLocked(True) for attr in autoRollAttrList: pm.addAttr(ikAnimCon, ln=attr, nn=attr, at='float') ikAnimCon.attr(attr).setKeyable(True) pm.addAttr(ikAnimCon, ln='__FootRoll__', nn='__FootRoll__', at='bool') ikAnimCon.attr('__FootRoll__').setKeyable(True) ikAnimCon.attr('__FootRoll__').setLocked(True) for attr in normalRollAttrList: pm.addAttr(ikAnimCon, ln=attr, nn=attr, at='float') ikAnimCon.attr(attr).setKeyable(True) pm.addAttr(ikAnimCon, ln='__FootAttr__', nn='__FootAttr__', at='bool') ikAnimCon.attr('__FootAttr__').setKeyable(True) ikAnimCon.attr('__FootAttr__').setLocked(True) for attr in footAttrList: pm.addAttr(ikAnimCon, ln=attr, nn=attr, at='float') ikAnimCon.attr(attr).setKeyable(True) ikAnimCon.attr('ToeStart').set(40) ikAnimCon.attr('BallStraight').set(80) bdCreateReverseFootRoll(ikAnimCon, heelLoc, ballLoc, toeLoc) # connect the attributes ikAnimCon.attr('HeelTwist').connect(heelLoc.rotateY) ikAnimCon.attr('BallTwist').connect(ballTwistLoc.rotateY) ikAnimCon.attr('TipTwist').connect(toeLoc.rotateY) ikAnimCon.attr('ToeBend').connect(toeBendLoc.rotateX) bdConnectBank(ikAnimCon, innerLoc, outerLoc) # START no flip knee knee mirror = 1 if side == 'R': mirror = -1 poleVectorLoc = pm.spaceLocator(name=side + '_knee_loc_PV') poleVectorLocGrp = pm.group(poleVectorLoc, n=poleVectorLoc + '_GRP') thighPos = legBones[0].getTranslation(space='world') poleVectorLocGrp.setTranslation( [thighPos[0] + mirror * 5, thighPos[1], thighPos[2]]) pm.poleVectorConstraint(poleVectorLoc, footIk) adlNode = pm.createNode('addDoubleLinear', name=side + '_adl_twist') adlNode.input2.set(mirror * 90) ikAnimCon.attr('KneeTwist').connect(adlNode.input1) adlNode.output.connect(footIk.twist) startTwist = mirror * 90 limit = 0.001 increment = mirror * 0.01 while True: pm.select(cl=True) thighRot = pm.xform(legBones[0], q=True, ro=True, os=True) if ((thighRot[0] > limit)): startTwist = startTwist - increment adlNode.input2.set(startTwist) else: break # END knee pm.parent(ankleLoc, ikAnimCon)
def bdRigLegBones(side): ikAnimCon = pm.ls(side.upper() + '_Foot_CON',type='transform')[0] legBonesNames = ['Thigh','Shin','Foot','Toe'] legBones = [] for bone in legBonesNames: legBone = pm.ls(side + bone)[0] legBones.append(legBone) print legBone.name() toeEnd = pm.ls(side + 'Toe_end')[0] legBones.append(toeEnd) #START setup foot roll footIk = pm.ikHandle(sol= 'ikRPsolver',sticky='sticky', startJoint=legBones[0],endEffector = legBones[2],name = side + '_foot_ikHandle')[0] footIk.visibility.set(0) ballIk = pm.ikHandle(sol= 'ikSCsolver',sticky='sticky', startJoint=legBones[2],endEffector = legBones[3],name = side + '_ball_ikHandle')[0] ballIk.visibility.set(0) toeIk = pm.ikHandle(sol= 'ikSCsolver',sticky='sticky', startJoint=legBones[3],endEffector = legBones[4],name = side + '_toe_ikHandle')[0] toeIk.visibility.set(0) #create the groups that will controll the foot animations ( roll, bend, etc etc) footHelpers = pm.ls(side + '*_helper',type='transform') ankleLoc = bdCreateOffsetLoc(legBones[2],side + '_ankle_loc') footLoc = bdCreateOffsetLoc(legBones[2],side + '_foot_loc') ballLoc = bdCreateOffsetLoc(legBones[3],side + '_ball_loc') ballTwistLoc = bdCreateOffsetLoc(legBones[3],side + '_ball_twist_loc') toeLoc = bdCreateOffsetLoc(legBones[4],side + '_toe_loc') toeBendLoc = bdCreateOffsetLoc(legBones[3],side + '_toe_bend_loc') innerLoc = outerLoc = heelLoc = '' for helper in footHelpers: if 'inner' in helper.name(): innerLoc = bdCreateOffsetLoc(helper,side + '_inner_bank_loc') elif 'outer' in helper.name(): outerLoc = bdCreateOffsetLoc(helper,side + '_outer_bank_loc') elif 'heel' in helper.name(): heelLoc = bdCreateOffsetLoc(helper,side + '_heel_loc') #pm.delete(footHelpers) pm.parent(footIk, footLoc) pm.parent(ballIk, ballLoc) pm.parent(toeIk,toeBendLoc) pm.parent(toeBendLoc,toeLoc) pm.parent(footLoc,ballLoc) pm.parent(ballLoc,toeLoc) pm.parent(toeLoc,ballTwistLoc) pm.parent(ballTwistLoc,innerLoc) pm.parent(innerLoc,outerLoc) pm.parent(outerLoc,heelLoc) pm.parent(heelLoc,ankleLoc) #add atributes on the footGrp - will be conected later to an anim controler autoRollAttrList = ['Roll','ToeStart','BallStraight'] footAttrList = ['HeelTwist','BallTwist','TipTwist','Bank','ToeBend','KneeTwist'] normalRollAttrList = ['HeelRoll','BallRoll','TipRoll'] pm.addAttr(ikAnimCon ,ln='__AutoFootRoll__',nn='__AutoFootRoll__',at='bool' ) ikAnimCon.attr('__AutoFootRoll__').setKeyable(True) ikAnimCon.attr('__AutoFootRoll__').setLocked(True) pm.addAttr(ikAnimCon ,ln='Enabled',nn='Enabled',at='long' ) ikAnimCon.attr('Enabled').setKeyable(True) ikAnimCon.attr('Enabled').setMin(0) ikAnimCon.attr('Enabled').setMax(1) ikAnimCon.attr('Enabled').set(1) pm.addAttr(ikAnimCon ,ln='______',nn='______',at='bool' ) ikAnimCon.attr('______').setKeyable(True) ikAnimCon.attr('______').setLocked(True) for attr in autoRollAttrList: pm.addAttr(ikAnimCon ,ln=attr,nn=attr,at='float' ) ikAnimCon.attr(attr).setKeyable(True) pm.addAttr(ikAnimCon ,ln='__FootRoll__',nn='__FootRoll__',at='bool' ) ikAnimCon.attr('__FootRoll__').setKeyable(True) ikAnimCon.attr('__FootRoll__').setLocked(True) for attr in normalRollAttrList: pm.addAttr(ikAnimCon ,ln=attr,nn=attr,at='float' ) ikAnimCon.attr(attr).setKeyable(True) pm.addAttr(ikAnimCon ,ln='__FootAttr__',nn='__FootAttr__',at='bool' ) ikAnimCon.attr('__FootAttr__').setKeyable(True) ikAnimCon.attr('__FootAttr__').setLocked(True) for attr in footAttrList: pm.addAttr(ikAnimCon ,ln=attr,nn=attr,at='float' ) ikAnimCon.attr(attr).setKeyable(True) ikAnimCon.attr('ToeStart').set(40) ikAnimCon.attr('BallStraight').set(80) bdCreateReverseFootRoll(ikAnimCon,heelLoc,ballLoc,toeLoc) #connect the attributes ikAnimCon.attr('HeelTwist').connect(heelLoc.rotateY) ikAnimCon.attr('BallTwist').connect(ballTwistLoc.rotateY) ikAnimCon.attr('TipTwist').connect(toeLoc.rotateY) ikAnimCon.attr('ToeBend').connect(toeBendLoc.rotateX) bdConnectBank(ikAnimCon,innerLoc,outerLoc) #START no flip knee knee mirror = 1 if side == 'r': mirror = -1 offset = 90 poleVectorLoc = pm.spaceLocator(name = side + '_knee_loc_PV') poleVectorLocGrp = pm.group(poleVectorLoc,n=poleVectorLoc + '_GRP') thighPos = legBones[0].getTranslation(space='world') poleVectorLocGrp.setTranslation([thighPos[0] + mirror * 5,thighPos[1],thighPos[2]]) pm.poleVectorConstraint(poleVectorLoc,footIk) adlNode = pm.createNode('addDoubleLinear',name = side + '_adl_twist') adlNode.input2.set(mirror * offset) ikAnimCon.attr('KneeTwist').connect(adlNode.input1) adlNode.output.connect(footIk.twist) startTwist = mirror * offset limit = 0.001 increment = mirror * 0.01 while True: pm.select(cl=True) thighRot = pm.xform(legBones[0],q=True,ro=True,os=True) print thighRot[0] if ((thighRot[2] > limit)): startTwist = startTwist - increment adlNode.input2.set(startTwist) else: break #END knee pm.parent(ankleLoc,ikAnimCon)
def bdRigLegBones(side): ikAnimCon = pm.ls(side + "*foot*IK_CON", type="transform")[0] legBonesNames = ["thigh", "knee", "foot", "toe"] legBones = [] for bone in legBonesNames: legBone = pm.ls(side + "_" + bone + "_ik")[0] legBones.append(legBone) print legBone.name() toeEnd = pm.ls(side + "_" + "toe_ik_end")[0] legBones.append(toeEnd) # START setup foot roll footIk = pm.ikHandle( sol="ikRPsolver", sticky="sticky", startJoint=legBones[0], endEffector=legBones[2], name=side + "_foot_ikHandle" )[0] footIk.visibility.set(0) ballIk = pm.ikHandle( sol="ikSCsolver", sticky="sticky", startJoint=legBones[2], endEffector=legBones[3], name=side + "_ball_ikHandle" )[0] ballIk.visibility.set(0) toeIk = pm.ikHandle( sol="ikSCsolver", sticky="sticky", startJoint=legBones[3], endEffector=legBones[4], name=side + "_toe_ikHandle" )[0] toeIk.visibility.set(0) # create the groups that will controll the foot animations ( roll, bend, etc etc) footHelpers = pm.ls(side + "*_helper", type="transform") ankleLoc = bdCreateOffsetLoc(legBones[2], side + "_ankle_loc") footLoc = bdCreateOffsetLoc(legBones[2], side + "_foot_loc") ballLoc = bdCreateOffsetLoc(legBones[3], side + "_ball_loc") ballTwistLoc = bdCreateOffsetLoc(legBones[3], side + "_ball_twist_loc") toeLoc = bdCreateOffsetLoc(legBones[4], side + "_toe_loc") toeBendLoc = bdCreateOffsetLoc(legBones[3], side + "_toe_bend_loc") innerLoc = outerLoc = heelLoc = "" for helper in footHelpers: if "inner" in helper.name(): innerLoc = bdCreateOffsetLoc(helper, side + "_inner_bank_loc") elif "outer" in helper.name(): outerLoc = bdCreateOffsetLoc(helper, side + "_outer_bank_loc") elif "heel" in helper.name(): heelLoc = bdCreateOffsetLoc(helper, side + "_heel_loc") # pm.delete(footHelpers) pm.parent(footIk, footLoc) pm.parent(ballIk, ballLoc) pm.parent(toeIk, toeBendLoc) pm.parent(toeBendLoc, toeLoc) pm.parent(footLoc, ballLoc) pm.parent(ballLoc, toeLoc) pm.parent(toeLoc, ballTwistLoc) pm.parent(ballTwistLoc, innerLoc) pm.parent(innerLoc, outerLoc) pm.parent(outerLoc, heelLoc) pm.parent(heelLoc, ankleLoc) print "start adding attributes" # add atributes on the footGrp - will be conected later to an anim controler autoRollAttrList = ["Roll", "ToeStart", "BallStraight"] footAttrList = ["HeelTwist", "BallTwist", "TipTwist", "Bank", "ToeBend", "KneeTwist"] normalRollAttrList = ["HeelRoll", "BallRoll", "TipRoll"] pm.addAttr(ikAnimCon, ln="__AutoFootRoll__", nn="__AutoFootRoll__", at="bool") ikAnimCon.attr("__AutoFootRoll__").setKeyable(True) ikAnimCon.attr("__AutoFootRoll__").setLocked(True) pm.addAttr(ikAnimCon, ln="Enabled", nn="Enabled", at="long") ikAnimCon.attr("Enabled").setKeyable(True) ikAnimCon.attr("Enabled").setMin(0) ikAnimCon.attr("Enabled").setMax(1) ikAnimCon.attr("Enabled").set(1) pm.addAttr(ikAnimCon, ln="______", nn="______", at="bool") ikAnimCon.attr("______").setKeyable(True) ikAnimCon.attr("______").setLocked(True) for attr in autoRollAttrList: pm.addAttr(ikAnimCon, ln=attr, nn=attr, at="float") ikAnimCon.attr(attr).setKeyable(True) pm.addAttr(ikAnimCon, ln="__FootRoll__", nn="__FootRoll__", at="bool") ikAnimCon.attr("__FootRoll__").setKeyable(True) ikAnimCon.attr("__FootRoll__").setLocked(True) for attr in normalRollAttrList: pm.addAttr(ikAnimCon, ln=attr, nn=attr, at="float") ikAnimCon.attr(attr).setKeyable(True) pm.addAttr(ikAnimCon, ln="__FootAttr__", nn="__FootAttr__", at="bool") ikAnimCon.attr("__FootAttr__").setKeyable(True) ikAnimCon.attr("__FootAttr__").setLocked(True) for attr in footAttrList: pm.addAttr(ikAnimCon, ln=attr, nn=attr, at="float") ikAnimCon.attr(attr).setKeyable(True) ikAnimCon.attr("ToeStart").set(40) ikAnimCon.attr("BallStraight").set(80) bdCreateReverseFootRoll(ikAnimCon, heelLoc, ballLoc, toeLoc) # connect the attributes ikAnimCon.attr("HeelTwist").connect(heelLoc.rotateY) ikAnimCon.attr("BallTwist").connect(ballTwistLoc.rotateY) ikAnimCon.attr("TipTwist").connect(toeLoc.rotateY) ikAnimCon.attr("ToeBend").connect(toeBendLoc.rotateX) bdConnectBank(ikAnimCon, innerLoc, outerLoc) # START no flip knee knee mirror = 1 if side == "R": mirror = -1 poleVectorLoc = pm.spaceLocator(name=side + "_knee_loc_PV") poleVectorLocGrp = pm.group(poleVectorLoc, n=poleVectorLoc + "_GRP") thighPos = legBones[0].getTranslation(space="world") poleVectorLocGrp.setTranslation([thighPos[0] + mirror * 5, thighPos[1], thighPos[2]]) pm.poleVectorConstraint(poleVectorLoc, footIk) adlNode = pm.createNode("addDoubleLinear", name=side + "_adl_twist") adlNode.input2.set(mirror * 90) ikAnimCon.attr("KneeTwist").connect(adlNode.input1) adlNode.output.connect(footIk.twist) startTwist = mirror * 90 limit = 0.001 increment = mirror * 0.01 while True: pm.select(cl=True) thighRot = pm.xform(legBones[0], q=True, ro=True, os=True) if thighRot[0] > limit: startTwist = startTwist - increment adlNode.input2.set(startTwist) else: break # END knee pm.parent(ankleLoc, ikAnimCon)
def Build(): try: pm.newFile() except: result = pm.confirmDialog(title='Build Error', message='Unsaved changes. Continue?', button=['OK', 'Cancel'], db='Cancel') if result == 'OK': pm.newFile(force=True) else: return # Model pm.importFile( 'D:\GameProgramming\Spiral\Maya\Characters\Devil\Devil_model.ma', loadNoReferences=True) # Skel pm.importFile( 'D:\GameProgramming\Spiral\Maya\Characters\Devil\Devil_skel.ma', loadNoReferences=True) for joint in pm.listRelatives('M_root_jnt', ad=True, type=pm.nt.Joint): joint.segmentScaleCompensate.set(0) rootSpace, rootCon = CreateControl('M_root_jnt', radius=2, normal=[0, 1, 0]) rootOffsetSpace, rootOffsetCon = CreateControl('M_root_jnt', name='M_root_offset_con', parentCon=rootCon, radius=1.5, normal=[0, 1, 0]) cogSpace, cogCon = CreateControl('M_hips_jnt', name='M_cog_con', parentCon=rootOffsetCon, radius=1, constrain=False) hipSpace, hipCon = CreateControlHierarchy('M_hips_jnt', parentCon=cogCon) # IK Controls for side in ['R', 'L']: flip = -1 if side == 'L' else 1 poleCon = pm.spaceLocator(n=side + '_legIkPole_con') poleConSpace = pm.group(poleCon, n=side + '_legIkPole_space') pm.delete(pm.parentConstraint(side + '_loLeg_jnt', poleConSpace)) pm.move(poleConSpace, [0, flip, 0], r=True, os=True, wd=True) poleConSpace.r.set([0, 0, 0]) poleConSpace.s.set([0.1, 0.1, 0.1]) pm.parent(poleConSpace, rootCon) ikHandle, ikEffector = pm.ikHandle(sol='ikRPsolver', n=side + '_leg_ik', sj=side + '_upLeg_jnt', ee=side + '_legEnd_jnt', srp=True) pm.poleVectorConstraint(poleCon, ikHandle) footSpace, footCon = CreateControlHierarchy(side + '_foot_jnt', rootCon) pm.parentConstraint(footCon, ikHandle)
def BasicStretchyIK(_rootJoint, _endJoint, _container = None, _lockMinimumLength = True, _poleVectorObject = None, _scaleCorrectionAttribute = None): from math import fabs containedNodes = [] totalOriginalLength = 0 done = False parent = _rootJoint childJoints = [] # Measure and store length of each joint segment in joint chain while not done: children = pm.listRelatives(parent, children = True) children = pm.ls(children, type = 'joint') # Empty list, break loop if len(children) == 0: done = True # Loop until end of joint chain else: child = children[0] childJoints.append(child) totalOriginalLength += fabs(pm.getAttr("%s.translateX" %child)) parent = child if repr(child) == repr(_endJoint): done = True # Create RP IK on joint chain ikNodes = pm.ikHandle(startJoint = _rootJoint, endEffector = _endJoint, solver = 'ikRPsolver', name = "%s_ikHandle" %_rootJoint) ikNodes[1] = pm.rename(ikNodes[1], "%s_ikEffector" %_rootJoint) ikHandle = ikNodes[0] ikEffector = ikNodes[1] pm.setAttr("%s.visibility" %ikHandle, 0) containedNodes.extend(ikNodes) # Create polevector locator if _poleVectorObject == None: _poleVectorObject = pm.spaceLocator(name = "%s_poleVector" %ikHandle) containedNodes.append(_poleVectorObject) pm.xform(_poleVectorObject, worldSpace = True, absolute = True, translation = pm.xform(_rootJoint, query = True, worldSpace = True, translation = True)) pm.xform(_poleVectorObject, worldSpace = True, relative = True, translation = [0.0, 1.0, 0.0]) pm.setAttr("%s.visibility" %_poleVectorObject, 0) poleVectorConstraint = pm.poleVectorConstraint(_poleVectorObject, ikHandle) containedNodes.append(poleVectorConstraint) # Create root and end locators rootLocator = pm.spaceLocator(name = "%s_rootPosLocator" %_rootJoint) rootLocator_pointConstraint = pm.pointConstraint(_rootJoint, rootLocator, maintainOffset = False, name = "%s_pointConstraint" %rootLocator) endLocator = pm.spaceLocator(name = "%s_endPosLocator" %_rootJoint) pm.xform(endLocator, worldSpace = True, absolute = True, translation = pm.xform(ikHandle, query = True, worldSpace = True, translation = True)) ikHandle_pointConstraint = pm.pointConstraint(endLocator, ikHandle, maintainOffset = False, name = "%s_pointConstraint" %endLocator) containedNodes.extend([rootLocator, endLocator, rootLocator_pointConstraint, ikHandle_pointConstraint]) pm.setAttr("%s.visibility" %rootLocator, 0) pm.setAttr("%s.visibility" %endLocator, 0) # Create distance between node between locators rootLocatorWithoutNamespace = StripAllNamespaces(rootLocator)[1] endLocatorWithoutNamespace = StripAllNamespaces(endLocator)[1] moduleNamespace = StripAllNamespaces(_rootJoint)[0] distNode = pm.shadingNode('distanceBetween', asUtility = True, name = "%s:distBetween_%s_%s" %(moduleNamespace, rootLocatorWithoutNamespace, endLocatorWithoutNamespace)) containedNodes.append(distNode) pm.connectAttr("%sShape.worldPosition[0]" %rootLocator, "%s.point1" %distNode) pm.connectAttr("%sShape.worldPosition[0]" %endLocator, "%s.point2" %distNode) scaleAttr = "%s.distance" %distNode # Divide distance by total original length scaleFactor = pm.shadingNode('multiplyDivide', asUtility = True, name = "%s_scaleFactor" %ikHandle) containedNodes.append(scaleFactor) pm.setAttr("%s.operation" %scaleFactor, 2) # divide pm.connectAttr(scaleAttr, "%s.input1X" %scaleFactor) pm.setAttr("%s.input2X" %scaleFactor, totalOriginalLength) translationDriver = "%s.outputX" %scaleFactor # Connect joint to stretchy calculations for joint in childJoints: multNode = pm.shadingNode('multiplyDivide', asUtility = True, name = "%s_scaleMultiply" %joint) containedNodes.append(multNode) pm.setAttr("%s.input1X" %multNode, pm.getAttr("%s.translateX" %joint)) pm.connectAttr(translationDriver, "%s.input2X" %multNode) pm.connectAttr("%s.outputX" %multNode, "%s.translateX" %joint) if _container != None: AddNodeToContainer(_container, containedNodes, _includeHierarchyBelow = True) returnDict = {} returnDict["ikHandle"] = ikHandle returnDict["ikEffector"] = ikEffector returnDict["rootLocator"] = rootLocator returnDict["endLocator"] = endLocator returnDict["poleVectorObject"] = _poleVectorObject returnDict["ikHandle_pointConstraint"] = ikHandle_pointConstraint returnDict["rootLocator_pointConstraint"] = rootLocator_pointConstraint return returnDict
def ikLimb( self, *args ): print 'ehm_leg........................ikLimb' #=============================================================================== # duplicate main leg joints and rename IK joints self.IKJnts = pm.duplicate (self.upLegJnt ) pm.select (self.IKJnts[0]) self.IKJnts = SearchReplaceNames ( "jnt", "IK_jnt", self.IKJnts[0] ) #=============================================================================== # create ik handles self.legIKStuff = pm.ikHandle( sj = self.IKJnts[0], ee = self.IKJnts[2], solver = "ikRPsolver" ) pm.rename (self.legIKStuff[0] , (self.side + "_leg_ikh") ) #=============================================================================== # distance nodes for stretching purpose self.IKLegDist = pm.distanceDimension ( sp = self.upLegPos , ep = self.anklePos ) self.IKupLegDist = pm.distanceDimension ( sp = self.upLegPos , ep = self.kneePos ) self.IKKneeDist = pm.distanceDimension ( sp = self.kneePos , ep = self.anklePos ) self.IKLegDistT = pm.listRelatives ( self.IKLegDist , p=True)[0] self.IKupLegDistT = pm.listRelatives ( self.IKupLegDist , p=True)[0] self.IKKneeDistT = pm.listRelatives ( self.IKKneeDist , p=True)[0] #=============================================================================== # find the leg locs from distance shape node self.IKlegDistLocs = pm.listConnections (self.IKLegDist , plugs=False) self.IKKneeDistLocs = pm.listConnections (self.IKKneeDist , plugs=False) pm.rename (self.IKlegDistLocs[0] , self.side + "_upLeg_dist_loc" ) pm.rename (self.IKlegDistLocs[1] , self.side + "_ankle_dist_loc" ) pm.rename (self.IKKneeDistLocs[0] , self.side + "_knee_dist_loc" ) #=============================================================================== # parent ikHandle to ankle loc pm.parent ( self.legIKStuff[0] , self.IKKneeDistLocs[1] ) #=============================================================================== # make ik joints stretchy defaultIKLegLen = pm.getAttr ( self.IKupLegDist.distance ) + pm.getAttr ( self.IKKneeDist.distance ) self.IKLeg_stretch_mdn = pm.createNode ("multiplyDivide" , n = self.side + "_IKLeg_stretch_mdn" ) pm.setAttr ( self.IKLeg_stretch_mdn.input2X, defaultIKLegLen ) self.IKLegDist.distance >> self.IKLeg_stretch_mdn.input1X pm.setAttr ( self.IKLeg_stretch_mdn.operation, 2 ) self.IKLeg_stretch_cnd = pm.createNode ("condition" , n = self.side + "_IKLeg_stretch_cnd") self.IKLegDist.distance >> self.IKLeg_stretch_cnd.firstTerm pm.setAttr ( self.IKLeg_stretch_cnd.secondTerm , defaultIKLegLen ) pm.setAttr ( self.IKLeg_stretch_cnd.operation , 2 ) self.IKLeg_stretch_mdn.outputX >> self.IKLeg_stretch_cnd.colorIfTrueR #================================================================================ # Knee Lock pm.addAttr ( self.IKKneeDistLocs[0] ,dv = 0 ,min=0 ,max=10 , keyable = True , ln = "kneeLock" , at = "double") defaultIKupLegLen = pm.getAttr ( self.IKupLegDist.distance ) self.IKupLeg_kneeLock_mdn = pm.createNode ("multiplyDivide" , n = self.side + "_IKupLeg_kneeLock_mdn" ) pm.setAttr ( self.IKupLeg_kneeLock_mdn.input2X, defaultIKupLegLen ) self.IKupLegDist.distance >> self.IKupLeg_kneeLock_mdn.input1X pm.setAttr ( self.IKupLeg_kneeLock_mdn.operation, 2 ) defaultIKKneeLen = pm.getAttr ( self.IKKneeDist.distance ) self.IKKnee_kneeLock_mdn = pm.createNode ("multiplyDivide" , n = self.side + "_IKKnee_kneeLock_mdn" ) pm.setAttr ( self.IKKnee_kneeLock_mdn.input2X, defaultIKKneeLen ) self.IKKneeDist.distance >> self.IKKnee_kneeLock_mdn.input1X pm.setAttr ( self.IKKnee_kneeLock_mdn.operation, 2 ) #================================================================================ # make kneeLock more animation friendly by dividing it by 10 self.IKLeg_kneeLockAnimFriend_mdn = pm.createNode ("multiplyDivide" , n = self.side + "_IKLeg_kneeLockAnimFriend_mdn" ) pm.setAttr ( self.IKLeg_kneeLockAnimFriend_mdn.input2X, 10 ) pm.setAttr ( self.IKLeg_kneeLockAnimFriend_mdn.operation, 2 ) self.IKKneeDistLocs[0].attr ( "kneeLock" ) >> self.IKLeg_kneeLockAnimFriend_mdn.input1X #================================================================================ # conncet result of stretch and knee lock to joint with a blend switch on the knee locator self.upLeg_stretchKneeLock_bta = pm.createNode ("blendTwoAttr" , n = self.side + "_upLeg_stretchKneeLock_bta" ) self.IKLeg_kneeLockAnimFriend_mdn.outputX >> self.upLeg_stretchKneeLock_bta.attributesBlender self.IKLeg_stretch_cnd.outColorR >> self.upLeg_stretchKneeLock_bta.input[0] self.IKupLeg_kneeLock_mdn.outputX >> self.upLeg_stretchKneeLock_bta.input[1] self.knee_stretchKneeLock_bta = pm.createNode ("blendTwoAttr" , n = self.side + "_knee_stretchKneeLock_bta" ) self.IKLeg_kneeLockAnimFriend_mdn.outputX >> self.knee_stretchKneeLock_bta.attributesBlender self.IKLeg_stretch_cnd.outColorR >> self.knee_stretchKneeLock_bta.input[0] self.IKKnee_kneeLock_mdn.outputX >> self.knee_stretchKneeLock_bta.input[1] self.upLeg_stretchKneeLock_bta.output >> self.IKJnts[0].scaleX self.knee_stretchKneeLock_bta.output >> self.IKJnts[1].scaleX #================================================================================ # force leg distance dimentions to be scalable by mainCtrl DistGlobalScale (mainCtrl=self.mainCtrl , dist=self.IKLegDist) DistGlobalScale (mainCtrl=self.mainCtrl , dist=self.IKupLegDist) DistGlobalScale (mainCtrl=self.mainCtrl , dist=self.IKKneeDist) # create IK ankle control curve with transforms of the ankle joint self.ankleIKCtrl = CubeCrv( self.legSize*1.5 , self.side + "_ankle_IK_ctrl" ) pm.select ( self.ankleIKCtrl ) self.ankleIKCtrlZero = ZeroGrp()[0] pm.parent ( self.ankleIKCtrlZero , self.IKJnts[2] ) self.ankleIKCtrlZero.translate.set( 0,0,0 ) # self.ankleIKCtrlZero.rotate.set( 0,0,0 ) pm.parent ( self.ankleIKCtrlZero , w=True ) pm.parent ( self.IKlegDistLocs[1] , self.ankleIKCtrl ) #============================================================================ # add attributes to leg_ctrl pm.addAttr ( self.ankleIKCtrl , ln = "stretch_off_on" , at = "double" , min = 0 , max = 1 , dv = 1 , k = True ) pm.addAttr ( self.ankleIKCtrl , ln = "roll" , at = "double" , min = -10 , max = 10 , dv = 0 , k = True ) pm.addAttr ( self.ankleIKCtrl , ln = "toe" , at = "double" , min = -10 , max = 10 , dv = 0 , k = True ) pm.addAttr ( self.ankleIKCtrl , ln = "side_to_side" , at = "double" , min = -10 , max = 10 , dv = 0 , k = True ) #============================================================================ # create foot ik handles self.toeIKStuff = pm.ikHandle( sj = self.IKJnts[2], ee = self.IKJnts[3], solver = "ikSCsolver" ) pm.rename(self.toeIKStuff[0], self.side + "_toe_ikh") self.toeEndIKStuff = pm.ikHandle( sj = self.IKJnts[3], ee = self.IKJnts[4], solver = "ikSCsolver" ) pm.rename(self.toeEndIKStuff[0], "_toe_end_ikh") #============================================================================ # foot ik groups and set driven keys self.heelUpSdk = pm.group ( self.toeIKStuff[0] , self.IKlegDistLocs[1] , n = self.side + "_heel_up_sdk" ) pm.xform ( os= True , piv = self.toePos ) self.toeSdk = pm.group( self.toeEndIKStuff[0] , n = self.side + "_toe_sdk" ) pm.xform ( os= True , piv = self.toePos ) self.tipSdk = pm.group ( self.heelUpSdk , self.toeSdk , n = self.side + "_tip_sdk" ) pm.xform ( os= True , piv = ( self.toeEndPos[0] , 0 , self.toeEndPos[2] ) ) self.heelSdk = pm.group ( self.tipSdk , n = self.side + "_heel_sdk" ) pm.xform ( os= True , piv = ( self.heelPos[0] , 0 , self.heelPos[2] ) ) self.inFootSdk = pm.group ( self.heelSdk, n = self.side + "_in_foot_sdk" ) pm.xform ( os= True , piv = ( self.inPivPos[0] , 0 , self.inPivPos[2] ) ) self.outFootSdk = pm.group ( self.inFootSdk , n = self.side + "_out_foot_sdk" ) pm.xform ( os= True , piv = ( self.outPivPos[0] , 0 , self.outPivPos[2] ) ) pm.parent ( self.outFootSdk , self.ankleIKCtrl ) #============================================================================ # foot set driven keys # toe set driven keys pm.setDrivenKeyframe ( self.toeSdk.rotateX , currentDriver = self.ankleIKCtrl.toe , dv = 0 , v = 0 ) pm.setDrivenKeyframe ( self.toeSdk.rotateX , currentDriver = self.ankleIKCtrl.toe , dv = 10 , v = -45 ) pm.setDrivenKeyframe ( self.toeSdk.rotateX , currentDriver = self.ankleIKCtrl.toe , dv = -10 , v = 70 ) # roll set driven keys pm.setDrivenKeyframe ( self.heelSdk.rotateX , currentDriver = self.ankleIKCtrl.roll , dv = 0 , v = 0 ) pm.setDrivenKeyframe ( self.tipSdk.rotateX , currentDriver = self.ankleIKCtrl.roll , dv = 0 , v = 0 ) pm.setDrivenKeyframe ( self.heelUpSdk.rotateX , currentDriver = self.ankleIKCtrl.roll , dv = 0 , v = 0 ) pm.setDrivenKeyframe ( self.heelSdk.rotateX , currentDriver = self.ankleIKCtrl.roll , dv = 10 , v = -30 ) pm.setDrivenKeyframe ( self.tipSdk.rotateX , currentDriver = self.ankleIKCtrl.roll , dv = -10 , v = 45 ) pm.setDrivenKeyframe ( self.heelUpSdk.rotateX , currentDriver = self.ankleIKCtrl.roll , dv = -10 , v = 0 ) pm.setDrivenKeyframe ( self.tipSdk.rotateX , currentDriver = self.ankleIKCtrl.roll , dv = -5 , v = 0 ) pm.setDrivenKeyframe ( self.heelUpSdk.rotateX , currentDriver = self.ankleIKCtrl.roll , dv = -5 , v = 30 ) #================================================================================ # create IK knee control curve self.kneeIKCtrl = SoftSpiralCrv( self.legSize , self.side + "_knee_IK_ctrl" ) if self.side == "R" : self.kneeIKCtrl.scale.scaleY.set (-1) pm.makeIdentity (self.kneeIKCtrl , apply = True , t = 1 , r = 1 , s = 1 , n = 0) pm.select ( self.kneeIKCtrl ) self.kneeIKCtrlZO = ZeroGrp() pm.parent ( self.kneeIKCtrlZO[0] , self.IKJnts[1] ) self.kneeIKCtrlZO[0].translate.set( 0,0,0 ) #self.kneeIKCtrlZO[0].rotate.set( 0,0,0 ) pm.parent ( self.kneeIKCtrlZO[0] , w=True ) pm.parent ( self.IKKneeDistLocs[0] , self.kneeIKCtrl ) # direction of the knee ctrl is defined here. ???????????????????????????????? self.kneeIKCtrlZO[1].translate.set (0,0, self.legSize*3) pm.poleVectorConstraint( self.IKKneeDistLocs[0] , self.legIKStuff[0] ) #=========== # pv guide curve self.PVGuideCrv = pm.curve ( d = 1 , p = ( (self.kneePos) , (0,0,0 ) ) , k = (1,2) , name = self.side + "_PV_guide_crv" ) self.PVGuideStartJnt =pm.joint ( p = (self.kneePos) , name = ( self.side + "_PV_guide_start_jnt" ) ) pm.select (cl=True) self.PVGuideEndJnt =pm.joint ( p = (0,0,0) , name = ( self.side + "_PV_guide_end_jnt" ) ) pm.skinCluster( self.PVGuideCrv , self.PVGuideStartJnt , self.PVGuideEndJnt , toSelectedBones = True ) pm.parent (self.PVGuideEndJnt , self.kneeIKCtrl) self.PVGuideEndJnt.translate.set(0,0,0) pm.setAttr ( self.PVGuideCrv.overrideEnabled , True) pm.setAttr ( self.PVGuideCrv.overrideDisplayType , True) pm.setAttr ( self.PVGuideCrv.inheritsTransform , False) LockHideAttr ( objs=self.PVGuideStartJnt , attrs="vv") LockHideAttr ( objs=self.PVGuideEndJnt , attrs="vv") #================================================================================ # if just ik leg is needed then delete leg joints and us ik joints as leg joints # this way we won't have extra result joint, just ik joints will remain in the scene if self.FKIKMode == "IK" : pm.delete (self.upLegJnt) self.upLegJnt = self.IKJnts[0] self.kneeJnt = self.IKJnts[1] self.ankleJnt = self.IKJnts[2] self.toeJnt = self.IKJnts[3]
def RigIK( jnts=None, side='L', ctrlSize=1.0, mode='arm', characterMode='biped',mirrorMode=False,poleVectorTransform=None,footRotate=None,rigHandOrFoot=False ): # find color of the ctrls color = 'y' if side == 'L': color = 'r' elif side == 'R': color = 'b' # biped mode # ----------------------------------------------------------- if characterMode=='biped': # biped inputs check if not jnts: jnts = pm.ls(sl=True) if not len(jnts) == 4 : pm.error( 'ehm_tools...rigIK: (biped mode) select uparm, elbow, hand and hend end joints.' ) # check mode - arm or leg if mode=='arm': limbName = 'hand' secondLimb = 'elbow' elif mode=='leg': limbName = 'foot' secondLimb = 'knee' else: pm.error('ehm_tools...rigIK: mode argument must be either "arm" or "leg"!') # start rigging biped uparmJnt = jnts[0] elbowJnt = jnts[1] handJnt = jnts[2] handEndJnt = jnts[3] # find control size if mode=='arm': ctrlSize = Dist( uparmJnt, elbowJnt )* 0.4 * ctrlSize elif mode=='leg': ctrlSize = Dist( uparmJnt, elbowJnt )* 0.3 * ctrlSize # find arm limbs position uparmPos = pm.xform(uparmJnt,q=True,t=True,ws=True) elbowPos = pm.xform(elbowJnt,q=True,t=True,ws=True) handPos = pm.xform(handJnt ,q=True,t=True,ws=True) # create ik handle armIKStuff = pm.ikHandle( sj = uparmJnt, ee = handJnt, solver = "ikRPsolver" ) armIK = pm.rename ( armIKStuff[0] , ( side + "_arm_ikh" ) ) # make Ik Stretchy locs, dists = MakeIkStretchy( ikh=armIK , elbowLock=True ) #======================================================================================================== # create and position the IK elbow control curve if mode=='arm': elbowIKCtrl = SoftSpiralCrv ( ctrlSize , '%s_%s_IK_ctrl'%(side,secondLimb) ) # rotate elbowIKCtrl to be seen from side view elbowIKCtrl.rotateZ.set(90) elbowIKCtrl.scaleZ.set(-1) if mirrorMode: ReverseShape( objs=elbowIKCtrl, axis='y') ReverseShape( objs=elbowIKCtrl, axis='z') elif mode=='leg': elbowIKCtrl = SharpSpiralCrv ( ctrlSize , '%s_%s_IK_ctrl'%(side,secondLimb) ) # rotate elbowIKCtrl to be seen from side view elbowIKCtrl.rotate.set(90,90,-90) if mirrorMode: ReverseShape( objs=elbowIKCtrl, axis='y') ReverseShape( objs=elbowIKCtrl, axis='z') pm.makeIdentity( elbowIKCtrl, apply=True ) # give it color Colorize( shapes=elbowIKCtrl.getShape(), color=color ) tmpAim = pm.group( em=True ) if poleVectorTransform: # pole vector position is given elbowIKCtrl.translate.set( poleVectorTransform[0] ) elbowIKCtrl.rotate.set( poleVectorTransform[1] ) else: # pole vector position is NOT given, we'll guess it aimPos = FindPVposition( objs = (uparmJnt,elbowJnt,handJnt) ) if aimPos: # if pole vector position was found by FindPVposition def, we're done :) pm.xform( elbowIKCtrl, ws=True, t = aimPos ) else: # limb is straight pm.delete( pm.pointConstraint( elbowJnt , elbowIKCtrl ) ) # position the elbowIKCtrl if mode=='arm': # find elbow pole vector position and rotation tmpAim.translate.set( elbowPos[0], elbowPos[1], elbowPos[2]-ctrlSize ) # position it slightly behind elbow joint pm.delete( pm.aimConstraint( tmpAim , elbowIKCtrl , upVector = (0,1,0) , aimVector = (0,0,-1) ) ) # rotate elbowIKCtrl to point to tmpAim if mode=='leg': # find knee pole vector position tmpAim.translate.set( elbowPos[0], elbowPos[1], elbowPos[2]+ctrlSize ) # position it slightly behind elbow joint pm.delete( pm.aimConstraint( tmpAim , elbowIKCtrl , upVector = (0,1,0) , aimVector = (0,0,1) ) ) # elbow IK control is in place now, parent elbow loc to it and offset it from arm a bit elbowIKCtrlZeros = ZeroGrp(elbowIKCtrl) pm.parent( locs[1], elbowIKCtrl ) locs[1].translate.set(0,0,0) locs[1].rotate.set(0,0,0) ''' if mode=='arm': elbowIKCtrl.translateZ.set( -ctrlSize*2.0 ) if mode=='leg': elbowIKCtrl.translateZ.set( ctrlSize*2.0 ) ''' # use elbow control curve instead of locator as the pole vector TransferOutConnections( source=locs[1], dest=elbowIKCtrl ) LockHideAttr( objs=elbowIKCtrl, attrs='r') LockHideAttr( objs=elbowIKCtrl, attrs='s') # create pole vector pm.poleVectorConstraint( locs[1], armIK ) #======================================================================================================== # rig hand or foot and position them in the correct place if mode=='arm': # position the hand control handIKCtrl = Circle3ArrowCrv ( ctrlSize , '%s_%s_IK_ctrl'%(side,limbName) ) MatchTransform( force=True, folower=handIKCtrl, lead=handJnt ) if rigHandOrFoot: RigHand( handJnt, handEndJnt, handIKCtrl ) locs[2].setParent( handIKCtrl ) elif mode=='leg': # position the foot control handIKCtrl = CubeCrv ( ctrlSize , '%s_%s_IK_ctrl'%(side,limbName) ) handIKCtrl.translate.set( pm.xform(handJnt, q=True, ws=True, t=True) ) handIKCtrl.rotate.set( footRotate ) if rigHandOrFoot: # rig foot ankleJnt = jnts[2] ballJnt = jnts[3] toeEndJnt = jnts[4] ballPos = pm.xform( jnts[3], q=True, t=True, ws=True ) toeEndPos = pm.xform( jnts[4], q=True, t=True, ws=True ) heelPos = pm.xform( jnts[5], q=True, t=True, ws=True ) outsidePos = pm.xform( jnts[6], q=True, t=True, ws=True ) insidePos = pm.xform( jnts[7], q=True, t=True, ws=True ) # create foot ik handles ankleBallIKStuff = pm.ikHandle( sj = ankleJnt, ee = ballJnt, solver = "ikSCsolver" ) ankleBallIK = pm.rename ( ankleBallIKStuff[0] , ( side + "_ankleBall_ikh" ) ) ballToeEndIKStuff = pm.ikHandle( sj = ballJnt, ee = toeEndJnt, solver = "ikSCsolver" ) ballToeIK = pm.rename ( ballToeEndIKStuff[0] , ( side + "_ballToeEnd_ikh" ) ) # add attributes to foot controler pm.addAttr(handIKCtrl, ln="roll", at='double', min=-10, max=10, dv=0, keyable=True ) pm.addAttr(handIKCtrl, ln="sideToSide", at='double', min=-10, max=10, dv=0, keyable=True ) pm.addAttr(handIKCtrl, ln="toes", at='double', min=-10, max=10, dv=0, keyable=True ) # toe group toeGrp = pm.group( ballToeIK, name='%s_toe_IK_grp'%side ) pm.xform( toeGrp, os=True, piv=( ballPos ) ) # heelUp group heelUpGrp = pm.group( ankleBallIK, locs[2], name='%s_heelUp_IK_grp'%side ) pm.xform( heelUpGrp, os=True, piv=( ballPos ) ) # pivOnToe group outsideGrp = pm.group( toeGrp, heelUpGrp, name='%s_outside_IK_grp'%side ) pm.xform( outsideGrp, os=True, piv=( outsidePos ) ) # pivOnHeel group insideGrp = pm.group( outsideGrp, name='%s_inside_IK_grp'%side ) pm.xform( insideGrp, os=True, piv=( insidePos ) ) # pivOutSide group toeTipGrp = pm.group( insideGrp, name='%s_toeTip_IK_grp'%side ) pm.xform( toeTipGrp, os=True, piv=( toeEndPos ) ) # pivInSide group heelGrp = pm.group( toeTipGrp, name='%s_heel_IK_grp'%side ) pm.xform( heelGrp, os=True, piv=( heelPos ) ) footGrp = pm.group( heelGrp, name='%s_foot_IK_grp'%side) footGrp.setParent( handIKCtrl ) # toe set driven keys pm.setDrivenKeyframe( toeGrp.rotateX, currentDriver=handIKCtrl.toes, itt='linear', ott='linear', driverValue=10 ,value=-90 ) pm.setDrivenKeyframe( toeGrp.rotateX, currentDriver=handIKCtrl.toes, itt='linear', ott='linear', driverValue=-10 ,value=90 ) # roll set driven keys pm.setDrivenKeyframe( heelUpGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=0 ,value=0 ) pm.setDrivenKeyframe( heelUpGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=-5 ,value=45 ) pm.setDrivenKeyframe( heelUpGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=10 ,value=0 ) pm.setDrivenKeyframe( toeTipGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=-5 ,value=0 ) pm.setDrivenKeyframe( toeTipGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=-10 ,value=60 ) pm.setDrivenKeyframe( heelGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=10 ,value=-45 ) pm.setDrivenKeyframe( heelGrp.rotateX, currentDriver=handIKCtrl.roll, itt='linear', ott='linear', driverValue=0 ,value=0 ) # sideToSide set driven keys value = 45 if mirrorMode: value = -45 pm.setDrivenKeyframe( outsideGrp.rotateZ, currentDriver=handIKCtrl.sideToSide, itt='linear', ott='linear', driverValue=0 ,value=0 ) pm.setDrivenKeyframe( outsideGrp.rotateZ, currentDriver=handIKCtrl.sideToSide, itt='linear', ott='linear', driverValue=10 ,value=-value ) pm.setDrivenKeyframe( insideGrp.rotateZ, currentDriver=handIKCtrl.sideToSide, itt='linear', ott='linear', driverValue=0 ,value=0 ) pm.setDrivenKeyframe( insideGrp.rotateZ, currentDriver=handIKCtrl.sideToSide, itt='linear', ott='linear', driverValue=-10 ,value=value ) # delete joint that determine foot's different pivots pm.delete( jnts[-3:] ) # hide extras LockHideAttr( objs=(ankleBallIKStuff,ballToeEndIKStuff) , attrs='vv' ) handIKCtrlZeros = ZeroGrp( handIKCtrl) handIKCtrlZero = handIKCtrlZeros[0] TransferOutConnections( source = locs[2], dest= handIKCtrl ) # colorize hand control Colorize( shapes=handIKCtrl.getShape(), color=color ) # check if joints are mirrored, if so, we must reverse the hand control vertices if mirrorMode: ReverseShape( axis = 'x', objs = handIKCtrl ) # hide extra stuff LockHideAttr( objs=locs, attrs='vv' ) LockHideAttr( objs=dists, attrs='vv' ) ikGrp = pm.group( jnts[0], dists, locs[0], name= '%s_ik_arm'%side ) pm.xform( ikGrp, os=True, piv=(0,0,0) ) # create guide curves for pole vector elbowGuide = GuideCrv( elbowIKCtrl,elbowJnt ) elbowIKCtrl.v >> elbowGuide.getShape().v elbowGuide.setParent( ikGrp ) # clean up pm.delete( tmpAim ) # return return ( handIKCtrl, elbowIKCtrl, jnts, locs, dists, handIKCtrlZeros, elbowIKCtrlZeros, ikGrp ) # quadruped mode # ----------------------------------------------------------- if characterMode=='quadruped': # quadruped inputs check if not jnts: jnts = pm.ls(sl=True) if not len(jnts) == 7 : pm.error( 'ehm_tools...rigIK: (quadruped mode) jnts arguments needs 7 joints.' ) # check mode - arm or leg if mode=='arm': pm.error('ehm_tools...rigIK: quadruped arm is not defined yet!') elif mode=='leg': firstLimbName = 'pelvis' secondLimbName = 'hip' thirdLimbName = 'stifle' forthLimbName = 'hock' fifthLimbName = 'ankle' sixthLimbName = 'hoof' seventhLimbName = 'hoofEnd' else: pm.error('ehm_tools...rigIK: mode argument must be either "arm" or "leg"!') # start rigging the quadruped pelvisJnt = jnts[0] hipJnt = jnts[1] stifleJnt = jnts[2] hockJnt = jnts[3] ankleJnt = jnts[4] hoofJnt = jnts[5] hoofEndJnt = jnts[6] # find arm limbs position pelvisPos = pm.xform( pelvisJnt ,q=True,t=True,ws=True ) hipPos = pm.xform( hipJnt ,q=True,t=True,ws=True ) stiflePos = pm.xform( stifleJnt ,q=True,t=True,ws=True ) hockPos = pm.xform( hockJnt ,q=True,t=True,ws=True ) anklePos = pm.xform( ankleJnt ,q=True,t=True,ws=True ) hoofPos = pm.xform( hoofJnt ,q=True,t=True,ws=True ) hoofEndPos = pm.xform( hoofEndJnt ,q=True,t=True,ws=True ) # find control size ctrlSize = Dist( hipJnt, hockJnt )* 0.2 * ctrlSize # set preferred angle if mode=='arm' : pm.error('ehm_tools...rigIK: quadruped arm is not defined yet!') else: stifleJnt.preferredAngleZ.set( 10 ) hockJnt.preferredAngleZ.set( -10 ) # create ik handle for main joint chain IKstuff = pm.ikHandle( sj = hipJnt, ee = hockJnt, solver = "ikRPsolver" ) ankleIKstuff = pm.ikHandle( sj = hockJnt, ee = ankleJnt, solver = "ikSCsolver" ) # create 3 extra joint chains for making some auto movements on the leg: # chain 1. upper leg, lower leg, foot # - this chain is used for automatic upper leg bending when foot control is moved pm.select(clear=True) autoUpLegJnt_tmp = pm.duplicate( hipJnt )[0] autoJnts_tmp = GetAllChildren( objs=autoUpLegJnt_tmp, childType='joint') autoUpLegJnt = pm.rename( autoJnts_tmp[0], '%s_autoUpLegJnt'%side ) autoLowLegJnt = pm.rename( autoJnts_tmp[1], '%s_autoLowLegJnt'%side ) autoKneeJnt = pm.rename( autoJnts_tmp[2], '%s_autoKneeJnt'%side ) autoKneeEndJnt = pm.rename( autoJnts_tmp[3], '%s_autoKneeEndJnt'%side ) autoIKstuff = pm.ikHandle( sj = autoUpLegJnt, ee = autoKneeEndJnt, solver = "ikRPsolver" ) # chain 2 and 3: # - these chains are needed for automatic pole vector PV = autoPoleVector( baseJnt=hipJnt, endJnt=hockJnt, side=side ) autoPV = autoPoleVector( baseJnt=autoUpLegJnt, endJnt=autoKneeEndJnt, side='L' ) # create automatic pole vector and set the twist parameter pm.poleVectorConstraint( PV[0], IKstuff[0] ) pm.poleVectorConstraint( autoPV[0], autoIKstuff[0] ) if side=='L': IKstuff[0].twist.set( 90 ) autoIKstuff[0].twist.set( 90 ) elif side=='R': IKstuff[0].twist.set( -90 ) autoIKstuff[0].twist.set( -90 ) # parent all ikhandles to auto kneeEnd joint. # now we're controling 3 joint chain ik handle with one joint # which itself is being controled by foot control. IKstuffGrp = pm.group( ankleIKstuff[0], IKstuff[0], PV[1][0] ) pm.xform( os=True, piv=( pm.xform(ankleJnt,q=True,t=True,ws=True) ) ) IKstuffGrp.setParent( autoKneeEndJnt ) autoIKstuffZeros = ZeroGrp( autoIKstuff[0] ) autoPV[1][0].setParent( autoIKstuffZeros[1] ) # make Ik Stretchy locs, dists = MakeIkStretchy( ikh=autoIKstuff[0] , elbowLock=False ) # Finally, parent main upLeg joint to autoUpLegJnt. The purpose of whole auto joint chain pm.parent( locs[0], autoUpLegJnt ) ZeroGrp() pm.parentConstraint( autoUpLegJnt, hipJnt, mo=True ) # create IK hand control if mode=='arm': pm.error('ehm_tools...rigIK: quadruped arm is not defined yet!') else: IKCtrl = CubeCrv ( size=ctrlSize , name= '%s_%s_IK_ctrl'%(side,ankleJnt) ) # position the hand control pm.addAttr( IKCtrl, ln="upLeg_rotation", at='double', keyable=True ) # find color of the ctrls color = 'y' if side == 'L': color = 'r' elif side == 'R': color = 'b' Colorize( shapes=IKCtrl.getShape(), color=color ) # position the hand control if mode=='arm': pm.error('ehm_tools...rigIK: quadruped arm is not defined yet!') else: pm.delete( pm.pointConstraint( ankleJnt , IKCtrl ) ) IKCtrl.rotateY.set( ProjectedAim( objs=(hipJnt,stifleJnt), fullCircle=False )) IKCtrlZeros = ZeroGrp( IKCtrl ) #IKCtrlZero = IKCtrlZeros[0] pm.pointConstraint( IKCtrl, PV[1][0] ) pm.parent ( autoIKstuff[0], locs[2] , IKCtrl ) TransferOutConnections( source = locs[2], dest= IKCtrl ) # check if joints are mirrored, if so, we must reverse the hand control vertices #x = kneeEndJnt.translateX.get() #y = kneeEndJnt.translateY.get() #z = kneeEndJnt.translateZ.get() #if x < 0: # ReverseShape( axis = 'x', objs = IKCtrl ) #elif y < 0: # ReverseShape( axis = 'y', objs = IKCtrl ) #elif z < 0: # ReverseShape( axis = 'z', objs = IKCtrl ) # hide extra stuff LockHideAttr( objs=locs, attrs='vv' ) LockHideAttr( objs=dists, attrs='vv' ) LockHideAttr( objs=PV[0], attrs='vv' ) LockHideAttr( objs=PV[1], attrs='vv' ) LockHideAttr( objs=autoIKstuff, attrs='vv' ) LockHideAttr( objs=autoUpLegJnt, attrs='vv' ) LockHideAttr( objs=PV[2][0], attrs='vv' ) # cleaup outliner ikGrp = pm.group( hipJnt, autoUpLegJnt, PV[2][0], dists, locs[1],PV[1][0], IKCtrlZeros[0], name= '%s_ik_leg'%side ) pm.xform( ikGrp, os=True, piv=(0,0,0) ) # return # return ( IKCtrl, jnts, locs, dists, IKCtrlZeros, ikGrp )
def stretchy_ik(self, root_joint, end_joint, container = None, poleVector_object = None): """ Creates basic stretchy IK """ root_joint = pm.PyNode(root_joint) end_joint = pm.PyNode(end_joint) module_namespace = root_joint.namespace() if poleVector_object != None: poleVector_object = pm.PyNode(poleVector_object) or poleVector_object or pm.ls(sl = True)[2] doNotTouch_grp = pm.group(empty = True, name = module_namespace + root_joint.stripNamespace() + "_doNotTouchGrp") return_nodes = {} child_joints = [] utility_nodes = [] total_orig_length = 0.0 done = False parent = root_joint while not done: # get the child of the parent joint child = parent.getChildren()[0] child_joints.append(child) # get the translateX of the child joint and add the translateX to total_orig_length total_orig_length += fabs(child.translateX.get() ) # parent joint is now equal to the child joint parent = child # if the child joint is equal to the end joint, loops ends if parent == end_joint: done = True ## create and rename all IK handle related objects ikHandle, ikEffector = pm.ikHandle(name = module_namespace + root_joint.stripNamespace() + "_ikHandle", sj = root_joint, ee = end_joint, solver = "ikRPsolver") pm.rename(ikEffector, end_joint + "_effector") # if no poleVector object is given, a space locator is created above the root locator if poleVector_object == None: poleVector_object = pm.spaceLocator(n = ikHandle + '_poleVectorLocator') poleVector_object.visibility.set(0) pm.delete(pm.parentConstraint(root_joint, poleVector_object, maintainOffset = False)) doNotTouch_grp.addChild(poleVector_object) pm.poleVectorConstraint(poleVector_object, ikHandle, name = ikHandle + '_poleVectorLocator') ## create locators at root joint and end joint root_locator = pm.spaceLocator(name = module_namespace + root_joint.stripNamespace() + "_rootLoc") pm.pointConstraint(root_joint, root_locator, maintainOffset = False, n = module_namespace + "_" + root_locator + "_pointConstraint") end_locator = pm.spaceLocator(name = module_namespace + end_joint.stripNamespace() + "_endLoc") pm.xform(end_locator, ws = True, translation = (pm.xform(end_joint, q = True, ws = True, translation = True) ) ) pm.pointConstraint(end_locator, ikHandle, maintainOffset = False, n = module_namespace + end_joint.stripNamespace() + "_pointConstraint") ## add distance between node distance_node = pm.shadingNode("distanceBetween", asUtility = True, name =module_namespace + root_joint.stripNamespace() + "distanceBetween_node") root_locator.getShape().worldPosition.connect(distance_node.point1) end_locator.getShape().worldPosition.connect(distance_node.point2) # the scale factor node determines how much to multiply it against the joint length to get the stretch # setup the scale factor node scaleFactor_node = pm.shadingNode("multiplyDivide", asUtility = True, name = module_namespace + root_joint.stripNamespace() + "_scaleFactor_node") # set operation to divide scaleFactor_node.operation.set(2) scaleFactor_node.input2X.set(total_orig_length) distance_node.distance.connect(scaleFactor_node.input1X) utility_nodes.append(scaleFactor_node) if len(child_joints) == 1: for joint in child_joints: # multiply factor node takes the scale factor and multiplies it with original joint length tmp_multiplyFactor_node = pm.shadingNode("multiplyDivide", asUtility = True, name = module_namespace + root_joint.stripNamespace() + "_multiplyFactor_node") # set node input1X to translateX of joint tmp_multiplyFactor_node.input1X.set(joint.translateX.get() ) scaleFactor_node.outputX.connect(tmp_multiplyFactor_node.input2X) tmp_multiplyFactor_node.outputX.connect(joint.translateX) utility_nodes.append(tmp_multiplyFactor_node) for node in [root_locator, end_locator, ikHandle]: node.visibility.set(0) doNotTouch_grp.addChild(node) if container != None: utils.addNodeToContainer(container, doNotTouch_grp, ihb = True, includeNetwork = True) return_nodes["ikHandle"] = ikHandle return_nodes["ikEffector"] = ikEffector return_nodes["root_locator"] = root_locator return_nodes["end_locator"] = end_locator return_nodes["poleVector_object"] = poleVector_object return_nodes["doNotTouch_grp"] = doNotTouch_grp return_nodes["distance_node"] = distance_node return_nodes["utility_node"] = utility_nodes return return_nodes
def createIK(sel = None, resizeAttr = True, squashAttr = True, hideSystem = False, tmpGrp = None, mirroredJoint = False, ikRoot = None): """ maj: x-- invert pole vector translate z on mirrored joint -- make useable on selection with more or les then three objects -- add anchor """ # check selection if not sel: return ctrlsList = [] ######################################################################## IK simple ikTmp = pm.ikHandle(startJoint=sel[0], endEffector=sel[-1]) ikHandle = ikTmp[0] # create pole vector locator poleVectorLoc = pm.spaceLocator() pm.rename(poleVectorLoc, 'poleVectorLoc') zVal = 1 if not mirroredJoint: zVal = -1 pm.parent(poleVectorLoc, sel[1], r = True) poleVectorLoc.translate.set(0,0, zVal) poleVectorLoc.rotate.set([0, 0, 0]) pm.parent(poleVectorLoc.name(), world=True) # change iksolver to rotate plane solver ikSolver = pm.createNode("ikRPsolver") pm.disconnectAttr("%s.ikSolver" % ikHandle.name()) pm.connectAttr("%s.message" % ikSolver.name(), "%s.ikSolver" % ikHandle.name()) # constrain pole vector pm.poleVectorConstraint(poleVectorLoc, ikHandle, weight=1) PVctrlGrp, PVctrl = helpers.createOneHelper(type = "cube", sel = poleVectorLoc, scale = 0.5, freezeGrp= True, hierarchyParent = "insert") ctrlsList.append(PVctrl) # poleVectorLoc.setParent(PVctrl) PVctrlGrp.setParent(tmpGrp) # rotate du locator a zero # poleVectorLoc.rotate.set([0, 0, 0]) # add ikhandle controller ikCtrlGrp, ikCtrl = helpers.createOneCircle(axis = [1, 0, 0], sel=sel[-1], suf = "_IK_ctrl") ctrlsList.append(ikCtrl) pm.pointConstraint(ikCtrl, ikHandle) ikHandle.setParent(tmpGrp) ikCtrlGrp.setParent(tmpGrp) # add attributes pm.addAttr(ikCtrl, ln="_______" , attributeType="enum", enumName="CTRLS:") pm.addAttr(ikCtrl, ln="followCtrl" , at='double', min=0, max=1, dv = 1) pm.addAttr(ikCtrl, ln="followJoint" , at='double', min=0, max=1, dv = 0) pm.setAttr(ikCtrl._______ , keyable=True, lock=True) pm.setAttr(ikCtrl.followCtrl , keyable=True) pm.setAttr(ikCtrl.followJoint , keyable=True) subFollowNode = pm.createNode('plusMinusAverage') subFollowNode.setAttr("input1D[0]", 1) subFollowNode.setAttr('operation', 2) pm.connectAttr(ikCtrl.followCtrl, subFollowNode.input1D[1], f = True) pm.connectAttr(subFollowNode.output1D, ikCtrl.followJoint, f = True) # create follow orient joint ikOrientLoc = helpers.createOneLoc(sel[2]) ikOrientLoc.setParent(tmpGrp) constrain = pm.orientConstraint(ikCtrl, sel[2], ikOrientLoc) pm.pointConstraint(sel[2], ikOrientLoc) followJoint = pm.duplicate(sel[2], name = ("%s_follow" % sel[2].nodeName()))[0] followJoint.setParent(ikOrientLoc) followJoint.rotate.set(0,0,0) followJoint.translate.set(0,0,0) # clean followJoint orient for attr in pm.listAttr(constrain, visible = True, keyable= True): if 'IKW' in attr: print(attr) pm.connectAttr(ikCtrl.followJoint, '%s.%s' % (constrain,attr)) elif 'ctrlW' in attr: print(attr) pm.connectAttr(ikCtrl.followCtrl, '%s.%s' % (constrain,attr)) ############################################################################################### pole vector multiple parent ############################################################################################ add stretch sur ik pm.addAttr(ikCtrl, ln="stretch" , at='double', min=0, max=1, dv = 0) pm.setAttr(ikCtrl.stretch , keyable=True) # distance hankle knee distSel = [ikRoot, ikCtrl] distShape, locs = helpers.creatDist(sel=distSel) tmpChild = distShape.getParent() distGrp = pm.group(em=True) distGrp.rename('%s_grp' % distShape.nodeName()) tmpChild.setParent(distGrp) for l in locs: l.setParent(distGrp) distGrp.setParent(tmpGrp) # calculate maximum leg size # plusMinusAverage fixedSize_sumNode = pm.createNode('plusMinusAverage') pm.rename(fixedSize_sumNode, 'fixedSize_sum') pm.connectAttr(sel[1].tx, fixedSize_sumNode.input1D[0]) pm.connectAttr(sel[2].tx, fixedSize_sumNode.input1D[1]) # create distance pm.select(distShape) # calculate ratio leg fixed/stretched stretchRatio_div = pm.createNode('multiplyDivide') pm.rename(stretchRatio_div, 'stretchRatio_div') # multiplydivide # connect sum to multiply pm.connectAttr(fixedSize_sumNode.output1D, stretchRatio_div.input2X) # connect distance to divide input1x pm.connectAttr(distShape.distance, stretchRatio_div.input1X) pm.setAttr(stretchRatio_div.operation, 2) # stretch Condition stretchCond = pm.createNode('condition') pm.rename(stretchCond, 'stretch_condition') # condition pm.connectAttr(stretchRatio_div.outputX, stretchCond.firstTerm) pm.setAttr(stretchCond.secondTerm, 1) pm.connectAttr(stretchCond.firstTerm, stretchCond.colorIfTrueR) pm.setAttr(stretchCond.operation, 2) # calculate maj # plusminusAverage stretchMaj_sub = pm.createNode('plusMinusAverage') pm.rename(stretchMaj_sub, 'stretchMaj_sub') pm.connectAttr(stretchCond.outColorR, stretchMaj_sub.input1D[0]) pm.setAttr(stretchMaj_sub.input1D[1], 1) stretchMaj_sub.operation.set(2) # strtch control variator # multiply divide stretchVariation_multi = pm.createNode('multiplyDivide') pm.rename(stretchVariation_multi, 'stretch_Variation_multi') pm.connectAttr(stretchMaj_sub.output1D, stretchVariation_multi.input1X) pm.connectAttr(ikCtrl.stretch, stretchVariation_multi.input2X) # calculate final # plusminusaverage finalStretch_sum = pm.createNode('plusMinusAverage') pm.rename(finalStretch_sum, 'finalStretch_sum') finalStretch_sum.input1D[0].set(1) pm.connectAttr(stretchVariation_multi.outputX, finalStretch_sum.input1D[1]) pm.connectAttr(finalStretch_sum.output1D, sel[0].sx) pm.connectAttr(finalStretch_sum.output1D, sel[1].sx) ####################################################################################### add resize on ik if resizeAttr: pm.addAttr(ikCtrl, ln= "lockElbow" , at='double', min=0, max=1, dv = 0) pm.setAttr(ikCtrl.lockElbow , keyable=True) ####################################################################################### add squash on ik if squashAttr: pm.addAttr(ikCtrl, ln= "squash" , at='double', min=0, max=1, dv = 0) pm.setAttr(ikCtrl.squash , keyable=True) #################################################### System Vis if hideSystem: sel[0].visibility.set(0) poleVectorLoc.visibility.set(0) ikOrientLoc.visibility.set(0) distGrp.visibility.set(0) ikHandle.visibility.set(0) return followJoint, ctrlsList
def rigLimbCmd( prefix='leg_', suffix=None, side=LEFT_SIDE, hasStretch=False, hasFootRoll=False, footRollMode=FOOTROLL_AUTO ): suffix = suffix or ('_l','_r')[side] exp_template = "" labels = { 'control' : prefix + 'control' + suffix, 'aimControl' : prefix + 'aim' + suffix, 'ik' : prefix + 'ik' + suffix, 'ikEnd' : prefix + 'ik_end' + suffix, 'expression' : prefix + 'control' + suffix + '_EXP', 'guideJointIk' : prefix + 'ik_guide_', 'guideJoint' : prefix + 'guide_', 'ikStretch' : prefix + 'ik_stretch' + suffix, 'locStart' : prefix + 'loc_start' + suffix, 'locMid' : prefix + 'loc_mid' + suffix, 'locEnd' : prefix + 'loc_end' + suffix, 'locGuide' : prefix + 'loc_guide' + suffix, 'ikGuide' : prefix + 'ik_guide' + suffix, } try: start_joint, end_joint = pm.ls(sl=1,type="joint") except ValueError: raise ValueError, "Select the start and end joints to setup." mid_joint = end_joint.getParent() parent_joint = start_joint.getParent() unit_scale = start_joint.getRotatePivot(ws=1)[-1] # -- positions and length start_point = start_joint.getRotatePivot(ws=1) * unit_scale end_point = end_joint.getRotatePivot(ws=1) * unit_scale mid_point = mid_joint.getRotatePivot(ws=1) * unit_scale length = start_point.distanceTo( end_point ) # -- Create Control control = createNurbsShape( labels['control'], 'sphere', size=length*.2 ) control2 = createNurbsShape( labels['control'], 'locator', size=length*.3 ) pm.parent( control2.getShape(), control, r=1, s=1 ) pm.delete( control2 ) control.translate.set( end_point ) pm.makeIdentity( control, apply=True, s=0, r=0, t=1, n=0 ) control.addAttr( "ikBlend", at='double', k=1, dv=0, min=0, max=1 ) control.addAttr( "orientBlend", at='double', k=1, dv=0, min=0, max=1 ) # -- Create Aim Control v1 = end_point - start_point v2 = mid_point - start_point v3 = v1.cross( v2 ) v4 = v3.cross( v1 ) aim_point = start_point + ( v4.normal() * length * 1.5 ) aim_control = createNurbsShape( labels['aimControl'], 'arrow', size=length/5 ) pm.xform( aim_control, t=aim_point ) pm.makeIdentity( apply=True, s=0, r=0, t=1, n=0 ) pm.aimConstraint( mid_joint, aim_control, weight=1, aimVector=(0, 0, 1) ) # -- Create Aim Line aim_line = pm.curve( name=labels['aimControl']+'_line', d=1, p=[aim_point, mid_point], k=[0, 1] ) line_cluster0, line_handle0 = pm.cluster( aim_line+'.cv[0]', n=labels['aimControl']+'_line_0', en=1, rel=1 ) line_cluster1, line_handle1 = pm.cluster( aim_line+'.cv[1]', n=labels['aimControl']+'_line_1', en=1, rel=1 ) pm.pointConstraint( aim_control, line_handle0, offset=(0,0,0), weight=1 ) pm.pointConstraint( mid_joint, line_handle1, offset=(0,0,0), weight=1 ) line_group0 = pm.group( line_handle0, name=line_handle0.name() + "_grp" ) line_group1 = pm.group( line_handle1, name=line_handle0.name() + "_grp" ) pm.parent( [aim_line, line_group0, line_group1, aim_control] ) line_group0.v.set(0) line_group1.v.set(0) setAttrs( line_group0, ['t','r','s','v'], lock=1 ) setAttrs( line_group1, ['t','r','s','v'], lock=1 ) setAttrs( aim_line, ['t','r','s','v'], lock=1 ) aim_line.overrideEnabled.set(1) aim_line.overrideDisplayType.set(1) if hasStretch: guide_ik_start = pm.duplicate( start_joint, rc=1 )[0] guide_ik_mid, guide_ik_end = pm.ls( guide_ik_start, dag=1 )[1:3] for n in pm.ls( guide_ik_start, dag=1 ): pm.rename( n, labels['guideJointIk'] + n[:-1] ) guide_start = pm.duplicate( start_joint, rc=1 )[0] guide_mid, guide_end = pm.ls( guide_start, dag=1 )[1:3] for n in pm.ls( guide_start, dag=1 ): pm.rename( n, labels['guideJoint'] + n[:-1] ) parent_group = pm.group( name=labels['ikStretch'], em=1 ) if parent_joint is not None: parent_group.setRotatePivot( parent_joint.getRotatePivot(ws=1) * unit_scale, ws=1 ) pm.parentConstraint( parent_joint, parent_group, weight=1 ) pm.parent( guide_ik_start, guide_start, parent_group ) # -- build a temp joint chain to get loc_mid position loc_start = pm.group( n=labels['locStart'], em=1 ) pm.parent( loc_start, parent_group ) loc_start.setRotatePivot( start_joint.getRotatePivot( ws=1) * unit_scale, ws=1 ) pm.aimConstraint( control, loc_start, weight=1, aimVector=(1,0,0) ) loc_end = pm.group( n=labels['locEnd'], em=1, parent=loc_start ) loc_end.setRotatePivot( start_joint.getRotatePivot( ws=1) * unit_scale, ws=1 ) pm.pointConstraint( control, loc_end, offset=(0,0,0), skip=('y','z'), weight=1 ) pm.select(cl=1) temp_start = pm.joint( p=start_point ) temp_end = pm.joint( p=end_point ) pm.joint( temp_start, edit=1, oj='xyz', secondaryAxisOrient='yup', ch=1 ) pm.pointConstraint( mid_joint, temp_end, offset=(0,0,0), skip=('y','z'), weight=1 ) loc_mid_point = temp_end.getRotatePivot(ws=1) * unit_scale pm.delete( temp_start ) # -- create the mid locator loc_mid = pm.group( n=labels['locMid'], em=1)#spaceLocator() loc_mid.translate.set( loc_mid_point ) pm.makeIdentity( apply=True, s=0, r=0, t=1, n=0 ) pm.pointConstraint( loc_start, loc_mid, mo=1, weight=1 ) pm.pointConstraint( loc_end, loc_mid, mo=1, weight=1 ) # -- create the guide locator loc_guide = pm.group( n=labels['locGuide'], em=1) guide_constraint = pm.pointConstraint( loc_mid, loc_guide, offset=(0,0,0), weight=1 ) pm.pointConstraint( guide_ik_mid, loc_guide, offset=(0,0,0), weight=1 ) pm.parent( loc_mid, loc_guide, parent_group ) guide_ik, guide_ee = pm.ikHandle( sj=guide_ik_start, ee=guide_ik_end, solver="ikRPsolver", dh=1 ) pm.poleVectorConstraint( aim_control, guide_ik, weight=1 ) pm.delete( guide_ik_end ) pm.rename( guide_ik, labels['ikGuide'] ) # -- SET STRETCH BLEND START guide_ik.addAttr( "stretchStart", at='double', k=1 ) guide_ik.stretchStart.set( loc_end.tx.get() ) # -- SET STRETCH BLEND END guide_ik.addAttr( "stretchEnd", at='double', k=1 ) guide_ik.stretchEnd.set( loc_end.tx.get()*1.1 ) # -- SET STRETCH BLEND END guide_ik.addAttr( "stretchFactor", at='double', k=1 ) guide_ik.stretchFactor.set( 0.22 ) # -- setup guide joints pm.aimConstraint( loc_guide, guide_start, weight=1, aimVector=(1,0,0) ) pm.aimConstraint( loc_end, guide_mid, weight=1, aimVector=(1,0,0) ) pm.pointConstraint( loc_guide, guide_mid, offset=(0,0,0), skip=('y','z'), weight=1 ) pm.pointConstraint( loc_end, guide_end, offset=(0,0,0), skip=('y','z'), weight=1 ) pm.parent( guide_ik, loc_end ) pm.parent( guide_ik, control ) # -- add stretch addtributes start_joint.addAttr( "stretch", at='double', k=1, dv=0 ) mid_joint.addAttr( "stretch", at='double', k=1, dv=0 ) control.addAttr( "stretchBlend", at='double', k=1, dv=0, min=0, max=1 ) # -- build the expression exp_template += EXP_STRETCH \ % { 'guide_ik' : guide_ik, 'loc_end' : loc_end, 'constraint' : guide_constraint, # -- we only need these names for the constraint attribute names 'guide_ik_mid' : guide_ik_mid.split('|')[-1], 'loc_mid' : loc_mid.split('|')[-1], 'control' : control, 'start_joint' : start_joint, 'mid_joint' : mid_joint, 'end_joint' : end_joint, 'guide_mid' : guide_mid, 'guide_end' : guide_end, } # -- make things look pretty for n in pm.ls( [ parent_group, guide_ik ], dag=1 ): n.visibility.set(0) for obj in guide_end.getChildren( type='joint' ): try: pm.delete( obj ) except: pass # -- hook up the original joints main_ik, main_ee = pm.ikHandle( sj=start_joint, ee=end_joint, solver="ikRPsolver", dh=1 ) pm.poleVectorConstraint( aim_control, main_ik, weight=1 ) pm.rename( main_ik, labels['ik'] ) end_ik, end_ee = pm.ikHandle( sj=end_joint, ee=end_joint.getChildren(type='joint')[0], solver="ikRPsolver", dh=1 ) pm.rename( end_ik, labels['ikEnd'] ) pm.parent( main_ik, end_ik, control ) # -- fill out the expression template exp_template += EXP_IKFK + EXP_VIS exp_str = exp_template \ % { #'guide_ik' : guide_ik, #'loc_end' : loc_end, #'constraint' : guide_constraint, #we only need these names for the constraint attribute names #'guide_ik_mid' : guide_ik_mid.split('|')[-1], #'loc_mid' : loc_mid.split('|')[-1], 'control' : control, 'start_joint' : start_joint, 'mid_joint' : mid_joint, 'end_joint' : end_joint, #'guide_mid' : guide_mid, #'guide_end' : guide_end, 'main_ik' : main_ik, 'end_ik' : end_ik, 'shape1' : control.getChildren(type="nurbsCurve")[0], 'shape2' : control.getChildren(type="nurbsCurve")[1], } pm.expression( s=exp_str, o=control, n=labels['expression'], a=1, uc='all' ) if hasFootRoll: rigFootRoll( end_joint, control, prefix, suffix, side=side, footRollMode=footRollMode ) resetIkSetupCmd(end_joint, control) resetIkSetupCmd(start_joint, aim_control) # -- make things look pretty for n in pm.ls( control, dag=1, type="transform" )[1:]: if n.type() != "transform": n.visibility.set(0) setAttrs( control, ['sx','sy','sz'], channelBox=0, keyable=0, lock=1 ) setAttrs( aim_control, ['rx','ry','rz','sx','sy','sz'], channelBox=0, keyable=0, lock=1 ) pm.setAttr(control.v, keyable=0 ) pm.setAttr(aim_control.v, keyable=0 ) addToSet( [control, aim_control], 'controlsSet' ) pm.select( [control, aim_control], r=1 ) pm.color( ud=(CntlColors.left, CntlColors.right)[side] ) control.displayHandle.set(1) pm.select( control, r=1 ) pm.reorder( control.getShape(), back=1 ) return [ control, aim_control ]
def build(self, _bOrientIkCtrl=True, *args, **kwargs): super(IK, self).build(*args, **kwargs) # Duplicate input chain (we don't want to move the hierarchy) # Todo: implement a duplicate method in omtk.libs.libPymel.PyNodeChain # Create ikChain and fkChain self._chain_ik = pymel.duplicate(self.input, renameChildren=True, parentOnly=True) for oInput, oIk, in zip(self.input, self._chain_ik): pNameMap = NameMap(oInput, _sType='rig') oIk.rename(pNameMap.Serialize('ik')) self._chain_ik[0].setParent(self._oParent) # Trick the IK system (temporary solution) oChainS = self._chain_ik[0] oChainE = self._chain_ik[self.iCtrlIndex] # Compute chain length self._chain_length = self._chain.length() # Compute swivel position p3SwivelPos = self.calc_swivel_pos() # Create ikChain grp_ikChain = pymel.createNode('transform', name=self._pNameMapRig.Serialize('ikChain'), parent=self.grp_rig) grp_ikChain.setMatrix(oChainS.getMatrix(worldSpace=True), worldSpace=True) oChainS.setParent(grp_ikChain) # Create ikEffector self._oIkHandle, oIkEffector = pymel.ikHandle(startJoint=oChainS, endEffector=oChainE, solver='ikRPsolver') self._oIkHandle.rename(self._pNameMapRig.Serialize('ikHandle')) self._oIkHandle.setParent(grp_ikChain) oIkEffector.rename(self._pNameMapRig.Serialize('ikEffector')) # Create ctrls if not isinstance(self.ctrlIK, CtrlIk): self.ctrlIK = CtrlIk() self.ctrlIK.build() #self.ctrlIK = CtrlIk(_create=True) self.ctrlIK.setParent(self.grp_anm) self.ctrlIK.rename(self._pNameMapAnm.Serialize('ik')) self.ctrlIK.offset.setTranslation(oChainE.getTranslation(space='world'), space='world') if _bOrientIkCtrl is True: self.ctrlIK.offset.setRotation(oChainE.getRotation(space='world'), space='world') if not isinstance(self.ctrl_swivel, CtrlIkSwivel): self.ctrl_swivel = CtrlIkSwivel() self.ctrl_swivel.build() #self.ctrl_swivel = CtrlIkSwivel(_oLineTarget=self.input[1], _create=True) self.ctrl_swivel.setParent(self.grp_anm) self.ctrl_swivel.rename(self._pNameMapAnm.Serialize('ikSwivel')) self.ctrl_swivel.offset.setTranslation(p3SwivelPos, space='world') self.ctrl_swivel.offset.setRotation(self.input[self.iCtrlIndex - 1].getRotation(space='world'), space='world') self.swivelDistance = self._chain_length # Used in ik/fk switch # # Create softIk node and connect user accessible attributes to it. # oAttHolder = self.ctrlIK fnAddAttr = functools.partial(libAttr.addAttr, hasMinValue=True, hasMaxValue=True) attInRatio = fnAddAttr(oAttHolder, longName='SoftIkRatio', niceName='SoftIK', defaultValue=0, minValue=0, maxValue=.5, k=True) attInStretch = fnAddAttr(oAttHolder, longName='Stretch', niceName='Stretch', defaultValue=0, minValue=0, maxValue=1.0, k=True) rig_softIkNetwork = SoftIkNode() rig_softIkNetwork.build() pymel.connectAttr(attInRatio, rig_softIkNetwork.inRatio) pymel.connectAttr(attInStretch, rig_softIkNetwork.inStretch) pymel.connectAttr(grp_ikChain.worldMatrix, rig_softIkNetwork.inMatrixS) pymel.connectAttr(self.ctrlIK.worldMatrix, rig_softIkNetwork.inMatrixE) rig_softIkNetwork.inChainLength.set(self._chain_length) # Constraint effector attOutRatio = rig_softIkNetwork.outRatio attOutRatioInv = libRigging.CreateUtilityNode('reverse', inputX=rig_softIkNetwork.outRatio).outputX pymel.select(clear=True) pymel.select(self.ctrlIK, grp_ikChain, self._oIkHandle) constraint = pymel.pointConstraint() constraint.rename(constraint.name().replace('pointConstraint', 'softIkConstraint')) pymel.select(constraint) weight_inn, weight_out = constraint.getWeightAliasList() pymel.connectAttr(attOutRatio, weight_inn) pymel.connectAttr(attOutRatioInv, weight_out) # Constraint joints stretch attOutStretch = rig_softIkNetwork.outStretch num_jnts = len(self._chain_ik) for i in range(1, num_jnts): obj = self._chain_ik[i] pymel.connectAttr( libRigging.CreateUtilityNode('multiplyDivide', input1X=attOutStretch, input1Y=attOutStretch, input1Z=attOutStretch, input2=obj.t.get()).output, obj.t, force=True) # Connect rig -> anm pymel.orientConstraint(self.ctrlIK, oChainE, maintainOffset=True) pymel.poleVectorConstraint(self.ctrl_swivel, self._oIkHandle) # Connect to parent if libPymel.is_valid_PyNode(self.parent): pymel.parentConstraint(self.parent, grp_ikChain, maintainOffset=True) for source, target in zip(self._chain_ik, self._chain): pymel.parentConstraint(source, target)
def pvc_ik(self, controller, pvc_target=None): """ Pole Vector IK """ # Parameter validation if not isinstance(controller, pm.nodetypes.Transform): raise ValueError("Bad data type for parameter 'controller'") if pvc_target and not isinstance(pvc_target, pm.nodetypes.Transform): raise ValueError("Bad data type for parameter 'pvc_target'") # Get position vectors for all joints in limb vectors = [ om.MVector(pm.joint(x, q=True, p=True, a=True)) for x in self.joints ] # Define a line between first and last joint line = utils.vectors.Line(vectors[0], vectors[-1]) # Get an average position for all joints excluding first and last in list. avg = utils.vectors.average(vectors[1:-1]) # Get world position along line closest to avg vector. mid = line.closest_point_along_line_to(avg) print("Mid Position: {}".format(mid)) print("Avg Position: {}".format(avg)) # Get a direction along which to place pvc target. direction = om.MVector(avg - mid).normal() print("Dir Pre: {}".format(direction)) # Add magnitude to vector, either closest distance to our line, or length of our limb. if pvc_target: direction *= line.distance_to( pm.xform(pvc_target, q=True, ws=True, t=True)) else: direction *= self.length() print("Dir Post: {}".format(direction)) # TODO Debug Position, am I starting from first joint? # Get position to place our PVC Target position = om.MVector(avg + direction) print("Position: {}".format(position)) if pvc_target: # Position the pvc target controller, pm.xform(pvc_target, ws=True, t=position) # Create the srt buffer group to zero out the controller ctrl.srt_buffer(target=pvc_target, child=pvc_target) else: pvc_target = pm.spaceLocator(p=position, a=True, name="{}_pvc_target".format( self.name)) pm.xform(pvc_target, centerPivots=True) self.ikHandle = pm.ikHandle(name='{}_ikHandle'.format( self.joints[-1].nodeName()), sj=self.joints[0], ee=self.joints[-1], solver='ikRPsolver')[0] pm.poleVectorConstraint(pvc_target, self.ikHandle) pm.parent(self.ikHandle, controller)
def __armIK__(self): self.armIk = self.__armPlaceJnt__(parent=self.gp['arm'], prefix='ik') # create ik controlor ikCtrl = arShapeBiblio.circleX(name=self.wristTPL.replace('_TPLjnt', 'Ctrl'), color=self.colorOne, parent=self.gp['arm']) matrixConstrain.snapObject(self.armIk[-1], ikCtrl) xfm.__xfm__(ikCtrl) # orient constrain to control the latest joint on arm pmc.orientConstraint(ikCtrl, self.armIk[-1], name=self.armIk[-1].name()+'_orCst', maintainOffset=False) # create ik handle ikHand = pmc.ikHandle( name=self.armTPL[0].name().replace('_TPLjnt', 'ikHand') ,startJoint=self.armIk[0], endEffector=self.armIk[-1], priority=1, weight=1.0, solver='ikRPsolver', snapHandleFlagToggle=False ) ikHand[1].rename(self.wristTPL.replace('_TPLjnt', 'ikEff')) ikHand[0].setParent(self.gp['tool']) ikHand[0].visibility.set(False) # constrain between the controlor and the handle pmc.pointConstraint(ikCtrl, ikHand[0], name=ikHand[0].name()+'_ptCst', maintainOffset=False) # pole vector pvCtrl = arShapeBiblio.diamondSpike(name=self.armTPL[0].replace('_TPLjnt', '_pv'), color=self.colorOne, parent=self.gp['ctrl']) # place pvCtrl.setTransformation( rig.matrix.vecToMat( dir=(self.wristTPL.getTranslation(space='world') - self.armTPL[0].getTranslation(space='world')), up=(((self.armTPL[0].getTranslation(space='world') + self.wristTPL.getTranslation(space='world'))/2.0) - self.armTPL[len(self.armTPL)/2].getTranslation(space='world')), pos=self.armTPL[len(self.armTPL)/2].getTranslation(space='world'), order='xyz' ) ) pvCtrl.translateBy([0,-((self.length / len(self.armTPL)) * 1.5),0], space='preTransform') pvCtrl.rotate.set([0,0,0]) xfm.__xfm__(pvCtrl, suffix='_grp') # clean channel clean.__lockHideTransform__(pvCtrl, channel=['r', 's']) # add constrain pmc.poleVectorConstraint(pvCtrl, ikHand[0], name=pvCtrl.name()+'_pvCst') # stretch part # create distance tools distGrp = pmc.createNode('transform', name=self.name+'_dist', parent=self.gp['dist']) dist = pmc.createNode('distanceDimShape', parent=distGrp) # locators distStart = pmc.createNode('locator') distEnd = pmc.createNode('locator') distStart.getParent().rename(self.arm[0].name()+'_distStart') distEnd.getParent().rename(self.arm[-1].name()+'_distEnd') distStart.getParent().setParent(self.gp['dist']) distEnd.getParent().setParent(self.gp['dist']) distStart.worldPosition[0] >> dist.startPoint distEnd.worldPosition[0] >> dist.endPoint distStart = distStart.getParent() distEnd = distEnd.getParent() # hide dist.getParent().visibility.set(False) distStart.visibility.set(False) distEnd.visibility.set(False) # constrain pmc.pointConstraint(self.armIk[0], distStart, name=distStart.name()+'_ptCst', maintainOffset=False) pmc.pointConstraint(ikCtrl, distEnd, name=distEnd.name()+'_ptCst', maintainOffset=False) # get global scale # check if the plug in decompose matrix is load pmc.loadPlugin('decomposeMatrix', quiet=True) decoMat = pmc.createNode('decomposeMatrix', name=self.name + '_decoMat', skipSelect=True) self.gp['scale'].worldMatrix >> decoMat.inputMatrix # multiply the global scale by the length globalScaleMult = pmc.createNode('multDoubleLinear', name=self.name+'GlobalScale_mlt') decoMat.outputScaleX >> globalScaleMult.input1 globalScaleMult.input2.set(self.length) # divide current length by the defaut one self.distMult = pmc.createNode('multiplyDivide', name=dist.getParent().name()+'_mlt') self.distMult.operation.set(2) dist.distance >> self.distMult.input1X globalScaleMult.output >> self.distMult.input2X # clamp distClamp = pmc.createNode('clamp', name=dist.getParent().name()+'_clp') distClamp.minR.set(1.0) distClamp.maxR.set(1.0) self.distMult.outputX >> distClamp.inputR # stretch factor distFactorMult = pmc.createNode('multDoubleLinear', name=dist.getParent().name()+'Factor_mlt') distClamp.outputR >> distFactorMult.input1 # condition distCond = pmc.createNode('condition', name=dist.getParent().name()+'_cdt') distCond.secondTerm.set(1.0) distCond.colorIfFalseR.set(1.0) distFactorMult.output >> distCond.colorIfTrueR # create smooth Ik anim = pmc.createNode('animCurveUU', name=self.name+'_crv') pmc.setKeyframe(anim, float=0.8, value=0.0, inTangentType='flat', outTangentType='flat') pmc.setKeyframe(anim, float=1.0, value=0.01, inTangentType='flat', outTangentType='linear') pmc.setKeyframe(anim, float=1.05, value=0.0, inTangentType='flat', outTangentType='flat') self.distMult.outputX >> anim.input # mutliply by user smoothIk animMult = pmc.createNode('multDoubleLinear', name=self.name+'Curve_mlt') anim.output >> animMult.input1 # add with previous scale process animAdd = pmc.createNode('addDoubleLinear', name=self.name+'Curve_add') distCond.outColorR >> animAdd.input1 animMult.output >> animAdd.input2 # squash a=1/stretch squash = pmc.createNode('multiplyDivide', name=self.name+'Squash_mlt') squash.operation.set(2) squash.input1X.set(1.0) animAdd.output >> squash.input2X # squash difference b=a-1 squashDif = pmc.createNode('addDoubleLinear', name=self.name+'Squash_min') #squashDif.operation.set(2) squash.outputX >> squashDif.input1 squashDif.input2.set(-1.0) # squash factor c=b*UI squashFactor = pmc.createNode('multDoubleLinear', name=self.name+'Squash_mdl') squashDif.output >> squashFactor.input1 # add attribut for controlor pmc.addAttr(ikCtrl, longName='subCtrlVisible', attributeType='enum', enumName='None:Offset:Sub:Debug', keyable=False, hidden=False) attribut.addAttrSeparator(ikCtrl, 'ik') pmc.addAttr(ikCtrl, longName='ikfk', attributeType='float', defaultValue=1.0, keyable=True, minValue=0.0, maxValue=1.0 ) pmc.addAttr(ikCtrl, longName='twist', attributeType='float', keyable=True) pmc.addAttr(ikCtrl, longName='smoothIk', attributeType='float', defaultValue=0.0, keyable=True, minValue=0.0, maxValue=1.0 ) ikCtrl.subCtrlVisible.showInChannelBox(True) attribut.addAttrSeparator(ikCtrl, 'Stretch') pmc.addAttr(ikCtrl, longName='stretch', attributeType='bool', defaultValue=True, keyable=True ) pmc.addAttr(ikCtrl, longName='stretchFactor', attributeType='float', defaultValue=1.0, keyable=True, minValue=0.001 ) pmc.addAttr(ikCtrl, longName='stretchMin', attributeType='float', defaultValue=1.0, keyable=True, minValue=0.0, maxValue=1.0 ) pmc.addAttr(ikCtrl, longName='stretchMax', attributeType='float', defaultValue=1.05, keyable=True, minValue=1.0 ) attribut.addAttrSeparator(ikCtrl, 'Squash') pmc.addAttr(ikCtrl, longName='squash', attributeType='bool', defaultValue=True, keyable=True ) pmc.addAttr(ikCtrl, longName='squashFactor', attributeType='float', defaultValue=1.0, keyable=True ) pmc.addAttr(ikCtrl, longName='squashFalloff', attributeType='float', defaultValue=0.5, keyable=True ) attribut.addAttrSeparator(ikCtrl, 'Circle') # connect attribut for controlor ikCtrl.twist >> ikHand[0].twist ikCtrl.stretch >> distCond.firstTerm ikCtrl.stretchFactor >> distFactorMult.input2 ikCtrl.stretchMin >> distClamp.minR ikCtrl.stretchMax >> distClamp.maxR ikCtrl.squashFactor >> squashFactor.input2 ikCtrl.smoothIk >> animMult.input2 # prepare falloff squash system size = len(self.arm) if size%2: half = [size/2, size/2] else: half = [(size/2)-1, size/2] if half[0] != 0: unit = (1.0/half[0]) else: unit = 0 # create system for squash fallof Ui squashUiMdl = pmc.createNode('multDoubleLinear', name=ikCtrl.name()+'_mdl') ikCtrl.squashFalloff >> squashUiMdl.input1 squashUiMdl.input2.set(-1.0) # loop on each bone for i in range(len(self.arm)): # create attribut for each bones about his position if i < half[0]: defaultVal = (unit*(half[0]-i)) elif i in half: defaultVal = 0.0 elif i > half[1]: defaultVal = (unit*(i-half[1])) # add attribut into ik bone pmc.addAttr(self.armIk[i], longName='falloff', attributeType='float', defaultValue=defaultVal, keyable=True, minValue=0.0, maxValue=1.0 ) # A=UI* falloff attribut present in Ik bone sqBoneUi = pmc.createNode('multDoubleLinear', name=self.armIk[i].name()+'SquashPerBoneUI_mdl') self.armIk[i].falloff >> sqBoneUi.input1 squashUiMdl.output >> sqBoneUi.input2 # B=c*A sqBone = pmc.createNode('multDoubleLinear', name=self.armIk[i].name()+'SquashPerBone_mdl') sqBoneUi.output >> sqBone.input1 squashFactor.output >> sqBone.input2 # C=c+B sqBoneAdd = pmc.createNode('addDoubleLinear', name=self.armIk[i].name()+'SquashPerBone_add') squashFactor.output >> sqBoneAdd.input1 sqBone.output >> sqBoneAdd.input2 # squash D=1+C sqBonePlus = pmc.createNode('addDoubleLinear', name=self.armIk[i].name()+'SquashPerBone_plu') sqBonePlus.input1.set(1.0) sqBoneAdd.output >> sqBonePlus.input2 # condition squashCond = pmc.createNode('condition', name=self.armIk[i].name()+'SquashPerBone_cdt') ikCtrl.squash >> squashCond.firstTerm squashCond.secondTerm.set(1.0) squashCond.colorIfFalseR.set(1.0) sqBonePlus.output >> squashCond.colorIfTrueR # # connections with scale # stretch animAdd.output >> self.armIk[i].scaleX # squash squashCond.outColorR >> self.armIk[i].scaleY squashCond.outColorR >> self.armIk[i].scaleZ # visibility logic self.visCond = [] for i in range(2,4): self.visCond.append( pmc.createNode('condition', name=self.name+'Vis'+str(i)+'_cdt') ) self.visCond[-1].secondTerm.set(i) self.visCond[-1].operation.set(4) ikCtrl.subCtrlVisible >> self.visCond[-1].firstTerm # hide subRoll for key in self.rollArm: self.rollArm[key][1].visibility.setLocked(False) self.visCond[1].outColorR >> self.rollArm[key][1].visibility self.rollArm[key][1].visibility.setLocked(True) # hide first roll arm self.rollArm[self.arm[0]][0].visibility.setLocked(False) ikCtrl.subCtrlVisible >> self.rollArm[self.arm[0]][0].visibility self.rollArm[self.arm[0]][0].visibility.setLocked(True) # hide latest FK control self.armFk[-1].visibility.setLocked(False) self.visCond[1].outColorR >> self.armFk[-1].visibility self.armFk[-1].visibility.setLocked(True) # add attribut for pole vector attribut.addAttrSeparator(pvCtrl) # ADD CONSTRAINT ORIENT # pickwalk arPickwalk.setPickWalk([ikCtrl, pvCtrl], type='LR') return {self.mainSets:[ikCtrl, pvCtrl]}
def createIKLeg( listJnts, side ): toeBaseJnt = listJnts[-3] # create ik handle ikh = pm.ikHandle( sj=listJnts[0], ee=toeBaseJnt, sol='ikRPsolver', name=toeBaseJnt + '_' +Names.suffixes['ikhandle'] ) ikh[0].hide() # create ik sc solvers for foot and toe ikhfoot = pm.ikHandle( sj=toeBaseJnt, ee=listJnts[-2], sol='ikSCsolver', name=listJnts[-2] + '_' +Names.suffixes['ikhandle'] ) ikhfoot[0].hide() ikhtoe = pm.ikHandle( sj=listJnts[-2], ee=listJnts[-1], sol='ikSCsolver', name=listJnts[-1] + '_' +Names.suffixes['ikhandle'] ) ikhtoe[0].hide() # parent ik handles to inverse foot inverseFoot = str(toeBaseJnt.name()) inverseFoot = pm.ls( inverseFoot.replace('_'+Names.suffixes['ik'], '_inversefoot'),r=1 )[0] inverseToe = pm.ls(str(inverseFoot.name())+'1',r=1)[0] inverseToeEnd = pm.ls(str(inverseFoot.name()+'2'),r=1)[0] # create offset for toe roll offsetGrp = pm.group(em=1,name=str(inverseToeEnd.name()) + '_offsetGrpA') offsetGrpB = pm.group(em=1,name=str(inverseToeEnd.name()) + '_offsetGrpB') offsetGrp.setParent( inverseToe ) offsetGrp.setTranslation([0,0,0]) offsetGrp.setRotation([0,0,0]) offsetGrp.setParent(w=1) offsetGrpB.setParent(offsetGrp) offsetGrpB.setTranslation([0,0,0]) offsetGrpB.setRotation([0,0,0]) ikh[0].setParent(inverseFoot) ikhfoot[0].setParent(inverseToe) ikhtoe[0].setParent(offsetGrpB) offsetGrp.setParent(inverseToeEnd) # create curve for ik foot if side == Names.prefixes['left']: ctrl = Names.controls_leftLegIK elif side ==Names.prefixes['right']: ctrl = Names.controls_rightLegIK else: raise Exception('Make sure side: %s is valid '%side) posjnt = pm.xform(toeBaseJnt, query = True, translation = True, ws=1) rotjnt = pm.xform(toeBaseJnt, query = True, ro = True, ws=1) foot_cnt = Control.create( name=ctrl, offsets=1, shape='circle_01', size=1.5, color=getSideColor(side), pos=posjnt,rot=rotjnt, parent=None, typ='body' ) ############ fix this! need to rotate 180 to make sure that ctrl behaves properly if side == Names.prefixes['right']: pm.rotate(foot_cnt,0,0,180,os=1, r=1) ankleFloorJnt = pm.ls('%s%s' %(side,'AnkleFloor_if'),r=1 )[0] foot_ctrl = foot_cnt.listRelatives(ad=1)[0].getParent() ankleFloorJnt.setParent( foot_ctrl ) ankleFloorJnt.hide() # add attr to foot control pm.addAttr(foot_ctrl, longName='heel_roll',k=True) pm.addAttr(foot_ctrl, longName='toe_roll',k=True) pm.addAttr(foot_ctrl, longName='toeEnd_roll',k=True) pm.addAttr(foot_ctrl, longName='toe_up_down',k=True) # connect attrs pm.connectAttr( foot_ctrl + '.' + 'heel_roll', ankleFloorJnt + '.' + 'rotateZ' ) pm.connectAttr( foot_ctrl + '.' + 'toe_roll', inverseToe + '.' + 'rotateZ' ) pm.connectAttr( foot_ctrl + '.' + 'toeEnd_roll', inverseToeEnd + '.' + 'rotateZ' ) pm.connectAttr( foot_ctrl + '.' + 'toe_up_down', offsetGrpB + '.' + 'rotateZ' ) ##################### # create pole vector if side == Names.prefixes['left']: ctrl = Names.controls_leftLegIKPV elif side ==Names.prefixes['right']: ctrl = Names.controls_rightLegIKPV else: raise Exception('Make sure side: %s is valid '%side) pv_cnt = Control.create( name=ctrl, offsets=1, shape='cube', size=0.4, color=getSideColor(side), pos=None, parent=None, typ='body' ) # parent constraint w/o offsets to UpLeg, Leg cons = pm.parentConstraint( listJnts[0], listJnts[1],listJnts[2], pv_cnt, mo=0 ) pm.delete(cons) # aim contraint to leg cons = pm.aimConstraint( listJnts[1], pv_cnt,mo=0 ) pm.move( pv_cnt, 10,0,0, os=1,r=1) pm.delete(cons) # connect pole vector pm.poleVectorConstraint( pv_cnt.getChildren()[0], ikh[0] ) #################### rList = [pv_cnt, foot_cnt, ikh] return rList
pm.setAttr('L_Foot_Ctrl.ball_pivot',0) #create Pole Vector Controller pm.curve(n='Left_Knee_Controller',d=1,p=[(0 ,-0.798312, 4.287838),(0, 0.798312 ,3.580731),(-0.707107 ,-0.798312 ,3.580731), (0 , -0.798312 ,2.873624),(0, 0.798312 ,3.580731), (0.707107, -0.798312 ,3.580731) ,(0 ,-0.798312 ,4.287838),(-0.707107, -0.798312, 3.580731),( 0, -0.798312, 2.873624),(0.707107 ,-0.798312, 3.580731)],k=[0,1,2,3,4,5,6,7,8,9]) pm.xform(r=True,cp=True) pm.setAttr('Left_Knee_Controller.rotateX',90) pm.move(1.242267, -5.730831, -0.297442,rpr=True) pm.duplicate('Left_Knee_Controller',n='Right_Knee_Controller') pm.select('Right_Knee_Controller',r=True) pm.move(-1.211395, -5.816898 ,-0.460511,rpr=True) pm.select('Left_Knee_Controller','Right_Knee_Controller') pm.move(0, 0, 7.844711,r=True) pm.makeIdentity(apply=True,t=1,r=1,s=1,n=0,pn=1) pm.select('Left_Knee_Controller','L_Leg') pm.poleVectorConstraint(w=1) pm.select('Right_Knee_Controller','R_Leg') pm.poleVectorConstraint(w=1) #Add Attribute Values Right Heel Pivot pm.select('R_Foot_Ctrl',r=True) pm.addAttr(ln='heel_pivot',at='double',min=-10,max=10,dv=0) pm.setAttr('R_Foot_Ctrl.heel_pivot',keyable=True) pm.select('R_Foot_Ctrl',r=True) pm.setDrivenKeyframe('R_Heel_Ctrl_Jnt.rotateZ',cd='R_Foot_Ctrl.heel_pivot') pm.setAttr('R_Foot_Ctrl.heel_pivot',10,keyable=True) pm.setAttr('R_Heel_Ctrl_Jnt.rotateZ',60,keyable=True) pm.setDrivenKeyframe('R_Heel_Ctrl_Jnt.rotateZ',cd='R_Foot_Ctrl.heel_pivot') pm.setAttr('R_Foot_Ctrl.heel_pivot',-10)
def makeIk(sel, inputRoot): currentChain = pm.ls(selection = True, dag = True) if sel == False: currentChain = pm.ls(inputRoot, dag = True) ikControlName = nameField.getText() + '_ctrl' ikControl = createCube(ikControlName) should = currentChain[0] elb = currentChain[1] wrist = currentChain[2] poleName = nameField.getText() + '_poleVec' baseNameI = should.find('_') baseName = should[:baseNameI] + '_stretchy' poleVec = createPointer(name = poleName + '_ctrl') polePad = createPad(poleVec) aimGrp = pm.group(em = True, w = True) aimGrpUp = pm.group(em = True) pm.parent(aimGrpUp, aimGrp, a = True) pm.move(0,1,0, aimGrpUp, r = True) elbGrp = pm.group(em = True, w = True) pm.parent(polePad, aimGrp, a = True) pm.move(0, 0, -5, polePad, r = True) tempConstA = pm.pointConstraint(should, wrist, aimGrp, mo = False) tempConstB = pm.pointConstraint(elb, elbGrp, mo = False) tempConstC = pm.aimConstraint(elbGrp, aimGrp, mo = False, aim = [0,0,-1]) tempConstD = pm.pointConstraint(wrist, ikControl, mo = False) pm.delete(tempConstA, tempConstB, tempConstC, tempConstD) createPad(currentChain[0]) pm.parent(polePad, w = True) pm.delete(aimGrp, elbGrp) poleVecCurve = pm.curve(n = poleName + '_curve', d = 1, p = [(0,0,0), (0,0,1)], k = [0,1]) firstCluster = True clusterNameA = poleName + '_cluster_00' clusterNameB = poleName + '_cluster_01' newClusterA = pm.cluster(poleVecCurve + '.cv[0]', n = clusterNameA)[1] newClusterB = pm.cluster(poleVecCurve + '.cv[1]', n = clusterNameB)[1] pm.parentConstraint(elb, newClusterA) pm.parentConstraint(poleVec, newClusterB) pm.parent(newClusterA, clusterGrp) pm.parent(newClusterB, clusterGrp) newIkHandle = pm.ikHandle(n = poleName + '_ikHandle',sj = should, ee = wrist, sol = 'ikRPsolver', shf = False, s = 0)[0] pm.poleVectorConstraint(poleVec, newIkHandle) pm.parentConstraint(ikControl, newIkHandle) createPad(ikControl) if stretchyCheckBox.getValue(): pm.addAttr(ikControl, ln = 'elbowLock', keyable = True, attributeType = 'double', min = 0, max = 1) pm.addAttr(ikControl, ln = 'stretchy', keyable = True, attributeType = 'double', min = 0, max = 1) shoulderNull = pm.group(em = True, w = True, n = baseName + '_should_DDNull') elbowNull = pm.group(em = True, w = True, n = baseName + '_elbow_DDNull') wristNull = pm.group(em = True, w = True, n = baseName + '_wrist_DDNull') pm.pointConstraint(should, shoulderNull) elbowPointConstraint = pm.pointConstraint(elb, elbowNull) pm.pointConstraint(ikControl, wristNull) pm.delete(elbowPointConstraint) totalDistanceDimension = pm.createNode('distanceDimShape', n = baseName + '_DDTot') upperArmDistanceDimension = pm.createNode('distanceDimShape', n = baseName + '_DDUp') lowerArmDistanceDimension = pm.createNode('distanceDimShape', n = baseName + '_DDLow') totArmMD = pm.createNode('multiplyDivide', n = baseName + '_MDTot') upArmMD = pm.createNode('multiplyDivide', n = baseName + '_MDUp') lowArmMD = pm.createNode('multiplyDivide', n = baseName + '_MDLow') totArmMD.operation.set(2) upArmMD.operation.set(1) lowArmMD.operation.set(1) shoulderNull.translate.connect(totalDistanceDimension.startPoint) wristNull.translate.connect(totalDistanceDimension.endPoint) shoulderNull.translate.connect(upperArmDistanceDimension.startPoint) elbowNull.translate.connect(upperArmDistanceDimension.endPoint) elbowNull.translate.connect(lowerArmDistanceDimension.startPoint) wristNull.translate.connect(lowerArmDistanceDimension.endPoint) totalLength = upperArmDistanceDimension.distance.get() + lowerArmDistanceDimension.distance.get() totArmMD.input2X.set(totalLength) upArmMD.input2X.set(upperArmDistanceDimension.distance.get()) lowArmMD.input2X.set(lowerArmDistanceDimension.distance.get()) totalDistanceDimension.distance.connect(totArmMD.input1X) totArmMD.outputX.connect(upArmMD.input1X) totArmMD.outputX.connect(lowArmMD.input1X) upperArmCondition = pm.createNode('condition', n = baseName + '_UpCond') lowerArmCondition = pm.createNode('condition', n = baseName + '_LowCond') upperArmCondition.operation.set(2) lowerArmCondition.operation.set(2) upperArmBlend = pm.createNode('blendTwoAttr', n = baseName + 'upBlend') lowerArmBlend = pm.createNode('blendTwoAttr', n = baseName + 'lowBlend') ikControl.elbowLock.connect(upperArmBlend.attributesBlender) ikControl.elbowLock.connect(lowerArmBlend.attributesBlender) totalDistanceDimension.distance.connect(upperArmCondition.firstTerm) totalDistanceDimension.distance.connect(lowerArmCondition.firstTerm) upperArmCondition.secondTerm.set(totalLength) lowerArmCondition.secondTerm.set(totalLength) upArmMD.outputX.connect(upperArmCondition.colorIfTrueR) lowArmMD.outputX.connect(lowerArmCondition.colorIfTrueR) upperArmCondition.colorIfFalseR.set(upperArmDistanceDimension.distance.get()) lowerArmCondition.colorIfFalseR.set(lowerArmDistanceDimension.distance.get()) upperArmDistanceDimension.distance.connect(upperArmBlend.input[0]) upperArmCondition.outColorR.connect(upperArmBlend.input[1]) lowerArmDistanceDimension.distance.connect(lowerArmBlend.input[0]) lowerArmCondition.outColorR.connect(lowerArmBlend.input[1]) #finishCondition #create second pv elbowLockConstraint = pm.poleVectorConstraint(elbowNull, newIkHandle, w = 0) #lower keyframe pm.setDrivenKeyframe(elbowLockConstraint, at = elbowLockConstraint.w0, cd = ikControl.elbowLock, v = 0, dv = 0 ) pm.setDrivenKeyframe(elbowLockConstraint, at = elbowLockConstraint.w0, cd = ikControl.elbowLock, v = 1, dv = 1 ) pm.setDrivenKeyframe(elbowLockConstraint, at = elbowLockConstraint.w1, cd = ikControl.elbowLock, v = 1, dv = 0 ) pm.setDrivenKeyframe(elbowLockConstraint, at = elbowLockConstraint.w1, cd = ikControl.elbowLock, v = 0, dv = 1 ) #create full stretch togle upperArmBlend.output.connect(elb.translateX) lowerArmBlend.output.connect(wrist.translateX) kneeLock = pm.circle(nr = [1,0,0], n = baseName + '_kneeLock_ctrl')[0] kneeLockPad = createPad(kneeLock) tempParent = pm.parentConstraint(elb, kneeLockPad, mo = False) pm.delete(tempParent) pm.parentConstraint(kneeLock, elbowNull, mo = True) pm.parentConstraint(kneeLockPad, (ikControl, should))
def RP_2segment_stretchy_IK(_rootJoint, _hingeJoint, _endJoint, _container = None, _scaleCorrectionAttribute = None): moduleNamespaceInfo = StripAllNamespaces(_rootJoint) moduleNamespace = "" if moduleNamespaceInfo != None: moduleNamespace = moduleNamespaceInfo[0] rootLocation = pm.xform(_rootJoint, query = True, worldSpace = True, translation = True) elbowLocation = pm.xform(_hingeJoint, query = True, worldSpace = True, translation = True) endLocation = pm.xform(_endJoint, query = True, worldSpace = True, translation = True) # Create Rotate-Plane IK ikNodes = pm.ikHandle(startJoint = _rootJoint, endEffector = _endJoint, name = "%s_ikHandle" %_rootJoint, solver = "ikRPsolver") ikNodes[1] = pm.rename(ikNodes[1], "%s_ikEffector" %_rootJoint) ikHandle = ikNodes[0] ikEffector = ikNodes[1] pm.setAttr("%s.visibility" %ikHandle, 0) # Create control locators rootLocator = pm.spaceLocator(name = "%s_positionLocator" %_rootJoint) pm.xform(rootLocator, worldSpace = True, absolute = True, translation = rootLocation) pm.parent(_rootJoint, rootLocator, absolute = True) endLocator = pm.spaceLocator(name = "%s_positionLocator" %ikHandle) pm.xform(endLocator, worldSpace = True, absolute = True, translation = endLocation) pm.parent(ikHandle, endLocator, absolute = True) elbowLocator = pm.spaceLocator(name = "%s_positionLocator" %_hingeJoint) pm.xform(elbowLocator, worldSpace = True, absolute = True, translation = elbowLocation) elbowLocatorConstraint = pm.poleVectorConstraint(elbowLocator, ikHandle) # Create stretchy setup utilityNodes = [] for locators in ( (rootLocator, elbowLocator, _hingeJoint), (elbowLocator, endLocator, _endJoint) ): from math import fabs startLocatorNamespaceInfo = StripAllNamespaces(locators[0]) startLocatorWithoutNamespace = "" if startLocatorNamespaceInfo != None: startLocatorWithoutNamespace = startLocatorNamespaceInfo[1] endLocatorNamespaceInfo = StripAllNamespaces(locators[1]) endLocatorWithoutNamespace = "" if endLocatorNamespaceInfo != None: endLocatorWithoutNamespace = startLocatorNamespaceInfo[1] startLocatorShape = "%sShape" %locators[0] endLocatorShape = "%sShape" %locators[1] # Setup utility nodes distNode = pm.shadingNode("distanceBetween", asUtility = True, name = "%s:distBetween_%s_%s" %(moduleNamespace, startLocatorWithoutNamespace, endLocatorWithoutNamespace)) pm.connectAttr("%s.worldPosition[0]" %startLocatorShape, "%s.point1" %distNode) pm.connectAttr("%s.worldPosition[0]" %endLocatorShape, "%s.point2" %distNode) utilityNodes.append(distNode) scaleFactor = pm.shadingNode("multiplyDivide", asUtility = True, name = "%s_scaleFactor" %distNode) utilityNodes.append(scaleFactor) pm.setAttr("%s.operation" %scaleFactor, 2) # divide originalLength = pm.getAttr("%s.translateX" %locators[2]) pm.connectAttr("%s.distance" %distNode, "%s.input1X" %scaleFactor) pm.setAttr("%s.input2X" %scaleFactor, originalLength) translationDriver = "%s.outputX" %scaleFactor translateX = pm.shadingNode("multiplyDivide", asUtility = True, name = "%s_translationValue" %distNode) utilityNodes.append(translateX) pm.setAttr("%s.input1X" %translateX, fabs(originalLength)) pm.connectAttr(translationDriver, "%s.input2X" %translateX) pm.connectAttr("%s.outputX" %translateX, "%s.translateX" %locators[2]) # Add created nodes to container if _container != None: containedNodes = list(utilityNodes) containedNodes.extend(ikNodes) containedNodes.extend([rootLocator, elbowLocator, endLocator]) containedNodes.append(elbowLocatorConstraint) AddNodeToContainer(_container, containedNodes, _includeHierarchyBelow=True) return (rootLocator, elbowLocator, endLocator, utilityNodes)
def addConstraint(self, _constraint, _drivenObj, _driverList, _force = False, _f = False, _tx = False, _ty = False, _tz = False, _t = True, _rx = False, _ry = False, _rz = False, _r = True, _sx = False, _sy = False, _sz = False, _s = True ): """ Method: addConstraint A method that adds constraints from the driverList to the specified object Inputs: _constraint: A string defining the constraint type _drivenObject: The child object of the Constraint _driverList: The driver objects _force: Defaults to false, defines whther or not to replace existing contraints with the one specified, if left false, the constraint will be put onto attributes that aren't already controlled, is set to true any confilcting connections will be broken and replaced witht he inputted ones _f: Short name for _force attribute specifics: These are keyword arguments for each axis of translate rotate and scale, default to false, if all values pertinant to the specified constraint are false, defaults will be used (i.e. all of them) if any of them are set, those ones will be constrained and the ones left at the default of false will not. The _t, _r and _s keywords give the option to turn off all three axis in any given transformation type. The keywords and default settings: _tx = False, _ty = False, _tz = False, _t = True, _rx = False, _ry = False, _rz = False, _r = True, _sx = False, _sy = False, _sz = False, _s = True On Exit: The specified constraints have been added to the control """ #first check that a constraint has been entered if _constraint != "": #set boolean values for whether or not to constrain each transformation in each axis #create a boolean which says whether or not any of the translate, rotation, and scale #attributes are connected doTrans = ((_drivenObj.tx.isFreeToChange() and _drivenObj.ty.isFreeToChange() and _drivenObj.tz.isFreeToChange() ) or (_f or _force)) and _t doRot = ((_drivenObj.rx.isFreeToChange() and _drivenObj.ry.isFreeToChange() and _drivenObj.rz.isFreeToChange() ) or (_f or _force)) and _r doScale = ((_drivenObj.sx.isFreeToChange() and _drivenObj.sy.isFreeToChange() and _drivenObj.sz.isFreeToChange() ) or (_f or _force)) and _s #then make a boolean for each transformation type which sayes whether all of the #individual values were left at default transSet = _tx or _ty or _tz rotSet = _rx or _ry or _rz sclSet = _sx or _sy or _sz #switch through constraint types if (_constraint == "parent" and (doTrans or doRot)): #set up skip strings based on the boolean inputs and checks stList = [] srList = [] #if translate is not meant to be contrained if not doTrans: #add all of the strings to the list stList = ["x","y","z"] #otherwise else: #if one or more of the translate axis flags are set if transSet: #add the appropriate strings to the list if not _tx: stList.append("x") if not _ty: stList.append("y") if not _tz: stList.append("z") #if force is set, break all rotate conenctions if _f or _force: self.breakConnection(_drivenObj.tx) self.breakConnection(_drivenObj.ty) self.breakConnection(_drivenObj.tz) #repeat for rotate if not doRot: srList = ["x","y","z"] else: if rotSet: #add the appropriate strings to the list if not _rx: srList.append("x") if not _ry: srList.append("y") if not _rz: srList.append("z") if _f or _force: self.breakConnection(_drivenObj.rx) self.breakConnection(_drivenObj.ry) self.breakConnection(_drivenObj.rz) #set up a parent constraint between the control and the template object return pm.parentConstraint(_driverList,_drivenObj, mo = True, st = stList, sr = srList) #if orient constraint is chosen and the constraint is meant to be made elif (_constraint == "orient" and doRot): srList = [] #and some of the rotate axis flags have been set if rotSet: if not _rx: srList.append("x") if not _ry: srList.append("y") if not _rz: srList.append("z") #if force is set breack connections if _f or _force: self.breakConnection(_drivenObj.rx) self.breakConnection(_drivenObj.ry) self.breakConnection(_drivenObj.rz) #set up an orient constraint between the control and the template object return pm.orientConstraint(_driverList,_drivenObj, mo = True, sk = srList) elif (_constraint == "point" and doTrans): stList = [] if transSet: #add the appropriate strings to the list if not _tx: stList.append("x") if not _ty: stList.append("y") if not _tz: stList.append("z") #if force is set breack connections if _f or _force: self.breakConnection(_drivenObj.tx) self.breakConnection(_drivenObj.ty) self.breakConnection(_drivenObj.tz) #set up a parent constraint between the control and the template object return pm.pointConstraint(_driverList,_drivenObj, mo = True, sk = stList) elif (_constraint == "scale" and doScale): ssList = [] if sclSet: #add the appropriate strings to the list if not _sx: ssList.append("x") if not _sy: ssList.append("y") if not _sz: ssList.append("z") #if force is set breack connections if _f or _force: self.breakConnection(_drivenObj.sx) self.breakConnection(_drivenObj.sy) self.breakConnection(_drivenObj.sz) #set up a parent constraint between the control and the template object return pm.scaleConstraint(_driverList,_drivenObj, mo = True, sk = ssList) #for the polevector constraint elif (_constraint == "poleVector"): #set up a parent constraint between the control and the template object return pm.poleVectorConstraint(_driverList,_drivenObj) """--------------------"""