Exercise: Point Instances#

Authoring Point Instances#

In this exercise, we will take an export data set of a scatter of boxes and pallets. We’ll use this data to create a PointInstancer.

  1. Open instancing_exercises/ex_pt_author/author_point_instancer.py in VSCode to inspect the code.

  2. Run in the terminal:

python .\instancing_exercises\ex_pt_author\author_point_instancer.py
  1. Run in the terminal:

.\scripts\usdview.bat .\instancing_exercises\ex_pt_author\Scenario.usd --camera ExCam_01

  1. Close usdview.

Refining Point Instances#

In this exercise, we will refine point instances in three ways:

  • Deactivating an instance to prune it.

  • Promoting an instance to a fully editable asset.

  • Using primvars to add shading diversity.

  1. Run in the terminal:

.\scripts\usdview.bat .\instancing_exercises\ex_pt_refine\Scenario.usd --camera ExCam_01

Tip

Click Camera > Select Camera > ExCam_01 if you ever lose your place in the scene or want to get back to this camera position.

In the horizontal center of the Viewport, there is a box just in front of a pallet. This is the point that we want to prune. We know ahead of time that this is index 1228 in our PointInstancer arrays.

  1. Click Window > Interpreter to open the Interpreter window.

  2. Run the following code in the Interpreter window:

1stage = usdviewApi.stage
2prim = stage.GetPrimAtPath("/World/Scatter")
3pi = UsdGeom.PointInstancer(prim)
4pi.DeactivateId(1228)

You should notice that the box we called out disappeared. This code deactivates the given ID from the PointInstancer. This authors metadata on the PointInstancer that indicates that the given point should be pruned entirely.

What if we didn’t want to prune this point, but wanted to promote it instead into a fully editable asset. Promotion starts with pruning, but then you replace the pruned point with the full asset. Let’s run some code to reference a new asset and place it in the same place as our pruned point.

  1. Run the following code in the Interpreter window:

1from pathlib import Path
2box = stage.DefinePrim("/World/CubeBox_A04_26cm_01")
3stage_path = Path(stage.GetRootLayer().identifier)
4box_asset_path = stage_path.parent.parent / "src_assets" / "Assets" / "Components" / "CubeBox_A04_26cm" / "CubeBox_A04_26cm.usd"
5box.GetReferences().AddReference(str(box_asset_path))
6box_xform = UsdGeom.Xformable(box)
7box_xform.GetTranslateOp().Set(pi.GetPositionsAttr().Get()[1228])
8box_xform.AddOrientOp(precision=UsdGeom.XformOp.PrecisionHalf).Set(pi.GetOrientationsAttr().Get()[1228])

The box looks just like it did before in the Viewport, but now we have a new prim hierarchy in the scenegraph where we can author new opinions to manipulate this asset.

Now let’s look at a third refinement option using primvars. In this case, we’re going to use primvars:cleanness to change how clean each of the scattered boxes are.

  1. Run the following code in the Interpreter window:

1import random
2pv_api = UsdGeom.PrimvarsAPI(pi)
3cleanness = pv_api.CreatePrimvar("cleanness", Sdf.ValueTypeNames.FloatArray, UsdGeom.Tokens.vertex)
4cleanness.Set([random.uniform(0.3,1) for x in range(2000)])

This code creates primvars:cleanness on our PointInstancer, but it uses “vertex” for the variability. What this means is that each item in our array will be assigned to a different PointInstancer point. We’re using the random library to set 2000 random values.

But nothing changed in the viewport. This is because primvars are inherited, but only if a value hasn’t been set by a descendant. The descendant opinion on the prototype that we referenced is stronger than ancestor opinion of the PointInstancer. Fortunately, we can block the prototypes opinion to complete our task.

  1. Run the following code in the Interpreter window:

1box_proto = stage.GetPrimAtPath("/World/Scatter/Prototypes/CubeBox_A04_26cm")
2box_proto.GetAttribute("primvars:cleanness").Block()

  1. Close usdview.