Skip to content

Instantly share code, notes, and snippets.

@chris-lesage
Last active April 20, 2024 14:07
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save chris-lesage/0fcc9a344f2096cf6c82a353cb735b3e to your computer and use it in GitHub Desktop.
Save chris-lesage/0fcc9a344f2096cf6c82a353cb735b3e to your computer and use it in GitHub Desktop.
Autodesk Maya script to calculate pole vector position based on 3 input objects
import pymel.core as pm
'''
An Autodesk Maya PyMEL script that calculates a pole vector position
based on 3 input PyNode objects. example: leg, knee, ankle bones.
Chris Lesage chris@rigmarolestudio.com
'''
def calculate_pole_vector(p1, p2, p3, poleDistance=1):
"""
This function takes 3 PyMEL PyNodes as inputs.
Creates a pole vector position at a "nice" distance away from a triangle of positions.
Normalizes the bone lengths relative to the knee to calculate straight ahead
without shifting up and down if the bone lengths are different.
Returns a pymel.core.datatypes.Vector
"""
vec1 = p1.getTranslation(space='world') # "hips"
vec2 = p2.getTranslation(space='world') # "knee"
vec3 = p3.getTranslation(space='world') # "ankle"
# 1. Calculate a "nice distance" based on average of the two bone lengths.
legLength = (vec2-vec1).length()
kneeLength = (vec3-vec2).length()
distance = (legLength + kneeLength) * 0.5 * poleDistance
# 2. Normalize the length of leg and ankle, relative to the knee.
# This will ensure that the pole vector goes STRAIGHT ahead of the knee
# Avoids up-down offset if there is a length difference between the two bones.
vec1norm = ((vec1 - vec2).normal() * distance) + vec2
vec3norm = ((vec3 - vec2).normal() * distance) + vec2
# 3. given 3 points, calculate a pole vector position
mid = vec1norm + (vec2-vec1norm).projectionOnto(vec3norm-vec1norm)
# 4. Move the pole vector in front of the knee by the "nice distance".
midPointer = vec2 - mid
poleVector = (midPointer.normal() * distance) + vec2
return poleVector
import pymel.core as pm
# EXAMPLE script
poleControl = pm.PyNode('poleVector_ctrl')
p1 = pm.PyNode('leg_bone')
p2 = pm.PyNode('knee_bone')
p3 = pm.PyNode('ankle_bone')
polePosition = calculate_pole_vector(p1, p2, p3, poleDistance=1)
poleControl.setTranslation(polePosition, space='world')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment