Skip to content

Instantly share code, notes, and snippets.

@rondreas
Last active September 19, 2017 16:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rondreas/7390736b5c3c5312c3bfdd7745dcd7d6 to your computer and use it in GitHub Desktop.
Save rondreas/7390736b5c3c5312c3bfdd7745dcd7d6 to your computer and use it in GitHub Desktop.
import pymel.core as pymel
import maya.api.OpenMaya as om
def flattenAlongPlane(joints):
# Get worldspace position every joint but for first and last, and get their average position
vectors = [om.MVector(pymel.joint(x,q=True, p=True, a=True)) for x in joints[1:-1]]
avg = om.MPoint([sum(v)/len(vectors) for v in zip(*vectors)])
p1 = om.MPoint(pymel.joint(joints[0], q=True, p=True, a=True))
p2 = om.MPoint(pymel.joint(joints[-1], q=True, p=True, a=True))
# Get normal, by getting cross product of avg point to both start and end point
normal = om.MVector(avg - p1) ^ om.MVector(avg - p2)
# Create a plane and set it's normal
mPlane = om.MPlane()
mPlane.setPlane(normal.normalize(), 0)
# Get distance to our avg point
d = mPlane.distanceToPoint(om.MVector(avg))
# Set plane to our point average
mPlane.setPlane(normal.normalize(), d)
# Unparent last joint to not have translation propage further than selected section
pymel.parent(joints[-1], world = True)
for joint in joints[1:-1]:
pos = om.MVector(pymel.joint(joint, q=True, p=True, a=True))
distance = mPlane.distanceToPoint(pos)
# Dot product to check if joint is below or above desired plane.
r = normal * om.MVector(om.MPoint(pos) - avg)
nPos = None
if r > 0:
nPos = om.MVector(pos - om.MVector(normal*distance))
elif r < 0:
nPos = om.MVector(pos - om.MVector(normal*-distance))
else:
# Point is on our plane
pass
# Unsure about me flagging for children, don't think I am using
pymel.joint(joint, e = True, p = nPos, a = True)
pymel.parent(joints[-1], joints[-2])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment