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) pm.refresh(f=True) # delete new eff, and hdl pm.delete(temp_ik) # snap polevector to n2 snap_to(polevector, new2, rotate=False) # delete n1-n3 pm.delete(new1, new2, new3) # reselect pm.select(sel)