Home Website Youtube GitHub

Unable to mirror IK hand rotation on EPIC_arm component

I’m having trouble mirroring the EPIC_arm IK hand in a Z-Up scene with the character facing X-forward.

The arm guides are created by default in a Y-forward arrangement, and if I leave them that way there’s no issue with mirroring.

But if I reposition and rotate the arm guides to be X-forward (to match our character mesh), the mirroring on the hand rotation breaks even after checking and unchecking all the different possible ‘Invert Mirror R*’ combinations. No combination of these checkboxes can give me a proper rotational mirror. The FK rotations do mirror correctly, though.

Is there any way around this or do I have to set everything up Y-forward and then counter rotate everything after the rig is built?

I found a way, I don’t know if it’s a ‘good’ way, but it’s a way.

After I build, I match ikcns_ctl rotation to the wrist guide, then I match the ik_ctl rotation to the wrist guide. (Could also match to the FK hand).

Then I zero out each IK control by putting all the transform values in to the OffsetParentMatrix and setting the regular transform values to 0.0.

Now the IK controls seem to correctly mirror. So I just need to figure out how to do this in a POST script.

It’d sure be nice to be able to set either global or component orientation spaces though to avoid this kind of thing. I’d love to be able to set a variable somewhere in the Guide Setting to tell mgear whether I’m Z or Y-up, and which axis my character is facing, or what axis I want an arm or a spine to rotate along.

This POST script seems to do the trick. I modified a script from another thread that @chrislesage made that aligns the IK controls to the FK hand controls. But I had to match the rotation the the wrist guide instead of the FK hand, otherwise the hand would flip 180.

Then I added a snippet that zeros out the transforms by transferring them to the offset parent matrix, instead of adding an npo node. It’d probably be better to move this function someplace else but I’m still learning this stuff.

I’m not a very good scripter but maybe it’ll help somebody out somewhere down the line.

import maya.cmds as cmds
import pymel.core as pm
import mgear.shifter.custom_step as cstp

class CustomShifterStep(cstp.customShifterMainStep):
    """Custom Step description

    def setup(self):
        self.name = "HandIKAlign"

    def run(self):
        for side in 'LR':

    def zero_OPM(self, obj): 
        joints = obj
        aux = pm.group(em=True)
        for jnt in joints:
            aux.setMatrix(jnt.getMatrix(ws=True), ws=True)
            pm.parent(aux, jnt.getParent())
            aux.matrix >> jnt.offsetParentMatrix
            pm.xform(jnt, t=[0,0,0], ro=[0,0,0], s=[1,1,1])
            if pm.objectType( jnt, isType='joint' ): 
            aux.matrix // jnt.offsetParentMatrix
    def fix_ik_hand_orientation(self, side):
        handRef = pm.PyNode('arm_{}0_wrist'.format(side))
        ikCns = pm.PyNode('arm_{}0_ikcns_ctl'.format(side))
        ikCtrl = pm.PyNode('arm_{}0_ik_ctl'.format(side))
        handChildren = ikCtrl.getChildren(type='transform')
        cmds.matchTransform(str(ikCns), str(handRef), rot=True)
        cmds.matchTransform(str(ikCtrl), str(handRef), rot=True)
        obj = [ikCns, ikCtrl]

The downside of aligning the IK controls to the wrists and zeroing them out is that moving the IK control straight up in world Z, for example, will now drive values in all 3 axis’, which sucks. But I can’t get the rotations to mirror on an X-forward character without doing it. So the Y-forward way still gets better results.


There IS a way to mirror the rotation on an X-forward character and it’s much simpler than all this other stuff I tried.

All I had to do was put a value of -180 in the offset parent matrix’ Z rotation of arm_R0_ik_ctrl, then re-align it back in to it’s original orientation. NOW the mirroring works without messing up the world translation values.

Phew, thanks for coming along on this trip with me. :sweat_smile:

1 Like