def setJointRotation(sourceList, targetList, x, sParentMat, tParentMat):
    for i, (sourceChild, targetChild) in enumerate(zip(sourceList,
                                                       targetList)):
        """Get keyframe rotations as k"""
        k = pm.getAttr(sourceChild + '.rotate', time=x)
        k = dt.EulerRotation(k[0], k[1], k[2]).asMatrix()
        """Create isolatedRotation"""
        isolatedRotation = sBindPoseInversed[i] * k
        """Change of basis to world space rotation"""
        sOrientation = sourceChild.getOrientation().asMatrix()
        sOrientationInversed = sOrientation.transpose()
        sParentsInversed = sParentMat[i].transpose()
        worldspaceRotation = sOrientationInversed * sParentsInversed * isolatedRotation * sParentMat[
            i] * sOrientation
        """Second change of basis to the space of target"""
        tOrientation = targetChild.getOrientation().asMatrix()
        tOrientationInversed = tOrientation.transpose()
        tParentsInversed = tParentMat[i].transpose()
        translatedRotation = tOrientation * tParentMat[
            i] * worldspaceRotation * tParentsInversed * tOrientationInversed

        tRot = pm.getAttr(targetChild + '.rotate', t=0)
        tRot = dt.EulerRotation(tRot[0], tRot[1], tRot[2]).asMatrix()
        finalRotation = tRot * translatedRotation
        """Get rotation values from the translated rotation matrix and set key for target"""
        eulRot = dt.EulerRotation(finalRotation)
        eulRot = dt.degrees(eulRot)
        pm.setAttr(targetChild + '.rotate', eulRot.x, eulRot.y, eulRot.z)
        """If joint is root, then also set translation"""
        if sourceChild.getParent() is None:
            sKmove = pm.getAttr(sourceChild + '.translate', time=x)
            pm.setAttr(targetChild + '.translate', sKmove[0], sKmove[1],
                       sKmove[2])

        pm.setKeyframe(targetChild, t=(x), edit=True)
def calcSourceParentBP(child, parentBindPose):
    parent = child.getParent()
    if parent:
        parentBindPose = calcSourceParentBP(parent, parentBindPose)
        #parentBindPose = (parent.getRotation().asMatrix() * parent.getOrientation().asMatrix()) * parentBindPose
        parentBindPose = (dt.EulerRotation(parent.rotate.get(t=0)).asMatrix() *
                          dt.EulerRotation(parent.jointOrient.get(
                              t=0)).asMatrix()) * parentBindPose

    return parentBindPose
Beispiel #3
0
    def _add_rotate(cls, node, rotation):
        rotation = dt.EulerRotation([axis for axis in rotation])
        matrix = dt.TransformationMatrix()

        q = rotation.asQuaternion()
        matrix.addRotationQuaternion(q.x, q.y, q.z, q.w, space='object')
        cls._add_transformation(node, matrix)
Beispiel #4
0
def setRotOrder(node, s="XYZ"):
    """Set the rotorder of the object.

    Arguments:
        node (dagNode): The object to set the rot order on.
        s (str): Value of the rotorder.
            Possible values : ("XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX")
    """

    a = ["XYZ", "YZX", "ZXY", "XZY", "YXZ", "ZYX"]

    if s not in a:
        mgear.log("Invalid Rotorder : " + s, mgear.siError)
        return False

    # Unless Softimage there is no event on the rotorder parameter to
    # automatically adapt the angle values
    # So let's do it manually using the EulerRotation class

    er = datatypes.EulerRotation([
        pm.getAttr(node + ".rx"),
        pm.getAttr(node + ".ry"),
        pm.getAttr(node + ".rz")
    ],
                                 unit="degrees")
    er.reorderIt(s)

    node.setAttr("ro", a.index(s))
    node.setAttr("rotate", er.x, er.y, er.z)
