Hey,

I'm trying to reconstruct a MTransformationMatrix from maya's MFnIkJoint in maya 2015. According to the docs the construction works as such:

The transformation matrix for a joint node is below.

• matrix = [S] * [RO] * [R] * [JO] * [IS] * [T]

(where '*' denotes matrix multiplication).

These matrices are defined as follows:

• [S] : scale
• [RO] : rotateOrient (attribute name is rotateAxis)
• [R] : rotate
• [JO] : jointOrient
• [IS] : parentScaleInverse
• [T] : translate

So I've followed that and written the code below. The problem is that the constructed matrix I created does not seem to respect joint orientation.

If I get the MTransformationMatrix directly from the MFnIkJoint function it somehow seems to store the joint orientation. Does anyone know where the MTransformationMatrix is storing joint orientation? It seems to be a mystery to me as it isn't in MTransformationMatrix::rotationOrientation or MTransformationMatrix::rotation.

import time
from maya import cmds
from maya import OpenMaya, OpenMayaAnim

# Make a joint
jnt = cmds.joint(orientation=[0, 45, 0])
jnt2 = cmds.joint(p=[2, 0, -2])

# get a dagPath
mSel = OpenMaya.MSelectionList()
dagPath = OpenMaya.MDagPath()
mSel.getDagPath(0, dagPath)

# Put it in MFnIkJoint function set
startJointFn = OpenMayaAnim.MFnIkJoint(dagPath)
initMatrix = startJointFn.transformation()

# Make a scale pointer
util = OpenMaya.MScriptUtil()
util.createFromList([1.0, 1.0, 1.0], 3)
scalePtr = util.asDoublePtr()

# Get scale
startJointFn.getScale(scalePtr)
S_MTMatrix = OpenMaya.MTransformationMatrix()
S_MTMatrix.setScale(scalePtr, OpenMaya.MSpace.kTransform)
S = S_MTMatrix.asMatrix()

# Get rotate orientation
RO_Quat = OpenMaya.MQuaternion()
startJointFn.getScaleOrientation(RO_Quat)
RO_MTMatrix = OpenMaya.MTransformationMatrix()
RO_MTMatrix.rotateBy(RO_Quat, OpenMaya.MSpace.kTransform)
RO = RO_MTMatrix.asMatrix()

# Get Rotation
R_Quat = OpenMaya.MQuaternion()
startJointFn.getRotation(R_Quat)
R_MTMatrix = OpenMaya.MTransformationMatrix()
R_MTMatrix.rotateBy(R_Quat, OpenMaya.MSpace.kTransform)
R = R_MTMatrix.asMatrix()

# Get joint orientation
JO_Quat = OpenMaya.MQuaternion()
startJointFn.getOrientation(JO_Quat)
JO_MTMatrix = OpenMaya.MTransformationMatrix()
JO_MTMatrix.rotateBy(JO_Quat, OpenMaya.MSpace.kTransform)
JO = JO_MTMatrix.asMatrix()

# Get inverse scale of parent.
parentMObj = startJointFn.parent(0)
if not parentMObj.apiTypeStr() == "kWorld":
parentFn = OpenMaya.MFnTransform(parentMObj)
parentFn.getScale(scalePtr)

IS_MTMatrix = OpenMaya.MTransformationMatrix()
IS_MTMatrix.setScale(scalePtr, OpenMaya.MSpace.kTransform)
IS = IS_MTMatrix.asMatrixInverse()

# Get Translation
T_Vector = startJointFn.getTranslation(OpenMaya.MSpace.kTransform)
T_MTMatrix = OpenMaya.MTransformationMatrix()
T_MTMatrix.setTranslation(T_Vector, OpenMaya.MSpace.kTransform)
T = T_MTMatrix.asMatrix()

# Multiply like the docs say.
matrix = S * RO * R * JO * IS * T

# Put it into MTransformationMatrix
TMatrix = OpenMaya.MTransformationMatrix(matrix)

# If the two MTransformationMatrices are equal.
if TMatrix.isEquivalent(initMatrix):

