Siggraph Presentation

This guide will be officially introduced at Siggraph 2023 - Houdini Hive on Wednesday, 9. of August 2023 at 11:00 AM PST.

Bounding Box Queries

Whenever we change our geometry data, we have to update our "extents" attribute on boundable prims. The bbox cache allows us to efficiently query bounding boxes. The result is always returned in the form of a Gf.BBox3d object.

For some production related examples, check out our Frustum Culling and Particles sections.

Checkout the official API docs for more info.

The "extents" attribute is managed via the UsdGeom.Boundable schema, you can find the docs here. This has to be set per boundable prim.

The "extensHint" attribute is managed via the UsdGeom.ModeAPI, you can find the docs here. This can be used to accelerate lookups, by not looking into the child-hierarchy. We typically write it on prims that load payloads, to have extent data when the payload is unloaded.

from pxr import Gf,  Sdf, Usd, UsdGeom, Vt
stage = Usd.Stage.CreateInMemory()
# Setup scene
root_prim_path = Sdf.Path("/root")
root_prim = stage.DefinePrim(root_prim_path, "Xform")
cone_prim_path = Sdf.Path("/root/cone")
cone_prim = stage.DefinePrim(cone_prim_path, "Cone")

root_xformable = UsdGeom.Xformable(root_prim)
root_translate_op = root_xformable.AddTranslateOp()
root_translate_op.Set(Gf.Vec3h([50, 30, 10]))
root_rotate_op = root_xformable.AddRotateZOp()
root_rotate_op.Set(45)

cone_xformable = UsdGeom.Xformable(cone_prim)
cone_translate_op = cone_xformable.AddTranslateOp()
cone_rotate_op = cone_xformable.AddRotateXYZOp()

## UsdGeom.BBoxCache()
# Get: 'GetTime', 'GetIncludedPurposes',  'GetUseExtentsHint',
# Set: 'SetTime', 'SetIncludedPurposes',
# Clear: 'Clear'

# Compute: 'ComputeWorldBound', 'ComputeLocalBound', 'ComputeRelativeBound', 'ComputeUntransformedBound', 
# Compute Instances: 'ComputePointInstanceWorldBound', 'ComputePointInstanceWorldBounds',
#                    'ComputePointInstanceLocalBound',  'ComputePointInstanceLocalBounds',
#                    'ComputePointInstanceRelativeBound', 'ComputePointInstanceRelativeBounds',
#                    'ComputePointInstanceUntransformedBounds', 'ComputePointInstanceUntransformedBound'
time_code = Usd.TimeCode(1) # Determine frame to lookup
bbox_cache = UsdGeom.BBoxCache(time_code, [UsdGeom.Tokens.default_, UsdGeom.Tokens.render],
                               useExtentsHint=False, ignoreVisibility=False)
# Useful for intersection testing:
bbox = bbox_cache.ComputeWorldBound(cone_prim)
print(bbox) # Returns: [([(-1, -1, -1)...(1, 1, 1)]) (( (0.7071067811865475, 0.7071067811865476, 0, 0), (-0.7071067811865476, 0.7071067811865475, 0, 0), (0, 0, 1, 0), (50, 30, 10, 1) )) false]
# When payloading prims, we want to write an extentsHint attribute to give a bbox hint
# We can either query it via UsdGeom.BBoxCache or for individual prims via UsdGeom.Xformable.ComputeExtentsHint
root_geom_model_API = UsdGeom.ModelAPI.Apply(root_prim)
extentsHint = root_geom_model_API.ComputeExtentsHint(bbox_cache)
root_geom_model_API.SetExtentsHint(extentsHint, time_code)
# Or
bbox = bbox_cache.ComputeUntransformedBound(root_prim)
aligned_range = bbox.ComputeAlignedRange()
extentsHint = Vt.Vec3hArray([Gf.Vec3h(list(aligned_range.GetMin())), Gf.Vec3h(list(aligned_range.GetMax()))])
root_geom_model_API.SetExtentsHint(extentsHint, time_code)