Skip to content

Instantly share code, notes, and snippets.

@Muream
Created May 3, 2022 13:43
Show Gist options
  • Save Muream/32dcdf95163728efbd77a41ccb958624 to your computer and use it in GitHub Desktop.
Save Muream/32dcdf95163728efbd77a41ccb958624 to your computer and use it in GitHub Desktop.
Ensure Planar Orientation Maya
import maya.api.OpenMaya as om2
from maya import cmds
def ensure_planar_orientation(transform_a, transform_b, transform_c):
"""Orients the three given transform based on the plane they form.
X axis aims at the next transform.
Z axis is the normal axis to the plane.
Y axis is the tertiary axis, computed based on the 2 previous ones.
"""
a = om2.MVector(
cmds.xform(transform_a, query=True, translation=True, worldSpace=True)
)
b = om2.MVector(
cmds.xform(transform_b, query=True, translation=True, worldSpace=True)
)
c = om2.MVector(
cmds.xform(transform_c, query=True, translation=True, worldSpace=True)
)
# get the aim vectors for transforms a and b.
# this will be the X axis of our transforms.
ab_vec = (b - a).normal()
bc_vec = (c - b).normal()
# The normal vector is the cross product of the two vectors defining our plane
# This will be the Z Axis of our transforms.
# It is the same for all the joints.
plane_normal_vec = (ab_vec ^ bc_vec).normal()
# the tertiary vector is simply a cross product of the aim and normal vectors
# This will be the Y Axis of our transforms.
a_tertiary_vec = (plane_normal_vec ^ ab_vec).normal()
b_tertiary_vec = (plane_normal_vec ^ bc_vec).normal()
# fmt: off
# We construct the matrix of each transform based on the computed vectors
transform_a_matrix = om2.MMatrix([
ab_vec.x, ab_vec.y, ab_vec.z, 0,
a_tertiary_vec.x, a_tertiary_vec.y, a_tertiary_vec.z, 0,
plane_normal_vec.x, plane_normal_vec.y, plane_normal_vec.z, 0,
a.x, a.y, a.z, 1,
])
transform_b_matrix = om2.MMatrix([
bc_vec.x, bc_vec.y, bc_vec.z, 0,
b_tertiary_vec.x, b_tertiary_vec.y, b_tertiary_vec.z, 0,
plane_normal_vec.x, plane_normal_vec.y, plane_normal_vec.z, 0,
b.x, b.y, b.z, 1,
])
# Transform `c` has the same orientation as `b` but uses its own translation
transform_c_matrix = om2.MMatrix([
bc_vec.x, bc_vec.y, bc_vec.z, 0,
b_tertiary_vec.x, b_tertiary_vec.y, b_tertiary_vec.z, 0,
plane_normal_vec.x, plane_normal_vec.y, plane_normal_vec.z, 0,
c.x, c.y, c.z, 1,
])
# fmt: on
# Finally we apply those matrices onto the actual transforms
cmds.xform(transform_a, matrix=transform_a_matrix, worldSpace=True)
cmds.xform(transform_b, matrix=transform_b_matrix, worldSpace=True)
cmds.xform(transform_c, matrix=transform_c_matrix, worldSpace=True)
if __name__ == "__main__":
ensure_planar_orientation(*cmds.ls(sl=True))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment