![]() |
|
The code used in this tutorial is available in USD/extras/exec/examples/computingValues/
The purpose of this tutorial is to demonstrate how to use OpenExec APIs to request values to be computed.
For this tutorial, we will make use of the computeLocalToWorldTransform computations provided by UsdGeomXformable prims. The result of this computation on a given Xform is a 4x4 matrix that transforms points local to that Xform into points in world-space. The result of this computation depends on two values:
transform attribute on the given Xform.computeLocalToWorldTransform recursively invoked on the Xform's parent Xform.Note:
The API that is presented here is the lowest-level API, designed for performance-intensive clients, such as an imaging system. OpenExec will eventually include convenience APIs, layered on top of the API shown here, for use cases that don't require maximum performance and for use cases that adhere to certain patterns that allow for more convenient API while still maintaining maxiumum performance.
The first step is to create a UsdStage from a scene that contains UsdGeomXformable prims, such as the scene described by this usda file:
Assuming this layer is in a file named xformPrims.usda we can open the layer on a UsdStage as follows:
In order to compute values from a UsdStage, we need to create an ExecUsdSystem object from the stage:
The ExecUsdSystem maintains the internal state needed to compute values from a given UsdStage. In particular, the system object holds onto the compiled data flow network that is used for evaluation. Note that we can make requests for different sets of values originating from the same stage using the same system object and the execution processes benefit from the shared state, amortizing costs (including the cost of compiling the network) across different value requests.
A set of values to be computed is specified by building an ExecUsdRequest. Each requested value is identified by an ExecUsdValueKey, which contains a provider–a UsdObject that provides a computation–and a TfToken that gives the name of the requested computation.
To build a request containing a collection of value keys, we call ExecUsdSystem::BuildRequest:
A request maintains state that is required to efficiently compute the particular set of requested values that it represents. In particular, it holds onto a schedule that is used to accelerate evaluation, by amortizing the cost of creating the schedule across multiple rounds of computation using the same request.
Preparing the request, by calling ExecUsdSystem::PrepareRequest, does two things:
Note that explicitly preparing the request is optional; if a client calls Compute without first calling PrepareRequest, the call to Compute will prepare the request before computing. However, it is often desirable for client code to have explicit control over when the request is prepared, because of the cost of doing so. Specifically, compiling and scheduling tend to be more expensive than evaluation, so it often makes sense to ensure that these happen first, before multiple rounds of computation.
To compute the set of requested values, we simply call ExecUsdSystem::Compute:
The computed results are now ready, and can be accessed via the returned ExecUsdCacheView object.
To access the computed values, we call ExecUsdCacheView::Get to extract them, using indices that correspond to the order of the value keys in the vector used to build the request:
Bringing this all together into a single block of example code: