Home Website Youtube GitHub

Rotation space for FK arm and leg controls

Hi everyone,
Is there a feature in the mGear rig where the FK arm and leg controls’ rotation could be set to local or global space instead of following the upperbody’s rotation? Basically I’d like to have the option of keeping the hand/leg’s rotation isolated from the rest of the body. Please let me know if there’s a script or an option to enable this.

Thanks!

Hey Ragha!

I think you might be looking for a way to do “space switching”, right?

Try searching for “IK Reference” here in the forum.

There some posts about that may help you to figure it out.

Hope it helps you! :v:t4:

1 Like

Hi Robert!
Thanks so much for your reply! yes, I’m looking for space switching and I looked up the “IK Reference” too. As for IK controls, it works like a charm! What I’m looking for is if I could do the same for the FK arm controls.

When I looked up similar topics in the forum, this thread showed up ( Rotation isolation on FK component ) and I tried modifying the script by changing the controls to FK arm. It does work except, the FK arm gets flipped when I apply the script.

Would really appreciate it if you let me know if you might have a solution for this. :slight_smile: I’ll also keep looking out in the forum to see if I could find something.

1 Like

Here’s the script I edited from the thread I posted. I don’t know exactly if what I’m doing is right because I’m not a programmer but although it technically works, but the FK arm rotation gets Offset for some reason. -

import pymel.core as pm

print ‘POST: left hand isolate script’

control to isolate

isolate_ctrl = pm.PyNode(‘arm_L0_fk0_ctl’)

spaces to add to isolation

global_ctrl = pm.PyNode(‘local_C0_ctl’)
parent_ctrl = pm.PyNode(‘spine_C0_ik1_ctl’)

isolate_constrain_grp = pm.PyNode(‘arm_L0_fk0_npo’)
isolate_attr_holder = pm.PyNode(‘armUI_L0_ctl’)

create extra top group for isolate constrain

pm.select(isolate_constrain_grp, r=True)
isolate_grp = pm.group(n=isolate_constrain_grp.name() + ‘_isolate’, empty=True, world=True)
pm.delete(pm.parentConstraint(isolate_ctrl, isolate_grp, mo=False))

isolate_constrain_grp_parent = isolate_constrain_grp.getParent()
pm.parent(isolate_constrain_grp, isolate_grp)
pm.parent(isolate_grp, isolate_constrain_grp_parent)

add orientConstraint

con = pm.parentConstraint(global_ctrl, parent_ctrl, isolate_grp, mo=True, weight=0, skipTranslate=[‘x’, ‘y’, ‘z’])
con.interpType.set(2)

add attribute for switching spaces

pm.addAttr(isolate_attr_holder, type=‘float’, min=0, max=1, dv=0, longName=‘isolate_rotation’, keyable=True)

connect attr to constraint target weights

isolate_attr_holder.isolate_rotation >> con.getWeightAliasList()[0]

rev_node = pm.createNode(‘reverse’)
isolate_attr_holder.isolate_rotation >> rev_node.inputX
rev_node.outputX >> con.getWeightAliasList()[1]

Oh now I see what you mean.
Sorry to say I don’t know how to solve it, but I am guessing you may have to include the pole vector controls to that custom step because it could be what is causing it to flip.

I am not at my computer right now, and not code savvy too, but let me see if I can figure this out.

Since you shared your custom step, someone else can give it a try too this meanwhile.

Keep it up!

1 Like

Thanks Robert! Yeah it’ll be so helpful if you could look into this too. I’ll also wait and see if someone could point out what is wrong with the script.

I think i solved it!
The real reason for the flip was coming from this part of the code:

create extra top group for isolate constrain

pm.select(isolate_constrain_grp, r=True)
isolate_grp = pm.group(n=isolate_constrain_grp.name() + ‘_isolate’, empty=True, world=True)
pm.delete(pm.parentConstraint(isolate_ctrl, isolate_grp, mo=False))

isolate_constrain_grp_parent = isolate_constrain_grp.getParent()
pm.parent(isolate_constrain_grp, isolate_grp)
pm.parent(isolate_grp, isolate_constrain_grp_parent)strong text

1 Like

So what I did was, I created an empty group manually, renamed it to ‘arm_L0_fk0_npo_isolate’ and aligned it to ‘arm_L0_root’ and parented it under it.

Then I took the ‘arm_L0_fk0_npo’ and then made it a child of ‘arm_L0_fk0_npo’_isolate.

