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

Reply via email to