示例#1
0
def align( src, tgt, key=False ):
	'''
	this is separated into a separate proc, because its less "user friendly" ie require less syntax to work
	its better to call zooAlign in non speed intensive operations because the syntax for this command may change
	if the scope of the script is expanded in future - ie I add more functionality
	'''
	try:
		#grab the positions and rotations of the src object in world space
		srcRp = OpenMaya.MVector( *cmd.getAttr( src +'.rp' )[0] )
		srcMatrix = api.getMDagPath( src ).inclusiveMatrix()
		srcRp *= srcMatrix

		tgtRp = OpenMaya.MVector( *cmd.getAttr( tgt +'.rp' )[0] )
		tgtMatrix = api.getMDagPath( tgt ).exclusiveMatrix()
		tgtMatrixInv = api.getMDagPath( tgt ).exclusiveMatrixInverse()
		tgtRp *= tgtMatrix

		print mayaVectors.MayaVector( tgtRp )
		xformMatrix = srcMatrix * tgtMatrixInv
		new = mayaVectors.MayaMatrix( xformMatrix )

		pos = new.get_position() - mayaVectors.MayaVector( tgtRp ) + mayaVectors.MayaVector( srcRp )
		cmd.setAttr( tgt +'.t', *pos )
		cmd.setAttr( tgt +'.r', *new.get_rotXYZ( asdeg=True ) )
		raise Exception

		srcRo = kM_ROOS[ cmd.getAttr( src +".ro" ) ]
		tgtRo = kM_ROOS[ cmd.getAttr( tgt +".ro" ) ]
		rot = OpenMaya.MVector( *cmd.xform(src, q=True, ws=True, ro=True) )
		rot = OpenMaya.MEulerRotation( rot, srcRo ).asMatrix()
		tgtXformMatrixInv = api.getMDagPath( tgt ).exclusiveMatrixInverse()
	except RuntimeError, x:
		print 'ERRR', x
		return
示例#2
0
def bakeManualRotateDelta( src, ctrl, presetStr ):
	'''
	When you need to apply motion from a skeleton that is completely different from a skeleton driven
	by the rig you're working with (transferring motion from old assets to newer assets for example)
	you can manually align the control to the joint and then use this function to generate offset
	rotations and bake a post trace cmd.
	'''
	srcMat = api.getMDagPath( src ).inclusiveMatrix()
	ctrlMat = api.getMDagPath( ctrl ).inclusiveMatrix()

	#generate the offset matrix as
	mat_o = ctrlMat * srcMat.inverse()

	##put it into the space of the control
	#ctrlLocalMat = api.getMDagPath( ctrl ).exclusiveMatrixInverse()
	#mat_o = mat_o * ctrlLocalMat

	#now figure out the euler rotations for the offset
	tMat = api.OpenMaya.MTransformationMatrix( mat_o )
	asEuler = tMat.rotation().asEulerRotation()
	asEuler = map(api.OpenMaya.MAngle, (asEuler.x, asEuler.y, asEuler.z))
	asEuler = tuple( a.asDegrees() for a in asEuler )

	api.mel.zooSetPostTraceCmd( ctrl, presetStr % asEuler )
	#api.mel.zooAlign( "-src %s -tgt %s -postCmds 1" % (src, ctrl) )

	return asEuler
示例#3
0
def align(src, tgt, key=False):
    '''
	this is separated into a separate proc, because its less "user friendly" ie require less syntax to work
	its better to call zooAlign in non speed intensive operations because the syntax for this command may change
	if the scope of the script is expanded in future - ie I add more functionality
	'''
    try:
        #grab the positions and rotations of the src object in world space
        srcRp = OpenMaya.MVector(*cmd.getAttr(src + '.rp')[0])
        srcMatrix = api.getMDagPath(src).inclusiveMatrix()
        srcRp *= srcMatrix

        tgtRp = OpenMaya.MVector(*cmd.getAttr(tgt + '.rp')[0])
        tgtMatrix = api.getMDagPath(tgt).exclusiveMatrix()
        tgtMatrixInv = api.getMDagPath(tgt).exclusiveMatrixInverse()
        tgtRp *= tgtMatrix

        print mayaVectors.MayaVector(tgtRp)
        xformMatrix = srcMatrix * tgtMatrixInv
        new = mayaVectors.MayaMatrix(xformMatrix)

        pos = new.get_position() - mayaVectors.MayaVector(
            tgtRp) + mayaVectors.MayaVector(srcRp)
        cmd.setAttr(tgt + '.t', *pos)
        cmd.setAttr(tgt + '.r', *new.get_rotXYZ(asdeg=True))
        raise Exception

        srcRo = kM_ROOS[cmd.getAttr(src + ".ro")]
        tgtRo = kM_ROOS[cmd.getAttr(tgt + ".ro")]
        rot = OpenMaya.MVector(*cmd.xform(src, q=True, ws=True, ro=True))
        rot = OpenMaya.MEulerRotation(rot, srcRo).asMatrix()
        tgtXformMatrixInv = api.getMDagPath(tgt).exclusiveMatrixInverse()
    except RuntimeError, x:
        print 'ERRR', x
        return
