Beispiel #1
0
def getAverageNodeDirectionVector(nodes, axis = mayaMathUtil.Axis()):
    averageDir = om.MVector()
    
    for node in nodes:
        orientation = mayaMathUtil.eulerToDirectionVector(getObjectWorldOrientation(node), axis)
        averageDir.x += orientation[0]
        averageDir.y += orientation[1]
        averageDir.z += orientation[2]
                    
    averageDir.normalize()
    
    #force a direction vector if one isn't found
    if(averageDir.x == 0 and averageDir.y == 0 and averageDir.z == 0):
        averageDir.x = 1
                    
    return averageDir
def coplanarizeJoints(chainEnd,
                      chainRoot,
                      plane,
                      forwardAxis=mayaMathUtil.Axis(axis=0),
                      rotationAxis=mayaMathUtil.Axis(axis=2)):
    if (chainRoot is None or chainEnd is None or plane is None):
        return

    currJoint = chainEnd
    lastJoint = None

    while currJoint:
        currChildren = mayaUtil.getObjectChildren(currJoint)

        #unparent all children so this joint can move safely without affecting children
        if (currChildren is not None):
            for child in currChildren:
                cmds.parent(child, world=True)

        oldPos = mayaUtil.getJointWorldPosition(currJoint)
        oldOrient = mayaUtil.getObjectWorldOrientation(currJoint)

        #cmds.makeIdentity(currJoint, apply=True, translate=True, rotate=True, scale=True, jointOrient=True)

        #project the joint to the plane
        newPos = mayaMathUtil.closestPointOnPlane(plane=plane, point=oldPos)

        cmds.xform(currJoint,
                   absolute=True,
                   worldSpace=True,
                   translation=[newPos.x, newPos.y, newPos.z])

        #now orient the joint
        #don't orient if this is the last child in the chain and it has children of its own
        if (lastJoint is not None
                or (lastJoint is None and currChildren is None)):
            deleteAimTarget = False
            aimTarget = lastJoint

            #if no lastJoint, this is the last child in the joint chain so project its previous aim direction to a point on the plane and aim it in that direction to keep it approximately the same
            #there's probably a more mathematically correct way to do this but whatever...
            if (lastJoint is None):
                deleteAimTarget = True
                aimLocation = mayaMathUtil.closestPointOnPlane(
                    plane=plane,
                    point=oldPos + mayaMathUtil.eulerToDirectionVector(
                        oldOrient, forwardAxis) * 10)
                aimTarget = cmds.spaceLocator()
                cmds.xform(
                    aimTarget,
                    worldSpace=True,
                    absolute=True,
                    translation=[aimLocation.x, aimLocation.y, aimLocation.z])

            aimVector = mayaMathUtil.forwardVector(forwardAxis)
            turnVector = mayaMathUtil.forwardVector(rotationAxis)

            #not sure how else to do this easily, the idea is taken from Comet Joint Orient
            tempAimConstraint = cmds.aimConstraint(
                aimTarget,
                currJoint,
                weight=1,
                aimVector=[aimVector.x, aimVector.y, aimVector.z],
                upVector=[turnVector.x, turnVector.y, turnVector.z],
                worldUpVector=[
                    plane.normal().x,
                    plane.normal().y,
                    plane.normal().z
                ],
                worldUpType="vector")
            cmds.delete(tempAimConstraint)

            #delete the temporary locator we created if lastJoint was None
            if (deleteAimTarget):
                cmds.delete(aimTarget)

        cmds.joint(currJoint, edit=True, zeroScaleOrient=True)

        if (currChildren is not None):
            for child in currChildren:
                cmds.parent(child, currJoint)
                cmds.makeIdentity(child, apply=True, jointOrient=False)

        if (currJoint == chainRoot):
            return

        lastJoint = currJoint
        currJoint = mayaUtil.getObjectParent(currJoint)

    return
def coplanarizeJoints(chainEnd, chainRoot, plane, forwardAxis = mayaMathUtil.Axis(axis=0), rotationAxis = mayaMathUtil.Axis(axis=2)):    
    if(chainRoot is None or chainEnd is None or plane is None):
        return

    currJoint = chainEnd
    lastJoint = None
    
    while currJoint:        
        currChildren = mayaUtil.getObjectChildren(currJoint)
        
        #unparent all children so this joint can move safely without affecting children
        if(currChildren is not None):
            for child in currChildren:
                cmds.parent(child, world=True)
                
        oldPos = mayaUtil.getJointWorldPosition(currJoint)
        oldOrient = mayaUtil.getObjectWorldOrientation(currJoint)
                
        #cmds.makeIdentity(currJoint, apply=True, translate=True, rotate=True, scale=True, jointOrient=True)
        
        #project the joint to the plane
        newPos = mayaMathUtil.closestPointOnPlane(plane=plane, point=oldPos)
                        
        cmds.xform(currJoint, absolute=True, worldSpace=True, translation=[newPos.x, newPos.y, newPos.z])
                                
        #now orient the joint
        #don't orient if this is the last child in the chain and it has children of its own
        if(lastJoint is not None or (lastJoint is None and currChildren is None)):
            deleteAimTarget = False
            aimTarget = lastJoint
            
            #if no lastJoint, this is the last child in the joint chain so project its previous aim direction to a point on the plane and aim it in that direction to keep it approximately the same
            #there's probably a more mathematically correct way to do this but whatever...
            if(lastJoint is None):
                deleteAimTarget = True
                aimLocation = mayaMathUtil.closestPointOnPlane(plane=plane, point=oldPos + mayaMathUtil.eulerToDirectionVector(oldOrient, forwardAxis) * 10)
                aimTarget = cmds.spaceLocator()
                cmds.xform(aimTarget, worldSpace=True, absolute=True, translation=[aimLocation.x, aimLocation.y, aimLocation.z])
            
            aimVector = mayaMathUtil.forwardVector(forwardAxis)
            turnVector = mayaMathUtil.forwardVector(rotationAxis)
    
            #not sure how else to do this easily, the idea is taken from Comet Joint Orient
            tempAimConstraint = cmds.aimConstraint(aimTarget, currJoint, weight=1, aimVector=[aimVector.x, aimVector.y, aimVector.z], upVector=[turnVector.x, turnVector.y, turnVector.z], worldUpVector=[plane.normal().x, plane.normal().y, plane.normal().z], worldUpType="vector")        
            cmds.delete(tempAimConstraint)
            
            #delete the temporary locator we created if lastJoint was None
            if(deleteAimTarget):
                cmds.delete(aimTarget)
        
        cmds.joint(currJoint, edit=True, zeroScaleOrient=True)
                
        if(currChildren is not None):
            for child in currChildren:
                cmds.parent(child, currJoint)
                cmds.makeIdentity(child, apply=True, jointOrient=False)
        
        if(currJoint == chainRoot):
            return
            
        lastJoint = currJoint
        currJoint = mayaUtil.getObjectParent(currJoint)

    return