Hi all,

Given a world matrix, how can I convert this into translate/rotate suitable
for a node with a potentially edited..

   - rotateAxis
   - rotatePivot
   - rotatePivotTranslate
   - jointOrient, in the case of joints

In addition to being the child of another node with equally edited pivots
and axes and orientations.

Here’s what works if the target node has a parent, but zeroed out axes,
pivots and orients.

from maya import cmdsfrom maya.api import OpenMaya as om
def setup():
    cmds.file(new=True, force=True)

    cube1, _ = cmds.polyCube(width=5)
    cube2, _ = cmds.polyCube(width=5)
    cmds.parent(cube2, cube1)

    cmds.rotate(0, 0, 30, cube1)
    cmds.rotate(0, 0, -60, cube2)
    cmds.move(0, 2, 0, cube1)
    cmds.move(5.1, 2, 0, cube2, absolute=True)

    # Now make a new world matrix
    cube3, _ = cmds.polyCube(width=6, height=0.5, depth=0.5)
    cmds.move(4, 2, -2, cube3, absolute=True)
    cmds.rotate(25, 15, 50, cube3)

Starting off with some general setup, this is for a scene that looks like
this, where I would like to copy the worldmatrix of one onto the other.

[image: image.png]

Here’s some boilerplate for applying a MMatrix onto any node.

def setMatrix(mobj, matrix):
    fn = om.MFnDagNode(mobj)

    # Decompose
    tm = om.MTransformationMatrix(matrix)
    translate = tm.translation(om.MSpace.kPostTransform)
    rotate = tm.rotation()

    # Assign
    tx = fn.findPlug("translateX", False)
    ty = fn.findPlug("translateY", False)
    tz = fn.findPlug("translateZ", False)
    rx = fn.findPlug("rotateX", False)
    ry = fn.findPlug("rotateY", False)
    rz = fn.findPlug("rotateZ", False)

    tx.setDouble(translate.x)
    ty.setDouble(translate.y)
    tz.setDouble(translate.z)
    rx.setMAngle(om.MAngle(rotate.x, om.MAngle.kRadians))
    ry.setMAngle(om.MAngle(rotate.y, om.MAngle.kRadians))
    rz.setMAngle(om.MAngle(rotate.z, om.MAngle.kRadians))

And finally, the meat of our problem.

def copyMatrix(mobj1, mobj2):
    # Parent inverse
    obj2fn = om.MFnDagNode(mobj2)
    parentInverseMatrixPlug = obj2fn.findPlug("parentInverseMatrix",
True).elementByLogicalIndex(0)
    parentInverseMatrix =
om.MFnMatrixData(parentInverseMatrixPlug.asMObject()).matrix()

    # Get target worldmatrix we'd like cube2 to receive
    obj1fn = om.MFnDagNode(mobj1)
    worldMatrixPlug = obj1fn.findPlug("worldMatrix",
False).elementByLogicalIndex(0)
    worldMatrix = om.MFnMatrixData(worldMatrixPlug.asMObject()).matrix()

    # Cancel out the parent matrix
    outMatrix = worldMatrix * parentInverseMatrix

    # Apply the thing and profit
    setMatrix(mobj2, outMatrix)

setup()

selectionList = om.MSelectionList()
selectionList.add("pCube2")
selectionList.add("pCube3")

cube2obj = selectionList.getDependNode(0)
cube3obj = selectionList.getDependNode(1)
# Copy from pCube3 -> pCube2
copyMatrix(cube3obj, cube2obj)

This works just fine. When you run it, you’ll find pCube2 perfectly aligns
with pCube3, whilst still being parented to pCube1. Great.

[image: image.png]
Problem

Now let’s give pCube2 a custom rotatePivot. We’ll swap out our setup() with
this.

def setup():
    cmds.file(new=True, force=True)

    cube1, _ = cmds.polyCube(width=5)
    cube2, _ = cmds.polyCube(width=5)
    cmds.parent(cube2, cube1)

    # Here's our rotate pivot
    cmds.setAttr(cube2 + ".rotatePivot", -2.5, 0, 0, type="double3")

    cmds.move(0, 2, 0, cube1)
    cmds.move(5.1, 0, 0, cube2, relative=True)
    cmds.rotate(0, 0, 30, cube1)
    cmds.rotate(0, 0, -60, cube2)

    cube3, _ = cmds.polyCube(width=6, height=0.5, depth=0.5)
    cmds.move(4, 2, -2, cube3, absolute=True)
    cmds.rotate(25, 15, 50, cube3)

And presto, we’ve got a problem.

[image: image.png]

I figure maybe I could somehow include the pivots..

def copyMatrix(mobj1, mobj2):
    # Parent inverse
    obj2fn = om.MFnDagNode(mobj2)
    parentInverseMatrixPlug = obj2fn.findPlug("parentInverseMatrix",
True).elementByLogicalIndex(0)
    parentInverseMatrix =
om.MFnMatrixData(parentInverseMatrixPlug.asMObject()).matrix()

    # Get target worldmatrix we'd like cube2 to receive
    obj1fn = om.MFnDagNode(mobj1)
    worldMatrixPlug = obj1fn.findPlug("worldMatrix",
False).elementByLogicalIndex(0)
    worldMatrix = om.MFnMatrixData(worldMatrixPlug.asMObject()).matrix()

    rotatePivot = obj1fn.findPlug("rotatePivot",
False).asMDataHandle().asVector()
    rotatePivotTranslate = obj1fn.findPlug("rotatePivotTranslate",
False).asMDataHandle().asVector()

    # Cancel out the parent matrix
    tm = om.MTransformationMatrix(worldMatrix * parentInverseMatrix)
    tm.setRotatePivot(om.MPoint(rotatePivot), om.MSpace.kPostTransform, False)
    tm.setRotatePivotTranslation(rotatePivotTranslate, om.MSpace.kPostTransform)

    # Apply the thing and profit
    setMatrix(mobj2, tm.asMatrix())

But it doesn’t work and also makes my brain spin.

So the question is; given an arbitrary world matrix from node A, how can I
apply it to the translate/rotate of node B such that its world matrix is
identical?

-- 
You received this message because you are subscribed to the Google Groups 
"Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to python_inside_maya+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOBeNYv4G2ftidW9RCOGviFCcNiAgHVGOmjqCiRrcNystQ%40mail.gmail.com.

Reply via email to