I've been trying to convert a python test to a C++ node for speed, I'm not very advanced in C++ but I did have success writing MPxNodes before...
So I inherited an MPxNode, gave it 2 input mesh and 1 output mesh attrs (using an instance of MFnTypedAttribute's create).
I steppd through my init function and all operations succeed but the compute never triggers a breakpoint even after connecting both inputs, then the output, disconnecting the output & reconnecting the output, to visible mesh nodes.
So here's my code and any tips to try are appreciated...
Header:
#ifndef NORMALWRAPNODE
#define NORMALWRAPNODE
#include "main.h"
class NormalWrap : public MPxNode
{
public:
NormalWrap(){ }
virtual ~NormalWrap(){ }
static void* creator(){ return new NormalWrap; }
virtual MStatus compute( MPlug&, MDataBlock& );
static MStatus initialize();
static MString nodeName;
static MTypeId typeId;
protected:
void projectMesh( MObject&, MObject&, MObject& );
static MObject inMesh;
static MObject colMesh;
static MObject outMesh;
};
#endif
Source:
#include "NormalWrapNode.h"
#include <maya/MIOStream.h>
MString NormalWrap::nodeName = MString("normalWrap");
MTypeId NormalWrap::typeId = MTypeId(0x8700B);
MObject NormalWrap::inMesh = MObject();
MObject NormalWrap::outMesh = MObject();
MObject NormalWrap::colMesh = MObject();
MStatus NormalWrap::initialize()
{
MStatus stat;
MFnTypedAttribute typedAttr;
inMesh = typedAttr.create("inMesh", "in", MFnData::kMesh, &stat);
colMesh = typedAttr.create("collisionMesh", "col", MFnData::kMesh, &stat);
outMesh = typedAttr.create("outMesh", "iout", MFnData::kMesh, &stat);
stat = addAttribute(inMesh);
stat = addAttribute(colMesh);
stat = addAttribute(outMesh);
stat = attributeAffects(inMesh, outMesh);
stat = attributeAffects(colMesh, outMesh);
return stat;
}
MStatus NormalWrap::compute(MPlug& plug, MDataBlock& data)
{
if( plug.attribute() != outMesh )
{
return MS::kUnknownParameter;
}
//validate & grab inputs
MDataHandle inData = data.inputValue(inMesh);
MDataHandle colData = data.inputValue(colMesh);
if( inData.type() != MFnData::kMesh || colData.type() != MFnData::kMesh )
{
return MS::kInvalidParameter;
}
//prep incoming data
MObject inObj = inData.asMeshTransformed();
MObject colObj = inData.asMeshTransformed();
//get writable object
MObject outData = MFnMeshData().create();
//apply functionality
projectMesh(inObj, colObj, outData);
//push into out channel
MDataHandle outHandle = data.outputValue(outMesh);
outHandle.setMObject(outData);
data.setClean(plug);
return MS::kSuccess;
}
void NormalWrap::projectMesh( MObject& inMesh, MObject& inCollider, MObject& outObject )
{
MFnMesh mesh( inMesh );
MFnMesh collider( inCollider );
MPointArray points = MPointArray();
mesh.getPoints( points, MSpace::kWorld );
MVector normal ;
MPointArray outPoints;
MPoint closest;
bool pointFound;
for( unsigned int i = 0 ; i < points.length() ; ++i )
{
mesh.getVertexNormal(i, normal, MSpace::kWorld);
pointFound = false;
if( collider.intersect( points[i], normal, outPoints, 0.0001, MSpace::kWorld ) )
{
closest = outPoints[0];
pointFound = true;
}
if( collider.intersect( points[i], -normal, outPoints, 0.0001, MSpace::kWorld ) )
{
if( !pointFound || points[i].distanceTo(closest) > points[i].distanceTo(outPoints[0]) )
{
closest = outPoints[0];
pointFound = true;
}
}
if( pointFound )
{
points.set( closest, i );
}
}
mesh.setPoints( points, MSpace::kWorld );
mesh.copy( inMesh, outObject );
}