Beispiel #5
0
def targetTree(node, currTime, jointIndex=0, targetIndex=0):
    for child in node.getChildren():
        if child.numChildren() > 0:
            jointIndex, targetIndex = targetTree(child, currTime, jointIndex,
                                                 targetIndex)

        if myUI.targetIndex[targetIndex] > -1:
            if getBindPose == 0:
                tJointRotation.append(child.getRotation().asMatrix())
                pm.setKeyframe(child)

            #pm.currentTime(0)

            parentBindPose = 1
            targetParentBP = calcSourceParentBP(child, parentBindPose)

            pm.currentTime(currTime)

            translatedRotation.append(
                child.getOrientation().asMatrix() * targetParentBP *
                worldSpaceRotation[jointIndex] * targetParentBP.inverse() *
                child.getOrientation().asMatrix().inverse())

            translatedRotation[jointIndex] = tJointRotation[
                jointIndex] * translatedRotation[jointIndex]

            child.setRotation(
                dt.degrees(dt.EulerRotation(translatedRotation[jointIndex])))

            jointIndex += 1

        targetIndex += 1
    return jointIndex, targetIndex
def sRotation(sourceNames):
    parentMatrix = dt.Matrix()
    for node in sourceNames:
        if (node is not sourceNames[0]):
            nodeRot = pm.getAttr(node + '.rotate', time=0)
            nodeRot = dt.EulerRotation(nodeRot[0], nodeRot[1],
                                       nodeRot[2]).asMatrix()
            parentMatrix *= node.getOrientation().asMatrix() * nodeRot
    return parentMatrix
Beispiel #7
0
def PerentRotAndOr(node, orient, jointsRoatations):
    if node.getParent():
        tempPerent = node.getParent()
        orient.append(tempPerent.getOrientation().asMatrix())
        
        rotation = dt.Matrix()
        pm.currentTime(0.0)
        rot = tempPerent.getRotation()
        rotation = dt.EulerRotation(rot).asMatrix() 
        jointsRoatations.append(rotation)
        
        if tempPerent.getParent():
            PerentRotAndOr(tempPerent, orient, jointsRoatations)
Beispiel #8
0
 def test_control_curve_worldspace_orientation(self):
     """
     Test if the control curve in orientated in worldspace zero.
     """
     self.single_control.set_worldspace_orientation(True)
     self.single_control.build_from_operator()
     control_curve = self.single_control.controls[0]
     ws_matrix = control_curve.getMatrix(worldSpace=True)
     tm_matrix = dt.TransformationMatrix(ws_matrix)
     self.assertEqual(
         tm_matrix.getRotation(),
         dt.EulerRotation([0.0, -0.0, 0.0], unit="radians"),
     )
Beispiel #9
0
    def current_distance():
        # Return the distance between the IK and FK positions.  This measures the error in our current pole
        # vector angle.
        #
        # We can use both distance and orientation to decide how close the pose is.  Distance doesn't work when
        # the elbow is locked straight, since the pole vector will only rotate the elbow and not rotate it.
        if mode == 'angle':
            # Read the difference in orientation.
            r1 = pm.xform(fk_2, q=True, ws=True, ro=True)
            r2 = pm.xform(ik_2, q=True, ws=True, ro=True)

            q1 = dt.EulerRotation(*r1).asQuaternion()
            q2 = dt.EulerRotation(*r2).asQuaternion()

            angle = angle_between_quaternions(q1, q2)
            angle = angle / math.pi * 180.0
            return angle
        else:
            # Read the difference in position.
            t1 = pm.xform(fk_2, q=True, ws=True, t=True)
            t2 = pm.xform(ik_2, q=True, ws=True, t=True)

            return dist(t1, t2)
