Automatic Polevector Correction

The polevector (green) is not co-planar (in line with) the joints (navy) that it will be connected to

I created a script to automatically correct the position of polevector controllers. This helps when rigging IK systems, as if the controller is not perfectly in line with the IK, the knee/elbow will snap to face the polevector and have non-zero rotations by default.

While working on my rigging tools, I came up with a way to tweak the position of polevectors (PVs) in IK systems so they are perfectly co-planar with their joints. I could have written an algorithm to calculate the coordinates of the closest point normal to the plane described by the 3 joint origins used in a simple IK system, however I realised that an IK system already does this.

What I decided to do was to create a temporary IK system, where the middle joint and the PV swap positions. Now they are perfectly co-planar, so we just need to delete the constraint and swap their positions again.

Below is a manual example of how this works:

Now all that needs to be done is to delete the temporary IK joints and PV, and freeze the PV into its new position.

Here is a python script to automate this:

'''
correct_pv
@author: Michael Stickler
repositions the polevector to be co-planar to the IK joints
select the joints, top, middle then end, then select the polevector
then run the following code:

import pymel.core as pm
import correct_pv

correct_pv.correct(*pm.selected()[:4])
'''
import pymel.core as pm
def snap_to(obj, target, **kwargs):
    '''
    snap the first object to the target, can specify to limit to just translate or rotate
    '''
    translate = kwargs.setdefault("translate", True)
    rotate = kwargs.setdefault("rotate", True)

    if translate:
        point = pm.pointConstraint(target, obj)
        pm.delete(point)

    if rotate:
        orient = pm.orientConstraint(target, obj)
        pm.delete(orient)
def correct(joint1, joint2, joint3, polevector):
    '''move the polevector to be coplanar with the IK joints.'''
    # new 3 joints
    sel = pm.selected()
    pm.select(d=True)
    new1 = pm.joint()
    new2 = pm.joint()
    new3 = pm.joint()

    # snap n1 to j1, n2 to polevector, n3 to j3
    snap_to(new1, joint1, rotate=False)
    snap_to(new2, polevector, rotate=False)
    snap_to(new3, joint3, rotate=False)

    # snap polevector to joint2
    snap_to(polevector, joint2, rotate=False)

    # ik rp on n1-n3
    temp_ik = pm.ikHandle(sj=new1, ee=new3, sol="ikRPsolver")

    # polevector new hdl to polevector
    pm.poleVectorConstraint(polevector, temp_ik[0])

    pm.refresh(f=True)
    # delete new eff, and hdl

    pm.delete(temp_ik[0])

    # snap polevector to n2
    snap_to(polevector, new2, rotate=False)

    # delete n1-n3
    pm.delete(new1, new2, new3)

    # reselect
    pm.select(sel)

Leave a Reply

Your email address will not be published. Required fields are marked *