Search code examples
pivotmayacentering

Center object pivot with world center after combine


When I take 2 objects in Maya and combine them, the pivot of the combined object is the center of the world, therefore I am using the ModifyCenter Pivot option.

But after that the object has different center from other objects, for example when I set its location to (0, 0, 0) it is not the world's center.

I know I can take the combined object and move it to the world's center and then use ModifyCenter Pivot but it is inaccurate.

Is there something I am missing? How can I center an object's pivot and keep it relative to the world?

This is what I mean, as you can see the object is in (0,0,0) location but not the world's center:

This is what I mean, as you can see the object is in (0,0,0) location but not the world's center


Solution

  • What's going on is that when you're using center pivot, instead of effecting the object's translate values it offsets it with its pivots instead (local rotate pivot attribute). So even though your translates are all zero, the values from the pivots cause your object to be offset from the world origin.

    Although this makes sense knowing the above, it's still pretty annoying how Maya handles it.

    Here's a script that will try to fix that. What it's essentially doing is taking its pivot values, zeroing it out, and adding it to its translation:

    Maya 2018

    import maya.cmds as cmds
    
    sel = cmds.ls(sl=True)[0]  # Get selection.
    
    cmds.xform(sel, cpc=True)  # Center its pivot. Comment this out if you don't want to force it to center and use the pivot as-is.
    pivots = cmds.xform(sel, q=True, piv=True)[:3]  # Get its pivot values.
    
    temp_nul = cmds.createNode("transform")  # Create a temporary transform.
    cmds.matchTransform(temp_nul, sel)  # Align the transform to our object.
    
    try:
        cmds.xform(sel, piv=[0, 0, 0])  # Zero-out object's pivot values.
        cmds.move(-pivots[0], -pivots[1], -pivots[2], "{}.vtx[*]".format(sel), os=True, r=True)  # Negate and move object via its old pivot values.
        cmds.matchTransform(sel, temp_nul)  # Align the object back to the temporary transform, to maintain its old position.
    finally:
        cmds.delete(temp_nul)  # Delete temporary transform.
        cmds.select(sel)  # Restore old selection.
    

    Maya 2016 and <

    import maya.cmds as cmds
    import maya.mel as mel
    
    sel = cmds.ls(sl=True)[0]  # Get selection.
    
    mel.eval("CenterPivot;")  # Center its pivot. Comment this out if you don't want to force it to center and use the pivot as-is.
    pivots = cmds.xform(sel, q=True, piv=True)[:3]  # Get its pivot values.
    old_tm = cmds.xform(sel, q=True, ws=True, m=True) # Get its transform matrix.
    
    temp_nul = cmds.createNode("transform")  # Create a temporary transform.
    cmds.xform(temp_nul, ws=True, m=old_tm)  # Align it to the matrix.
    cmds.xform(temp_nul, os=True, r=True, t=pivots)  # Move it to include the pivot offsets.
    new_tm = cmds.xform(temp_nul, q=True, ws=True, m=True)  # Store it's transform matrix to align to later.
    
    try:
        cmds.xform(sel, piv=[0, 0, 0])  # Zero-out object's pivot values.
        cmds.move(-pivots[0], -pivots[1], -pivots[2], "{}.vtx[*]".format(sel), os=True, r=True)  # Negate and move object via its old pivot values.
        cmds.xform(sel, ws=True, m=new_tm)  # Align the object back to the temporary transform, to maintain its old position.
    finally:
        cmds.delete(temp_nul)  # Delete temporary transform.
        cmds.select(sel)  # Restore old selection.
    

    Select your object then execute the script to run it. I tested it on a combined object with random rotations, while being parented to an object with a random rotation. It seems to work ok without popping.

    You can also achieve the same effect with a combo of nodes using a polyMoveVertex node instead of scripting.