Houdini Engine 7.0
|
One way to handle instancing in Houdini and Houdini Engine is using packed primitives. Packed primitives are essentially primitives that live purely inside of SOPs and contain one or more primitives with their own transforms. Packed primitives can easily contain other packed primtivies allowing you to have a full transform hierarchy completely inside of SOPs. Furthermore, contained packed primitives which happen to be duplicates will be properly instanced meaning that only one copy of the unique geometry will be stored in memory.
It's better, going foward, to have a real asset in mind. Here is our simple packed primitive asset:
The result being:
Where the only thing to note is that each Copy SOP has its Pack Geometry Before Copying option turned on:
In Houdini Engine, packed primitives show up like any other primitive, as Parts Parts. The way you can tell if a part is a packed primitive is that the HAPI_PartInfo::type will be set to HAPI_PARTTYPE_INSTANCER. You can also tell if a part is being instanced by checking HAPI_PartInfo::isInstanced.
First thing to do is set the desired packed primitive mode for cooking. For this, there is HAPI_CookOptions::packedPrimInstancingMode. The modes are:
Next is getting finding out who is instancing who. Use each instancer part's HAPI_PartInfo::instancedPartCount to get the HAPI_PartId's of the parts being instanced with HAPI_GetInstancedPartIds(). With our asset above, for example, the instancer part corresponding to the copy2 node would have a HAPI_PartInfo::instancedPartCount of 2 and HAPI_GetInstancedPartIds() would give you the HAPI_PartId's of the instanced box and curve parts.
Finally, we need to know where to instance our instanced parts. Use each instancer part's HAPI_PartInfo::instanceCount to get the instance transforms with HAPI_GetInstancerPartTransforms(). With our asset above, for example, the instancer part corresponding to the copy2 node would have a HAPI_PartInfo::instanceCount of 4 and HAPI_GetInstancerPartTransforms() would return the points (transforms) of grid2. Here's an example that parses a packed primitive part hierachy of the example asset above and gets all the instance transforms:
Another way to handle instancing in Houdini and Houdini Engine is by the use of Instance objects. An Instance object is an object level node with some special properties. Inside Houdini, an Instance node looks like the following:
The first thing is to make sure the Point Instancing parameter is set to Full point instancing as shown in the screenshot.
If the Instance Object parameter is filled out, Houdini will try to create instances of the specified object. If the instance object is something that resides within the same asset, then it will be brought in along with the rest of the asset into the host environment, and the HAPI_ObjectInfo::objectToInstanceId will be set to the object id of that object. The host can then look up the object by its id and instance it.
Underneath the instance object (or inside it, rather) is another network of nodes, where geometry is being computed (a SOP network, in Houdini speak). Only in this case, the geometry isn't in the form of triangles and normals that you'd display directly, but rather it is a point cloud. Each point of the this point cloud has a position and several other attributes on it that indicate the proper orientation of the object to be instanced ("N", "up", "scale"). Here is a picture of what that point cloud might look like:
Once objects have been instanced onto the points, here is what Houdini Engine would give a host application:
To find the transform to use at each point, use ::HAPI_GetInstanceTransforms(). This function takes into account the reserved attributes (such as "N" and "up") and returns a transform for every single point in the point cloud. You could then apply this transform in the host environment to the object you wish to instance.
The instance object
field is simple, but it has a shortcoming: it assumes only one object is to be instanced. In many cases, such as the pictures above, each point might have a different geometry instanced to it. In this case, we can make use of a special attribute with the name instance:
As you can see from the figure above, the per point attribute instance
is determining the model to be used at each point. This information can be extracted in the host environment through the attribute query functions covered in Query Attribute Information.