Beispiel #10
0
def transferMatrices(tIndex, sUIJoints, tUIJoints, currentKF):

    tRIndex = 0
    for joints in tJoints:
        if joints == tUIJoints[tIndex]:
            break
        tRIndex += 1

    sRIndex = 0
    for joints in sJoints:
        if joints == sUIJoints[tIndex]:
            break
        sRIndex += 1

    sOrientation = sOrientations[sRIndex]
    sCurrentRotation = sJoints[sRIndex].getRotation().asMatrix()
    tOrientation = tOrientations[tRIndex]
    tCurrentRotation = tJoints[tRIndex].getRotation().asMatrix()

    SPM, TPM = getParentMatrix(sJoints[sRIndex], tJoints[tRIndex])

    isolatedRotation = sRotations[sRIndex].inverse() * sCurrentRotation
    worldSpaceRotation = sOrientation.inverse() * SPM.inverse(
    ) * isolatedRotation * SPM * sOrientation
    translatedRotation = tOrientation * TPM * worldSpaceRotation * TPM.inverse(
    ) * tOrientation.inverse()
    translatedRotation = tRotations[tRIndex] * translatedRotation
    finalRotation = dt.degrees(dt.EulerRotation(translatedRotation))
    tJointsFinalMatrix.append(finalRotation)

    pm.setKeyframe(tJoints[tRIndex],
                   v=finalRotation[0],
                   at='rotateX',
                   t=(currentKF, currentKF))
    pm.setKeyframe(tJoints[tRIndex],
                   v=finalRotation[1],
                   at='rotateY',
                   t=(currentKF, currentKF))
    pm.setKeyframe(tJoints[tRIndex],
                   v=finalRotation[2],
                   at='rotateZ',
                   t=(currentKF, currentKF))

    tIndex += 1

    if tIndex < len(tUIJoints) and tIndex < len(sUIJoints):
        transferMatrices(tIndex, sUIJoints, tUIJoints, currentKF)
def WriteToFile(newFile, hirarchy, rotationsInvert, orentInvert,
                perentMatrixListInvers, perentMatrixList, orent, frameStart,
                frameEnd, nrOfframes):

    if (newFile[0] == None):
        sys.stdout.write(
            'Error: A name or a path for the file was never chosen.')
        return

    exportFile = open(newFile[0], 'wb')

    exportFile.write(struct.pack('ii', nrOfframes, len(hirarchy)))

    frameList = list(range(frameStart, (frameEnd + 1)))

    for index, h in enumerate(hirarchy):
        exportFile.write(struct.pack('i', len(str(h))))
        exportFile.write(str(h))

        for i in frameList:

            fRotation = dt.Matrix()

            # Get Final source rotation at this keyframe:
            pm.currentTime(i)

            fRotation = h.getRotation()
            fRotation = dt.EulerRotation(fRotation).asMatrix()

            # Isolated rotation:
            k = rotationsInvert[index] * fRotation

            # World space rotation:
            kPrim = orentInvert[index] * perentMatrixListInvers[
                index] * k * perentMatrixList[index] * orent[index]

            # Export every float in matrix in one chunk of data:
            exportFile.write(
                struct.pack('ffffffffffffffff', kPrim.a00, kPrim.a01,
                            kPrim.a02, kPrim.a03, kPrim.a10, kPrim.a11,
                            kPrim.a12, kPrim.a13, kPrim.a20, kPrim.a21,
                            kPrim.a22, kPrim.a23, kPrim.a30, kPrim.a31,
                            kPrim.a32, kPrim.a33))

    exportFile.close()
    sys.stdout.write('Info: File successfully exported.')
