A Tour of USD Houdini Primitives
To import geometry from a USD file into Houdini we use the USD Import SOP. This SOP will create USD Packed Primitives. This tutorial will explain the most useful options on the USD Import SOP and the characteristics for the USD Packed Primitive.
Open Houdini. Create a geometry node. Jump inside it. Delete the default file node and drop down a USD Import SOP.
In the "USD File" parameter, select "Toaster.usd" from the "$USD/extras/usd/tutorials/Houdini" directory.
Press the "Tree View" button.
This will bring up a window that displays the object hierarchy in the file. Note the object types. You should see xforms and meshes. In USD lingo the drawable leaves of the this hierarchy are called gprims. Xforms are a group containing a transform.
Another way to look at USD graph hierarchies is to use the usdview executable. It can show you a lot more information.
Select the import check box next to the "Toaster" and close the tree view window. Middle click on the import node in the network view. You should see we have one "USD Packed Primitive" and a "P" point attribute.
USD Packed primitives also have intrinsic attributes. Open the geometry spread sheet, select primitive attributes and show the "usdFileName", "usdPrimPath", and "usdType" intrinsics.
"usdFileName" and "usdPrimPath" are the primary intrinsics that the packed primitive needs to read the geometry from the file. "usdType" is a read only intrinsic that is just there for info or use in expressions and wrangles.
Because this primitive is Packed Primitive, you can do the same sorts of things with it that you can with the Geometry Packed Prims created with the Pack SOP. You can rigidly transform it, use it in a Bullet simulation etc. If you want to modify the geometry contained in the prim, you have to unpack it. You can do this with the normal Unpack SOP or you can use the USD Unpack SOP.
Drop a Unpack SOP and connect it to the import node. Each iteration of the Unpack SOP will unpack one level in the USD hierarchy. In our toaster example, 1 iteration doesn't do much for us. It just returns the /Toaster/Geom scope. 2 levels is a bit more interesting. In this case we unpack to 3 USD packed prims.
This might be useful if we wanted to do a rigid body sim where the pieces of the toaster break and fly off.
Unpacking to Houdini Geometry
If we turn off the iterations check box on the Unpack SOP it unpack all the way to Houdini geometry. Here is the geometry info if we do that:
Two important attributes to notice are the "usdpath" and the "usdprimpath". These contain the values that were in the intrinsics in the original prims. We keep these values in attributes so you can modify the geometry and re-export it as a overlay.
The P attribute is what you expect. USD primitives always have an attribute called "displayColor". This is translated to Cd when we import into Houdini. All the other attributes came from USD "primvars". They are shading signals.
Lets go back and look at the import node again and look at the "Traversal" parameter. If it is set to "No Traversal" the SOP will create one USD Packed Prim for each entry in the "Prim Path" parameter window. If it is set to anything else, it will traverse the hierarchy of each prim listed in the "Prim Path" parameter window looking for ancestor prims that match a criteria.
So if we know we are going to unpack all the way to Houdini geometry, it would be more efficient to import just the gprims in the first place.
Now we can use a Unpack SOP to do one iteration to unpack to polygons. Obviously with a toaster this doesn't matter at all but if you had a deep hierarchy with lots of gprims it can be a bigger deal. Recursively iterating over a deep hierarchy with the Unpack SOP can be slow.
Packed prims in Houdini can be very light weight if you don't display the full geometry. Sometimes is is useful to import a lot of packed prims and cull them based on their point positions or their intrinsic attributes before displaying them.
Here is a silly contrived example of doing that. On the import node, the "Display As" attribute is set to "Centroid". We use a wrangle to delete all the bits that don't have "Plastic" in the name and then we turn on "display full geo" using a "Packed Edit" SOP.
So that our primary traversal is as fast a possible, we don't support wildcards in the "Prim Path" parameter window. If we need to use wildcards we could do something like the above with a wrangle node or we could use a custom traversal.
The SOP has a few fixed traversal criteria that are designed to be as fast as possible. It also has the option of using a custom criteria designed to be flexible. A custom traversal can query various USD concepts.
When we set the "Traversal" parameter to "Custom Traversal" there is a second pane displayed in the parameter window called "Advanced".
If we set the "Name Mask" parameter to "*Plastic*" we can achieve the same results we did with the wrangle example above.
If we ran a custom traversal like this over a really big hierarchy it would be slow. The trick is to try and narrow your traversal as much as possible by selecting the right starting points in the "Prim Path" parameter window.
USD Unpack SOP
The USD Unpack SOP uses the exact same traversal mechanism as the USD Import SOP. It just traverses the primitive hierarchy referenced by existing USD Packed Primitives rather than importing from a file.
Another feature of the USD Unpack SOP is that you can filter the primvars you unpack. When we unpack a USD Packed Primitive to Houdini geometry we copy the values of any primvars defined on the USD primitives to attribute on the Houdini primitives. The normal Unpack SOP will extract all the primvars. In some cases this can be heavy and there might be problems with clashes between primvars defined on different prims. In Houdini all primitives in a SOP geometry share the same set of attributes. We can specify a regular expression on the USD Unpack SOP to just extract the primvars we need.
If we use the USD Import SOP to load the toaster without doing any traversal, connect a USD Unpack SOP and set it's "Geometry Type" parameter to "Polygons" we can use it just to limit the our primvars.
In this I just want Cd. The USD Unpack return polygons with a Cd attribute and usdpath and usdprimpath. The path attributes will always be created when we unpack USD packed primitives.
A Point Instancer is a USD primitive that contains an array of instances. Each instance has a reference to a prototype, a position, scale and orientation.
Load the example file "rocks.usd" from the "$USD/extras/usd/tutorials/Houdini" directory. Open the tree view.
Note that the type of the primitive "/Rocks/Instances" is a point instancer. It should contain 500 instances of one prototype rock with random positions, scales and orientations. To understand this prim it is work looking at it in usdview. This is usdview's display of the attributes in "/Rocks/Instances".
The "prototypes" attribute says where to find the prototypes. In this case there is only one and it is a child of the instancer. The "protoIndicies" attribute specifies which entry in the "prototype" attribute prototype to use for each instance and because we only have one prototype its all 0. The position, orientation and scale attributes do what you would expect.
If we load the PointInstancer primitive using the USD SOP with no traversal, we get a single USD Packed Primitive. If we then unpack that primitive, we get 500 USD Packed Primitives, one for each instance. These instance primitives have a couple of extra intrinsic attributes, "usdSrcPrimPath" and "usdIndex".
For most purposes all we need is the usdPrimPath and the transform intrinsics that every prim have. However, to be able to write these prototype back into a file, we need to know which point instancer prim they came from. The usdSrcPrimPath intrinsic does that.
USD Scenegraph Instances
USD also supports another form of instancing where several prims can share an explicit master. A USD Packed Prim can refer to an instance but it can't reference anything inside the instance and it would defeat the purpose of instancing to modify anything inside an instance anyway. If you attempt to unpack an instance, the unpack SOP will expand the instance to Houdini geometry without the usual usdprimpath attributes. This can be confusing but it is typically an indication that you are attempting to do something that doesn't make sense.
Each USD Packed Primitive also has a intrinsic attribute called usdFrame. This intrinsic is initialized from the time parameter on the import SOP. The default value for that parameter is $FF. If you are loading geometry that is not animated, you can get better performance if you change that parameter to a constant value.
Theoretically, you can change the value of this intrinsic anywhere in the SOP graph. However, in practice, we have seen some viewport redraw issues when you do this. Particularly when scrubbing the timeline.