Hi all - so, while we've been using alembic here at Luma for a while, and have been generally quite pleased with it; one area that's always created headaches, though, is the use of alembic nodes and references.
NOTE: throughout here, I'll be talking about about "meshes" for simplicity, but the same principles can be applied to all the shape types that alembic supports - ie, replace "outPolyMesh" with "outNSurface", etc...
The Issue
In maya, meshes originate as numbered indices on AlembicNode.outPolyMesh, which are then connected to normal mesh nodes:
myAlembicNode.outPolyMesh[12] => trogdorShape.inMesh
The problem is that many maya operations will try to insert themselves in this chain. For instance, if you try to do per-face-assignment, you get:
myAlembicNode.outPolyMesh[12] => groupParts1.inputGeometry
groupParts3.outputGeometry => trogdorShape.inMesh
...and if myAlembicNode is inside of a reference, these reference edits are created:
disconnectAttr("myAlembicNode.outPolyMesh[12]", "trogdorShape.inMesh")
connectAttr("myAlembicNode.outPolyMesh[12]", "groupParts1.inputGeometry")
connectAttr("groupParts3.outputGeometry", "trogdorShape.inMesh")
So far, so good... the problem is that if the alembic file is updated - for instance, if a completely new mesh is added - there is no guarantee that "trogdorShape" will still map to outPolyMesh[12] - it might become outPolyMesh[29] after. So maya's referencing system will now effectively break - it may connect the wrong input mesh into trogdorShape.inMesh, or it may connect nothing at all.
The Proposed Solution
You could try to solve this by some sort of solution which automatically remaps connections when an alembic node is updated, but this approach is sort of fragile, and is sort of trying to fight the way that maya referencing wants to work.
In my opinion, the best solution is one which makes the attribute names much more tightly tied to the underlying shape names, so that if the shape name hasn't changed, the attribute name won't either. Ideally, we could create attribute names that directly mapped in an easy one-to-one way to the underlyingShape names - ie:
myAlembicNode.outPolyMeshByName.trogdorShape => trogdorShape.inMesh
Unfortunately, this doesn't work, because the shape names can have hierarchies, and attribute names on maya nodes must be unique across the whole node (not just unique amongst it's parent attribute's children). Furthermore, alembic node names allow a greater range of characters than maya attribute names.
So, since we can't make the attribute names match directly, the next best solution would be to generate the attribute name based on a hash of the shape name - something like:
myAlembicNode.outPolyMeshByHash._138be907f2[0] => trogdorShape.inMesh
The idea is that we would have a guarantee that "trogdorShape" would always map to 138be907f2, so as long as it's name didn't change, it's attribute wouldn't either... unless there was a hash collision. We should choose the length of the hash such that hash collisions should be EXTREMELY unlikely... but we can also make the hash-attribute-name an array node to deal with collisions, if they do happen (thus the [0] in the above example). Or, we could just say that hash collisions are sufficiently unlikely that we can ignore the possibility, and not bother with making it an array.
In any case, this would solve the issue with alembic nodes breaking under maya referencing. For backwards compatibility, we could make it so that both outPolyMesh and outPolyMeshByHash exist, and are valid... but that newly created nodes would make their connections using the named hash attributes by default.
Querying Mesh Names
Additionally, it would be nice if there were a way to query the AlembicNode directly about what the source mesh name was for a given output, to help fix things up in case something goes wrong. Simple read-only attributes on the AlembicNode would help - ie, we could create an array of string names corresponding to the indices of outPolyMesh:
myAlembicNode.outPolyMeshNames[12]: "world/trogdor/trogdorShape"
Or, if we go with a new hash-based attribute naming scheme, we could make the new attributes compound attrs:
myAlembicNode.polyMeshByHash._138be907f2[0].outMesh => trogdorShape.inMesh
myAlembicNode.polyMeshByHash._138be907f2[0].name: "
world/trogdor/trogdorShape"
myAlembicNode.polyMeshByHash._138be907f2[0].index: 12 (for tying to the "old" outPolyMesh attribute)
So - any thoughts on all this? Anybody else have similar problems, or better solutions? Is this something the maintainers might address in a future release? Or at least would endorse?