Custom MPxSurfaceShape, for component manipulation


#1

Hi all,

I’m looking to develop a custom node with component manipulation, and found MPxSurfaceShape to fit the description, but am having trouble figuring out how to actually implement it.

Does anyone have either a smaller example of their own, a link to some kind of tutorial or even knowledge of how to use the supplied pyApiMeshShape.py?


#2

A search on GitHub, for any non-default or code completion-related example containing the word MPxSurfaceShape, reveals 2 examples, one a duplicate of the other.

But no indication as to how to get component selection/manipulation in there. From pyApiMeshShape.py there are two implementations of what looks like component manipulation, one referring to something called MPxSubSceneOverride and the other MPxComponentConverter. At first I figured one must be for Viewport 2.0, but they both seem to require it. When and why to prefer one over the other? Documentation indicate sub-scenes are preferable when you “require a large number of drawable entities”, so maybe that’s safe to exclude.

The custom node I’ve got in mind is perfectly adequate as an MPxLocatorNode except now I’d like to add component manipulation similar to the “Local Rotation Axes”.

components

Any ideas?


#3

I would say what you want is not really what the Maya API provides for component manipulation. I have implemented an alembic cache MPxSurfaceShape similar to the SDK’s gpuCache node where each mesh in the cache can be individually selected using the face component attribute (select character.f[0] actually selects the first mesh of the alembic cache). It took some monkeying around to get this to work and documentation was less than helpful, but it’s not very flexible and it has to fit pretty much with Maya’s idea of component selection.

That being said, if there is a particular question you have about how I got it too work, let me know.


#4

Thanks @mje11even, that fits my impression of things so far. Selecting individual meshes within an opaque blob of meshes is next on my list, so that’s encouraging to hear it’s possible.

What I haven’t found yet is the ability to make components out of things other than what I found in the apiMeshShape example, such as that Local Rotation Axes component above, do you know whether this is possible? That would cover most of my needs, I would prefer to draw it myself, but suspect Maya has its own way of drawing components like it does with face centers and vertices etc.

Preferably, the components wouldn’t involve geometry at all, just transforms. The alternative I’m looking at is MPxContext, do you or anyone else have experience with that?

For future reference, I managed to find how to use apiMeshShape.py by running the MEL script found in the C++ equivalent of the example.

loadPlugin apiMeshShape;
createNode apiMesh; 
createNode apiMeshCreator;
connectAttr apiMeshCreator1.outputSurface apiMesh1.inputSurface ;
sets -edit -forceElement initialShadingGroup |transform1|apiMesh1;

apiMeshShape


#5

You are limited to created components using the attributes that maya uses for components - v, e, and f. But like I did for the alembic node, the “components” don’t really have to be vertices, edges, or faces. As for drawing, you just have to detect if there are active components and then draw something different in your draw function for Legacy Viewport or by adding different render items in VP2. Here’s the code I use to detect what the active components are:

std::set<int> selectedComps;
if (surfaceShape->hasActiveComponents()) {
   MObjectArray activeComps = surfaceShape->activeComponents();
   if (activeComps.length() > 0) {
      MFnSingleIndexedComponent fnComp(activeComps[0]);
      if (fnComp.elementCount()) {
         MIntArray activeIds;
         fnComp.getElements(activeIds);
         if (fnComp.componentType() == MFn::kMeshPolygonComponent) {
            for (size_t i = 0; i < activeIds.length(); ++i) {
               selectedComps.insert(activeIds[i]);
            }
        }
    }
}

The MFn::kMeshPolygonComponent is for the .f attribute.

I have no experience using MPxContext.