Beispiel #12
0
    def test_world_position(self):
        """
        Test the world space position in translate and rotate.
        """
        ws_matrix_test_op_1 = datatypes.TransformationMatrix(
            self.test_op_1.get_main_op_ws_matrix()
        )
        test_ws_vec = datatypes.Vector(
            [27.820655082060398, -0.7524801847300928, -4.0237613976076]
        )
        test_ws_rotation = datatypes.EulerRotation(
            [1.934698909968065, -0.16331263127797427, 1.1967119606022243],
            unit="radians",
        )

        ws_matrix_test_op_1_subs = [
            datatypes.TransformationMatrix(matrix)
            for matrix in self.test_op_1.get_sub_op_nodes_ws_matrix()
        ]

        ws_vec_test_op_1_subs = [
            ts_matrix.getTranslation("world")
            for ts_matrix in ws_matrix_test_op_1_subs
        ]

        test_ws_vec_subs = [
            datatypes.Vector(
                [31.42623634611877, 8.432088910758539, -2.397884932907285]
            ),
            datatypes.Vector(
                [35.03181761017714, 17.61665800624717, -0.7720084682069708]
            ),
            datatypes.Vector(
                [38.637398874235515, 26.801227101735805, 0.8538679964933436]
            ),
        ]

        self.assertEqual(ws_vec_test_op_1_subs, test_ws_vec_subs)

        self.assertEqual(
            ws_matrix_test_op_1.getTranslation("world"), test_ws_vec
        )

        self.assertEqual(ws_matrix_test_op_1.getRotation(), test_ws_rotation)
def targetTree(targetTreeItem, currTime, listLength):
    global targetCount
    global newTargetList
    global getBindPose
    global tJointRotation

    if targetCount != 0:
        for items in range(listLength):

            if getBindPose == 0:
                tJointRotation.append(targetTreeItem.getRotation().asMatrix())
                pm.setKeyframe(targetTreeItem)

                #pm.currentTime(0)

            parentBindPose = 1
            targetParentBP = calcSourceParentBP(targetTreeItem, parentBindPose)

            pm.currentTime(currTime)

            translatedRotation.append(
                targetTreeItem.getOrientation().asMatrix() * targetParentBP *
                worldSpaceRotation[targetCount] * targetParentBP.inverse() *
                targetTreeItem.getOrientation().asMatrix().inverse())

            translatedRotation[targetCount] = tJointRotation[
                targetCount] * translatedRotation[targetCount]

            targetTreeItem.setRotation(
                dt.degrees(dt.EulerRotation(translatedRotation[targetCount])))

            targetCount += 1
            if listLength != targetCount:
                targetTree(targetList[targetCount], currTime, listLength)

            #Calculate the rotation for the node and set keyframe if node is still in the list
            checkViable = checkInList(node, aList)

            if checkVialbe == 1:
                pm.setKeyFrame()
    else:
        targetCount += 1
        targetTree(targetList[targetCount], currTime, listLength)
Beispiel #14
0
def setRotOrder(node, s="XYZ"):

    a = ["XYZ", "YZX", "ZXY", "XZY", "YXZ", "ZYX"]

    if s not in a:
        mgear.log("Invalid Rotorder : " + s, mgear.siError)
        return False

    # Unless Softimage there is no event on the rotorder parameter to automatically adapt the angle values
    # So let's do it manually using the EulerRotation class

    er = dt.EulerRotation(
        [getAttr(node + ".rx"),
         getAttr(node + ".ry"),
         getAttr(node + ".rz")],
        unit="degrees")
    er.reorderIt(s)

    node.setAttr("ro", a.index(s))
    node.setAttr("rotate", er.x, er.y, er.z)
Beispiel #15
0
def setTargetTree(node, jointIndex=0, targetIndex=0):
    for child in node.getChildren():
        if child.numChildren() > 0:
            jointIndex, targetIndex = setTargetTree(child, jointIndex,
                                                    targetIndex)

        if myUI.targetIndex[targetIndex] < len(myUI.targetTree) + 1:
            if myUI.targetIndex[targetIndex] > -1:
                child.setRotation(
                    dt.degrees(
                        dt.EulerRotation(translatedRotation[
                            myUI.targetIndex[targetIndex]])))
                pm.setKeyframe(child)
                jointIndex += 1
        else:
            jointIndex += 1

        targetIndex += 1

    return jointIndex, targetIndex
