[Maya API] get the translation matrix from the previous frame

1,372 views
Skip to first unread message

David DeJuan

unread,
Apr 30, 2017, 2:50:34 PM4/30/17
to Python Programming for Autodesk Maya
Hi,
I'm trying to do a Node, where the input is a mesh and get the translation matrix of it in the previous frame. But I don't get it.
I have tried using the MPlug getValue setting the MDGContext one frame before, but it doesn't work. 
This is the code, it is in C++

MStatus node::compute(const MPlug& plug, MDataBlock& data){

if (plug == dirX) {
MDataHandle dirXHandle = data.outputValue(dirX);
MDataHandle dirXHandleOld = data.outputValue(dirXOld);
MTime time = MAnimControl::currentTime();

MDGContext timeContextOld(time - 1);

MObject inputMeshObj = inputMeshHandle.asMesh();
MFnMesh meshFn(inputMeshObj);

MDagPath dagPath;
dagPath
= meshFn.dagPath();
MFnDagNode transFn(dagPath);

MPlug matrixPlugArray = transFn.findPlug("worldMatrix");
matrixPlugArray
.evaluateNumElements();
MPlug matrixPlug = matrixPlugArray.elementByPhysicalIndex(0);

MObject matrixO;
matrixPlug
.getValue(matrixO, timeContextOld);
MFnMatrixData fnMat(matrixO);
MVector res = fnMat.transformation().getTranslation(MSpace::kWor ld);

// Set the output data.
dirXHandle
.setFloat(0.0);
dirXHandleOld
.setFloat(res.x);
}else {
return MS::kUnknownParameter;
}

return MS::kSuccess;
}


I am wondering also how the cacheFrame node works.
Can anyone help me?
Thanks

Michael Boon

unread,
May 1, 2017, 12:06:11 AM5/1/17
to Python Programming for Autodesk Maya
I've done a similar thing successfully in Python, but I used MPlug::asMObject and MFnMatrixData::matrix instead of MPlug::getValue. I don't remember if I tried using getValue, but I do remember that I found it extremely finicky and I tried a lot of approaches before I found one that gave me a result. Maybe this approach will work for you too.

This is in Python, but I think it will translate to C++:
        matMObj = matrixPlug.asMObject(timeContext)
        mat
= om.MFnMatrixData(matMObj).matrix()

David DeJuan

unread,
May 1, 2017, 5:29:20 AM5/1/17
to Python Programming for Autodesk Maya
Hi,
thanks so much for answering. I have tried what you said, I read thet getValue is not possible to use in python, and that asMObject has to.
But the results are the same. I'm having the translation of the current frame.
Here it is my code in python:

        if( pPlug == DirectionMovNode.dirXAttribute ):
           
# Get our custom input node attributes and values.
            inputMeshHandle
= pDataBlock.inputValue( DirectionMovNode.inputMeshAttribute )
            inputMeshObj
= inputMeshHandle.asMesh()
            meshFn
= OpenMaya.MFnMesh(inputMeshObj)
           
            transFn
= OpenMaya.MFnDagNode  (meshFn.dagPath())

            matrixPlugArray
= transFn.findPlug("worldMatrix")
            matrixPlugArray
.evaluateNumElements()

            matrixPlug
= matrixPlugArray.elementByPhysicalIndex(0)
            time
= OpenMayaAnim.MAnimControl.currentTime()
            timeContext
= OpenMaya.MDGContext(time-1)
            matrixO
= matrixPlug.asMObject(timeContext)
            fnMat
= OpenMaya.MFnMatrixData(matrixO)
            matrix
=  fnMat.matrix()
            result
= '% .06f, % .06f, % .06f, % .06f,\n% .06f, % .06f, % .06f, % .06f,\n% .06f, % .06f, % .06f, % .06f,\n% .06f, % .06f, % .06f, % .06f,\n'
           
print result % (matrix(0, 0), matrix(0, 1), matrix(0, 2), matrix(0, 3), matrix(1, 0), matrix(1, 1), matrix(1, 2), matrix(1, 3), matrix(2, 0), matrix(2, 1), matrix(2, 2 ), matrix(2, 3), matrix(3, 0), matrix(3, 1), matrix(3, 2), matrix(3, 3))
           
           
# Set the output data.
            dirX
= pDataBlock.outputValue( DirectionMovNode.dirXAttribute )
            dirX
.setFloat(matrix(3, 0))

            

Michael Boon

unread,
May 1, 2017, 7:31:41 PM5/1/17
to Python Programming for Autodesk Maya
Can you clarify, what matrix do you get? Is it the matrix of the correct object, but not the frame you want? Or is it all wrong?

I ran your Python code under Python API 2.0 and it worked for me, except I skipped the part about inputMeshAttribute, and got my MFnMesh by getting a MDagPath from an MSelectionList, using a utility function I have.
import maya.api.OpenMaya as om
import maya.api.OpenMayaAnim as oma
import maya_utils as mu # Sorry, this is a library I use at work.
meshFn = mu.mFnMeshFromName('pSphere1')

transFn = om.MFnDagNode(meshFn.dagPath()); print 'transFn:', transFn.name()
matrixPlugArray = transFn.findPlug("worldMatrix", 0)
matrixPlugArray.evaluateNumElements()
matrixPlug = matrixPlugArray.elementByPhysicalIndex(0)
time = oma.MAnimControl.currentTime()
timeContext = om.MDGContext(time); print 'time:', time
matrixO = matrixPlug.asMObject(timeContext)
fnMat = om.MFnMatrixData(matrixO)
matrix =  fnMat.matrix(); print list(matrix)[12:16]
timeContext = om.MDGContext(time-1); print 'time-1:', time-1
matrixO = matrixPlug.asMObject(timeContext)
fnMat = om.MFnMatrixData(matrixO)
matrix =  fnMat.matrix(); print list(matrix)[12:16]
and it prints
transFn: pSphereShape1
time: 2 kNTSCFrame
[-138.33162561773997, -552.7601891996619, 0.0, 1.0]
time-1: 1 kNTSCFrame
[-138.33162561773997, 185.2440600553723, 0.0, 1.0]
which matches what I have in my scene.

So it seems likely that the problem is your incoming MFnMesh. My guess is that you either need to use MDataHandle::asMeshTransformed, or find a way to get a dag path instead of a mesh. Perhaps you could link either a matrix or a transform node to your plug, instead of linking a shape node.

I hope that helps :)

Neil Roche

unread,
May 2, 2017, 5:57:55 AM5/2/17
to Python Programming for Autodesk Maya
The frameCache Node is pretty good if you want to get a translation or rotation from a previous frame but you can only use it on a single attribute so if you if you need it to do it on translation and rotation together you would need six frameCache nodes.  It's a pretty easy node to use, just plug your driver attribute into the frameCache stream attribute and use the varyTime attribute for your offset (it can be positive or negative). Plug the varying attribute into the driven attribute and hey presto!
Reply all
Reply to author
Forward
0 new messages