Maya API [C++] - worldMatrix to translate

0

I'm new to Maya API/C++ in general and I'm trying to write a simple plugin. I have the relevant code pasted below but I have also attached dropbox link to a .zip if you'd prefer to download it as a package.

https://dl.dropboxusercontent.com/u/40345020/inverseMatrixNode03.zip

This code in particular is sampled from a .pdf I got off Autodesk Developer Network although I have tried other methods, including ones provided in "Complete Maya Programming" (David Gould). The files compile without error and so I believe I erred somewhere in my method. Anyway, onto the code.

Synopsis of the file:

  1. Read a matrix input as MTransformationMatrix
  2. Invert the matrix (used later for comparison output)
  3. Get translate of unaltered matrix as a vector
  4. Get translate of inverted matrix as, again, another vector
  5. Assign each x,y,z component of the two vectors as individual doubles so I can get tx,ty,tz for both the original matrix and its inverse
  6. Assign those values as outputAttributes

-- END --

.h header, named "inverseMatrixNode.h"

#include <maya/MPxNode.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MMatrix.h>
#include <maya/MFnMatrixAttribute.h>
#include <maya/MTransformationMatrix.h>
#include <maya/MVector.h>

#include <math.h>
#include <iostream>

#include <maya/MFnPlugin.h>


class matrixInverseNode : public MPxNode
{
public:
                        matrixInverseNode();
virtual                 ~matrixInverseNode();
static      void*       creator();

virtual     MStatus     compute( const MPlug &plug, MDataBlock& data);
static      MStatus     initialize();

static      MTypeId     id;

//input
static      MObject     aInMatrix;

//output
static      MObject     aOutInvMatrix;
static      MObject     aOutTrans;
static      MObject     aOutTransX;
static      MObject     aOutTransY;
static      MObject     aOutTransZ;
static      MObject     aOutInvTrans;
static      MObject     aOutInvTransX;
static      MObject     aOutInvTransY;
static      MObject     aOutInvTransZ;


};

and the .cpp

#include "inverseMatrixNode.h"

MTypeId matrixInverseNode::id( 0x00000233 );
MObject matrixInverseNode::aInMatrix;
MObject matrixInverseNode::aOutTrans;
MObject matrixInverseNode::aOutTransX;
MObject matrixInverseNode::aOutTransY;
MObject matrixInverseNode::aOutTransZ;
MObject matrixInverseNode::aOutInvTrans;
MObject matrixInverseNode::aOutInvTransX;
MObject matrixInverseNode::aOutInvTransY;
MObject matrixInverseNode::aOutInvTransZ;


matrixInverseNode::matrixInverseNode()
{
}

matrixInverseNode::~matrixInverseNode()
{
}

MStatus matrixInverseNode::compute( const MPlug& plug, MDataBlock& data )
{
MStatus status;

//create matrix handle
MTransformationMatrix inMatrix = data.inputValue( aInMatrix, &status ).asMatrix();
CHECK_MSTATUS_AND_RETURN_IT( status );

// Get Translate as vector then assign vector components to individual values
MVector transInMatrix = inMatrix.getTranslation( MSpace::kWorld );
double transInMatrixX = transInMatrix.x;
double transInMatrixY = transInMatrix.y;
double transInMatrixZ = transInMatrix.z;

// And again for the inverseMatrix
MTransformationMatrix invInMatrix = inMatrix.asMatrixInverse();

MVector transInvInMatrix = invInMatrix.getTranslation( MSpace::kWorld );
double transInvInMatrixX = transInvInMatrix.x;
double transInvInMatrixY = transInvInMatrix.y;
double transInvInMatrixZ = transInvInMatrix.z;

//create handles for outTrans and its inverse
MDataHandle hOutTransX = data.outputValue( aOutTransX, &status );
CHECK_MSTATUS_AND_RETURN_IT( status );
MDataHandle hOutTransY = data.outputValue( aOutTransY, &status );
CHECK_MSTATUS_AND_RETURN_IT( status );
MDataHandle hOutTransZ = data.outputValue( aOutTransZ, &status );
CHECK_MSTATUS_AND_RETURN_IT( status );

MDataHandle hOutInvTransX = data.outputValue( aOutInvTransX, &status );
CHECK_MSTATUS_AND_RETURN_IT( status );
MDataHandle hOutInvTransY = data.outputValue( aOutInvTransY, &status );
CHECK_MSTATUS_AND_RETURN_IT( status );
MDataHandle hOutInvTransZ = data.outputValue( aOutInvTransZ, &status );
CHECK_MSTATUS_AND_RETURN_IT( status );

// set value to handle and then set clean
hOutTransX.set( transInMatrixX );
hOutTransX.setClean();
hOutTransY.set( transInMatrixY );
hOutTransY.setClean();
hOutTransZ.set( transInMatrixZ );
hOutTransZ.setClean();

hOutInvTransX.set( transInvInMatrixX );
hOutInvTransX.setClean();
hOutInvTransY.set( transInvInMatrixY );
hOutInvTransY.setClean();
hOutInvTransZ.set( transInvInMatrixZ );
hOutInvTransZ.setClean();

return MS::kSuccess;
}

void* matrixInverseNode::creator()
{
return new matrixInverseNode();
}