def HirarchyListCreator(hirarchy, orient, jointsRoatations, perentMatrixList,
                        perentMatrixListInvers, orentations, orentationsInvert,
                        rotations, rotationsInvert):
    sorce = pm.ls(sl=True)[0]

    if sorce is None:
        sys.stdout.write('Error: At least one joint must be selected.')
        return

    # Makes sure the joint selected is really the root joint:
    rootSorce = ReversedHierarchy(sorce)
    rootSorce = pm.ls(sl=True)[0]

    # Hierarchy Calculations:
    # Add root joint to the list first:
    hirarchy.append(rootSorce)
    # Add all roots children:
    Hirarchy(rootSorce, hirarchy)

    for s in hirarchy:
        tempParentMatrix = dt.Matrix()
        # For sorce:
        PerentRotAndOr(s, orient, jointsRoatations)
        tempParentMatrix = CalculateOriAndRot(orient, jointsRoatations)
        perentMatrixList.append(tempParentMatrix)
        perentMatrixListInvers.append(tempParentMatrix.inverse())

        orient[:] = []
        jointsRoatations[:] = []

    for h in hirarchy:
        pm.currentTime(0.0)
        rot = h.getRotation()
        rotation = dt.EulerRotation(rot).asMatrix()
        rotations.append(rotation)
        rotationsInvert.append(rotation.inverse())

    Orientations(hirarchy, orentations, orentationsInvert)

    sys.stdout.write('Info: Target skeleton hierarchy calculated.')
Beispiel #17
0
def CreateLayers(animLayerName, hirarchy, nrOfFrames, rotations, orent, orentInvert, perentMatrixList, perentMatrixListInvers, jointMatrixesList, animLayerList):
    animLayer1 = pm.animLayer(animLayerName)
    animLayerList.append(animLayer1)
    
    for index, h in enumerate(hirarchy):
        
        pm.select(h, replace=True)
        
        pm.animLayer(animLayerName, edit=True, addSelectedObjects=True)
        
        # Loop through Keys: 
        for i in range(0, (nrOfFrames + 1)):
            
            # Get Final source rotation at this keyframe:
            pm.currentTime(i)
    
            kBiss = orent[index] * perentMatrixList[index] * jointMatrixesList[index][i] * perentMatrixListInvers[index] * orentInvert[index]
                    
            # Final rotation:
            finalRotation = rotations[index] * kBiss
            
            #=====================================================================
            # Get the right format for rotations:
            keyRotQ = dt.EulerRotation(finalRotation)
            keyRotDegree = dt.degrees(keyRotQ)
            
            #=====================================================================
            # Set rotations at current time:
            h.setRotation(keyRotDegree)
            
            # Save to keyframe:
            pm.setKeyframe(h, time = (i,i), edit = True, animLayer = animLayerName)
    
    #Set weights to 0.0 so they dont influence other layers when baked:        
    pm.animLayer(animLayerName, edit = True, w=0.0)
    sys.stdout.write('Info: Animation layers successfully created.\n')
