Home Website Youtube GitHub

IK clavicle for shoulder module

Hello!

I am currently using EPIC_shoulder_01 and an arm. I am a bit new with some of the modules but I want to make it so when I translate the orbit of the shoulder, the shoulder follows it (like it’s aimed at).

Is there a setting in the shoulder module to do so? Or any other shoulder module that does this? I am trying to run more tests on all the available shoulder modules but I am happy with any suggestions and ideas!

Thank you!

There is no setting for this. I do this with a post script, shared below. I also make sure translating the shoulder works. I forget if Shifter does that by default or not.

(I aim my neck and fingers too.)

I don’t use the EPIC shoulder, so there is a chance this script might need a bit of adjustment. Especially in the aim and up vectors.

Also, one thing to note. “# add a root to the aimConstrained node to give it a stable reference space.” If you parent constrain an aimed node’s parent, you don’t need an upvector object. I’m not sure if that’s well known, but that’s how I do mine below:

import mgear
import mgear.shifter.custom_step as cstp
import pymel.core as pm
from mgear.core import attribute, transform
from mgear import rigbits


class CustomShifterStep(cstp.customShifterMainStep):
    def __init__(self):
        self.name = "final_rig_cleanup"
        self.charName = pm.PyNode('guide').rig_name.get()


    def run(self, stepDict):
        oModel = stepDict['mgearRun'].model

        for side in 'LR':
            self.add_clavicle_aimer(side)


    def add_clavicle_aimer(self, side):
        ### AIM THE CLAVICLES WHEN MOVING THE shoulder_L0_orbit_ctl
        orbitControl = pm.PyNode('shoulder_{}0_orbit_ctl'.format(side))
        armAimer = pm.PyNode('arm_{}0_eff_loc'.format(side)).getParent()
        shoulderRoot = pm.PyNode('shoulder_{}0_ctl_npo'.format(side)).getParent()
        shoulderJoint = pm.PyNode('shoulder_{}0_shoulder_jnt'.format(side))
        shoulderControl = pm.PyNode('shoulder_{}0_ctl'.format(side))
        armRoot = pm.PyNode('shoulder_{}0_orbit_ctl'.format(side))

        clavOriLoc = pm.group(em=True, name='shoulder_{}0_clav_ori'.format(side))
        transform.matchWorldTransform(shoulderJoint, clavOriLoc)
        pm.parent(clavOriLoc, shoulderRoot)
        
        # add a root to the aimConstrained node to give it a stable reference space.
        clavOriLocRoot = rigbits.addNPO(clavOriLoc)[0]
        pm.pointConstraint(shoulderControl, clavOriLoc, mo=False)
        pm.parentConstraint(shoulderControl, clavOriLocRoot, mo=False)
        if side == 'L':
            pAimVector = (1,0,0)
            pUpVector = (0,0,1)
        elif side == 'R':
            pAimVector = (-1,0,0)
            pUpVector = (0,0,-1)
        pm.aimConstraint(
            armAimer,
            clavOriLoc,
            maintainOffset=False,
            aimVector=pAimVector,
            upVector=pUpVector,
            worldUpType='none',
            )
        # delete the decomposeMatrix that is driving the rotation of the shoulder joint
        pm.delete(shoulderJoint.rx.inputs()[0])
        pm.orientConstraint(clavOriLoc, shoulderJoint)
        attribute.lockAttribute(armRoot, attributes=['v', 'sx', 'sy', 'sz'])
        attribute.lockAttribute(shoulderControl, attributes=['v', 'sx', 'sy', 'sz'])
4 Likes

Hello, thank you so much for replying, this is very helpful!

1 Like