示例#4
0
    def applyToObj(self, obj=None, applyAsWorld=False, clearFirst=False):
        '''applies the current clip to an object - if the animation is being applied as world space, first check to make
		sure the world space animation for the clip exists.  then separate the transform channels out of the channels list
		and apply them as world space data.  then we need to apply the rest of the channels as per normal'''
        if obj is None:
            obj = self.obj

        if applyAsWorld and self.hasWorld:
            for matrix in self.world:
                cmd.currentTime(matrix.time)
                tfn = OpenMaya.MFnTransform(api.getMDagPath(obj))
                tfn.set(OpenMaya.MTransformationMatrix(key[0]))
            '''nonTransformChannels = []
			for channel in self.channels:
				if channel.attr not in g_validWorldAttrs: nonTransformChannels.append(channel)

			frames = self.as_frames(transformChannels)
			for channel in self.world:
				tgtAttrpath = obj +'.'+ channel.attr
				channel.applyToObj(obj,applyAsWorld)

			#run a euler filter over the resulting rotation animation - converting to world space
			#rotations often causes all sorts of nasty euler flips
			maya.mel.eval('filterCurve %s.rx %s.ry %s.rz;'%(obj,obj,obj))

			for channel in transformChannels:
				channel.applyToObj(obj)'''
        else:
            for channel in self.channels.values():
                channel.applyToObj(obj, clearFirst=clearFirst)
示例#5
0
	def applyToObj( self, obj=None, applyAsWorld=False, clearFirst=False ):
		'''applies the current clip to an object - if the animation is being applied as world space, first check to make
		sure the world space animation for the clip exists.  then separate the transform channels out of the channels list
		and apply them as world space data.  then we need to apply the rest of the channels as per normal'''
		if obj is None:
			obj = self.obj

		if applyAsWorld and self.hasWorld:
			for matrix in self.world:
				cmd.currentTime(matrix.time)
				tfn = OpenMaya.MFnTransform( api.getMDagPath(obj) )
				tfn.set( OpenMaya.MTransformationMatrix( key[0] ) )

			'''nonTransformChannels = []
			for channel in self.channels:
				if channel.attr not in g_validWorldAttrs: nonTransformChannels.append(channel)

			frames = self.as_frames(transformChannels)
			for channel in self.world:
				tgtAttrpath = obj +'.'+ channel.attr
				channel.applyToObj(obj,applyAsWorld)

			#run a euler filter over the resulting rotation animation - converting to world space
			#rotations often causes all sorts of nasty euler flips
			maya.mel.eval('filterCurve %s.rx %s.ry %s.rz;'%(obj,obj,obj))

			for channel in transformChannels:
				channel.applyToObj(obj)'''
		else:
			for channel in self.channels.values():
				channel.applyToObj(obj,clearFirst=clearFirst)
