Using Vector Math to Rig an Arm…
Quick example on how to use vector math (mostly) to get the most out of locator based rigging. The following example makes a joint chain and a pole vector locator using 3 positions (Shoulder, elbow, and wrist). All the joint orientations and pole vector position are worked out automatically by the use of some simple subtraction addition and cross multiplication of vectors. In the future, I’m hoping to write a more in-depth explanation of my process. But, in the mean while I hope it helps those diving into auto rigging who might not be so fresh on vector math 🙂
The example is done in Maya, since Maya joints can have much different orientations than those visually displayed in the view-port.
Being that this snippet is in python, we must make use of the mayaAPIs vector and matrix classes which is a departure to the way in which we used to do it, in mel.
Here’s the snippet!
hope you find it useful 🙂
from maya import cmds import maya.api.OpenMaya as om def makeIkPlaneSetup(helpers, poleVectorDistance=5.0): if len(helpers) != 3: raise Exception('makeIkPlaneSetup input error, you need objects to pull positions from there were %s inputs\n' % len(helpers)) shld = om.MVector(cmds.xform(helpers[0],q=True,ws=True,t=True)) elbow = om.MVector(cmds.xform(helpers[1],q=True,ws=True,t=True)) wrist = om.MVector(cmds.xform(helpers[2],q=True,ws=True,t=True)) #figure out the upNode (plane direction) planeX = wrist - shld planeXL = planeX.length() armDis = (elbow - shld).length() foreArmDis = (wrist-elbow).length() fraction = armDis/(foreArmDis+armDis) planeP = shld + (planeX.normalize() * (planeXL*fraction)) upNode = (elbow-planeP).normalize() pvPos = shld + (upNode * poleVectorDistance) #shoulder orintation matrix shdXAxis = (elbow-shld).normalize() shdYAxis = (upNode ^ shdXAxis).normalize() #cross product a noramalize.... shdZAxis = (shdXAxis ^ shdYAxis).normalize() #cross product a noramalize.... shldM = om.MMatrix([[shdXAxis.x,shdXAxis.y,shdXAxis.z,0], [shdYAxis.x,shdYAxis.y,shdYAxis.z,0], [shdZAxis.x,shdZAxis.y,shdZAxis.z,0], [shld.x,shld.y,shld.z,1]]) elbowXAxis = (wrist-elbow).normalize() elbowYAxis = shdYAxis elbowZAxis = (elbowXAxis ^ elbowYAxis).normalize() elbowM = om.MMatrix([[elbowXAxis.x,elbowXAxis.y,elbowXAxis.z,0], [elbowYAxis.x,elbowYAxis.y,elbowYAxis.z,0], [elbowZAxis.x,elbowZAxis.y,elbowZAxis.z,0], [elbow.x,elbow.y,elbow.z,1]]) wristM = om.MMatrix([[elbowXAxis.x,elbowXAxis.y,elbowXAxis.z,0], [elbowYAxis.x,elbowYAxis.y,elbowYAxis.z,0], [elbowZAxis.x,elbowZAxis.y,elbowZAxis.z,0], [wrist.x,wrist.y,wrist.z,1]]) pvM = om.MMatrix([[shdXAxis.x,shdXAxis.y,shdXAxis.z,0], [shdYAxis.x,shdYAxis.y,shdYAxis.z,0], [shdZAxis.x,shdZAxis.y,shdZAxis.z,0], [pvPos.x,pvPos.y,pvPos.z,1]]) #convert matrix values to list for xform input shldML = [v for v in shldM] elbowML = [v for v in elbowM] wristML = [v for v in wristM] pvML = [v for v in pvM] #make pole vector point pv = cmds.spaceLocator() cmds.select(clear=True) #we'll keep joints parented to avoid rotation offset which maya creates when parenting joints post creation shldJ = cmds.joint() elbowJ = cmds.joint() wristJ = cmds.joint() cmds.xform(shldJ,ws=True,m=shldML) cmds.xform(elbowJ,ws=True,m=elbowML) cmds.xform(wristJ,ws=True,m=wristML) cmds.xform(pv,ws=True,m=pvML) makeIkPlaneSetup(cmds.ls(sl=True))