Matching Transformation in Maya and MFnTransform pitfalls

I used to rely a lot on the MFnTransform class solely to match the transformation of one object to another and it has worked great for me (until recently).

In my own rigging system and the ones I built for my employers I never freeze transformations. I usually create an offset/buffer group and never mess with the object's pivot. I also never have multiple rotation offsets on top of my nodes (which actually complicate the process of matching transformations of one object to another with the MfnTransform like explained below)

However, now that I am dealing with all kind of rigs from different sources I can't force my aesthetic on them and instead I have to find a way that can work around all kind of the above issues to be able to wrap them to my rigging system.

The translation methods of the MFnTransform work great in all cases, especially that you can get the rotatePivot point in worldspace directly which is beneficial if you are dealing with objects that have frozen transformations. However, it is very prone to fail with objects that have -1 scale or with frozen transformation. That is when I realised I will have to rely more on MTransformationMatrix to decompose my target node matrix to guarantee the correct rotation values that I need to apply to my object to match.

Here is the code (With Maya API 2) I use to match transformations now and tested with every case and so far worked great. I will also comment out the previous methods I used to match the rotations with the MFnTransform class and when did they fail for me in case anyone is interested in testing for themselves.

import maya.api.OpenMaya as OpenMaya
def getMDagPath(node):
    selList=OpenMaya.MSelectionList()
    selList.add(node)
    return selList.getDagPath(0)
    
def getMObject(node):
    selList=OpenMaya.MSelectionList()
    selList.add(node)
    return selList.getDependNode(0)

def matchTranformation(targetNode, followerNode, translation=True, rotation=True):
    followerMTransform=OpenMaya.MFnTransform(getMDagPath(followerNode))
    targetMTransform=OpenMaya.MFnTransform(getMDagPath(targetNode))
    targetMTMatrix=OpenMaya.MTransformationMatrix(OpenMaya.MMatrix(cmds.xform(targetNode, matrix=True, ws=1, q=True)))
    if translation:
        targetRotatePivot=OpenMaya.MVector(targetMTransform.rotatePivot(OpenMaya.MSpace.kWorld))
        followerMTransform.setTranslation(targetRotatePivot,OpenMaya.MSpace.kWorld)
    if rotation:
        #using the target matrix decomposition
        #Worked on all cases tested
        followerMTransform.setRotation(targetMTMatrix.rotation(True),OpenMaya.MSpace.kWorld)
        
        #Using the MFnTransform quaternion rotation in world space
        #Doesn't work when there is a -1 scale on the object itself
        #Doesn't work when the object has frozen transformations and there is a -1 scale on a parent group.
        #followerMTransform.setRotation(MFntMainNode.rotation(OpenMaya.MSpace.kWorld, asQuaternion=True),OpenMaya.MSpace.kWorld)

So as you can see in the code, I still use the MFnTransform to match the translation of my object to the target's rotate pivot. Then I use the MTransformationMatrix to decompose the world Matrix of the target node so I can get the correct rotation no matter what rotation order, negative scale and whatever offsets in the target's hierarchy.

PS:Using Maya API doesn't support UNDO. If you want to be able to undo the snapping consider using the API to decompose and store information and use the maya.cmds xform command to move the object instead.

Space Switch Tool 1.0 for Maya

I think creating a space switch setup in Maya can be fairly easy if you know how to code. However, editing and debugging the setup can be complicated and needs a management system to handle the data.

I made this tool so it is both animator and riggers friendly. The UI is pretty interactive and the requirements for creating the setup are minimal. When adding a new space the tool guides the user by loading the previous made setup info to the tool.
The Marking menu provides a fast way to switch between spaces and executes a script to maintain the objects transformation when switching between spaces.
In the Edit and Debug tab you can view all the driver spaces and also edit their order and display names. You can even remove any of them or the whole setup cleanly if you want with out worrying about leaving some connected nodes behind in the scene.

For full explanation please check the tool's documentation page. Here is a quick video that covers most of the tool's functionality.

What rigging tools do you need?

Hey guys, it been a while since I shared an update here.
I have been working on encapsulating some of my most used Modular functions that I use in my rigging pipeline and I believe that every rigger or an animator would need and sell it (for a reasonable price) on my cubebrush store.

I have already two modules prepared so far:

  1. A tool that would add stretch properties to an IK Handle joint chain. It doesn't just make the IK Handle stretchy but It would also allow for every joint in the chain to scale individually while the IK handle still evaluating properly. It would also create the common stretch lock feature.
  2. A space switching tool. A non destructive rigging tool, where you can always go back to the node and add more spaces on the fly.

Do you think you will find a use for these tools in your rigs? What are your favourite tools or modules that you like to use to create or enhance your rigs?