示例#6
0
def getJointBounds(joints, threshold=0.65, space=SPACE_OBJECT):
    '''
	if the joints are skinned, then the influenced verts that have weights greater than the given
	influenced are transformed into the space specified (if SPACE_OBJECT is used, the space of the
	first joint is used), and the bounds of the verts in this space are returned as a 2-tuple of
	bbMin, bbMax
	'''

    global MVector, MTransformationMatrix, Vector

    if not isinstance(joints, (list, tuple)):
        joints = [joints]

    theJoint = joints[0]
    verts = []

    for j in joints:
        verts += meshUtils.jointVertsForMaya(j, threshold)

    jointDag = api.getMDagPath(theJoint)

    if space == SPACE_OBJECT:
        jointMatrix = jointDag.inclusiveMatrix()
    elif space == SPACE_LOCAL:
        jointMatrix = jointDag.exclusiveMatrix()
    elif space == SPACE_WORLD:
        jointMatrix = OpenMaya.MMatrix()
    else:
        raise TypeError("Invalid space specified")

    vJointPos = MTransformationMatrix(jointMatrix).rotatePivot(
        kWorld) + MTransformationMatrix(jointMatrix).getTranslation(kWorld)
    vJointPos = Vector([vJointPos.x, vJointPos.y, vJointPos.z])

    vJointBasisX = MVector(-1, 0, 0) * jointMatrix
    vJointBasisY = MVector(0, -1, 0) * jointMatrix
    vJointBasisZ = MVector(0, 0, -1) * jointMatrix

    bbox = MBoundingBox()
    for vert in verts:
        #get the position relative to the joint in question
        vPos = Vector(xform(vert, query=True, ws=True, t=True))
        vPos = vJointPos - vPos

        #now transform the joint relative position into the coordinate space of that joint
        #we do this so we can get the width, height and depth of the bounds of the verts
        #in the space oriented along the joint
        vPosInJointSpace = Vector(vPos)
        vPosInJointSpace = vPosInJointSpace.change_space(
            vJointBasisX, vJointBasisY, vJointBasisZ)

        bbox.expand(MPoint(*vPosInJointSpace))

    bbMin, bbMax = bbox.min(), bbox.max()
    bbMin = Vector([bbMin.x, bbMin.y, bbMin.z])
    bbMax = Vector([bbMax.x, bbMax.y, bbMax.z])

    return bbMin, bbMax
示例#7
0
def getJointBounds( joints, threshold=0.65, space=SPACE_OBJECT ):
	'''
	if the joints are skinned, then the influenced verts that have weights greater than the given
	influenced are transformed into the space specified (if SPACE_OBJECT is used, the space of the
	first joint is used), and the bounds of the verts in this space are returned as a 2-tuple of
	bbMin, bbMax
	'''

	global MVector, MTransformationMatrix, Vector

	if not isinstance( joints, (list, tuple) ):
		joints = [ joints ]

	theJoint = joints[ 0 ]
	verts = []

	for j in joints:
		verts += meshUtils.jointVertsForMaya( j, threshold )

	jointDag = api.getMDagPath( theJoint )

	if space == SPACE_OBJECT:
		jointMatrix = jointDag.inclusiveMatrix()
	elif space == SPACE_LOCAL:
		jointMatrix = jointDag.exclusiveMatrix()
	elif space == SPACE_WORLD:
		jointMatrix = OpenMaya.MMatrix()
	else: raise TypeError( "Invalid space specified" )

	vJointPos = MTransformationMatrix( jointMatrix ).rotatePivot( kWorld ) + MTransformationMatrix( jointMatrix ).getTranslation( kWorld )
	vJointPos = Vector( [vJointPos.x, vJointPos.y, vJointPos.z] )

	vJointBasisX = MVector(-1,0,0) * jointMatrix
	vJointBasisY = MVector(0,-1,0) * jointMatrix
	vJointBasisZ = MVector(0,0,-1) * jointMatrix

	bbox = MBoundingBox()
	for vert in verts:
		#get the position relative to the joint in question
		vPos = Vector( xform( vert, query=True, ws=True, t=True ) )
		vPos = vJointPos - vPos

		#now transform the joint relative position into the coordinate space of that joint
		#we do this so we can get the width, height and depth of the bounds of the verts
		#in the space oriented along the joint
		vPosInJointSpace = Vector( vPos )
		vPosInJointSpace = vPosInJointSpace.change_space( vJointBasisX, vJointBasisY, vJointBasisZ )

		bbox.expand( MPoint( *vPosInJointSpace ) )

	bbMin, bbMax = bbox.min(), bbox.max()
	bbMin = Vector( [bbMin.x, bbMin.y, bbMin.z] )
	bbMax = Vector( [bbMax.x, bbMax.y, bbMax.z] )

	return bbMin, bbMax