# Set joint to calculated matrix
startJointFn.set(TMatrix)
cmds.refresh()

# Wait 1 second and set it back to the inital transformation matrix from the joint function
# This is just to see the difference between the two transformation matrices.
time.sleep(1)
startJointFn.set(initMatrix)

Appreciate any help!

Quote 0 0
transformation matrix != transform/joint node and their underlying classes.
The MFnTransformNode for example does so much more work on top of a base xform matrix.
So you won't be able to replicate this without taking into consideration everything that is happening in the other classes.
You have a lot more to reconstruct. :)
Quote 0 0
The MFnTransformationMatrices are the equivalent though. Is there just not an way to change joint orientation in the MFnTransformationMatrix unless it comes from the function set?
Quote 0 0
4x4 matrix is a simple data container.
MTransformationMatrix wraps the 4x4 matrix and in addition provides basic functionality to describe 3D transformations like translate, rotate, scale, shear, etc.
MFnTransform builds on that to provide extra things like limit translation/rotation/scale, joint orientation, pivots.
It actually does much more than that, but that's another story.

The easiest way to achieve what you are after is to use this class and directly call its *Pivot methods.
You don't need to initialize it to existing object. Create a new class instance, stick the input values to it and get the result matrix. Code will be much shorter than what you have now.

`import timefrom maya import cmdsfrom maya import OpenMaya, OpenMayaAnim# get a dagPathmSel = OpenMaya.MSelectionList()mSel.add("joint1")mSel.add("joint2")dagPath = OpenMaya.MDagPath()mSel.getDagPath(0, dagPath)# Put it in MFnIkJoint function setstartJointFn = OpenMayaAnim.MFnIkJoint(dagPath)initMatrix = startJointFn.transformation()# Make a scale pointerutil = OpenMaya.MScriptUtil()util.createFromList([1.0, 1.0, 1.0], 3)scalePtr = util.asDoublePtr()# Get scalestartJointFn.getScale(scalePtr)S_MTMatrix = OpenMaya.MTransformationMatrix()S_MTMatrix.setScale(scalePtr, OpenMaya.MSpace.kTransform)S = S_MTMatrix.asMatrix()# Get rotate orientationRO_Quat = OpenMaya.MQuaternion()startJointFn.getScaleOrientation(RO_Quat)RO_MTMatrix = OpenMaya.MTransformationMatrix()RO_MTMatrix.rotateBy(RO_Quat, OpenMaya.MSpace.kTransform)RO = RO_MTMatrix.asMatrix()# Get RotationR_Quat = OpenMaya.MQuaternion()startJointFn.getRotation(R_Quat)R_MTMatrix = OpenMaya.MTransformationMatrix()R_MTMatrix.rotateBy(R_Quat, OpenMaya.MSpace.kTransform)R = R_MTMatrix.asMatrix()# Get joint orientationJO_Quat = OpenMaya.MQuaternion()startJointFn.getOrientation(JO_Quat)JO_MTMatrix = OpenMaya.MTransformationMatrix()JO_MTMatrix.rotateBy(JO_Quat, OpenMaya.MSpace.kTransform)JO = JO_MTMatrix.asMatrix()IS_MTMatrix = OpenMaya.MTransformationMatrix()IS_MTMatrix.setScale(scalePtr, OpenMaya.MSpace.kTransform)IS = IS_MTMatrix.asMatrixInverse()# Get TranslationT_Vector = startJointFn.getTranslation(OpenMaya.MSpace.kTransform)T_MTMatrix = OpenMaya.MTransformationMatrix()T_MTMatrix.setTranslation(T_Vector, OpenMaya.MSpace.kTransform)T = T_MTMatrix.asMatrix()# Multiply like the docs say.matrix = S * RO * R * JO * IS * T# Put it into MTransformationMatrixTMatrix = OpenMaya.MTransformationMatrix(matrix)# Set joint to calculated matrixmSel.getDagPath(1, dagPath)endJointFn = OpenMayaAnim.MFnIkJoint(dagPath)endJointFn.set(TMatrix)`