I recently ran across a node which uses MPlugs to get and set its data rather than the appropriate MDataHandle from within the node's compute(). Will this cause any concerns for correct evaluation of the node? If not, are the advantages of using MDataHandles over MPlugs purely performance related?
For a bit of context, the reason the code was written this way is because the programmer was making use of some classes which generically instantiate a converter capable of transforming application data to their appropriate mapping on an MPlug tree (internal mesh representation to mesh plug, float to float plug, vector<double> to dblArrayPlug,... you get the idea). Rather than adding new functionality to create converters to MDataHandles they simply call the generic plug converter and get and set data through the MPlug. I didn't know this could be done. Perhaps it shouldn't be done this way, but is it legal to take this approach if performance is not a factor?
Solved! Go to Solution.
I recently ran across a node which uses MPlugs to get and set its data rather than the appropriate MDataHandle from within the node's compute(). Will this cause any concerns for correct evaluation of the node? If not, are the advantages of using MDataHandles over MPlugs purely performance related?
For a bit of context, the reason the code was written this way is because the programmer was making use of some classes which generically instantiate a converter capable of transforming application data to their appropriate mapping on an MPlug tree (internal mesh representation to mesh plug, float to float plug, vector<double> to dblArrayPlug,... you get the idea). Rather than adding new functionality to create converters to MDataHandles they simply call the generic plug converter and get and set data through the MPlug. I didn't know this could be done. Perhaps it shouldn't be done this way, but is it legal to take this approach if performance is not a factor?
Solved! Go to Solution.
Solved by negow. Go to Solution.
I have also seen this in other-peoples-code, but haven't found a reason for it, so this question is interesting to me as well.
Here's my take.
1. One caveat to MPlug is that you cannot write to an MPlug without dirtying anything connected to it. MDataHandle.outputValue(...).set() on the other hand wouldn't propagate any dirty flags. That is left to the MPxNode::attributeAffects mechanic.
2. Another caveat is that you also cannot *read* from an MPlug without evaluating any of its dependencies. Like if something is connected to it, that would first get evaluated. You could on the other hand call MDataHandle.outputValue(...).asInt() to fetch the last evaluated value of a plug, without causing any sort of evaluation or dirty propagation.
3. My understanding of MDataHandle.inputValue(...).asInt() versus MPlug.asInt() however isn't so clear cut. My *expectation* is that by using MDataHandle you give Maya more information to work with when it comes to rebuilding the Evaluation Graph, since that is where I expect it would be monitoring.
The first two points witness daily and am quite certain of, number (3) on the other hand is close to superstition and I'd love some clarity on it.
I have also seen this in other-peoples-code, but haven't found a reason for it, so this question is interesting to me as well.
Here's my take.
1. One caveat to MPlug is that you cannot write to an MPlug without dirtying anything connected to it. MDataHandle.outputValue(...).set() on the other hand wouldn't propagate any dirty flags. That is left to the MPxNode::attributeAffects mechanic.
2. Another caveat is that you also cannot *read* from an MPlug without evaluating any of its dependencies. Like if something is connected to it, that would first get evaluated. You could on the other hand call MDataHandle.outputValue(...).asInt() to fetch the last evaluated value of a plug, without causing any sort of evaluation or dirty propagation.
3. My understanding of MDataHandle.inputValue(...).asInt() versus MPlug.asInt() however isn't so clear cut. My *expectation* is that by using MDataHandle you give Maya more information to work with when it comes to rebuilding the Evaluation Graph, since that is where I expect it would be monitoring.
The first two points witness daily and am quite certain of, number (3) on the other hand is close to superstition and I'd love some clarity on it.
Those are good points. From more wandering on the web, it appears that this is handled gracefully (today anyway), even though it is not the correct way to do the computations. I happened upon this article which gives a short comparison at the very end: https://around-the-corner.typepad.com/adn/2015/03/evaluating-node-attribute.html
From what I can gather, it appears that the performance differences are mostly the result of copying data when using MPlug rather than MDataHandle. This is particularly noticeable in the case of "multi" plugs with lots of individual elements. It looks like most of the MDataHandle functions return by reference, so you literally have access to the memory in the dataBlock. MPlug, on the other hand, must be passed a reference for it to fill.
I am still really hoping that someone at Autodesk can weigh in on this one and give us a definitive answer.
Those are good points. From more wandering on the web, it appears that this is handled gracefully (today anyway), even though it is not the correct way to do the computations. I happened upon this article which gives a short comparison at the very end: https://around-the-corner.typepad.com/adn/2015/03/evaluating-node-attribute.html
From what I can gather, it appears that the performance differences are mostly the result of copying data when using MPlug rather than MDataHandle. This is particularly noticeable in the case of "multi" plugs with lots of individual elements. It looks like most of the MDataHandle functions return by reference, so you literally have access to the memory in the dataBlock. MPlug, on the other hand, must be passed a reference for it to fill.
I am still really hoping that someone at Autodesk can weigh in on this one and give us a definitive answer.
It would be rather trivial to test though; e.g. make a multi-plug with 10,000 elements and compare. You'd spot both timing and memory usage via a debugger like Visual Studio. Can't get more definitive than that. If you do, post it here so nobody will have to do it ever again.
It would be rather trivial to test though; e.g. make a multi-plug with 10,000 elements and compare. You'd spot both timing and memory usage via a debugger like Visual Studio. Can't get more definitive than that. If you do, post it here so nobody will have to do it ever again.
Can't find what you're looking for? Ask the community or share your knowledge.