So the hierarchy is as follows : ‘arm_L0_root’ > ‘arm_L0_fk0_isolate’ > ‘arm_l0_fk0_np0’.

Then i deleted that part of the script and ran the rest of it. and it’s working. :slight_smile: I hope I’m not making any major mistake.

Programmers, please let me know if this is okay. :slight_smile:

Here’s my final code :


print 'POST: left hand isolate script'

# control to isolate
isolate_ctrl = pm.PyNode('arm_L0_fk0_ctl')

# spaces to add to isolation
global_ctrl = pm.PyNode('body_C0_ctl')
parent_ctrl = pm.PyNode('shoulder_L0_ctl')

isolate_constrain_grp = pm.PyNode('arm_L0_fk1_npo')
isolate_attr_holder = pm.PyNode('armUI_L0_ctl')

# add orientConstraint
con = pm.parentConstraint(global_ctrl, parent_ctrl, isolate_grp, mo=True, weight=0, skipTranslate=['x', 'y', 'z'])
con.interpType.set(2)

# add attribute for switching spaces
pm.addAttr(isolate_attr_holder, type='float', min=0, max=1, dv=0, longName='isolate_rotation', keyable=True)

# connect attr to constraint target weights
isolate_attr_holder.isolate_rotation >> con.getWeightAliasList()[0]

rev_node = pm.createNode('reverse')
isolate_attr_holder.isolate_rotation >> rev_node.inputX
rev_node.outputX >> con.getWeightAliasList()[1]```
1 Like

One very important thing to add is that I aligned the ‘arm_L0_fk0_npo_isolate’ perfectly to the ‘arm_L0_root’ and made sure all the transforms were 0.

1 Like

I didn’t read the whole thread, so sorry if I’m repeating or misunderstanding. But in the mGear biped example template, there is an orbit control above the arm, which I think is part of the shoulder component. It should already have this space switch.

shoulder_L0_orbit_ctl

On your hostUI of the IK hand control, you’ll see this, and setting it to your world/global controls will give it a world space orientation:

If you aren’t using those components, and for your legs, you could use a control_01 component, and put a space switch on that, and set the connector to “orientation”, a setting which I believe exists in the component guide in recent versions of mGear. But in the past, you had to change this attribute in the attribute editor:

image

Once it is set to orientation, the space-switch works on orientation only.

2 Likes

In this forum, surround your code with triple backticks ``` so it formats as code.

1 Like

Hi Chris! Thanks for the tip! I’ve added that backticks.

Btw, thanks so much for your reply. I do recognize the space switching attribute in the IK hand control and I have that feature enabled in the rig. However, my request was for the FK arm controls.
With the code I’ve posted and the instructions I had mentioned, I’m able to get the desired result. But if you could let me know if it’s a clean method and won’t cause any issues, that’d be great because I don’t have any issues so far.

Please check this gif where I’ve captured my screen which explains the issue- ezgif 3 7bc7b228bf - Gifyu

Yes, I know you’re asking for the arm. My reply was about the arm. The attribute is found on the IK hand hostUI. But it controls the arm’s orientation, including FK. And my reply explains how to set something similar up for the legs.

arm_orientation

Oh I see! In that case, it’s strange that my FK arm’s orientation still remains the same when the orientation is set to global_C0_ctl.

image

Maybe there’s something I missed while setting it up. Will dig a little deeper into this.

Hey @chrislesage , I noticed the issue. Instead of parenting the ‘arm_L0_root’ to the ‘shoulder_L0_orbit’, I had by mistake parented it directly under ‘shoulder_L0_root’. Goes to show how important the hierarchy is when setting up the guides.

The orientation seems to work on the FK now without the need for any additional scripts. Thanks so much for your help! :slight_smile:

3 Likes

Thank you for this! I took your explanation and was able to fix the section of the code that you removed. The original script made the error of assuming that the ‘isolate_ctrl’ space was the same as the parent of the ‘isolate_constrain_group’ but this is not the case with the legs or arms.

    # create extra top group for isolate constrain
    isolate_grp = pm.group(n=isolate_constrain_grp.name() + '_isolate', empty=True, world=True)
    pm.delete(pm.parentConstraint(isolate_constrain_grp_parent, isolate_grp, mo=False))

    pm.parent(isolate_constrain_grp, isolate_grp)
    pm.parent(isolate_grp, isolate_constrain_grp_parent)