A Quick setup Orient Rig / Look At Constraint. There are times it is simpler and far more convenient to animate orientations in a look-at style situation.
Copy the code below and put it in a shelf icon in Maya. Select the object you wish to set up, and hit the button.
Pick your Up and Out axis (the option for reverse axis is there, -X, -Y, -Z) and GO!
# IK Orientation Control
# Created By Jason Dixon. http://internetimagery.com
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
import pymel.core as pmc
import maya.api.OpenMaya as om
def message(text):
pmc.confirmDialog(t="Uh oh...", m=text)
class Orient(object):
""" Orient setup using IK-like system """
AXIS = ("X","Y","Z","-X","-Y","-Z")
def __init__(s, obj):
if len(obj) != 1: return message("You must only select one Object")
s.obj = obj[0]
name = "ikorientwin"
if pmc.window(name, ex=True): pmc.deleteUI(name)
with pmc.window(name, t="IK-Like Orient Constraint") as s.win:
with pmc.columnLayout(adj=True):
s.fwd = pmc.optionMenuGrp(l="Forward Axis")
for ax in s.AXIS: pmc.menuItem(l=ax)
s.up = pmc.optionMenuGrp(l="Up Axis")
for ax in s.AXIS: pmc.menuItem(l=ax)
pmc.button(l="GO!", c=s.build)
def build(s, *_):
""" Build Setup """
err = None
cmds.undoInfo(openChunk=True)
try:
fwd = s.AXIS.index(s.fwd.getValue())
up = s.AXIS.index(s.up.getValue())
up, up_dir = (up, 1) if up < 3 else (up - 3, -1)
fwd, fwd_dir = (fwd, 1) if fwd < 3 else (fwd - 3, -1)
if up == fwd: return message("The two axis must be different.")
matrix = tuple(om.MVector(a[:3]) for a in s.obj.getMatrix(ws=True))
b_box = s.obj.getBoundingBox()
b_size = (b_box.width(), b_box.height(), b_box.depth())
cam_pos = om.MVector(pmc.modelEditor(pmc.playblast(ae=True), q=True, cam=True).getTranslation("world"))
offset = (cam_pos - matrix[3]).length() * 0.1
fwd_pos = matrix[fwd].normalize() * fwd_dir * (b_size[fwd] * 0.5 + offset) + matrix[3]
up_pos = matrix[up].normalize() * up_dir * (b_size[up] * 0.5 + offset) + matrix[3]
def locator(name, pos):
loc = pmc.spaceLocator(n="%s_%s" % (s.obj, name))
arrow = pmc.annotate(s.obj, tx="", p=(0,0,0))
arrow.template.set(1)
pmc.parent(arrow, loc)
shape = loc.setPosition(pos)
for ax in s.AXIS[:3]:
pmc.setAttr("%s.localScale%s" % (shape, ax), offset * 0.5)
return loc
fwd_loc = locator("forward", fwd_pos)
up_loc = locator("up", up_pos)
control = pmc.group(em=True, n="%s_attach" % s.obj)
pmc.pointConstraint(s.obj, control)
pmc.aimConstraint(
fwd_loc.name(),
control.name(),
worldUpType="object",
worldUpObject=up_loc.name()
)
pmc.orientConstraint(control, s.obj, mo=True)
pmc.group(fwd_loc, up_loc, control, n="%s_Orient_IK" % s.obj)
pmc.select(fwd_loc, r=True)
pmc.deleteUI(s.win)
except Exception as err:
raise
finally:
cmds.undoInfo(closeChunk=True)
if err: cmds.undo()
Orient(pmc.ls(sl=True, type="transform"))