Beispiel #18
0
def main(jointList, newJointList, hip, newHip):

    first = pm.findKeyframe(hip, which='first')
    last = pm.findKeyframe(hip, which='last')
    
    pm.setCurrentTime(0)
    
    parentList = []
    targetParentList = []
        
    parents(hip, dt.Matrix(), parentList, jointList)
    parents(newHip, dt.Matrix(), targetParentList, newJointList)
    
    i = 0
    a = 0
    
    identityMatrix = dt.Matrix()
    identityMatrix2 = dt.Matrix()
    
    while i < len(jointList):
        
        curr = first
        
        pm.setCurrentTime(0)
    
        pyJoint = pm.PyNode(jointList[i])
        targetJoint = pm.PyNode(newJointList[i])
        parentJoint = parentList[i]
        targetParentJoint = targetParentList[i]
        
        bindPoseInverse = pyJoint.getRotation().asMatrix().inverse()
        bindPose = pyJoint.getRotation().asMatrix()
        bindPoseTarget = targetJoint.getRotation().asMatrix()
    
        while curr <= last:
            curr = pm.findKeyframe(hip, time=curr, which='next')
            pm.setCurrentTime(curr)
            
            if i == 0:
               k =  pyJoint.getRotation().asMatrix() * bindPoseInverse
               
               kPrim = identityMatrix.setToIdentity().inverse() * k * identityMatrix2.setToIdentity()
               
               kPrim2 = parentList[i] * kPrim * parentList[i].inverse()
               
               final = bindPoseTarget * kPrim2
               
               targetJoint.setRotation(dt.degrees(dt.EulerRotation(final)))
                        
               targetJoint.setTranslation(pyJoint.getTranslation())
               
               pm.setKeyframe(targetJoint)
            else:
            ####################################HIP DONE###########################################
                
                bodyK = bindPoseInverse * pyJoint.getRotation().asMatrix()
                
                bodykPrim = parentList[i].inverse() * bodyK * parentList[i]
                
                bodykPrim2 =  targetParentList[i] * bodykPrim * targetParentList[i].inverse()
                
                bodyFinal =  bindPoseTarget * bodykPrim2
                
                targetJoint.setRotation(dt.degrees(dt.EulerRotation(bodyFinal)))
                
                pm.setKeyframe(targetJoint)
    
            
            # apply key values
            if curr==last:
                i = i + 1
                break   
Beispiel #19
0
def TransferAnimation(jointCount, frameCount, sourceList, targetList):

    #for every joint in source- and target skeleton
    for jointIndex in range(jointCount):
        """ SOURCE - Get bindpose and orientations """
        sourceJointBindPose = sourceList[jointIndex].getRotation().asMatrix()
        sourceJoindBindPoseInversed = sourceJointBindPose.inverse().asMatrix()

        sourceJointOrientation = sourceList[jointIndex].getOrientation(
        ).asMatrix()
        sourceJointOrientationInversed = sourceJointOrientation.inverse(
        ).asMatrix()
        """ SOURCE - Get parent Matricies """
        sourceParentMatrix = dt.Matrix()
        sourceParentList = []
        sourceParentList = sourceList[jointIndex].getAllParents()
        parLenS = len(sourceParentList)

        # get all parents rot + orient
        if parLenS > 0:
            for prnt in sourceParentList:
                rot = prnt.getRotation().asMatrix()
                ori = prnt.getOrientation().asMatrix()
                sourceParentMatrix *= ori * rot

        #if root joint, rot + orient = identity mat
        elif jointIndex is jointCount - 1:
            rot = dt.Matrix()
            ori = dt.Matrix()
            sourceParentMatrix *= ori * rot

        sourceParentMatrixInverse = sourceParentMatrix.inverse().asMatrix()
        """ TARGET -  Get Bindpose and Orientations """
        targetJointBindPose = targetList[jointIndex].getRotation().asMatrix()

        targetJointOrientation = targetList[jointIndex].getOrientation(
        ).asMatrix()
        targetJointOrientationInverse = targetJointOrientation.inverse(
        ).asMatrix()
        """ TARGET - Get parent matricies """
        targetParentMatrix = dt.Matrix()
        targetParentList = []
        targetParentList = targetList[jointIndex].getAllParents()
        parLenT = len(targetParentList)

        # get all parents rot + orient
        if parLenT > 0:
            for tPrnt in targetParentList:
                rotT = tPrnt.getRotation().asMatrix()
                oriT = tPrnt.getOrientation().asMatrix()
                targetParentMatrix *= oriT * rotT

        #if root joint, rot + orient = identity mat
        elif jointIndex is jointCount - 1:
            rotT = dt.Matrix()
            oriT = dt.Matrix()
            targetParentMatrix *= oriT * rotT

        targetParentMatrixInverse = targetParentMatrix.inverse().asMatrix()

        #for every frame in nrOf Frames for joint at joint index
        for frame in range(frameCount):
            """ SOURCE - Calculate K """

            #if root joint
            if jointIndex is jointCount - 1:
                sourceJointFinalRot = pm.keyframe(sourceList[jointIndex],
                                                  time=(frame, frame),
                                                  query=True,
                                                  eval=True)[7:10]

            else:
                sourceJointFinalRot = pm.keyframe(sourceList[jointIndex],
                                                  time=(frame, frame),
                                                  query=True,
                                                  eval=True)[6:9]

            sourceJointFinalRotEuler = dt.EulerRotation(
                sourceJointFinalRot).asMatrix()

            isolatedRotK = sourceJoindBindPoseInversed * sourceJointFinalRotEuler
            kPrim = sourceJointOrientationInversed * sourceParentMatrixInverse * isolatedRotK * sourceParentMatrix * sourceJointOrientation
            kBis = targetJointOrientation * targetParentMatrix * kPrim * targetParentMatrixInverse * targetJointOrientationInverse

            finalRotation = targetJointBindPose * kBis

            FinEuler = dt.EulerRotation(finalRotation)
            FinDegrees = dt.degrees(FinEuler)
            """SET FINAL ROTATION . . . . . . . . . . . . . . . . . . """
            pm.setKeyframe(targetList[jointIndex],
                           time=(frame, frame),
                           attribute='rotateX',
                           value=FinDegrees.x)
            pm.setKeyframe(targetList[jointIndex],
                           time=(frame, frame),
                           attribute='rotateY',
                           value=FinDegrees.y)
            pm.setKeyframe(targetList[jointIndex],
                           time=(frame, frame),
                           attribute='rotateZ',
                           value=FinDegrees.z)

        del targetParentList[:]
        del sourceParentList[:]
