Hi all,
Given a world matrix, how can I convert this into translate/rotate suitable for a node with a potentially edited..
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 cmds
from 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.
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.
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.
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?
Thanks for this! It’s the other way around, pCube3
goes into pCube2
, but it still works.
Looking closlier, I found that it does something sneaky. It changes the rotate pivot on the destination. Or rather, the rotatePivotTranslate
. So rather than just affecting translate
and rotate
- which is what I want - it most likely takes that worldmatrix and decomposes it into its components, including pivots, and overwrites everything on the destination node. That’s cool, but that’s cheating. :)
The only thing I want out of the worldmatrix is a rotate/translate for the destination. That translates and orients the destination to match the source.
And yes, sadly this needs to happen without cmds.xform, as it’s happening inside the MPxNode::compute
of a C++ plugin.
(Code formatting with “Markdown Here”, sent from my mailbox)
--
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_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/d50a8632-3c7c-4ed4-ae88-2cf10dec034bn%40googlegroups.com.
--
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_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/05c18bfa-a326-4626-a757-2a19700efbc7n%40googlegroups.com.