- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
This is a follow-up to this question.
https://forums.autodesk.com/t5/maya-programming/getting-set-data-in-node-s-compute-fails-when-loadin...
I have a node derived from MPxObjectSet so it can contain information about a set of edges on a mesh. The information is used in compute() to create UV maps for that mesh. For this, my node adds a mesh attribute to the attributes of MPxObjectSet, which is the mesh on which we will work.
When created, the node is inserted just before the final shape in the mesh history and we add the edge set information to it. We then use the set data to find the polygon vertices matching the selected edges. This works fine in simple situations, but if we add, for example, a smooth operation on the polygon, the edge indexes stop matching the polygon vertices we get from the mesh attribute.
I would like to know if there is a way to reconcile the index data from the set with the vertex data from the mesh attribute when the polygon has been smoothed.
I wrote a test node to isolate and illustrate the problem. The code is included at the end of this post and does not include the workaround for the problem when opening a file discussed in the question I asked last week.
The problem can be reproduced by following these steps after loading the test plugin.
We run the following MEL script that creates a cube and an instance of our test node. It also selects an edge on the cube and adds it to the test node (since it is also a set node). Finally, it inserts the test node just before the final shape in the mesh history.
Test script:
-----------
proc string getNodeName(string $nodeAttr)
{
string $buffer[];
tokenize($nodeAttr, ".", $buffer);
return $buffer[0];
}
$polys = `polyCube`;
$poly = $polys[0];
select -clear;
polySelect -shortestEdgePath 0 1 $poly;
// Create the test node
$setName = `sets`;
$nodeName = `createNode "setNodeTest"`;
$edges = `sets -q $setName`;
sets -e -addElement $nodeName $edges;
// Add the test node in the path for the mesh
$shape = `connectionInfo -sourceFromDestination ($nodeName + ".dagSetMembers[0]")`;
$shape = `getNodeName $shape`;
$meshsrc=`connectionInfo -sourceFromDestination ($shape + ".inMesh")`;
connectAttr $meshSrc ($nodeName + ".mesh");
connectAttr -force ($nodeName + ".mesh") ($shape + ".inMesh");
-----------
The resulting node network is as shown below (some unrelated nodes are not included to remove clutter).
The test node outputs the data from the set information of the node and the mesh attribute to the Output Window during compute() as follows:
----
Polygon 0 vertices:
0,1,3,2,
Polygon 1 vertices:
2,3,5,4,
Polygon 2 vertices:
4,5,7,6,
Polygon 3 vertices:
6,7,1,0,
Polygon 4 vertices:
1,7,5,3,
Polygon 5 vertices:
6,0,2,4,
Edge idx= [0,1]
----
We can see that the edge between vertices 0 and 1 is selected, which seems to be OK.
Next, we select the cube and execute "smooth" from the "Mesh" menu. This adds the node "polySmoothFace1" between our test node and the cube in the path of the mesh.
The new node network is shown below.
We disconnect the mesh input of our test node and then reconnect it to force an execution of its compute().
This time, the output is as follows.
----
Polygon 0 vertices:
0,1,3,2,
Polygon 1 vertices:
2,3,5,4,
Polygon 2 vertices:
4,5,7,6,
Polygon 3 vertices:
6,7,1,0,
Polygon 4 vertices:
1,7,5,3,
Polygon 5 vertices:
6,0,2,4,
Edge idx= [0,14]
Edge idx= [14,1]
----
So the set data now contains 2 edges connected at vertex 14. But our mesh data does not contain a vertex 14, which is our problem.
My guess is that the set data reflects the mesh after applying the smooth operation, while the mesh attribute data is the data before smooth, so there is a discrepancy. Is there a way to reconcile the data?
Thanks!
Source code for the test node.
#include <maya/MDagPath.h> #include <maya/MFnMesh.h> #include <maya/MFnMeshData.h> #include <maya/MFnPlugin.h> #include <maya/MFnSet.h> #include <maya/MFnTypedAttribute.h> #include <maya/MItMeshEdge.h> #include <maya/MItSelectionList.h> #include <maya/MPlugArray.h> #include <maya/MPxObjectSet.h> #include <maya/MSelectionList.h> class setNode : public MPxObjectSet { public: setNode(); virtual ~setNode(); static void* creator(); static MStatus initialize(); MStatus compute(const MPlug &plug, MDataBlock &block) override; // local node attributes static MTypeId id; static MObject aMesh; }; MTypeId setNode::id(0x8000c); // local attributes MObject setNode::aMesh; setNode::setNode() {} setNode::~setNode() {} void* setNode::creator() { return new setNode(); } MStatus setNode::initialize() { MStatus status; MFnTypedAttribute attrFn; aMesh = attrFn.create("mesh", "mes", MFnMeshData::kMesh, MObject::kNullObj, &status); CHECK_MSTATUS(status); CHECK_MSTATUS(addAttribute(aMesh)); attributeAffects(aMesh, aMesh); attributeAffects(dagSetMembers, aMesh); attributeAffects(DNSetMembers, aMesh); attributeAffects(partition, aMesh); attributeAffects(groupNodes, aMesh); return MStatus::kSuccess; } MStatus setNode::compute(const MPlug &plug, MDataBlock &block) { MStatus status; if (plug != aMesh) { return MS::kUnknownParameter; } MPlugArray arr; plug.connectedTo(arr, true, false); if (arr.length() == 0) { // No input mesh. Nothing to do. // Necessary because it looks like we are being called once before the mesh is connected // to the node. CHECK_MSTATUS(block.setClean(plug)); return MS::kSuccess; } MDataHandle inputData = block.inputValue(aMesh, &status); CHECK_MSTATUS_AND_RETURN_IT(status); MDataHandle outputData = block.outputValue(aMesh, &status); CHECK_MSTATUS_AND_RETURN_IT(status); CHECK_MSTATUS(outputData.copy(inputData)); MFnMesh fnMesh(outputData.asMesh(), &status); CHECK_MSTATUS_AND_RETURN_IT(status); int numPolys = fnMesh.numPolygons(&status); CHECK_MSTATUS_AND_RETURN_IT(status); MIntArray vertexList; for (int pIndex = 0; pIndex < numPolys; ++pIndex) { cerr << "Polygon " << pIndex << " vertices:\n"; fnMesh.getPolygonVertices(pIndex, vertexList); unsigned int nbV = vertexList.length(); cerr << " "; for (unsigned int i = 0; i < nbV; ++i) { cerr << vertexList[i] << ","; } cerr << "\n"; } MFnSet fnSet(thisMObject()); MSelectionList selectionList; CHECK_MSTATUS_AND_RETURN_IT(fnSet.getMembers(selectionList, true)); for (MItSelectionList iter(selectionList); !iter.isDone(); iter.next()) { MDagPath item; MObject component; iter.getDagPath(item, component); // Edge if (component.hasFn(MFn::kMeshEdgeComponent)) { MItMeshEdge edgeFn(item, component, &status); CHECK_MSTATUS(status); for (; !edgeFn.isDone(); edgeFn.next()) { cerr << "Edge idx= [" << edgeFn.index(0) << "," << edgeFn.index(1) << "]\n"; } } else { cerr << "Component is not an edge!\n"; } } outputData.setClean(); return MS::kSuccess; } // standard initialization procedures // MStatus initializePlugin( MObject obj ) { MStatus result; MFnPlugin plugin( obj, PLUGIN_COMPANY, "0.0", "Any"); result = plugin.registerNode("setNodeTest", setNode::id, setNode::creator, setNode::initialize, MPxNode::kObjectSet); return result; } MStatus uninitializePlugin( MObject obj) { MStatus result; MFnPlugin plugin( obj ); result = plugin.deregisterNode(setNode::id); return result; }
Solved! Go to Solution.