def getBindPoses(sourceList, newList):
    for joints in sourceList:
        bindPose = pm.getAttr(joints + '.rotate', t=0)
        bindPose = dt.EulerRotation(bindPose[0], bindPose[1],
                                    bindPose[2]).asMatrix()
        newList.append(bindPose.transpose())
Beispiel #21
0
def calcFinalRotation(sourceJ, targetJ, key):
    #Isolate rotation from keyframe
    cmds.currentTime(0)
    sBindPose = sourceJ.getRotation().asMatrix()
    invrsBindPose = sBindPose.inverse()
    cmds.currentTime(key)

    #Isolated Rotation
    kI = invrsBindPose * sourceJ.getRotation().asMatrix()

    #Convert rotation to standard coordinate space

    sBO = sourceJ.getOrientation().asMatrix()
    sBO2 = sBO.inverse()

    #Get Parents
    sBPOmtx = dt.Matrix()

    sParent = sourceJ.getParent()
    if (sParent != None):
        cmds.currentTime(0)
        sBPO = getParentsBPO(sourceJ, sBPOmtx)
        cmds.currentTime(key)
        sBPO2 = sBPO.inverse()
    else:
        sBPO = dt.Matrix()
        sBPO2 = sBPO.inverse()

    #World Space Rotation
    kII = sBO2 * sBPO2 * kI * sBPO * sBO

    #Convert rotation to target joint coordinate space

    tBO = targetJ.getOrientation().asMatrix()
    tBO2 = tBO.inverse()

    #Get Parents
    tBPOmtx = dt.Matrix()

    #TEST
    tParent = targetJ.getParent()
    if (tParent != None):
        cmds.currentTime(0)
        tBPO = getParentsBPO(targetJ, tBPOmtx)
        cmds.currentTime(key)
        tBPO2 = tBPO.inverse()
    else:
        tBPO = dt.Matrix()
        tBPO2 = tBPO.inverse()

    #Translated Rotation
    kIII = tBO * tBPO * kII * tBPO2 * tBO2

    #Calculate Final Rotation
    cmds.currentTime(0)
    tBindPose = targetJ.getRotation().asMatrix()
    finalRot = tBindPose * kIII
    cmds.currentTime(key)

    #Convert Matrix to Euler Rotation

    eulerRot = dt.EulerRotation(finalRot)
    degRot = dt.degrees(eulerRot)

    return degRot