we are currently using USD in a bit of an un-usual use-case. As part of that we have developed an exporter that exports scenes from 3dsmax and uses an ExportChaser to wrangle the USDs that are exported. As part of this we are injecting custom properties, flatten the hierarchy (as we are only interested in geo here), rename prims etc.
I am flattening the hierarchy using Sdf.CopySpec on the root layer (the exported files are fully self-contained single layer USDs) to copy prims to a newly created in-memory stage and save from there.
So far this works fine but i am facing one problem. The 3dsmax USD exporter exports instances as instances, which is obviously a feature. But that does not work with CopySpec. For every instanced object one of the instances remains the rest is lost.
I would like to make all instances actual copies. Is there an easy way to do that? If not, is my only way out to look for instances and adjust our copying code to make sure i make a copy of the original prototype prim and apply any chances?
Thanks in advance,
For reference: So it seems that it is enough to simply call
setInstanceable(False) to uninstance. That is kind of unintuitive to me, but at least works
Yeah, as you said setInstanceable(False) should work.
Setting it to true creates a hidden prototype in the stage which is being instanced.
This came up recently at NV too. One thing to look out for is that when you un-instance a prim, it will cause recomposition and may expose another instanced prim in the descendant prims that you would have missed with your initial traversal.
When we introduced native instancing, it saved our bacon on really huge sets on Coco, and when we considered how
Flatten() should handle instancing, added extra logic to preserve instancing, because a) the prototypes could be localized to the single layer we were producing, b) we thought that would always be better because the difference in stage weight could be so drastic.
But clearly our crystal ball was a bit foggy It probably should be an optional behavior, and as @mati-nvidia mentioned, it’s more than a few lines of code to “fully flatten” the results of Flatten() when there is nested instancing… please feel free to file a GitHub Issue, @instinct-vfx .
Thanks a lot @mati-nvidia and @spiff! The way we use USD in this case is very weird, niche and likely not intended That said i still find some rather “common” operations to be un-intuitive both in regards to naming and “how to call them”. I am still thinking about the proper approach here. This is caused by a mix of how max-usd exports and what we are doing in an export-chaser to wrangle the USD as we need it in this case. (For context: There are additional Xform Prims added (I think (!) due to the meshes being instances and that leads to all kinds of weirdness in the export chaser. Add to that, that what we are doing is likely not really how you would typically use USD and things get weird).
Oh yeah, the gprim-instancing case (which we don’t do internally) adds another wrinkle to what you’d really like a “remove native instancing form this stage” operation to do.
The possibly-overcautious reason we went with just
SetInstanceable(true|false) rather than
Instance mutators is that
Instance as a command can’t always succeed, because NI is predicated on there being composition arcs on the prim, whereas we think making something “instanceable” doesn’t convey a guarantee that it will be…