2
$\begingroup$

My character rig needs shape key correctives when it makes certain poses (eg. lifting the arms, the shoulders need to be corrected with a shape key so they don't lose volume).

I know you use a driver for that, but the way I find it in books and tutorials is to use a "Rotational Difference" driver between two bones (like between an arm bone and a reference bone pointing in the direction that should activate the shape key, so the driver is 1.0 - rotDifference), and use that driver on the shape key. Like this:

shapekey driver panel shapekey driver working

The problem is that this driver doesn't work well for this, because when the bones roll around their aim vectors (without changing their actual directions), it still triggers the shape key:

shapekey driver problem

How else can I activate shape key correctives based on the rotation between two bones (and only their directions)?

$\endgroup$
2
$\begingroup$

For an ultra-fast driver for corrective shape keys based on the angle between two bones, you can use this one:

posereader driver panel

The driver type is Scripted Expression, with this line:

poseBones[A].matrix.col[1] * poseBones[B].matrix.col[1]

It's the dot product of the bones' aim vectors, a mechanism known as a "pose reader", used with pose space deformation (PSD). As the bones rotate during animation or posing, the driver will output a value in the range [-1, +1], going from -1 when the bones point in opposite directions, up to 0 when they become perpendicular, up to +1 when they point in the same direction.

Replace A and B in the expression with the indices of the bones in the Pose Bones collection of the armature. The only way to find these indices is by using Python. It's simple:
Select your armature object, change the editor to Python Console and type this line:

C.object.pose.bones.find("My Bone")

Instead of "My Bone", use the name of the bone you want to find the index of inside those quotes, then press Enter to see the result. Do the same for the other bone. You'll have two numbers, like "12" and "103" for example. Put them in the expression (in any order), inside the poseBone brackets:

poseBones[103].matrix.col[1] * poseBones[12].matrix.col[1]

Next, the driver variables are:

  • A Single Property type variable (named 'poseBones' to be used in that expression), with the id-block type set to Object, and the object being your armature that has the two bones involved.
    The actual path to the property is pose.bones, write this in that field.
  • A Transform Channel type variable, it needs to point to any bone in that armature (any indeed, like the root bone). This variable is unused but is an essential piece, it's a way to force the driver to be evaluated every time a bone in your armature moves (from animation or posing).
    Set the channel type and space to Location X and World Space, respectively, which makes this very fast to evaluate.

Notes: the two bones used in the expression should not be animated in scale (either their own or inherited scale from their parents), they should only be animated in position and rotation (you can add child bones to them and animate the scale of the child, if necessary).
They need to have a scale of exactly 1 for the entire animation, otherwise this will mess with the speed of the driver because it affects the length of the matrix.col[1] vector.
If you need to, you can adjust the timing and speed of this driver by playing with the driver graph curve, like using easing or bezier handles.

Your driver is ready to be used, with no roll changes or sudden flips.

posereader driver working

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.