Home Website Youtube GitHub

Turn Off Upper Arm Roll for a cartoon character

Hi, I have been using the “arm_2jnt_1” component for a cartoon character who’s arms are not attached to its body.

When rotating the “arm_L0_fk0_ctl” the upper arm roll joints create a twisting effect in the arm. This makes sense for a human character, who’s arms are attached to the shoulder.

For the cartoon character I would like to turn off the twisting effect and have the “arm_L0_fk0_ctl” rotate only the “arm_L0_0_jnt”. This way the “arm_L0_fk0_ctl” will rotate the complete arm. I’ve had a look at the node editor, but can’t figure out how to modify the upper arm roll behavior, because I don’t understand how the roll joints are being driven by all the matrix nodes etc.

What would be the best way to achieve the above? My guess is I will have to change the way “arm_L0_fk0_ctl” drives the underlying joints in a custom post step somehow?

Okay, never mind. The easiest way to achieve what I wanted, was to make a direct connection of arm_L0_fk0_ctl.rotateX into armUI_L0_ctl.arm_aproll. Now the shoulder fully rotates with the arm.

Ofcourse it would be nice to understand how this works under the hood and maybe find a better solution, but for now it works.

Ah, well, of course this only works for the FK chain, not for the IK chain. So my problem still stands :frowning:

At least I found an attribute that negates the effect of the upper arm roll. If anyone could point me in the right direction how the “armpit roll” attribute of the “armUI_L0_ctl” of the “arm_2jnt_01” component does that, maybe I can figure out how to turn the roll off for the IK and FK chain…

“arm_L0_tws0_rot” is the node that drives the twist at the top of the arm.

What if you break the rotation connection on arm_L0_tws0_rot and then orient constrain arm_L0_tws0_rot to arm_L0_mid_ctl? This seems to work, but it might have some side effects I didn’t see yet.

3 Likes

Yeeess!! Thanks so much Chris!!! Seems to work fine.

Expanding on the answer Chris gave; I orient constrained the arm_L0_tws0_loc to arm_L0_mid_ctl and arm_L0_fk0_ctl. I think this helps lock the upper arm when in fk mode and rotating the arm_L0_fk1_ctl on multiple axis. Also preserves the armpit roll function. I Haven’t had any issues yet.

import maya.cmds as cmds

def arm_fk_lock():

	sides = ['L', 'R']

	for side in sides:
		fk_ctl = 'arm_'+side+'0_fk0_ctl'
		tws_loc = 'arm_'+side+'0_tws0_loc'
		mid_ctl = 'arm_'+side+'0_mid_ctl' 
		ui_ctl = 'armUI_'+side+'0_ctl'

		if cmds.objExists(fk_ctl):
			const = cmds.orientConstraint(fk_ctl, mid_ctl, tws_loc, skip=['y','z'], mo=False)[0]
			rev = cmds.createNode('reverse', name=tws_loc+'_rev')
			cmds.connectAttr(ui_ctl+'.arm_blend', rev+'.inputX')
			cmds.connectAttr(rev+'.outputX', const+'.'+fk_ctl+'W0')
			cmds.connectAttr(ui_ctl+'.arm_blend', const+'.'+mid_ctl+'W1')

		else:
			print 'Single sided rig?'
			pass
5 Likes

Hey,
Does anyone know how to do that for arm_2jnt_freeTangents_01? Can’t find the right node for that

Best,
K

This is how I did it - just in case someone is looking for it.
This connects it to the ‘main roll’ of the arm by referencing the rotation of the mid_ctl. This means rolling the lower arm will influence the roll of the upper arm.

import pymel.core as pm

for side in "LR":
    decomp_loc = pm.spaceLocator(name=f"armpitRollDecompensate_{side}_loc")
    pm.pointConstraint(f"arm_{side}0_mid_cns", decomp_loc)
    pm.orientConstraint(f"arm_{side}0_mid_cns", decomp_loc)
    
    pm.parent(decomp_loc, f"arm_{side}0_roll_ctl_npo")
    
    pm.connectAttr(decomp_loc.rotateX, f"arm_{side}0_tws0_rot.rotateX", force=True)

I needed the same for the 3jnt leg - robots being robots again…

And this did it for my specific case

import pymel.core as pm

for side in "LR":
    decomp_loc = pm.spaceLocator(name=f"hipRollDecompensate_{side}_loc")
    pm.pointConstraint(f"leg_{side}0_knee_ctl", decomp_loc)
    pm.orientConstraint(f"leg_{side}0_knee_ctl", decomp_loc)
    
    pm.parent(decomp_loc, f"leg_{side}0_rollChain0")
    
    pm.connectAttr(decomp_loc.rotateX, f"leg_{side}0_tws0_rot.rotateX", force=True)
2 Likes

And I needed to disconnect it from the lower arm as well essentially having no twist on the upper arm.
I’ll just orient-constraint it and drop the armpit roll. This might break what you’re doing in other ways.
Now… you have a whloe bunch of ways to try, hopefully one of them works for the specific case you’re working on.

( “you” is the person finding this from google in a few years :wink: )

rx_conn = pm.listConnections(f"arm_{side}0_tws0_rot.rotateX", source=True, destination=False, plugs=True, scn=True)[0]
pm.disconnectAttr(rx_conn, f"arm_{side}0_tws0_rot.rotateX")
pm.orientConstraint(f"arm_{side}0_0_bone", f"arm_{side}0_tws0_rot", skip=['z','y'])
2 Likes