示例#8
0
def getAlignedBoundsForJoint(joint, threshold=0.65, onlyVisibleMeshes=True):
    '''
	looks at the verts the given joint/s and determines a local space (local to the first joint
	in the list if multiple are given) bounding box of the verts, and positions the hitbox
	accordingly

	if onlyVisibleMeshes is True, then only meshes that are visible in the viewport will
	contribute to the bounds
	'''
    theJoint = joint
    verts = []

    #so this is just to deal with the input arg being a tuple, list or string.  you can pass in a list
    #of joint names and the verts affected just get accumulated into a list, and the resulting bound
    #should be the inclusive bounding box for the given joints
    if isinstance(joint, (tuple, list)):
        theJoint = joint[0]
        for joint in joint:
            verts += jointVertsForMaya(joint, threshold, onlyVisibleMeshes)
    else:
        verts += jointVertsForMaya(joint, threshold, onlyVisibleMeshes)

    jointDag = api.getMDagPath(theJoint)
    jointMatrix = jointDag.inclusiveMatrix()
    vJointPos = OpenMaya.MTransformationMatrix(jointMatrix).rotatePivot(
        OpenMaya.MSpace.kWorld) + OpenMaya.MTransformationMatrix(
            jointMatrix).getTranslation(OpenMaya.MSpace.kWorld)
    vJointPos = Vector([vJointPos.x, vJointPos.y, vJointPos.z])
    vJointBasisX = OpenMaya.MVector(-1, 0, 0) * jointMatrix
    vJointBasisY = OpenMaya.MVector(0, -1, 0) * jointMatrix
    vJointBasisZ = OpenMaya.MVector(0, 0, -1) * jointMatrix

    bbox = OpenMaya.MBoundingBox()
    for vert in verts:
        #get the position relative to the joint in question
        vPos = Vector(xform(vert, query=True, ws=True, t=True))
        vPos = vJointPos - vPos

        #now transform the joint relative position into the coordinate space of that joint
        #we do this so we can get the width, height and depth of the bounds of the verts
        #in the space oriented along the joint
        vPosInJointSpace = Vector((vPos.x, vPos.y, vPos.z))
        vPosInJointSpace = vPosInJointSpace.change_space(
            vJointBasisX, vJointBasisY, vJointBasisZ)
        bbox.expand(OpenMaya.MPoint(*vPosInJointSpace))

    minB, maxB = bbox.min(), bbox.max()

    return minB[0], minB[1], minB[2], maxB[0], maxB[1], maxB[2]
def getAlignedBoundsForJoint(joint, threshold=0.65, onlyVisibleMeshes=True):
    """
	looks at the verts the given joint/s and determines a local space (local to the first joint
	in the list if multiple are given) bounding box of the verts, and positions the hitbox
	accordingly

	if onlyVisibleMeshes is True, then only meshes that are visible in the viewport will
	contribute to the bounds
	"""
    theJoint = joint
    verts = []

    # so this is just to deal with the input arg being a tuple, list or string.  you can pass in a list
    # of joint names and the verts affected just get accumulated into a list, and the resulting bound
    # should be the inclusive bounding box for the given joints
    if isinstance(joint, (tuple, list)):
        theJoint = joint[0]
        for joint in joint:
            verts += jointVertsForMaya(joint, threshold, onlyVisibleMeshes)
    else:
        verts += jointVertsForMaya(joint, threshold, onlyVisibleMeshes)

    jointDag = api.getMDagPath(theJoint)
    jointMatrix = jointDag.inclusiveMatrix()
    vJointPos = OpenMaya.MTransformationMatrix(jointMatrix).rotatePivot(
        OpenMaya.MSpace.kWorld
    ) + OpenMaya.MTransformationMatrix(jointMatrix).getTranslation(OpenMaya.MSpace.kWorld)
    vJointPos = Vector([vJointPos.x, vJointPos.y, vJointPos.z])
    vJointBasisX = OpenMaya.MVector(-1, 0, 0) * jointMatrix
    vJointBasisY = OpenMaya.MVector(0, -1, 0) * jointMatrix
    vJointBasisZ = OpenMaya.MVector(0, 0, -1) * jointMatrix

    bbox = OpenMaya.MBoundingBox()
    for vert in verts:
        # get the position relative to the joint in question
        vPos = Vector(xform(vert, query=True, ws=True, t=True))
        vPos = vJointPos - vPos

        # now transform the joint relative position into the coordinate space of that joint
        # we do this so we can get the width, height and depth of the bounds of the verts
        # in the space oriented along the joint
        vPosInJointSpace = Vector((vPos.x, vPos.y, vPos.z))
        vPosInJointSpace = vPosInJointSpace.change_space(vJointBasisX, vJointBasisY, vJointBasisZ)
        bbox.expand(OpenMaya.MPoint(*vPosInJointSpace))

    minB, maxB = bbox.min(), bbox.max()

    return minB[0], minB[1], minB[2], maxB[0], maxB[1], maxB[2]