Referencing Basics#

What are References?#

This lesson talks briefly about references. The word may seem familiar – we introduced the concept in the previous lesson on composition and strength ordering, where “references” represents the R in LIVRPS.

A reference in Universal Scene Description is a composition arc that enables the composition of prims and their descendants onto other prims – this allows us to use references to aggregate larger scenes from smaller, modular units of scene description. This can be done with external references, which graft data from other files, or internal references, which graft data from other parts of the hierarchy.

They are fundamental in USD’s composition system, enabling modular and reusable scene description, and they are the second most important composition arc in USD, after sublayers.

How Does It Work?#

A reference arc includes the identifier of or path to the layer to reference from (which can be omitted for internal references) and the prim path to reference (which can be omitted if you want to load an entire external layer which has a default prim defined).

When a prim is composed via a reference arc, USD first composes the layer stack of the referenced prim, then adds the resulting prim spec to the destination prim. Then, it applies any overrides or additional composition arcs from the destination prim.

Working With Python#

Here are a few ways you can work with references using the Python API:

1# Return a UsdReferences object for managing references on a prim
2prim.GetReferences()
3
4# Add a reference to the specified asset and prim path
5references.AddReference(assetPath, primPath) 
6
7# Remove all references from a prim
8references.ClearReferences()

Examples#

Example 1: Adding a Reference#

References are a composition arc. References are like links to separate pieces of a project, allowing you to include and reuse these pieces without copying them.

Here’s an example of how a reference looks in .usda:

 1#usda 1.0
 2
 3def Xform "World"
 4{
 5    def Xform "Geometry"
 6    {
 7        def Xform "Box" (
 8            prepend references = @./cubebox_a02/cubebox_a02.usd@
 9        )
10        {
11        }
12    }
13}

Firstly, we want to grab all references of a prim. To do this we use GetReferences(). This returns a UsdReferences object, which allows us to add, remove, and modify references.

To add a reference, we use AddReference(). Let’s see these in practice.

 1from pxr import Usd, UsdGeom, Gf
 2
 3# Create a new stage and define a cube:
 4file_path = "_assets/cube.usda"
 5stage = Usd.Stage.CreateNew(file_path)
 6cube = UsdGeom.Cube.Define(stage, "/Cube")
 7stage.SetDefaultPrim(cube.GetPrim())
 8stage.Save()
 9
10# Create a second file path and stage, define a world and a sphere:
11second_file_path = "_assets/shapes.usda"
12stage = Usd.Stage.CreateNew(second_file_path)
13world = UsdGeom.Xform.Define(stage, "/World")
14UsdGeom.Sphere.Define(stage, world.GetPath().AppendPath("Sphere"))
15
16# Define a reference prim and set its translation:
17reference_prim = stage.DefinePrim(world.GetPath().AppendPath("Cube_Ref"))
18
19# Add a reference to the "cube.usda" file:
20reference_prim.GetReferences().AddReference("./cube.usda")
21# Position the cube
22UsdGeom.XformCommonAPI(reference_prim).SetTranslate(Gf.Vec3d(5, 0, 0))
23
24stage.Save()
Loading your model...
_assets/shapes.usda
        
    

Here we created a stage representing a Cube prim and then used a reference arc to incorporate it into a new stage, shapes.usda that also defined a Sphere prim. The result is a stage with a Sphere and a Cube.

Example 2: Referencing an External Asset#

References in OpenUSD allow for the inclusion of external assets or sub-scene data into a scene. This mechanism helps in modularizing and reusing assets across different scenes and projects, enabling efficient management of large-scale 3D environments.

Here, we’ll add a reference to a shipping box asset.

'_assets/cubebox_a02'
 1from pxr import Usd, UsdGeom
 2
 3file_path = "_assets/asset_ref.usda"
 4stage: Usd.Stage = Usd.Stage.CreateNew(file_path)
 5
 6# Define a root Xform named "World"
 7world_xform: UsdGeom.Xform = UsdGeom.Xform.Define(stage, "/World")
 8
 9# Define a child Xform named "Geometry" under the "World" Xform
10geometry_xform: UsdGeom.Xform = UsdGeom.Xform.Define(stage, world_xform.GetPath().AppendPath("Geometry"))
11
12# Define a new Xform named "Box" under the root "Geometry" Xform
13box_xform: UsdGeom.Xform = UsdGeom.Xform.Define(stage, geometry_xform.GetPath().AppendPath("Box"))
14box_prim: Usd.Prim = box_xform.GetPrim()
15
16# Add a reference to a USD file containing a box geometry
17box_prim.GetReferences().AddReference("./cubebox_a02/cubebox_a02.usd")
18
19stage.Save()
Loading your model...
_assets/asset_ref.usda
        
    

Key Takeaways#

So, why is it important to understand and leverage references properly? References have several practical use cases. As mentioned earlier, references are useful for building large, complex scenes by referencing smaller sub-scenes or components. We see referencing used commonly for asset libraries, where you might have assets, materials or other props reused across several scenes.

By leveraging references, artists and developers can create more efficient workflows, manage complex scenes, and collaborate more effectively across different departments and production stages.