Home Website Youtube GitHub

IK Foot Orientation at Bind Pose

Hi,

It doesn’t seem to matter how I manipulate the guides, the foot control “leg_L0_ik_ctl” is always aligned facing forwards (shown in red in the attached picture). Is there a way the local orientation can be in line with the foot (hilighted in green, and would coincide with the FK foot alignmentat bind pose)?

1 Like

Hello @rampant.animator that is expected and oriented in world space by desing.
You will need to create your own componet version/variant to support this option

1 Like

Or (carefully) adjust it with a Post Python script.

If you do that, you might also have to align any _mth nodes or _ref nodes, which I think are the nodes that are used to align the controls when IK/FK switching, or space-switching.

2 Likes

Can I know why there is an option that allows to leave the orientation “local” on the “leg_3jnt_01” control and not on those used for a standard leg?

It would be useful, because it forces us to model the characters in a specific and very rigid pose.

Another thing I was wondering… Why does the foot controller follow the orientation of the leg even though the guides are straight?

Well, I don’t know if you’ll get a satisfying answer to “why”. That’s the way the component was coded. And it’s open source, so you can modify it.

If you want to modify it, I suggest copying the component into a custom folder and adding MGEAR_SHIFTER_COMPONENT_PATH = P:/your/path/here/customComponents

Or better for the community, you can modify the component and submit it as a PR in Github.

Otherwise, the best bet might be to write one feature request per feature in a separate thread in the Feature Request category, so it doesn’t get lost.

For me, I often choose just to use post Python scripts to fix up some issues I have.

1 Like

Good to know that you can modify the orientation with a Post Python script. Could you provide an example of how to modify the orientation? It is a small detail but it makes life easier for animators to have already oriented the foot controller.

Here’s my post script to do exactly that - there are a few threads that have similar scripts but for some only this appears as a result.
So here’s my customstep just in case it helps someone. ( I deliberately commented out the ikcns because some people prefer the forward-pointing one and I can have both in this way )

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):
    """Custom Step description
    """

    def setup(self):
        """
        Setting the name property makes the custom step accessible
        in later steps.

        i.e: Running  self.custom_step("alignHandRotationToGuide")  from steps ran after
             this one, will grant this step.
        """
        self.name = "alignLegRotationToGuide"

    def run(self):
        """Run method.

            i.e:  self.mgear_run.global_ctl
                gets the global_ctl from shifter rig build base

            i.e:  self.component("control_C0").ctl
                gets the ctl from shifter component called control_C0

            i.e:  self.custom_step("otherCustomStepName").ctlMesh
                gets the ctlMesh from a previous custom step called
                "otherCustomStepName"

        Returns:
            None: None
        """

        for side in "LR":
            rotation_ref = pm.PyNode(f"leg_{side}0_ankle")
            fk_npo = pm.PyNode(f"leg_{side}0_fk2_npo")
            fk_ctl = pm.PyNode(f"leg_{side}0_fk2_ctl")
            
            ik_ctl = pm.PyNode(f"leg_{side}0_ik_ctl")
            # ik_cns_ctl = pm.PyNode(f"leg_{side}0_ikcns_ctl")
            
            # fix fk rot
            # unlock and unparent chihldren that we don't want to rotate
            self.unlockAllAxes(fk_npo, 'rotate')
            fk_children = fk_ctl.getChildren(type='transform')
            ik_children = ik_ctl.getChildren(type='transform')
            # ik_cns_children = ik_cns_ctl.getChildren(type='transform')
            
            
            pm.parent(fk_children, None)
            pm.parent(ik_children, None)
            # pm.parent(ik_cns_children, None)

            # match rotations to guide
            self.matchWorldRotation(rotation_ref, fk_npo)
            self.matchWorldRotation(rotation_ref, ik_ctl)
            # self.matchWorldRotation(rotation_ref, ik_cns_ctl)

            # reparent children / clean up
            pm.parent(fk_children, fk_ctl)
            pm.parent(ik_children, ik_ctl)
            # pm.parent(ik_cns_children, ik_cns_ctl)
            self.lockAllAxes(fk_npo, 'rotate')
            
            # match mth
            transform.matchWorldTransform(fk_ctl, pm.PyNode(fk_ctl.name().replace('_ctl', '_mth')))
            transform.matchWorldTransform(ik_ctl, pm.PyNode(ik_ctl.name().replace('_ctl', '_mth')))
            
            # make sure nulling the controller goes back to the the base rotation
            rigbits.addNPO(ik_ctl)
    
    
        return

    def matchWorldRotation(self, source, target):
        pm.matchTransform(target, source, rotation=True)
        
    def unlockAllAxes(self, node, channel):
        for axis in 'XYZ':
            node.setAttr(channel, lock=False)
            node.setAttr(f"{channel}{axis}", lock=False)

    def lockAllAxes(self, node, channel):
        for axis in 'XYZ':
            node.setAttr(channel, lock=True)
            node.setAttr(f"{channel}{axis}", lock=True)
6 Likes

Thank you very much for sharing your solution, it works great! :star_struck:

1 Like