MStatus matrixInverseNode::initialize()
{
MStatus status;


MFnNumericAttribute nAttr;

aOutTransX = nAttr.create( "outTranslateX", "oTx", MFnNumericData::kFloat, 0.0 );
nAttr.setKeyable( false );
nAttr.setStorable( false );
nAttr.setReadable( true );
nAttr.setWritable( false );
nAttr.setCached( false );
addAttribute( aOutTransX );
aOutTransY = nAttr.create( "outTranslateY", "oTy", MFnNumericData::kFloat, 0.0 );
nAttr.setKeyable( false );
nAttr.setStorable( false );
nAttr.setReadable( true );
nAttr.setWritable( false );
nAttr.setCached( false );
addAttribute( aOutTransY );
aOutTransZ = nAttr.create( "outTranslateZ", "oTz", MFnNumericData::kFloat, 0.0 );
nAttr.setKeyable( false );
nAttr.setStorable( false );
nAttr.setReadable( true );
nAttr.setWritable( false );
nAttr.setCached( false );
addAttribute( aOutTransZ );
aOutTrans = nAttr.create( "outTranslate", "oT", aOutTransX, aOutTransY, aOutTransZ );
nAttr.setKeyable( false );
nAttr.setStorable( false );
nAttr.setReadable( true );
nAttr.setWritable( false );
nAttr.setCached( false );
addAttribute( aOutTrans );

aOutInvTransX = nAttr.create( "outInverseTranslateX", "oITx", MFnNumericData::kFloat, 0.0 );
nAttr.setKeyable( false );
nAttr.setStorable( false );
nAttr.setReadable( true );
nAttr.setWritable( false );
nAttr.setCached( false );
addAttribute( aOutInvTransX );
aOutInvTransY = nAttr.create( "outInverseTranslateY", "oITy", MFnNumericData::kFloat, 0.0 );
nAttr.setKeyable( false );
nAttr.setStorable( false );
nAttr.setReadable( true );
nAttr.setWritable( false );
nAttr.setCached( false );
addAttribute( aOutInvTransY );
aOutInvTransZ = nAttr.create( "outInverseTranslateZ", "oITz", MFnNumericData::kFloat, 0.0 );
nAttr.setKeyable( false );
nAttr.setStorable( false );
nAttr.setReadable( true );
nAttr.setWritable( false );
nAttr.setCached( false );
addAttribute( aOutInvTransZ );
aOutInvTrans = nAttr.create( "outInverseTranslate", "oIT", aOutInvTransX, aOutInvTransY, aOutInvTransZ );
nAttr.setKeyable( false );
nAttr.setStorable( false );
nAttr.setReadable( true );
nAttr.setWritable( false );
nAttr.setCached( false );
addAttribute( aOutInvTrans );

MFnMatrixAttribute mAttr;

aInMatrix = mAttr.create( "inMatrix", "inM", MFnMatrixAttribute::kDouble );
mAttr.setStorable( true );
mAttr.setKeyable( false );
mAttr.setReadable( true );
mAttr.setWritable( true );
mAttr.setCached( false );
addAttribute( aInMatrix );
attributeAffects( aInMatrix, aOutTransX );
attributeAffects( aInMatrix, aOutTransY );
attributeAffects( aInMatrix, aOutTransZ );
attributeAffects( aInMatrix, aOutTrans );

attributeAffects( aInMatrix, aOutInvTransX );
attributeAffects( aInMatrix, aOutInvTransY );
attributeAffects( aInMatrix, aOutInvTransZ );
attributeAffects( aInMatrix, aOutInvTrans );

return MS::kSuccess;
}

MStatus initializePlugin( MObject obj )
{
MStatus status;

MFnPlugin fnPlugin( obj, "Colin Kennedy", "1.0", "Any" );

status = fnPlugin.registerNode( "matrixInverse", 
                                matrixInverseNode::id,
                                matrixInverseNode::creator,
                                matrixInverseNode::initialize );
CHECK_MSTATUS_AND_RETURN_IT( status );

return MS::kSuccess;
}

MStatus uninitializePlugin( MObject obj )
{
MStatus status;

MFnPlugin fnPlugin( obj );

status = fnPlugin.deregisterNode( matrixInverseNode::id );
CHECK_MSTATUS_AND_RETURN_IT( status );

return MS::kSuccess;
}       

Despite this being simple, I'm getting no results once the plugin is loaded inside Maya. My files compile without warning/error but when I actually try to grab a .worldMatrix from a transform in Maya, both the original matrix and its inverse translate values read (0,0,0).

If someone could shed some light on the error in my implementation or suggest a better way to get translate/rotate from a matrix, I'd appreciate it. The project is made using Maya Plugin Wizard in VS2010. The node is named matrixInverse as to not conflict with the native inverseMatrix node in Maya. Oh, also, if there's any egregious, noobish errors in my code, I'd love to know about those, too. Thank you.

c++
matrix
maya
matrix-inverse
asked on Stack Overflow May 11, 2014 by ColinKennedy

1 Answer

0

It won't calculate unless you plug the outputs into something usually, but you haven't given it an if statement to have it not compute. My guess is that your doing this:

 // set value to handle and then set clean
 hOutTransX.set( transInMatrixX );
 hOutTransX.setClean();
 hOutTransY.set( transInMatrixY );
 hOutTransY.setClean();
 hOutTransZ.set( transInMatrixZ );
 hOutTransZ.setClean();

Instead of:

 hOutTransX.setFloat(transInMatrixX);
 hOutTransY.setFloat(transInMatrixY);
 hOutTransZ.setFloat(transInMatrixZ);

 data.setClean(plug);

You have to specify what you're setting and just set the plug clean not the attribute. Since the output attributes are floats just do a setFloat to set the value.I would also make sure to instead of declaring the variable as a double declare it as float:

 float transInvInMatrixX = transInvInMatrix.x;

Instead of:

 double transInvInMatrixX = transInvInMatrix.x;

If you want to use doubles just change the variable in the init to MFnNumericData::kDouble instead of float.

Here's my simple node example that could help as well: http://goo.gl/PNcPW5

Hope that helps!

answered on Stack Overflow May 28, 2014 by chribis • edited May 28, 2014 by chribis

User contributions licensed under CC BY-SA 3.0