Awesome Cedric! Thanks for the help. Figured it out with a little less code
this time. ;)
The next step would be figuring out how to use this technique for points on a
curve. The idea is to have a curve and a start Object with a certain
orientation and an end object with a Certain orientation and along the curve
blend between these two orientations. Similar to the Maya Spline IK Advanced
Twist.
Here's my lookAt / aim script version supporting a source object, aimTarget
object and upTarget object. (Supporting the up target was quite some
experimenting and thinking it through for me.)
Also supporting any x, y, z aim axis and up axis as long as they are orthogonal.
####
import maya.cmds as mc
import maya.OpenMaya as om
def getDependNodeByName( name ):
selList = om.MSelectionList ()
selList.add (name)
node = om.MObject()
selList.getDependNode (0, node)
return node
def getDagPathByName( name ):
selList = om.MSelectionList ()
selList.add (name)
node = om.MDagPath()
selList.getDagPath (0, node)
return node
def gsOrthonormalize( normal, tangent ):
# Gram-Schmidt Orthonormalization
normal.normalize()
proj = normal * ( tangent * normal ) # normal * dotProduct(tangent,normal)
tangent = tangent - proj
tangent.normalize()
return normal, tangent
srcNode = getDagPathByName("pSphere1")
targetNode = getDagPathByName("pCube1")
upNode = getDagPathByName("pCube2")
fnTransform = om.MFnTransform()
fnTransform.setObject(srcNode)
srcTransformMatrix = fnTransform.transformation()
srcPos = srcTransformMatrix.getTranslation(om.MSpace.kWorld)
fnTransform.setObject(targetNode)
aimTargetTransformMatrix = fnTransform.transformation()
aimTargetPos = aimTargetTransformMatrix.getTranslation(om.MSpace.kWorld)
fnTransform.setObject(upNode)
upTargetTransformMatrix = fnTransform.transformation()
upTargetPos = upTargetTransformMatrix.getTranslation(om.MSpace.kWorld)
"""
Step one: Aim the aimAxis
"""
basisAimVec = om.MVector(0,0,1)
aimVec = aimTargetPos - srcPos
upVec = upTargetPos - srcPos
quat = basisAimVec.rotateTo(aimVec) # give the quaternion rotation so that x
points to basisAimVec
# Maybe if we addRotationQuaternion we can support beyond 360? (so it will aim
to the closest value?)
# Because the MQuaternion and MTransformMatrix classes support information
beyond 360 degrees
srcTransformMatrix.setRotationQuaternion( quat.x, quat.y, quat.z, quat.w,
om.MSpace().kWorld )
"""
Step two: Aim the upAxis (twisting around the aimAxis)
"""
mat = srcTransformMatrix.asMatrix()
basisUpVec = om.MVector(1,0,0)
basisUpVecObject = basisUpVec * mat
"""
# Option 1: Gram-Schmidt Orthonormalization
"""
tempVec,upVec = gsOrthonormalize(aimVec,upVec)
"""
# Option 2: Remove any distance in aimAxis from upAxis so vector becomes
orthogonal to aimAxis
Remove the rotation we have from the lookAt from the upVector (from
upTargetPos-srcPos)
Then remove any translation in the aimAxis (so we exclude changing that when
calculating the quaternion)
upVec = upVec * mat.inverse()
upVec.x = 0 # currently requires to hard-code which axis is the aim axis, could
be done otherwise though
upVec = upVec * mat
"""
quat = basisUpVecObject.rotateTo(upVec)
srcTransformMatrix.addRotationQuaternion( quat.x, quat.y, quat.z, quat.w,
om.MSpace().kWorld );
# Set the adjusted matrix
fnTransform.setObject(srcNode)
fnTransform.set(srcTransformMatrix)
mc.refresh()
###
Let me know if you guys see anything that can be done easier or better.
Really appreciate the help.
-Roy
--
view archives: http://groups.google.com/group/python_inside_maya
change your subscription settings:
http://groups.google.com/group/python_inside_maya/subscribe